ATA驱动- hardreset&softreset分析

内核文档

内核路径下的文档Documentation/DocBook/libata.tmpl

内核文档解释说明不同的reset调用对应的底层Error handler reset函数;

softreset&hardreset EH函数

在内核ata驱动中目前pata已经过时了,使用sata协议的硬盘需要使用AHCI协议作为上层接口协议,目前ata驱动框架需要调用libata库,scsi驱动,源码kernel/drivers/ata/libahci.c

而ahci作为上层驱动,作为底层驱动,定义ahci_ops后导出符号,在使用前声明即可

ahci_hardreset函数

源码位置:kernel/drivers/ata/

//libahci.c
    ahci_stop_engin(ap);//设置host controller CMD&CONTROL寄存器相关寄存器bit位

    ata_tf_init(link->device, &tf);//初始化taskfile寄存器
    tf.command = ATA_BUSY;
    ata_tf_to_fis(&tf, 0, 0, d2h_fis);

    sata_link_hardreset(link, timing, deadline, &online, ahci_check_ready);
        1 sata_set_spd_needed(link) //判断该link是否需要应用SATA 速度配置
            sata_scr_read(link, SCR_CONTROL, &scontrol)//判断CONTROL寄存器
            scontrol = (scontrol & 0x0f0) | 0x304;
            sata_scr_write(link, SCR_CONTROL, scontrol); //通过设置host controller让SATA interface处于Slumber&Partial关闭状态,无速度协商限制,让SATA接口关闭,port PHY处于离线状态
            sata_set_spd(link);//将SCONTROL寄存器配置的link数据配置下去、

        2   sata_scr_read(link, SCR_CONTROL, &scontrol); //再读SCR_CONTROL
            scontrol = (scontrol & 0x0f0) | 0x301; //配置SCONTROL寄存器执行接口初始化建立PHY
            通信,设置interface重启以及通信初始化
            sata_scr_write_flush(link, SCR_SCONTROL, scontrol);//将SCONTROL配置数据刷新
            ata_msleep(link->qp, 1);//按照协议进行1ms休眠

            /* bring link back */
            sata_link_resume(link, timing, deadline);//最多5次retry并消抖

            if (ata_phys_link_offline(link))//检测判断link是否处于离线状态
            if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) //判断当前link是否支持PMP(端口倍增器功能)
                if (check_ready) //判断link是否ready
                    ata_deadline(jiffies, ATA_TMOUT_PMP_WAIT);//设置deadline
                    if(time_after(pmp_deadline, deadline)) //判断pmp_deadline与deadline:若pmp_deadline在deadline之后返回TRUE;
                        pmp_deadline = deadline;
                    ata_wait_ready(link, pmp_deadline, cheakready);//等待link ready
            
            if (check_ready)
                ata_wait_ready(link, deadline, cheack_ready);//等待link ready

ahci_softreset函数

//libachi.c
    sata_srst_pmp(link); //判断是否支持PMP&&该link为host_link

    ahci_do_softreset(link, class, pmp, deadline, ahci__check_ready);
        ahci_kick_engine(ap); 
            ahci_stop_engin(ap);//设置host  controller CMD&CONTROL寄存器相关寄存器bit位
            /* need to do CL0?
             * always do CL0 if PMP is attached (AHCI-1.3 9.2)*/ //参考AHCI协议

        if ( !ata_is_host_link(link) && pp->fbs_enabled)
            ahci_disabled_fbs(ap);
            fbs_disabled = true;
        ata_tf_init(link->device, &tf);

        /* issue the first D2H Register FIS */
        tf.ctl = ATA_SRST;

        if (ahci_exec_polled_cmd(ap, pmp, &tf, 0, AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY, msecs))
        ata_msleep(ap, 1);
        
        /* issue the second D2H Register FIS */
        tf.ctl &= ~ATA_SRST;
        ahci_exec_polled_cmd(ap, pmp, &tf, 0, 0, 0);

        /* wait for link to become ready */
        rc = ata_wait_after_reset(link, deadline, check_ready);
        if (rc == -EBUSY && hpriv->flags & AHCI_HFLAG_SRST_TOUT_IS_OFFLINE) //返回值错误&掉线
            //掉线情况&设备未ready情况打印信息输出&goto对应处理
                ahci_dev_classify(ap);//设备分类
        if (fbs_disabled)
            ahci_enable_fbs(ap);//开启fbs

