/** @file\r
The file for AHCI mode of ATA host controller.\r
\r
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
which accompanies this distribution. The full text of the license may be found at \r
/**\r
Wait for memory set to the test value.\r
\r
- @param PciIo The PCI IO protocol instance.\r
- @param Offset The 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.\r
+ @param PciIo The PCI IO protocol instance.\r
+ @param Offset The 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.\r
\r
@retval EFI_DEVICE_ERROR The memory is not set.\r
@retval EFI_TIMEOUT The memory setting is time out.\r
return EFI_DEVICE_ERROR;\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] 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
+\r
+ @retval EFI_NOTREADY The memory is not set.\r
+ @retval EFI_TIMEOUT The memory setting retry times out.\r
+ @retval EFI_SUCCESS The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciCheckMemSet (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT32 Offset,\r
+ IN UINT32 MaskValue,\r
+ IN UINT32 TestValue,\r
+ IN OUT UINTN *RetryTimes\r
+ )\r
+{\r
+ UINT32 Value;\r
+\r
+ (*RetryTimes) --;\r
+ \r
+ Value = AhciReadReg (PciIo, Offset) & MaskValue;\r
+\r
+ if (Value == TestValue) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if ((*RetryTimes) == 0) {\r
+ return EFI_TIMEOUT;\r
+ } else {\r
+ return EFI_NOT_READY;\r
+ }\r
+}\r
+\r
/**\r
Check if the device is still on port. It also checks if the AHCI controller \r
- supports the address and data count will be transfered.\r
+ supports the address and data count will be transferred.\r
\r
- @param PciIo The PCI IO protocol instance.\r
- @param Port The number of port.\r
+ @param PciIo The PCI IO protocol instance.\r
+ @param Port The number of port.\r
\r
@retval EFI_SUCCESS The device is attached to port and the transfer data is \r
supported by AHCI controller.\r
IN UINT8 Port\r
)\r
{\r
- UINT32 Data; \r
+ UINT32 Data;\r
UINT32 Offset;\r
\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;\r
\r
if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {\r
- return EFI_SUCCESS; \r
+ return EFI_SUCCESS;\r
}\r
\r
return EFI_NOT_READY;\r
\r
//\r
// Clear any error status\r
- // \r
+ //\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));\r
\r
AhciWriteReg (PciIo, EFI_AHCI_IS_OFFSET, AhciReadReg (PciIo, EFI_AHCI_IS_OFFSET));\r
}\r
\r
+/**\r
+ This function is used to dump the Status Registers and if there is ERR bit set\r
+ in the Status Register, the Error Register's value is also be dumped.\r
+\r
+ @param PciIo The PCI IO protocol instance.\r
+ @param Port The number of port.\r
+ @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AhciDumpPortStatus (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN UINT8 Port,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
+ )\r
+{\r
+ UINT32 Offset;\r
+ UINT32 Data;\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
+ }\r
+ }\r
+}\r
+\r
+\r
/**\r
Enable the FIS running for giving port.\r
\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN UINT8 Port,\r
IN UINT64 Timeout\r
- ) \r
-{ \r
+ )\r
+{\r
UINT32 Offset;\r
\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));\r
\r
return AhciWaitMemSet (\r
- PciIo, \r
+ PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_FR,\r
0,\r
Timeout\r
- ); \r
+ );\r
}\r
\r
\r
/**\r
Build the command list, command table and prepare the fis receiver.\r
\r
- @param PciIo The PCI IO protocol instance.\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 PortMultiplier The timeout value of stop.\r
- @param CommandFis The control fis will be used for the transfer.\r
- @param CommandList The command list will be used for the transfer.\r
- @param AtapiCommand The atapi command will be used for the transfer.\r
- @param AtapiCommandLength The length of the atapi command.\r
- @param CommandSlotNumber The command slot will be used for the transfer.\r
+ @param Port The number of port.\r
+ @param PortMultiplier The timeout value of stop.\r
+ @param CommandFis The control fis will be used for the transfer.\r
+ @param CommandList The command list will be used for the transfer.\r
+ @param AtapiCommand The atapi command will be used for the transfer.\r
+ @param AtapiCommandLength The length of the atapi command.\r
+ @param CommandSlotNumber The command slot will be used for the transfer.\r
@param DataPhysicalAddr The pointer to the data buffer pci bus master address.\r
@param DataLength The data count to be transferred.\r
\r
IN UINT64 DataLength\r
) \r
{\r
- UINT64 BaseAddr; \r
+ UINT64 BaseAddr;\r
UINT64 PrdtNumber;\r
UINT64 PrdtIndex;\r
UINTN RemainedData;\r
\r
BaseAddr = Data64.Uint64;\r
\r
- ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS)); \r
+ ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));\r
\r
ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));\r
\r
AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));\r
}\r
\r
- RemainedData = DataLength;\r
+ RemainedData = (UINTN) DataLength;\r
MemAddr = (UINTN) DataPhysicalAddr;\r
CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;\r
\r
for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {\r
- if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) { \r
+ if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {\r
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;\r
} else {\r
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;\r
Data64.Uint64 = (UINT64)MemAddr;\r
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;\r
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;\r
- RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT; \r
+ RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;\r
MemAddr += EFI_AHCI_MAX_DATA_PER_PRDT;\r
}\r
\r
/**\r
Buid a command FIS.\r
\r
- @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.\r
+ @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.\r
@param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.\r
\r
**/\r
CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;\r
CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;\r
\r
- CmdFis->AhciCFisDevHead = AtaCommandBlock->AtaDeviceHead | 0xE0;\r
+ CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);\r
}\r
\r
/**\r
Start a PIO data transfer on specific port.\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 PortMultiplier The timeout value of stop.\r
- @param AtapiCommand The atapi command will be used for the transfer.\r
- @param AtapiCommandLength The length of the atapi command.\r
- @param Read The transfer direction.\r
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
- @param MemoryAddr The pointer to the data buffer.\r
- @param DataCount The data count to be transferred.\r
- @param Timeout The timeout value of non data transfer.\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\r
+ @param[in] AtapiCommandLength The length of the atapi command.\r
+ @param[in] Read The transfer direction.\r
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\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] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.\r
@retval EFI_TIMEOUT The operation is time out.\r
\r
**/\r
EFI_STATUS\r
+EFIAPI\r
AhciPioTransfer (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN EFI_AHCI_REGISTERS *AhciRegisters,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
IN OUT VOID *MemoryAddr,\r
IN UINT32 DataCount,\r
- IN UINT64 Timeout \r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
); \r
\r
Status = AhciStartCommand (\r
- PciIo, \r
- Port, \r
+ PciIo,\r
+ Port,\r
0,\r
Timeout\r
);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
- \r
+\r
//\r
- // Checking the status and wait the driver sending data\r
+ // Check the status and wait the driver sending data\r
//\r
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
//\r
//\r
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
do {\r
- Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET);\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
MicroSecondDelay(100);\r
\r
- Delay--; \r
+ Delay--;\r
} while (Delay > 0);\r
\r
if (Delay == 0) {\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- goto Exit; \r
+ goto Exit;\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
+ Offset,\r
EFI_AHCI_PORT_IS_PSS,\r
EFI_AHCI_PORT_IS_PSS,\r
Timeout\r
- ); \r
+ );\r
if (EFI_ERROR (Status)) {\r
- goto Exit; \r
+ goto Exit;\r
}\r
\r
-Exit: \r
+Exit:\r
AhciStopCommand (\r
- PciIo, \r
+ PciIo,\r
Port,\r
Timeout\r
);\r
\r
AhciDisableFisReceive (\r
- PciIo, \r
+ PciIo,\r
Port,\r
Timeout\r
);\r
Map\r
);\r
\r
+ AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+\r
return Status;\r
}\r
\r
/**\r
Start a DMA data transfer on specific port\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 PortMultiplier The timeout value of stop.\r
- @param AtapiCommand The atapi command will be used for the transfer.\r
- @param AtapiCommandLength The length of the atapi command.\r
- @param Read The transfer direction.\r
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
- @param MemoryAddr The pointer to the data buffer.\r
- @param DataCount The data count to be transferred.\r
- @param Timeout The timeout value of non data transfer.\r
-\r
- @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.\r
- @retval EFI_TIMEOUT The operation is time out.\r
- @retval EFI_UNSUPPORTED The device is not ready for transfer.\r
- @retval EFI_SUCCESS The DMA data transfer executes successfully.\r
- \r
+ @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\r
+ @param[in] AtapiCommandLength The length of the atapi command.\r
+ @param[in] Read The transfer direction.\r
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\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] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
+ @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.\r
+ @retval EFI_TIMEOUT The operation is time out.\r
+ @retval EFI_UNSUPPORTED The device is not ready for transfer.\r
+ @retval EFI_SUCCESS The DMA data transfer executes successfully.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
AhciDmaTransfer (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
IN EFI_AHCI_REGISTERS *AhciRegisters,\r
IN UINT8 Port,\r
IN UINT8 PortMultiplier,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
IN OUT VOID *MemoryAddr,\r
IN UINTN DataCount,\r
- IN UINT64 Timeout\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
EFI_AHCI_COMMAND_FIS CFis;\r
EFI_AHCI_COMMAND_LIST CmdList;\r
\r
- if (Read) {\r
- Flag = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- Flag = EfiPciIoOperationBusMasterRead;\r
- }\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_TPL OldTpl;\r
\r
- //\r
- // construct command list and command table with pci bus address\r
- //\r
- MapLength = DataCount;\r
- Status = PciIo->Map (\r
- PciIo,\r
- Flag,\r
- MemoryAddr,\r
- &MapLength,\r
- &PhyAddr,\r
- &Map\r
- );\r
+ Map = NULL;\r
+ PciIo = Instance->PciIo;\r
\r
- if (EFI_ERROR (Status) || (DataCount != MapLength)) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ if (PciIo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // Package read needed\r
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
+ // BlockIO tasks.\r
+ // Delay 100us to simulate the blocking time out checking.\r
//\r
- AhciBuildCommandFis (&CFis, AtaCommandBlock);\r
+ while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ AsyncNonBlockingTransferRoutine (NULL, Instance);\r
+ gBS->RestoreTPL (OldTpl); \r
+ //\r
+ // Stall for 100us.\r
+ //\r
+ MicroSecondDelay (100);\r
+ }\r
\r
- ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));\r
+ if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {\r
+ //\r
+ // Mark the Task to indicate that it has been started.\r
+ //\r
+ if (Task != NULL) {\r
+ Task->IsStart = TRUE;\r
+ Task->RetryTimes = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
+ }\r
+ if (Read) {\r
+ Flag = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ Flag = EfiPciIoOperationBusMasterRead;\r
+ }\r
\r
- CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;\r
- CmdList.AhciCmdW = Read ? 0 : 1;\r
+ //\r
+ // Construct command list and command table with pci bus address.\r
+ //\r
+ MapLength = DataCount;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ Flag,\r
+ MemoryAddr,\r
+ &MapLength,\r
+ &PhyAddr,\r
+ &Map\r
+ );\r
+\r
+ if (EFI_ERROR (Status) || (DataCount != MapLength)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- AhciBuildCommand (\r
- PciIo,\r
- AhciRegisters,\r
- Port,\r
- PortMultiplier,\r
- &CFis,\r
- &CmdList,\r
- AtapiCommand,\r
- AtapiCommandLength,\r
- 0,\r
- (VOID *)(UINTN)PhyAddr,\r
- DataCount\r
- ); \r
- \r
- Status = AhciStartCommand (\r
- PciIo, \r
- Port, \r
- 0,\r
- Timeout\r
- );\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
+ if (Task != NULL) {\r
+ Task->Map = Map;\r
+ }\r
+ //\r
+ // Package read needed\r
+ //\r
+ AhciBuildCommandFis (&CFis, AtaCommandBlock);\r
+\r
+ ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));\r
+\r
+ CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;\r
+ CmdList.AhciCmdW = Read ? 0 : 1;\r
+\r
+ AhciBuildCommand (\r
+ PciIo,\r
+ AhciRegisters,\r
+ Port,\r
+ PortMultiplier,\r
+ &CFis,\r
+ &CmdList,\r
+ AtapiCommand,\r
+ AtapiCommandLength,\r
+ 0,\r
+ (VOID *)(UINTN)PhyAddr,\r
+ DataCount\r
+ );\r
+\r
+ Status = AhciStartCommand (\r
+ PciIo,\r
+ Port,\r
+ 0,\r
+ Timeout\r
+ );\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
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- 0xFFFFFFFF,\r
- 0,\r
- Timeout\r
- );\r
+ if (Task != NULL) {\r
+ //\r
+ // For Non-blocking\r
+ //\r
+ Status = AhciCheckMemSet (\r
+ PciIo,\r
+ Offset,\r
+ 0xFFFFFFFF,\r
+ 0,\r
+ (UINTN *) (&Task->RetryTimes)\r
+ );\r
+ } else {\r
+ Status = AhciWaitMemSet (\r
+ PciIo,\r
+ Offset,\r
+ 0xFFFFFFFF,\r
+ 0,\r
+ Timeout\r
+ );\r
+ }\r
+\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_IS;\r
- Status = AhciWaitMemSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- EFI_AHCI_PORT_IS_DHRS,\r
- Timeout\r
- ); \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
}\r
\r
-Exit: \r
- AhciStopCommand (\r
- PciIo, \r
- Port,\r
- Timeout\r
- );\r
+Exit:\r
+ //\r
+ // For Blocking mode, the command should be stopped, the Fis should be disabled\r
+ // and the PciIo should be unmapped.\r
+ // For non-blocking mode, only when a error is happened (if the return status is \r
+ // EFI_NOT_READY that means the command doesn't finished, try again.), first do the \r
+ // context cleanup, then set the packet's Asb status.\r
+ //\r
+ if (Task == NULL ||\r
+ ((Task != NULL) && (Status != EFI_NOT_READY))\r
+ ) {\r
+ AhciStopCommand (\r
+ PciIo, \r
+ Port,\r
+ Timeout\r
+ );\r
\r
- AhciDisableFisReceive (\r
- PciIo, \r
- Port,\r
- Timeout\r
- );\r
+ AhciDisableFisReceive (\r
+ PciIo, \r
+ Port,\r
+ Timeout\r
+ );\r
\r
- PciIo->Unmap (\r
- PciIo,\r
- Map\r
- ); \r
- \r
+ PciIo->Unmap (\r
+ PciIo,\r
+ (Task != NULL) ? Task->Map : Map\r
+ );\r
+\r
+ if (Task != NULL) {\r
+ Task->Packet->Asb->AtaStatus = 0x01;\r
+ }\r
+ }\r
+\r
+ AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
return Status;\r
}\r
\r
/**\r
Start a non data transfer on specific port.\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 PortMultiplier The timeout value of stop.\r
- @param AtapiCommand The atapi command will be used for the transfer.\r
- @param AtapiCommandLength The length of the atapi command.\r
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.\r
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.\r
- @param Timeout The timeout value of non data transfer.\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.\r
+ @param[in] Port The number of port.\r
+ @param[in] PortMultiplier The timeout value of stop.\r
+ @param[in] AtapiCommand The atapi command will be used for the\r
+ transfer.\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] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.\r
@retval EFI_TIMEOUT The operation is time out.\r
IN UINT8 AtapiCommandLength,\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
- ) \r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
+ )\r
{\r
- EFI_STATUS Status; \r
+ EFI_STATUS Status;\r
UINTN FisBaseAddr;\r
UINT32 Offset;\r
UINT32 Value;\r
UINT32 Delay;\r
- \r
+\r
EFI_AHCI_COMMAND_FIS CFis;\r
EFI_AHCI_COMMAND_LIST CmdList;\r
\r
0,\r
NULL,\r
0\r
- ); \r
- \r
+ );\r
+\r
Status = AhciStartCommand (\r
- PciIo, \r
- Port, \r
+ PciIo,\r
+ Port,\r
0,\r
Timeout\r
);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
- \r
+\r
//\r
// Wait device sends the Response Fis\r
//\r
//\r
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
do {\r
- Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);\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
MicroSecondDelay(100);\r
\r
- Delay --; \r
+ Delay --;\r
} while (Delay > 0);\r
\r
if (Delay == 0) {\r
0xFFFFFFFF,\r
0,\r
Timeout\r
- ); \r
- \r
-Exit: \r
+ );\r
+\r
+Exit:\r
AhciStopCommand (\r
- PciIo, \r
+ PciIo,\r
Port,\r
Timeout\r
);\r
\r
AhciDisableFisReceive (\r
- PciIo, \r
+ PciIo,\r
Port,\r
Timeout\r
);\r
\r
+ AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);\r
+\r
return Status;\r
}\r
\r
Data = AhciReadReg (PciIo, Offset);\r
\r
if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {\r
- return EFI_SUCCESS; \r
+ return EFI_SUCCESS;\r
}\r
\r
if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {\r
}\r
\r
return AhciWaitMemSet (\r
- PciIo, \r
+ PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_CR,\r
0,\r
Timeout\r
- ); \r
+ );\r
}\r
\r
/**\r
Start command for give slot on specific port.\r
- \r
+\r
@param PciIo The PCI IO protocol instance.\r
@param Port The number of port.\r
- @param CommandSlot The number of CommandSlot.\r
+ @param CommandSlot The number of Command Slot.\r
@param Timeout The timeout value of start.\r
- \r
+\r
@retval EFI_DEVICE_ERROR The command start unsuccessfully.\r
@retval EFI_TIMEOUT The operation is time out.\r
@retval EFI_SUCCESS The command start successfully.\r
Port,\r
Timeout\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- //\r
- // Setting the command\r
- //\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;\r
- AhciAndReg (PciIo, Offset, 0);\r
- AhciOrReg (PciIo, Offset, CmdSlotBit);\r
-\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
- AhciAndReg (PciIo, Offset, 0);\r
- AhciOrReg (PciIo, Offset, CmdSlotBit);\r
-\r
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
PortStatus = AhciReadReg (PciIo, Offset);\r
- \r
+\r
StartCmd = 0;\r
if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {\r
StartCmd = AhciReadReg (PciIo, Offset);\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);\r
\r
AhciWaitMemSet (\r
- PciIo, \r
+ PciIo,\r
Offset,\r
EFI_AHCI_PORT_CMD_COL,\r
0,\r
Timeout\r
- ); \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_ST | StartCmd);\r
\r
+ //\r
+ // Setting the command\r
+ //\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;\r
+ AhciAndReg (PciIo, Offset, 0);\r
+ AhciOrReg (PciIo, Offset, CmdSlotBit);\r
+\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
+ AhciAndReg (PciIo, Offset, 0);\r
+ AhciOrReg (PciIo, Offset, CmdSlotBit);\r
+\r
return EFI_SUCCESS;\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
- UINT32 Offset; \r
- \r
+ UINT32 Offset;\r
+\r
AhciClearPortStatus (PciIo, Port);\r
\r
AhciStopCommand (PciIo, Port, Timeout);\r
AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);\r
\r
//\r
- // wait 5 milliseceond before de-assert DET \r
+ // wait 5 millisecond before de-assert DET\r
//\r
MicroSecondDelay (5000);\r
\r
AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);\r
\r
//\r
- // wait 5 milliseceond before de-assert DET \r
+ // wait 5 millisecond before de-assert DET\r
//\r
MicroSecondDelay (5000);\r
\r
EFI_AHCI_PORT_SSTS_DET_MASK,\r
EFI_AHCI_PORT_SSTS_DET_PCE,\r
Timeout\r
- ); \r
+ );\r
\r
if (EFI_ERROR (Status)) {\r
return Status;\r
\r
/**\r
Do AHCI HBA reset.\r
- \r
+\r
@param PciIo The PCI IO protocol instance.\r
@param Timeout The timeout value of reset.\r
- \r
- \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
@retval EFI_SUCCESS AHCI controller is reset successfully.\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Send SMART Return Status command to check if the execution of SMART cmd is successful or not.\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 PortMultiplier The timeout value of stop.\r
+ @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+\r
+ @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.\r
+ @retval Others Fail to get return status data.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AhciAtaSmartReturnStatusCheck (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_AHCI_REGISTERS *AhciRegisters,\r
+ IN UINT8 Port,\r
+ IN UINT8 PortMultiplier,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
+ UINT8 LBAMid;\r
+ UINT8 LBAHigh;\r
+ UINTN FisBaseAddr;\r
+ UINT32 Value;\r
+\r
+ ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
+\r
+ AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
+ AtaCommandBlock.AtaFeatures = ATA_SMART_RETURN_STATUS;\r
+ AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
+ AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
+\r
+ //\r
+ // Send S.M.A.R.T Read Return Status command to device\r
+ //\r
+ Status = AhciNonDataTransfer (\r
+ PciIo,\r
+ AhciRegisters,\r
+ (UINT8)Port,\r
+ (UINT8)PortMultiplier,\r
+ NULL,\r
+ 0,\r
+ &AtaCommandBlock,\r
+ AtaStatusBlock,\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
+\r
+ Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);\r
+\r
+ if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {\r
+ LBAMid = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[5];\r
+ LBAHigh = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[6];\r
+\r
+ if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {\r
+ //\r
+ // The threshold exceeded condition is not detected by the device\r
+ //\r
+ DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));\r
+\r
+ } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
+ //\r
+ // The threshold exceeded condition is detected by the device\r
+ //\r
+ DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Enable SMART command of the disk if supported.\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 PortMultiplier The timeout value of stop.\r
+ @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.\r
+ @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AhciAtaSmartSupport (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_AHCI_REGISTERS *AhciRegisters,\r
+ IN UINT8 Port,\r
+ IN UINT8 PortMultiplier,\r
+ IN EFI_IDENTIFY_DATA *IdentifyData,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
+\r
+ //\r
+ // Detect if the device supports S.M.A.R.T.\r
+ //\r
+ if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {\r
+ //\r
+ // S.M.A.R.T is not supported by the device\r
+ //\r
+ DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n", \r
+ Port, PortMultiplier));\r
+ } else {\r
+ //\r
+ // Check if the feature is enabled. If not, then enable S.M.A.R.T.\r
+ //\r
+ if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {\r
+ ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
+\r
+ AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
+ AtaCommandBlock.AtaFeatures = ATA_SMART_ENABLE_OPERATION;\r
+ AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
+ AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
+\r
+ //\r
+ // Send S.M.A.R.T Enable command to device\r
+ //\r
+ Status = AhciNonDataTransfer (\r
+ PciIo,\r
+ AhciRegisters,\r
+ (UINT8)Port,\r
+ (UINT8)PortMultiplier,\r
+ NULL,\r
+ 0,\r
+ &AtaCommandBlock,\r
+ AtaStatusBlock,\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
+ );\r
+\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Send S.M.A.R.T AutoSave command to device\r
+ //\r
+ ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
+\r
+ AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
+ AtaCommandBlock.AtaFeatures = 0xD2;\r
+ AtaCommandBlock.AtaSectorCount = 0xF1;\r
+ AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;\r
+ AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;\r
+\r
+ Status = AhciNonDataTransfer (\r
+ PciIo,\r
+ AhciRegisters,\r
+ (UINT8)Port,\r
+ (UINT8)PortMultiplier,\r
+ NULL,\r
+ 0,\r
+ &AtaCommandBlock,\r
+ AtaStatusBlock,\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = AhciAtaSmartReturnStatusCheck (\r
+ PciIo,\r
+ AhciRegisters,\r
+ (UINT8)Port,\r
+ (UINT8)PortMultiplier,\r
+ AtaStatusBlock\r
+ );\r
+ }\r
+ }\r
+ }\r
+ DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",\r
+ Port, PortMultiplier));\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
/**\r
Send Buffer cmd to specific device.\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 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 PortMultiplier The timeout value of stop.\r
- @param Buffer The data buffer to store IDENTIFY PACKET data.\r
+ @param Buffer The data buffer to store IDENTIFY PACKET data.\r
\r
@retval EFI_DEVICE_ERROR The cmd abort with error occurs.\r
@retval EFI_TIMEOUT The operation is time out.\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
AtaCommandBlock.AtaSectorCount = 1;\r
\r
&AtaStatusBlock,\r
Buffer,\r
sizeof (EFI_IDENTIFY_DATA),\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT, \r
+ NULL\r
);\r
\r
return Status;\r
/**\r
Send Buffer cmd to specific device.\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 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 PortMultiplier The timeout value of stop.\r
- @param Buffer The data buffer to store IDENTIFY PACKET data.\r
+ @param Buffer The data buffer to store IDENTIFY PACKET data.\r
\r
@retval EFI_DEVICE_ERROR The cmd abort with error occurs.\r
@retval EFI_TIMEOUT The operation is time out.\r
if (PciIo == NULL || AhciRegisters == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
\r
&AtaStatusBlock,\r
Buffer,\r
sizeof (EFI_IDENTIFY_DATA),\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
/**\r
Send SET FEATURE cmd on specific device.\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 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 PortMultiplier The timeout value of stop.\r
- @param Feature The data to send Feature register.\r
- @param FeatureSpecificData The specific data for SET FEATURE cmd.\r
+ @param Feature The data to send Feature register.\r
+ @param FeatureSpecificData The specific data for SET FEATURE cmd.\r
\r
@retval EFI_DEVICE_ERROR The cmd abort with error occurs.\r
@retval EFI_TIMEOUT The operation is time out.\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;\r
AtaCommandBlock.AtaFeatures = (UINT8) Feature;\r
AtaCommandBlock.AtaFeaturesExp = (UINT8) (Feature >> 8);\r
0,\r
&AtaCommandBlock,\r
&AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT, \r
+ NULL\r
);\r
\r
return Status;\r
Read = FALSE;\r
}\r
\r
- if (Length == 0) { \r
+ if (Length == 0) {\r
Status = AhciNonDataTransfer (\r
PciIo,\r
AhciRegisters,\r
Packet->CdbLength,\r
&AtaCommandBlock,\r
&AtaStatusBlock,\r
- Packet->Timeout\r
+ Packet->Timeout, \r
+ NULL\r
);\r
} else {\r
//\r
&AtaStatusBlock,\r
Buffer,\r
Length,\r
- Packet->Timeout\r
+ Packet->Timeout, \r
+ NULL\r
);\r
if (!EFI_ERROR (Status)) {\r
break;\r
UINT64 MaxReceiveFisSize;\r
UINT64 MaxCommandListSize;\r
UINT64 MaxCommandTableSize;\r
+ EFI_PHYSICAL_ADDRESS AhciRFisPciAddr;\r
+ EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr;\r
+ EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr;\r
\r
Buffer = NULL;\r
//\r
// Get the number of command slots per port supported by this HBA.\r
//\r
MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);\r
- Support64Bit = ((Capability & BIT31) != 0) ? TRUE : FALSE;\r
+ Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);\r
\r
MaxReceiveFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);\r
Status = PciIo->AllocateBuffer (\r
PciIo,\r
AllocateAnyPages,\r
EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (MaxReceiveFisSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),\r
&Buffer,\r
0\r
);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- ZeroMem (Buffer, MaxReceiveFisSize);\r
+ ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);\r
\r
AhciRegisters->AhciRFis = Buffer;\r
AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;\r
- Bytes = MaxReceiveFisSize;\r
+ Bytes = (UINTN)MaxReceiveFisSize;\r
\r
Status = PciIo->Map (\r
PciIo,\r
EfiPciIoOperationBusMasterCommonBuffer,\r
Buffer,\r
&Bytes,\r
- &(EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciRFisPciAddr,\r
+ &AhciRFisPciAddr,\r
&AhciRegisters->MapRFis\r
);\r
\r
goto Error6;\r
}\r
\r
- if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciRFisPciAddr > 0x100000000UL)) {\r
+ if ((!Support64Bit) && (AhciRFisPciAddr > 0x100000000ULL)) {\r
//\r
// The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.\r
//\r
Status = EFI_DEVICE_ERROR;\r
goto Error5;\r
}\r
+ AhciRegisters->AhciRFisPciAddr = (EFI_AHCI_RECEIVED_FIS *)(UINTN)AhciRFisPciAddr;\r
\r
//\r
// Allocate memory for command list\r
PciIo,\r
AllocateAnyPages,\r
EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (MaxCommandListSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),\r
&Buffer,\r
0\r
);\r
goto Error5;\r
}\r
\r
- ZeroMem (Buffer, MaxCommandListSize);\r
+ ZeroMem (Buffer, (UINTN)MaxCommandListSize);\r
\r
AhciRegisters->AhciCmdList = Buffer;\r
AhciRegisters->MaxCommandListSize = MaxCommandListSize;\r
- Bytes = MaxCommandListSize;\r
+ Bytes = (UINTN)MaxCommandListSize;\r
\r
Status = PciIo->Map (\r
PciIo,\r
EfiPciIoOperationBusMasterCommonBuffer,\r
Buffer,\r
&Bytes,\r
- &(EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciCmdListPciAddr,\r
+ &AhciCmdListPciAddr,\r
&AhciRegisters->MapCmdList\r
);\r
\r
goto Error4;\r
}\r
\r
- if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciCmdListPciAddr > 0x100000000UL)) {\r
+ if ((!Support64Bit) && (AhciCmdListPciAddr > 0x100000000ULL)) {\r
//\r
// The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.\r
//\r
Status = EFI_DEVICE_ERROR;\r
goto Error3;\r
}\r
+ AhciRegisters->AhciCmdListPciAddr = (EFI_AHCI_COMMAND_LIST *)(UINTN)AhciCmdListPciAddr;\r
\r
//\r
// Allocate memory for command table\r
PciIo,\r
AllocateAnyPages,\r
EfiBootServicesData,\r
- EFI_SIZE_TO_PAGES (MaxCommandTableSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),\r
&Buffer,\r
0\r
);\r
goto Error3;\r
}\r
\r
- ZeroMem (Buffer, MaxCommandTableSize);\r
+ ZeroMem (Buffer, (UINTN)MaxCommandTableSize);\r
\r
AhciRegisters->AhciCommandTable = Buffer;\r
AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;\r
- Bytes = MaxCommandTableSize;\r
+ Bytes = (UINTN)MaxCommandTableSize;\r
\r
Status = PciIo->Map (\r
PciIo,\r
EfiPciIoOperationBusMasterCommonBuffer,\r
Buffer,\r
&Bytes,\r
- &(EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciCommandTablePciAddr,\r
+ &AhciCommandTablePciAddr,\r
&AhciRegisters->MapCommandTable\r
);\r
\r
goto Error2;\r
}\r
\r
- if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)AhciRegisters->AhciCommandTablePciAddr > 0x100000000UL)) {\r
+ if ((!Support64Bit) && (AhciCommandTablePciAddr > 0x100000000ULL)) {\r
//\r
// The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.\r
//\r
Status = EFI_DEVICE_ERROR;\r
goto Error1;\r
}\r
+ AhciRegisters->AhciCommandTablePciAddr = (EFI_AHCI_COMMAND_TABLE *)(UINTN)AhciCommandTablePciAddr;\r
\r
return EFI_SUCCESS;\r
//\r
Error2:\r
PciIo->FreeBuffer (\r
PciIo,\r
- EFI_SIZE_TO_PAGES (MaxCommandTableSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),\r
AhciRegisters->AhciCommandTable\r
);\r
Error3:\r
Error4:\r
PciIo->FreeBuffer (\r
PciIo,\r
- EFI_SIZE_TO_PAGES (MaxCommandListSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),\r
AhciRegisters->AhciCmdList\r
);\r
Error5:\r
Error6:\r
PciIo->FreeBuffer (\r
PciIo,\r
- EFI_SIZE_TO_PAGES (MaxReceiveFisSize),\r
+ EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),\r
AhciRegisters->AhciRFis\r
);\r
\r
// Get the number of command slots per port supported by this HBA.\r
//\r
MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);\r
- Support64Bit = ((Capability & BIT31) != 0) ? TRUE : FALSE;\r
+ Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);\r
\r
//\r
// Get the bit map of those ports exposed by this HBA.\r
} else {\r
continue;\r
}\r
- \r
+\r
DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n", \r
Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));\r
\r
+ //\r
+ // If the device is a hard disk, then try to enable S.M.A.R.T feature\r
+ //\r
+ if (DeviceType == EfiIdeHarddisk) {\r
+ AhciAtaSmartSupport (\r
+ PciIo,\r
+ AhciRegisters,\r
+ Port,\r
+ 0,\r
+ &Buffer,\r
+ NULL\r
+ );\r
+ }\r
+\r
//\r
// Submit identify data to IDE controller init driver\r
//\r
}\r
\r
Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
continue;\r
return EFI_SUCCESS;\r
}\r
\r
-\r
-\r