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
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
+ UINTN 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
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);\r
\r
- return AhciWaitMmioSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_CMD_FR,\r
- EFI_AHCI_PORT_CMD_FR,\r
- Timeout\r
- );\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
Map\r
);\r
\r
- AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+ AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
\r
return Status;\r
}\r
}\r
}\r
\r
- AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+ AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
return Status;\r
}\r
\r
Timeout\r
);\r
\r
- AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+ AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);\r
\r
return Status;\r
}\r
{\r
UINT64 Delay;\r
UINT32 Value;\r
- UINT32 Capability;\r
\r
//\r
- // Collect AHCI controller information\r
- //\r
- Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);\r
- \r
- //\r
- // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set\r
+ // Make sure that GHC.AE bit is set before accessing any AHCI registers.\r
//\r
- if ((Capability & EFI_AHCI_CAP_SAM) == 0) {\r
+ Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);\r
+\r
+ if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {\r
AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);\r
}\r
\r
EFI_ATA_COLLECTIVE_MODE *SupportedModes;\r
EFI_ATA_TRANSFER_MODE TransferMode;\r
UINT32 PhyDetectDelay;\r
+ UINT32 Value;\r
\r
if (Instance == NULL) {\r
return EFI_INVALID_PARAMETER;\r
// Collect AHCI controller information\r
//\r
Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);\r
- \r
+\r
//\r
- // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set\r
+ // Make sure that GHC.AE bit is set before accessing any AHCI registers.\r
//\r
- if ((Capability & EFI_AHCI_CAP_SAM) == 0) {\r
+ Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);\r
+\r
+ if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {\r
AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);\r
}\r
- \r
+\r
+ //\r
+ // Enable 64-bit DMA support in the PCI layer if this controller\r
+ // supports it.\r
+ //\r
+ if ((Capability & EFI_AHCI_CAP_S64A) != 0) {\r
+ Status = PciIo->Attributes (\r
+ PciIo,\r
+ EfiPciIoAttributeOperationEnable,\r
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_WARN,\r
+ "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",\r
+ Status));\r
+ }\r
+ }\r
+\r
//\r
// Get the number of command slots per port supported by this HBA.\r
//\r
//\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);\r
- Status = AhciWaitMmioSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_CMD_FR,\r
- EFI_AHCI_PORT_CMD_FR,\r
- EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
\r
//\r
// Wait no longer than 10 ms to wait the Phy to detect the presence of a device.\r