]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/AtaAtapiPassThru: When D2H FIS received at PIO DATA-IN transfer, check...
authorReza Jelveh <reza.jelveh@tuhh.de>
Wed, 22 Oct 2014 05:52:48 +0000 (05:52 +0000)
committererictian <erictian@Edk2>
Wed, 22 Oct 2014 05:52:48 +0000 (05:52 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Reza Jelveh <reza.jelveh@tuhh.de>
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: A. Sava <asava.dev@gmail.com>
Reviewed-by: Star Zeng <Start.Zeng@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16225 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c

index 7fc7a2812676bcace176849a87558d2c20e41a0b..72b1e5cc7e85f32e8215af97813bc5e69595df54 100644 (file)
@@ -704,6 +704,8 @@ AhciPioTransfer (
   UINT32                        PortTfd;\r
   UINT32                        PrdCount;\r
   BOOLEAN                       InfiniteWait;\r
+  BOOLEAN                       PioFisReceived;\r
+  BOOLEAN                       D2hFisReceived;\r
 \r
   if (Timeout == 0) {\r
     InfiniteWait = TRUE;\r
@@ -780,15 +782,31 @@ AhciPioTransfer (
     Status = EFI_TIMEOUT;\r
     Delay  = DivU64x32 (Timeout, 1000) + 1;\r
     do {\r
+      PioFisReceived = FALSE;\r
+      D2hFisReceived = FALSE;\r
       Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;\r
-\r
       Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);\r
       if (!EFI_ERROR (Status)) {\r
+        PioFisReceived = TRUE;\r
+      }\r
+      //\r
+      // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.\r
+      // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device\r
+      // after the transaction is finished successfully.\r
+      // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.\r
+      // By this way, we can know if there is a real error happened.\r
+      //\r
+      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
+      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);\r
+      if (!EFI_ERROR (Status)) {\r
+        D2hFisReceived = TRUE;\r
+      }\r
+\r
+      if (PioFisReceived || D2hFisReceived) {\r
         Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
         PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
         //\r
         // PxTFD will be updated if there is a D2H or SetupFIS received. \r
-        // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.\r
         //\r
         if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
           Status = EFI_DEVICE_ERROR;\r
@@ -797,23 +815,20 @@ AhciPioTransfer (
 \r
         PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));\r
         if (PrdCount == DataCount) {\r
+          Status = EFI_SUCCESS;\r
           break;\r
         }\r
       }\r
 \r
-      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
-      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = EFI_DEVICE_ERROR;\r
-        break;\r
-      }\r
-\r
       //\r
       // Stall for 100 microseconds.\r
       //\r
       MicroSecondDelay(100);\r
 \r
       Delay--;\r
+      if (Delay == 0) {\r
+        Status = EFI_TIMEOUT;\r
+      }\r
     } while (InfiniteWait || (Delay > 0));\r
   } else {\r
     //\r