According to AHCI 1.3.1, 5.3.8.1 RegFIS:Entry, if ERR_STAT is set in the received FIS, the HBA shall jump to state ERR:FatalTaskfile, which will raise a TFES IRQ.
This means that if ERR_STAT is set in the recevied FIS, PxIS.TFES will be set, without either PxIS.DHRS or PxIS.PSS being set.
SeaBIOS function ahci_port_setup() will try to identify an AHCI device by sending an ATAPI identify device command. However, such a command will be aborted with ERR_STAT set for a regular (non-ATAPI) device.
ahci_command() already performs the correct error recovery steps when status is correctly set, so simply modify ahci_command() to read the correct status when PxIS.TFES is set.
It is safe to read PxTFD when PxIS.TFES is set, even for systems with a port multiplier, see AHCI 1.3.1, 9.3.7 PxTFD Register Information: "When a taskfile error occurs (PxIS.TFES is set to '1'), the host may refer to the values in PxTFD. The values in PxTFD at this time are guaranteed to correspond to the device that reported the taskfile error condition."
Without this, each boot will be delayed by 32 seconds, waiting for the AHCI command to timeout.
Signed-off-by: Niklas Cassel niklas.cassel@wdc.com --- src/hw/ahci.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index d45b430..3fa845a 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -138,6 +138,12 @@ static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, intbits = ahci_port_readl(ctrl, pnr, PORT_IRQ_STAT); if (intbits) { ahci_port_writel(ctrl, pnr, PORT_IRQ_STAT, intbits); + if (intbits & 0x40000000) { + u32 tf = ahci_port_readl(ctrl, pnr, PORT_TFDATA); + status = tf & 0xff; + error = (tf & 0xff00) >> 8; + break; + } if (intbits & 0x02) { status = GET_LOWFLAT(fis->psfis[2]); error = GET_LOWFLAT(fis->psfis[3]);