When binding AHCI controller to virtual machine, the attached ATA device cannot be recognized for the following reason: The first Identify PACKET CMD will be failed without dobut which will lead PORT_IRQ_TF_ERR be set in PxIS due to ERR bit set to 1 in D2H Register FIS(PxTFD.STS.ERR=1). In this case, the first CMD will be timeout for seabios only polling PORT_IRQ_D2H_REG_FIS & PORT_IRQ_PIOS_FIS before triggering error handling which leads AHCI controller is an error state, then the second IDENTIFY CMD cannot be issued by AHCI controller, no ATA device will be detected.
In AHCI spec HBA Port State Machine section(5.3.8.1 and 5.3.16.5), we can see this sequence: RegFIS:Entry --> ERR:FatalTaskfile (PxTFD.STS.ERR=1) --> ERR:WaitForClear, no entry for PORT_IRQ_D2H_REG_FIS/PORT_IRQ_PIOS_FIS to be set at this time.
May be we can also add PORT_IRQ_TF_ERR bit check when polling command completion status?
fail log: 02.386: |bffa6000| AHCI/1: link up 02.387: |bffa6000| AHCI/1: send cmd ... 02.387: |bffa7000| phys_free bffa9c00 (detail=0xbffaa320) 02.396: |bffa7000| phys_free bffaa200 (detail=0xbffaa1d0) 02.396: |bffa7000| phys_free bffaa000 (detail=0xbffaa1a0) 02.396: |bffa7000| phys_free bffaa380 (detail=0xbffaa350) 02.400: \bffa7000/ End thread 02.401: phys_free bffa7000 (detail=0xbffaa170) 34.391: |bffa6000| WARNING - Timeout at ahci_command:153! 34.392: |bffa6000| AHCI/1: send cmd ... 66.397: |bffa6000| WARNING - Timeout at ahci_command:153!
Signed-off-by: zhaoxin\runaguooc RunaGuo-oc@zhaoxin.com --- src/hw/ahci.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/hw/ahci.c b/src/hw/ahci.c index d45b430..bab5c35 100644 --- a/src/hw/ahci.c +++ b/src/hw/ahci.c @@ -104,7 +104,7 @@ static void ahci_port_writel(struct ahci_ctrl_s *ctrl, u32 pnr, u32 reg, u32 val static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, void *buffer, u32 bsize) { - u32 val, status, success, flags, intbits, error; + u32 val, status, success, flags, intbits, error, tf; struct ahci_ctrl_s *ctrl = port_gf->ctrl; struct ahci_cmd_s *cmd = port_gf->cmd; struct ahci_fis_s *fis = port_gf->fis; @@ -148,6 +148,14 @@ static int ahci_command(struct ahci_port_s *port_gf, int iswrite, int isatapi, error = GET_LOWFLAT(fis->rfis[3]); break; } + + if(intbits & PORT_IRQ_TF_ERR){ + tf = ahci_port_readl(ctrl,pnr,PORT_TFDATA); + status = tf & 0xff; + error = tf & 0xff00; + break; + } + } if (timer_check(end)) { warn_timeout(); -- 2.17.1