}\r
\r
/**\r
- Wait for memory set to the test value.\r
+ Wait for the value of the specified MMIO register set to the test value.\r
\r
@param PciIo The PCI IO protocol instance.\r
- @param Offset The memory address to test.\r
+ @param Offset The MMIO address to test.\r
@param MaskValue The mask value of memory.\r
@param TestValue The test value of memory.\r
- @param Timeout The time out value for wait memory set.\r
+ @param Timeout The time out value for wait memory set, uses 100ns as a unit.\r
\r
- @retval EFI_DEVICE_ERROR The memory is not set.\r
- @retval EFI_TIMEOUT The memory setting is time out.\r
- @retval EFI_SUCCESS The memory is correct set.\r
+ @retval EFI_TIMEOUT The MMIO setting is time out.\r
+ @retval EFI_SUCCESS The MMIO is correct set.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-AhciWaitMemSet (\r
+AhciWaitMmioSet (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 Offset,\r
+ IN UINTN Offset,\r
IN UINT32 MaskValue,\r
IN UINT32 TestValue,\r
IN UINT64 Timeout\r
UINT32 Value; \r
UINT32 Delay;\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
+ Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
\r
do {\r
- Value = AhciReadReg (PciIo, Offset) & MaskValue;\r
+ //\r
+ // Access PCI MMIO space to see if the value is the tested one.\r
+ //\r
+ Value = AhciReadReg (PciIo, (UINT32) Offset) & MaskValue;\r
\r
if (Value == TestValue) {\r
return EFI_SUCCESS;\r
\r
} while (Delay > 0);\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
+ return EFI_TIMEOUT;\r
+}\r
+\r
+/**\r
+ Wait for the value of the specified system memory set to the test value.\r
+ \r
+ @param Address The system memory address to test.\r
+ @param MaskValue The mask value of memory.\r
+ @param TestValue The test value of memory.\r
+ @param Timeout The time out value for wait memory set, uses 100ns as a unit.\r
+\r
+ @retval EFI_TIMEOUT The system memory setting is time out.\r
+ @retval EFI_SUCCESS The system memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciWaitMemSet (\r
+ IN EFI_PHYSICAL_ADDRESS Address,\r
+ IN UINT32 MaskValue,\r
+ IN UINT32 TestValue,\r
+ IN UINT64 Timeout\r
+ )\r
+{\r
+ UINT32 Value; \r
+ UINT32 Delay;\r
+\r
+ Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
+\r
+ do {\r
+ //\r
+ // Access sytem memory to see if the value is the tested one.\r
+ //\r
+ // The system memory pointed by Address will be updated by the\r
+ // SATA Host Controller, "volatile" is introduced to prevent\r
+ // compiler from optimizing the access to the memory address\r
+ // to only read once.\r
+ //\r
+ Value = *(volatile UINT32 *) (UINTN) Address;\r
+ Value &= MaskValue;\r
+\r
+ if (Value == TestValue) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Stall for 100 microseconds.\r
+ //\r
+ MicroSecondDelay (100);\r
+\r
+ Delay--;\r
\r
- return EFI_DEVICE_ERROR;\r
+ } while (Delay > 0);\r
+\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\r
Check the memory status to the test value.\r
\r
- @param[in] PciIo The PCI IO protocol instance.\r
- @param[in] Offset The memory address to test.\r
+ @param[in] Address The memory address to test.\r
@param[in] MaskValue The mask value of memory.\r
@param[in] TestValue The test value of memory.\r
- @param[in, out] RetryTimes The retry times value for waitting memory set.\r
+ @param[in, out] RetryTimes The retry times value for waitting memory set. If 0, then just try once.\r
\r
@retval EFI_NOTREADY The memory is not set.\r
@retval EFI_TIMEOUT The memory setting retry times out.\r
EFI_STATUS\r
EFIAPI\r
AhciCheckMemSet (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT32 Offset,\r
+ IN UINTN Address,\r
IN UINT32 MaskValue,\r
IN UINT32 TestValue,\r
- IN OUT UINTN *RetryTimes\r
+ IN OUT UINTN *RetryTimes OPTIONAL\r
)\r
{\r
UINT32 Value;\r
\r
- (*RetryTimes) --;\r
- \r
- Value = AhciReadReg (PciIo, Offset) & MaskValue;\r
+ if (RetryTimes != NULL) {\r
+ (*RetryTimes)--;\r
+ }\r
+ \r
+ Value = *(volatile UINT32 *) Address;\r
+ Value &= MaskValue;\r
\r
if (Value == TestValue) {\r
return EFI_SUCCESS;\r
}\r
\r
- if ((*RetryTimes) == 0) {\r
+ if ((RetryTimes != NULL) && (*RetryTimes == 0)) {\r
return EFI_TIMEOUT;\r
} else {\r
return EFI_NOT_READY;\r
\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
- @param Timeout The timeout value of enabling FIS.\r
+ @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR The FIS enable setting fails.\r
@retval EFI_TIMEOUT The FIS enable setting is time out.\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 AhciWaitMemSet (\r
+ return AhciWaitMmioSet (\r
PciIo, \r
Offset,\r
EFI_AHCI_PORT_CMD_FR,\r
\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
- @param Timeout The timeout value of disabling FIS.\r
+ @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR The FIS disable setting fails.\r
@retval EFI_TIMEOUT The FIS disable setting is time out.\r
\r
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));\r
\r
- return AhciWaitMemSet (\r
+ return AhciWaitMmioSet (\r
PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_FR,\r
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
@param[in, out] MemoryAddr The pointer to the data buffer.\r
@param[in] DataCount The data count to be transferred.\r
- @param[in] Timeout The timeout value of non data transfer.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
used by non-blocking mode.\r
\r
{\r
EFI_STATUS Status;\r
UINTN FisBaseAddr;\r
- UINT32 Offset;\r
- UINT32 Value;\r
+ UINTN Offset;\r
EFI_PHYSICAL_ADDRESS PhyAddr;\r
VOID *Map;\r
UINTN MapLength;\r
EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
UINT32 Delay;\r
EFI_AHCI_COMMAND_FIS CFis;\r
- EFI_AHCI_COMMAND_LIST CmdList;\r
+ EFI_AHCI_COMMAND_LIST CmdList; \r
+ UINT32 PortTfd;\r
+ UINT32 PrdCount;\r
\r
if (Read) {\r
Flag = EfiPciIoOperationBusMasterWrite;\r
// Check the status and wait the driver sending data\r
//\r
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
- //\r
- // Wait device sends the PIO setup fis before data transfer\r
- //\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
- do {\r
- Value = *(volatile UINT32 *) (FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET);\r
-\r
- if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_PIO_SETUP) {\r
- break;\r
- }\r
\r
+ if (Read && (AtapiCommand == 0)) {\r
//\r
- // Stall for 100 microseconds.\r
+ // Wait device sends the PIO setup fis before data transfer\r
//\r
- MicroSecondDelay(100);\r
+ Status = EFI_TIMEOUT;\r
+ Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
+ do {\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
+\r
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+ Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;\r
\r
- Delay--;\r
- } while (Delay > 0);\r
+ Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));\r
+ if (PrdCount == DataCount) {\r
+ break;\r
+ }\r
+ }\r
\r
- if (Delay == 0) {\r
- Status = EFI_TIMEOUT;\r
- goto Exit;\r
- }\r
+ Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
+ Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
\r
- //\r
- // Wait for command compelte\r
- //\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- 0xFFFFFFFF,\r
- 0,\r
- Timeout\r
- );\r
+ //\r
+ // Stall for 100 microseconds.\r
+ //\r
+ MicroSecondDelay(100);\r
\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
+ Delay--;\r
+ } while (Delay > 0);\r
+ } else {\r
+ //\r
+ // Wait for D2H Fis is received\r
+ //\r
+ Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
+ Status = AhciWaitMemSet (\r
+ Offset,\r
+ EFI_AHCI_FIS_TYPE_MASK,\r
+ EFI_AHCI_FIS_REGISTER_D2H,\r
+ Timeout\r
+ );\r
\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_IS_PSS,\r
- EFI_AHCI_PORT_IS_PSS,\r
- Timeout\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
}\r
\r
Exit:\r
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
@param[in, out] MemoryAddr The pointer to the data buffer.\r
@param[in] DataCount The data count to be transferred.\r
- @param[in] Timeout The timeout value of non data transfer.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
used by non-blocking mode.\r
\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
IN OUT VOID *MemoryAddr,\r
- IN UINTN DataCount,\r
+ IN UINT32 DataCount,\r
IN UINT64 Timeout,\r
IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
- UINT32 Offset;\r
+ UINTN Offset;\r
EFI_PHYSICAL_ADDRESS PhyAddr;\r
VOID *Map;\r
UINTN MapLength;\r
EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
EFI_AHCI_COMMAND_FIS CFis;\r
EFI_AHCI_COMMAND_LIST CmdList;\r
+ UINTN FisBaseAddr;\r
+ UINT32 PortTfd;\r
\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- EFI_TPL OldTpl;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_TPL OldTpl;\r
\r
Map = NULL;\r
PciIo = Instance->PciIo;\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
-\r
- //\r
- // Wait device PRD processed\r
- //\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_IS_DPS,\r
- EFI_AHCI_PORT_IS_DPS,\r
- Timeout\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
}\r
\r
//\r
// Wait for command compelte\r
//\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
+ FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
+ Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
if (Task != NULL) {\r
//\r
// For Non-blocking\r
//\r
Status = AhciCheckMemSet (\r
- PciIo,\r
Offset,\r
- 0xFFFFFFFF,\r
- 0,\r
+ EFI_AHCI_FIS_TYPE_MASK,\r
+ EFI_AHCI_FIS_REGISTER_D2H,\r
(UINTN *) (&Task->RetryTimes)\r
);\r
} else {\r
Status = AhciWaitMemSet (\r
- PciIo,\r
Offset,\r
- 0xFFFFFFFF,\r
- 0,\r
+ EFI_AHCI_FIS_TYPE_MASK,\r
+ EFI_AHCI_FIS_REGISTER_D2H,\r
Timeout\r
);\r
}\r
goto Exit;\r
}\r
\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
-\r
- if (Task != NULL) {\r
- //\r
- // For Non-blocking\r
- //\r
- Status = AhciCheckMemSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- (UINTN *) (&Task->RetryTimes)\r
- );\r
- } else {\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- Timeout\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
}\r
\r
Exit:\r
@param[in] AtapiCommandLength The length of the atapi command.\r
@param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
@param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
- @param[in] Timeout The timeout value of non data transfer.\r
+ @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.\r
@param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
used by non-blocking mode.\r
\r
{\r
EFI_STATUS Status;\r
UINTN FisBaseAddr;\r
- UINT32 Offset;\r
- UINT32 Value;\r
- UINT32 Delay;\r
-\r
+ UINTN Offset;\r
+ UINT32 PortTfd;\r
EFI_AHCI_COMMAND_FIS CFis;\r
EFI_AHCI_COMMAND_LIST CmdList;\r
\r
// Wait device sends the Response Fis\r
//\r
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
- //\r
- // Wait device sends the PIO setup fis before data transfer\r
- //\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
- do {\r
- Value = *(volatile UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);\r
-\r
- if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {\r
- break;\r
- }\r
+ Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
+ Status = AhciWaitMemSet (\r
+ Offset,\r
+ EFI_AHCI_FIS_TYPE_MASK,\r
+ EFI_AHCI_FIS_REGISTER_D2H,\r
+ Timeout\r
+ );\r
\r
- //\r
- // Stall for 100 microseconds.\r
- //\r
- MicroSecondDelay(100);\r
-\r
- Delay --;\r
- } while (Delay > 0);\r
-\r
- if (Delay == 0) {\r
- Status = EFI_TIMEOUT;\r
+ if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
-\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- 0xFFFFFFFF,\r
- 0,\r
- Timeout\r
- );\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
\r
Exit:\r
AhciStopCommand (\r
\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
- @param Timeout The timeout value of stop.\r
+ @param Timeout The timeout value of stop, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR The command stop unsuccessfully.\r
@retval EFI_TIMEOUT The operation is time out.\r
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));\r
}\r
\r
- return AhciWaitMemSet (\r
+ return AhciWaitMmioSet (\r
PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_CR,\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
@param CommandSlot The number of Command Slot.\r
- @param Timeout The timeout value of start.\r
+ @param Timeout The timeout value of start, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR The command start unsuccessfully.\r
@retval EFI_TIMEOUT The operation is time out.\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);\r
\r
- AhciWaitMemSet (\r
+ AhciWaitMmioSet (\r
PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_CLO,\r
\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
- @param Timeout The timeout value of reset.\r
+ @param Timeout The timeout value of reset, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR The port reset unsuccessfully\r
@retval EFI_TIMEOUT The reset operation is time out.\r
// Wait for communication to be re-established\r
//\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
- Status = AhciWaitMemSet (\r
+ Status = AhciWaitMmioSet (\r
PciIo,\r
Offset,\r
EFI_AHCI_PORT_SSTS_DET_MASK,\r
Do AHCI HBA reset.\r
\r
@param PciIo The PCI IO protocol instance.\r
- @param Timeout The timeout value of reset.\r
+ @param Timeout The timeout value of reset, uses 100ns as a unit.\r
\r
@retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.\r
@retval EFI_TIMEOUT The reset operation is time out.\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 = AhciWaitMemSet (\r
+ Status = AhciWaitMmioSet (\r
PciIo, \r
Offset,\r
EFI_AHCI_PORT_CMD_FR,\r
// When the first D2H register FIS is received, the content of PxSIG register is updated.\r
//\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;\r
- Status = AhciWaitMemSet (\r
+ Status = AhciWaitMmioSet (\r
PciIo, \r
Offset,\r
0x0000FFFF,\r