softreset&hardreset差异

1 hardreset较之于softreset不会去设置AHCI相关的寄存器;
2 hardreset除了操控host controller还会操作PHY;

拓展

AHCI 1.3 9.2 Port Multiplier Enumeration

协议原文
    In order to enumerate a Port Multiplier, a software reset is issued to port 0Fh (control port) on the Port 
Multiplier. If the signature returned corresponds to a Port Multiplier, then a Port Multiplier is attached. If 
the signature returned corresponds to another device type, then a Port Multiplier is not attached. 
To reliably enumerate the Port Multiplier, regardless of the presence of a device on Port Multiplier device 
port 0, the PxCMD.CLO (command list override) bit should be used if this feature is supported by the HBA 
(indicated by CAP.SCLO being set to ‘1’). Software should ensure that the PxCMD.ST bit is ‘0’. Then 
software should construct the two Register FISes required for a software reset in the command list, where 
the PM Port field value in the Register FIS is set to 0Fh. After constructing the FISes in the command list, 
software should set PxCMD.CLO to ‘1’ to force the BSY and DRQ bits in the Status register to be cleared. 
Then software should set the PxCMD.ST bit to ‘1’ and set appropriate PxCI bits in order to begin 
execution of the software reset command. 
If the CAP.SCLO bit is cleared to ‘0’, a Port Multiplier can only be enumerated after a device on Port 
Multiplier device port 0 sends a Register FIS to the host that clears PxTFD.STS.BSY and 
PxTFD.STS.DRQ to ‘0’.

抛砖引玉 - 疑问:分析ahci_softreset为什么issue两次D2H FIS?

内核ata驱动代码这里只是给出代码,并未解释,这里就是Linux驱动具体结合Specification的地方了!

AHCI Spec1.3 --- 10.4 Reset

