]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/AtaAtapiPassThru: update AtaStatusBlock after cmd exec
authorFeng Tian <feng.tian@intel.com>
Mon, 31 Oct 2016 05:46:08 +0000 (13:46 +0800)
committerFeng Tian <feng.tian@intel.com>
Tue, 1 Nov 2016 01:17:47 +0000 (09:17 +0800)
AhciDumpPortStatus doesn't fully populate all the fields of
AtaStatusBlock after completing command execution, which may bring
issue if someone depends on the return status.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c

index 68bce94810a6357ebe8fa73eb88e3ab53507a89e..533d2013894fdb850cd00046513978c243c6f6ae 100644 (file)
@@ -371,6 +371,7 @@ AhciClearPortStatus (
   in the Status Register, the Error Register's value is also be dumped.\r
 \r
   @param  PciIo            The PCI IO protocol instance.\r
+  @param  AhciRegisters    The pointer to the EFI_AHCI_REGISTERS.\r
   @param  Port             The number of port.\r
   @param  AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
 \r
@@ -379,24 +380,42 @@ VOID
 EFIAPI\r
 AhciDumpPortStatus (\r
   IN     EFI_PCI_IO_PROTOCOL        *PciIo,\r
+  IN     EFI_AHCI_REGISTERS         *AhciRegisters,\r
   IN     UINT8                      Port,\r
   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock\r
   )\r
 {\r
-  UINT32               Offset;\r
+  UINT               Offset;\r
   UINT32               Data;\r
+  UINTN                FisBaseAddr;\r
+  EFI_STATUS           Status;\r
 \r
   ASSERT (PciIo != NULL);\r
 \r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
-  Data   = AhciReadReg (PciIo, Offset);\r
-\r
   if (AtaStatusBlock != NULL) {\r
     ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
 \r
-    AtaStatusBlock->AtaStatus  = (UINT8)Data;\r
-    if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {\r
-      AtaStatusBlock->AtaError = (UINT8)(Data >> 8);\r
+    FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
+    Offset      = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
+\r
+    Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);\r
+    if (!EFI_ERROR (Status)) {\r
+      //\r
+      // If D2H FIS is received, update StatusBlock with its content.\r
+      //\r
+      CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK));\r
+    } else {\r
+      //\r
+      // If D2H FIS is not received, only update Status & Error field through PxTFD\r
+      // as there is no other way to get the content of the Shadow Register Block.\r
+      //\r
+      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+      Data   = AhciReadReg (PciIo, (UINT32)Offset);\r
+\r
+      AtaStatusBlock->AtaStatus  = (UINT8)Data;\r
+      if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {\r
+        AtaStatusBlock->AtaError = (UINT8)(Data >> 8);\r
+      }\r
     }\r
   }\r
 }\r
@@ -866,7 +885,7 @@ Exit:
     Map\r
     );\r
 \r
-  AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+  AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
 \r
   return Status;\r
 }\r
@@ -1085,7 +1104,7 @@ Exit:
     }\r
   }\r
 \r
-  AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+  AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
   return Status;\r
 }\r
 \r
@@ -1201,7 +1220,7 @@ Exit:
     Timeout\r
     );\r
 \r
-  AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+  AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
 \r
   return Status;\r
 }\r