AHCI supports three levels of reset:
• Software – a single device on one of the ports is reset, but the HBA and physical communication
remain intact. This is the least intrusive.
• Port – the physical communication between the HBA and device on a port are disabled. This is
more intrusive
• HBA – the entire HBA is reset, and all ports are disabled. This is the most intrusive.
When an HBA or port reset occurs, Phy communication shall be re-established with the device through a
COMRESET followed by the normal out-of-band communication sequence defined in Serial ATA. At the
end of the reset, the device, if working properly, will send a D2H Register FIS, which contains the device
signature. When the HBA receives this FIS, it updates PxTFD.STS and PxTFD.ERR register fields, and
updates the PxSIG register with the signature.
Software is recommended to follow a staggered reset approach, starting from a less intrusive reset
mechanism and then using a more intrusive reset mechanism only if the less intrusive mechanism does
not succeed in clearing the condition.
这里可以看出AHCI 协议原文支持三种reset级别,但软件处理分为两类:hardreset&softreset,但port&HBA这两个均会对PHY操作的reset归类到harddreset中,
因为softreset&hardreset在软件处理逻辑中均会利用到,除非在系统&uboot中设置关闭。以下是AHCI协议原文:
10.4.1 Software Reset
Legacy software contained a standard mechanism for generating a reset to a Serial ATA device – setting
the SRST (software reset) bit in the Device Control register. Serial ATA has a more robust mechanism
called COMRESET, also referred to as port reset. A port reset is the preferred mechanism for error
recovery and should be used in place of software reset.
To issue a software reset in AHCI, software builds two H2D Register FISes in the command list. The first
Register FIS has the SRST bit set to ‘1’ in the Control field of the Register FIS, the ‘C’ bit is set to ‘0’ in the
Register FIS, and the command table has the CH[R] (reset) and CH[C] (clear BSY on R_OK) bits set to
‘1’. The CH[R] (reset) bit causes the HBA to perform a SYNC escape if necessary to put the device into
an idle condition before sending the software reset. The CH[C] (clear BSY on R_OK) bit needs to be set
for the first Register FIS to clear the BSY bit and proceed to issue the next Register FIS since the device
does not send a response to the first Register FIS in a software reset sequence. The second Register
FIS has the SRST bit set to ‘0’ in the Control field of the Register FIS, the ‘C’ bit is set to ‘0’ in the Register
FIS, and the command table has the CH[R] (reset) and CH[C] (clear BSY on R_OK) bits cleared to ‘0’.
Refer to the Serial ATA Revision 2.6 specification for more information on the software reset FIS
sequence.
When issuing a software reset sequence, there should not be other commands in the command list.
Before issuing the software reset, software must clear PxCMD.ST, wait for the port to be idle (PxCMD.CR
= ‘0’), and then re-set PxCMD.ST. PxTFD.STS.BSY and PxTFD.STS.DRQ must be cleared prior to
issuing the reset. If PxTFD.STS.BSY or PxTFD.STS.DRQ is still set based on the failed command, then
a port reset should be attempted or command list override (PxCMD.CLO) should be used if supported.
Note that a device-to-host FIS from a previously failed command may be received after the PxCMD.ST bit
has been cleared and/or re-set. It is recommended that the HBA ignore such a FIS or SYNC Escape that
FIS (as directed by the CH[R] bit being set in the first software reset H2D Register FIS).
10.4.2 Port Reset
If a port is not functioning properly after a software reset, software may attempt to re-initialize
communication with the port via a COMRESET. It must first clear PxCMD.ST, and wait for PxCMD.CR to
clear to ‘0’ before re-initializing communication. However, if PxCMD.CR does not clear within a
reasonable time (500 milliseconds), it may assume the interface is in a hung condition and may continue
with issuing the port reset.
Software causes a port reset (COMRESET) by writing 1h to the PxSCTL.DET field to invoke a
COMRESET on the interface and start a re-establishment of Phy layer communications. Software shall
wait at least 1 millisecond before clearing PxSCTL.DET to 0h; this ensures that at least one COMRESET
signal is sent over the interface. After clearing PxSCTL.DET to 0h, software should wait for
communication to be re-established as indicated by bit 0 of PxSSTS.DET being set to ‘1’. Then software
should write all 1s to the PxSERR register to clear any bits that were set as part of the port reset.
When PxSCTL.DET is set to 1h, the HBA shall reset PxTFD.STS to 7Fh and shall reset PxSSTS.DET to
0h. When PxSCTL.DET is set to 0h, upon receiving a COMINIT from the attached device,
PxTFD.STS.BSY shall be set to ’1’ by the HBA.
10.4.3 HBA Reset
If the HBA becomes unusable for multiple ports, and a software reset or port reset does not correct the
problem, software may reset the entire HBA by setting GHC.HR to ‘1’. When software sets the GHC.HR
bit to ‘1’, the HBA shall perform an internal reset action. The bit shall be cleared to ‘0’ by the HBA when
the reset is complete. A software write of ‘0’ to GHC.HR shall have no effect. To perform the HBA reset,
software sets GHC.HR to ‘1’ and may poll until this bit is read to be ‘0’, at which point software knows that
the HBA reset has completed.
If the HBA has not cleared GHC.HR to ‘0’ within 1 second of software setting GHC.HR to ‘1’, the HBA is in
a hung or locked state.
When GHC.HR is set to ‘1’, GHC.AE, GHC.IE, the IS register, and all port register fields (except
PxFB/PxFBU/PxCLB/PxCLBU) that are not HwInit in the HBA’s register memory space are reset. The
HBA’s configuration space and all other global registers/bits are not affected by setting GHC.HR to ‘1’.
Any HwInit bits in the port specific registers are not affected by setting GHC.HR to ‘1’. The port specific
registers PxFB, PxFBU, PxCLB, and PxCLBU are not affected by setting GHC.HR to ‘1’. If the HBA
supports staggered spin-up, the PxCMD.SUD bit will be reset to ‘0’; software is responsible for setting the
PxCMD.SUD and PxSCTL.DET fields appropriately such that communication can be established on the
Serial ATA link. If the HBA does not support staggered spin-up, the HBA reset shall cause a COMRESET
to be sent on the port.

posted @ 2022-12-15 17:15  合滨  阅读(1151)  评论(0编辑  收藏  举报