diff options
author | qianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-05-03 10:31:41 +0000 |
---|---|---|
committer | qianouyang <qianouyang@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-05-03 10:31:41 +0000 |
commit | 490b5ea10bcdab3579d4c12056b177cea52d6f8e (patch) | |
tree | 8165cd5916a92a78ba6c7c869e23e173fa1b1b7b /MdeModulePkg/Bus/Ata/AtaAtapiPassThru | |
parent | c89ea31f52cd1748166e494d4fdadb19a6bd69a3 (diff) | |
download | edk2-platforms-490b5ea10bcdab3579d4c12056b177cea52d6f8e.tar.xz |
Add BlockIO2 Protocol.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11606 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Bus/Ata/AtaAtapiPassThru')
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c | 542 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h | 116 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c | 617 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h | 303 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c | 666 | ||||
-rw-r--r-- | MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h | 91 |
6 files changed, 1481 insertions, 854 deletions
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c index 8ba0201563..7765bfc75c 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c @@ -185,8 +185,49 @@ AhciWaitMemSet ( }
/**
+ Check the memory status to the test value.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Offset The memory address to test.
+ @param[in] MaskValue The mask value of memory.
+ @param[in] TestValue The test value of memory.
+ @param[in, out] RetryTimes The retry times value for waitting memory set.
+
+ @retval EFI_NOTREADY The memory is not set.
+ @retval EFI_TIMEOUT The memory setting retry times out.
+ @retval EFI_SUCCESS The memory is correct set.
+
+**/
+EFI_STATUS
+EFIAPI
+AhciCheckMemSet (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 Offset,
+ IN UINT32 MaskValue,
+ IN UINT32 TestValue,
+ IN UINTN *RetryTimes
+ )
+{
+ UINT32 Value;
+
+ (*RetryTimes) --;
+
+ Value = AhciReadReg (PciIo, Offset) & MaskValue;
+
+ if (Value == TestValue) {
+ return EFI_SUCCESS;
+ }
+
+ if ((*RetryTimes) == 0) {
+ return EFI_TIMEOUT;
+ } else {
+ return EFI_NOT_READY;
+ }
+}
+
+/**
Check if the device is still on port. It also checks if the AHCI controller
- supports the address and data count will be transfered.
+ supports the address and data count will be transferred.
@param PciIo The PCI IO protocol instance.
@param Port The number of port.
@@ -206,7 +247,7 @@ AhciCheckDeviceStatus ( IN UINT8 Port
)
{
- UINT32 Data;
+ UINT32 Data;
UINT32 Offset;
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
@@ -214,7 +255,7 @@ AhciCheckDeviceStatus ( Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
}
return EFI_NOT_READY;
@@ -240,7 +281,7 @@ AhciClearPortStatus ( //
// Clear any error status
- //
+ //
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
@@ -310,8 +351,8 @@ AhciEnableFisReceive ( IN EFI_PCI_IO_PROTOCOL *PciIo,
IN UINT8 Port,
IN UINT64 Timeout
- )
-{
+ )
+{
UINT32 Offset;
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
@@ -370,12 +411,12 @@ AhciDisableFisReceive ( AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
return AhciWaitMemSet (
- PciIo,
+ PciIo,
Offset,
EFI_AHCI_PORT_CMD_FR,
0,
Timeout
- );
+ );
}
@@ -412,7 +453,7 @@ AhciBuildCommand ( IN UINT64 DataLength
)
{
- UINT64 BaseAddr;
+ UINT64 BaseAddr;
UINT64 PrdtNumber;
UINT64 PrdtIndex;
UINTN RemainedData;
@@ -436,7 +477,7 @@ AhciBuildCommand ( BaseAddr = Data64.Uint64;
- ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
+ ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
@@ -466,7 +507,7 @@ AhciBuildCommand ( CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
- if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
+ if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
} else {
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;
@@ -475,7 +516,7 @@ AhciBuildCommand ( Data64.Uint64 = (UINT64)MemAddr;
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
- RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
+ RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
MemAddr += EFI_AHCI_MAX_DATA_PER_PRDT;
}
@@ -543,18 +584,21 @@ AhciBuildCommandFis ( /**
Start a PIO data transfer on specific port.
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param Read The transfer direction.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param MemoryAddr The pointer to the data buffer.
- @param DataCount The data count to be transferred.
- @param Timeout The timeout value of non data transfer.
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
+ @param[in] Port The number of port.
+ @param[in] PortMultiplier The timeout value of stop.
+ @param[in] AtapiCommand The atapi command will be used for the
+ transfer.
+ @param[in] AtapiCommandLength The length of the atapi command.
+ @param[in] Read The transfer direction.
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
+ @param[in, out] MemoryAddr The pointer to the data buffer.
+ @param[in] DataCount The data count to be transferred.
+ @param[in] Timeout The timeout value of non data transfer.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
@retval EFI_TIMEOUT The operation is time out.
@@ -576,7 +620,8 @@ AhciPioTransfer ( IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
IN OUT VOID *MemoryAddr,
IN UINT32 DataCount,
- IN UINT64 Timeout
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
)
{
EFI_STATUS Status;
@@ -639,17 +684,17 @@ AhciPioTransfer ( );
Status = AhciStartCommand (
- PciIo,
- Port,
+ PciIo,
+ Port,
0,
Timeout
);
if (EFI_ERROR (Status)) {
goto Exit;
}
-
+
//
- // Checking the status and wait the driver sending data
+ // Check the status and wait the driver sending data
//
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
//
@@ -668,7 +713,7 @@ AhciPioTransfer ( //
MicroSecondDelay(100);
- Delay--;
+ Delay--;
} while (Delay > 0);
if (Delay == 0) {
@@ -689,30 +734,30 @@ AhciPioTransfer ( );
if (EFI_ERROR (Status)) {
- goto Exit;
+ goto Exit;
}
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
Status = AhciWaitMemSet (
PciIo,
- Offset,
+ Offset,
EFI_AHCI_PORT_IS_PSS,
EFI_AHCI_PORT_IS_PSS,
Timeout
- );
+ );
if (EFI_ERROR (Status)) {
- goto Exit;
+ goto Exit;
}
-Exit:
+Exit:
AhciStopCommand (
- PciIo,
+ PciIo,
Port,
Timeout
);
AhciDisableFisReceive (
- PciIo,
+ PciIo,
Port,
Timeout
);
@@ -730,29 +775,32 @@ Exit: /**
Start a DMA data transfer on specific port
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param Read The transfer direction.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param MemoryAddr The pointer to the data buffer.
- @param DataCount The data count to be transferred.
- @param Timeout The timeout value of non data transfer.
+ @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
+ @param[in] Port The number of port.
+ @param[in] PortMultiplier The timeout value of stop.
+ @param[in] AtapiCommand The atapi command will be used for the
+ transfer.
+ @param[in] AtapiCommandLength The length of the atapi command.
+ @param[in] Read The transfer direction.
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
+ @param[in, out] MemoryAddr The pointer to the data buffer.
+ @param[in] DataCount The data count to be transferred.
+ @param[in] Timeout The timeout value of non data transfer.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
@retval EFI_TIMEOUT The operation is time out.
@retval EFI_UNSUPPORTED The device is not ready for transfer.
@retval EFI_SUCCESS The DMA data transfer executes successfully.
-
+
**/
EFI_STATUS
EFIAPI
AhciDmaTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
IN EFI_AHCI_REGISTERS *AhciRegisters,
IN UINT8 Port,
IN UINT8 PortMultiplier,
@@ -763,7 +811,8 @@ AhciDmaTransfer ( IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
IN OUT VOID *MemoryAddr,
IN UINTN DataCount,
- IN UINT64 Timeout
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
)
{
EFI_STATUS Status;
@@ -775,141 +824,224 @@ AhciDmaTransfer ( EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList;
- if (Read) {
- Flag = EfiPciIoOperationBusMasterWrite;
- } else {
- Flag = EfiPciIoOperationBusMasterRead;
- }
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_TPL OldTpl;
- //
- // construct command list and command table with pci bus address
- //
- MapLength = DataCount;
- Status = PciIo->Map (
- PciIo,
- Flag,
- MemoryAddr,
- &MapLength,
- &PhyAddr,
- &Map
- );
+ Map = NULL;
+ PciIo = Instance->PciIo;
- if (EFI_ERROR (Status) || (DataCount != MapLength)) {
- return EFI_OUT_OF_RESOURCES;
+ if (PciIo == NULL) {
+ return EFI_INVALID_PARAMETER;
}
//
- // Package read needed
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking
+ // BlockIO tasks.
+ // Delay 100us to simulate the blocking time out checking.
//
- AhciBuildCommandFis (&CFis, AtaCommandBlock);
+ while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ AsyncNonBlockingTransferRoutine (NULL, Instance);
+ gBS->RestoreTPL (OldTpl);
+ //
+ // Stall for 100us.
+ //
+ MicroSecondDelay (100);
+ }
- ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
+ if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {
+ //
+ // Mark the Task to indicate that it has been started.
+ //
+ if (Task != NULL) {
+ Task->IsStart = TRUE;
+ Task->RetryTimes = (UINT32) (DivU64x32(Timeout, 1000) + 1);
+ }
+ if (Read) {
+ Flag = EfiPciIoOperationBusMasterWrite;
+ } else {
+ Flag = EfiPciIoOperationBusMasterRead;
+ }
- CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
- CmdList.AhciCmdW = Read ? 0 : 1;
+ //
+ // Construct command list and command table with pci bus address.
+ //
+ MapLength = DataCount;
+ Status = PciIo->Map (
+ PciIo,
+ Flag,
+ MemoryAddr,
+ &MapLength,
+ &PhyAddr,
+ &Map
+ );
+
+ if (EFI_ERROR (Status) || (DataCount != MapLength)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- AhciBuildCommand (
- PciIo,
- AhciRegisters,
- Port,
- PortMultiplier,
- &CFis,
- &CmdList,
- AtapiCommand,
- AtapiCommandLength,
- 0,
- (VOID *)(UINTN)PhyAddr,
- DataCount
- );
-
- Status = AhciStartCommand (
- PciIo,
- Port,
- 0,
- Timeout
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- //
- // Wait device PRD processed
- //
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
- Status = AhciWaitMemSet (
- PciIo,
- Offset,
- EFI_AHCI_PORT_IS_DPS,
- EFI_AHCI_PORT_IS_DPS,
- Timeout
- );
-
- if (EFI_ERROR (Status)) {
- goto Exit;
+ if (Task != NULL) {
+ Task->Map = Map;
+ }
+ //
+ // Package read needed
+ //
+ AhciBuildCommandFis (&CFis, AtaCommandBlock);
+
+ ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
+
+ CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
+ CmdList.AhciCmdW = Read ? 0 : 1;
+
+ AhciBuildCommand (
+ PciIo,
+ AhciRegisters,
+ Port,
+ PortMultiplier,
+ &CFis,
+ &CmdList,
+ AtapiCommand,
+ AtapiCommandLength,
+ 0,
+ (VOID *)(UINTN)PhyAddr,
+ DataCount
+ );
+
+ Status = AhciStartCommand (
+ PciIo,
+ Port,
+ 0,
+ Timeout
+ );
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ //
+ // Wait device PRD processed
+ //
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
+ Status = AhciWaitMemSet (
+ PciIo,
+ Offset,
+ EFI_AHCI_PORT_IS_DPS,
+ EFI_AHCI_PORT_IS_DPS,
+ Timeout
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
}
//
// Wait for command compelte
//
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
- Status = AhciWaitMemSet (
- PciIo,
- Offset,
- 0xFFFFFFFF,
- 0,
- Timeout
- );
+ if (Task != NULL) {
+ //
+ // For Non-blocking
+ //
+ Status = AhciCheckMemSet (
+ PciIo,
+ Offset,
+ 0xFFFFFFFF,
+ 0,
+ (UINTN *) (&Task->RetryTimes)
+ );
+ } else {
+ Status = AhciWaitMemSet (
+ PciIo,
+ Offset,
+ 0xFFFFFFFF,
+ 0,
+ Timeout
+ );
+ }
+
if (EFI_ERROR (Status)) {
goto Exit;
}
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
- Status = AhciWaitMemSet (
- PciIo,
- Offset,
- EFI_AHCI_PORT_IS_DHRS,
- EFI_AHCI_PORT_IS_DHRS,
- Timeout
- );
+
+ if (Task != NULL) {
+ //
+ // For Non-blocking
+ //
+ Status = AhciCheckMemSet (
+ PciIo,
+ Offset,
+ EFI_AHCI_PORT_IS_DHRS,
+ EFI_AHCI_PORT_IS_DHRS,
+ (UINTN *) (&Task->RetryTimes)
+ );
+ } else {
+ Status = AhciWaitMemSet (
+ PciIo,
+ Offset,
+ EFI_AHCI_PORT_IS_DHRS,
+ EFI_AHCI_PORT_IS_DHRS,
+ Timeout
+ );
+ }
+
if (EFI_ERROR (Status)) {
goto Exit;
}
-Exit:
- AhciStopCommand (
- PciIo,
- Port,
- Timeout
- );
+Exit:
+ //
+ // For Blocking mode, the command should be stopped, the Fis should be disabled
+ // and the PciIo should be unmapped.
+ // For non-blocking mode, only when a error is happened (if the return status is
+ // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
+ // context cleanup, then set the packet's Asb status.
+ //
+ if (Task == NULL ||
+ ((Task != NULL) && (Status != EFI_NOT_READY))
+ ) {
+ AhciStopCommand (
+ PciIo,
+ Port,
+ Timeout
+ );
- AhciDisableFisReceive (
- PciIo,
- Port,
- Timeout
- );
+ AhciDisableFisReceive (
+ PciIo,
+ Port,
+ Timeout
+ );
- PciIo->Unmap (
- PciIo,
- Map
- );
-
- AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
+ PciIo->Unmap (
+ PciIo,
+ (Task != NULL) ? Task->Map : Map
+ );
+ if (Task != NULL) {
+ Task->Packet->Asb->AtaStatus = 0x01;
+ }
+ }
+
+ AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
return Status;
}
/**
Start a non data transfer on specific port.
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param Timeout The timeout value of non data transfer.
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
+ @param[in] Port The number of port.
+ @param[in] PortMultiplier The timeout value of stop.
+ @param[in] AtapiCommand The atapi command will be used for the
+ transfer.
+ @param[in] AtapiCommandLength The length of the atapi command.
+ @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
+ @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
+ @param[in] Timeout The timeout value of non data transfer.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
@retval EFI_TIMEOUT The operation is time out.
@@ -928,15 +1060,16 @@ AhciNonDataTransfer ( IN UINT8 AtapiCommandLength,
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
- )
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
+ )
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
UINTN FisBaseAddr;
UINT32 Offset;
UINT32 Value;
UINT32 Delay;
-
+
EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList;
@@ -961,18 +1094,18 @@ AhciNonDataTransfer ( 0,
NULL,
0
- );
-
+ );
+
Status = AhciStartCommand (
- PciIo,
- Port,
+ PciIo,
+ Port,
0,
Timeout
);
if (EFI_ERROR (Status)) {
goto Exit;
}
-
+
//
// Wait device sends the Response Fis
//
@@ -993,7 +1126,7 @@ AhciNonDataTransfer ( //
MicroSecondDelay(100);
- Delay --;
+ Delay --;
} while (Delay > 0);
if (Delay == 0) {
@@ -1009,17 +1142,17 @@ AhciNonDataTransfer ( 0xFFFFFFFF,
0,
Timeout
- );
-
-Exit:
+ );
+
+Exit:
AhciStopCommand (
- PciIo,
+ PciIo,
Port,
Timeout
);
AhciDisableFisReceive (
- PciIo,
+ PciIo,
Port,
Timeout
);
@@ -1056,7 +1189,7 @@ AhciStopCommand ( Data = AhciReadReg (PciIo, Offset);
if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
}
if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
@@ -1064,22 +1197,22 @@ AhciStopCommand ( }
return AhciWaitMemSet (
- PciIo,
+ PciIo,
Offset,
EFI_AHCI_PORT_CMD_CR,
0,
Timeout
- );
+ );
}
/**
Start command for give slot on specific port.
-
+
@param PciIo The PCI IO protocol instance.
@param Port The number of port.
- @param CommandSlot The number of CommandSlot.
+ @param CommandSlot The number of Command Slot.
@param Timeout The timeout value of start.
-
+
@retval EFI_DEVICE_ERROR The command start unsuccessfully.
@retval EFI_TIMEOUT The operation is time out.
@retval EFI_SUCCESS The command start successfully.
@@ -1119,14 +1252,14 @@ AhciStartCommand ( Port,
Timeout
);
-
+
if (EFI_ERROR (Status)) {
return Status;
}
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
PortStatus = AhciReadReg (PciIo, Offset);
-
+
StartCmd = 0;
if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
StartCmd = AhciReadReg (PciIo, Offset);
@@ -1143,12 +1276,12 @@ AhciStartCommand ( AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);
AhciWaitMemSet (
- PciIo,
+ PciIo,
Offset,
EFI_AHCI_PORT_CMD_COL,
0,
Timeout
- );
+ );
}
}
@@ -1190,8 +1323,8 @@ AhciPortReset ( )
{
EFI_STATUS Status;
- UINT32 Offset;
-
+ UINT32 Offset;
+
AhciClearPortStatus (PciIo, Port);
AhciStopCommand (PciIo, Port, Timeout);
@@ -1205,14 +1338,14 @@ AhciPortReset ( AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);
//
- // wait 5 milliseceond before de-assert DET
+ // wait 5 millisecond before de-assert DET
//
MicroSecondDelay (5000);
AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);
//
- // wait 5 milliseceond before de-assert DET
+ // wait 5 millisecond before de-assert DET
//
MicroSecondDelay (5000);
@@ -1226,7 +1359,7 @@ AhciPortReset ( EFI_AHCI_PORT_SSTS_DET_MASK,
EFI_AHCI_PORT_SSTS_DET_PCE,
Timeout
- );
+ );
if (EFI_ERROR (Status)) {
return Status;
@@ -1240,11 +1373,10 @@ AhciPortReset ( /**
Do AHCI HBA reset.
-
+
@param PciIo The PCI IO protocol instance.
@param Timeout The timeout value of reset.
-
-
+
@retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
@retval EFI_TIMEOUT The reset operation is time out.
@retval EFI_SUCCESS AHCI controller is reset successfully.
@@ -1340,7 +1472,8 @@ AhciAtaSmartReturnStatusCheck ( 0,
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
if (EFI_ERROR (Status)) {
@@ -1390,7 +1523,7 @@ AhciAtaSmartSupport ( IN EFI_AHCI_REGISTERS *AhciRegisters,
IN UINT8 Port,
IN UINT8 PortMultiplier,
- IN EFI_IDENTIFY_DATA *IdentifyData,
+ IN EFI_IDENTIFY_DATA *IdentifyData,
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
)
{
@@ -1430,7 +1563,8 @@ AhciAtaSmartSupport ( 0,
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
@@ -1455,7 +1589,8 @@ AhciAtaSmartSupport ( 0,
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
if (!EFI_ERROR (Status)) {
@@ -1469,7 +1604,7 @@ AhciAtaSmartSupport ( }
}
}
- DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
+ DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
Port, PortMultiplier));
}
@@ -1511,7 +1646,7 @@ AhciIdentify ( ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
-
+
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
AtaCommandBlock.AtaSectorCount = 1;
@@ -1527,7 +1662,8 @@ AhciIdentify ( &AtaStatusBlock,
Buffer,
sizeof (EFI_IDENTIFY_DATA),
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -1565,7 +1701,7 @@ AhciIdentifyPacket ( if (PciIo == NULL || AhciRegisters == NULL) {
return EFI_INVALID_PARAMETER;
}
-
+
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
@@ -1584,7 +1720,8 @@ AhciIdentifyPacket ( &AtaStatusBlock,
Buffer,
sizeof (EFI_IDENTIFY_DATA),
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -1623,7 +1760,7 @@ AhciDeviceSetFeature ( ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
-
+
AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;
AtaCommandBlock.AtaFeatures = (UINT8) Feature;
AtaCommandBlock.AtaFeaturesExp = (UINT8) (Feature >> 8);
@@ -1641,7 +1778,8 @@ AhciDeviceSetFeature ( 0,
&AtaCommandBlock,
&AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -1708,7 +1846,7 @@ AhciPacketCommandExecute ( Read = FALSE;
}
- if (Length == 0) {
+ if (Length == 0) {
Status = AhciNonDataTransfer (
PciIo,
AhciRegisters,
@@ -1718,7 +1856,8 @@ AhciPacketCommandExecute ( Packet->CdbLength,
&AtaCommandBlock,
&AtaStatusBlock,
- Packet->Timeout
+ Packet->Timeout,
+ NULL
);
} else {
//
@@ -1742,7 +1881,8 @@ AhciPacketCommandExecute ( &AtaStatusBlock,
Buffer,
Length,
- Packet->Timeout
+ Packet->Timeout,
+ NULL
);
if (!EFI_ERROR (Status)) {
break;
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h index 1efe0ebe73..9c4a9397e9 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h @@ -1,7 +1,7 @@ /** @file
Header file for AHCI mode of ATA host controller.
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -154,7 +154,7 @@ typedef union { #define EFI_AHCI_PORT_SERR_BDE BIT19
#define EFI_AHCI_PORT_SERR_DE BIT20
#define EFI_AHCI_PORT_SERR_CRCE BIT21
-#define EFI_AHCI_PORT_SERR_HE BIT22
+#define EFI_AHCI_PORT_SERR_HE BIT22
#define EFI_AHCI_PORT_SERR_LSE BIT23
#define EFI_AHCI_PORT_SERR_TSTE BIT24
#define EFI_AHCI_PORT_SERR_UFT BIT25
@@ -348,117 +348,5 @@ AhciStopCommand ( IN UINT64 Timeout
);
-/**
- Start a non data transfer on specific port.
-
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param Timeout The timeout value of non data transfer.
-
- @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The non data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciNonDataTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
- );
-
-/**
- Start a DMA data transfer on specific port
-
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param Read The transfer direction.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param MemoryAddr The pointer to the data buffer.
- @param DataCount The data count to be transferred.
- @param Timeout The timeout value of non data transfer.
-
- @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The DMA data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciDmaTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN OUT VOID *MemoryAddr,
- IN UINTN DataCount,
- IN UINT64 Timeout
- );
-
-/**
- Start a PIO data transfer on specific port.
-
- @param PciIo The PCI IO protocol instance.
- @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
- @param Port The number of port.
- @param PortMultiplier The timeout value of stop.
- @param AtapiCommand The atapi command will be used for the transfer.
- @param AtapiCommandLength The length of the atapi command.
- @param Read The transfer direction.
- @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
- @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
- @param MemoryAddr The pointer to the data buffer.
- @param DataCount The data count to be transferred.
- @param Timeout The timeout value of non data transfer.
-
- @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
- @retval EFI_TIMEOUT The operation is time out.
- @retval EFI_UNSUPPORTED The device is not ready for transfer.
- @retval EFI_SUCCESS The PIO data transfer executes successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-AhciPioTransfer (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_AHCI_REGISTERS *AhciRegisters,
- IN UINT8 Port,
- IN UINT8 PortMultiplier,
- IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
- IN UINT8 AtapiCommandLength,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN OUT VOID *MemoryAddr,
- IN UINT32 DataCount,
- IN UINT64 Timeout
- );
-
-
#endif
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c index ca64df7f6b..3e135d74ec 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c @@ -39,7 +39,7 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = { // bits.
// Note that the driver doesn't support AtaPassThru non blocking I/O.
//
- EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL,
+ EFI_ATA_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_ATA_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
//
// IoAlign
//
@@ -98,7 +98,12 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = { 0, // PreviousPort
0, // PreviousPortMultiplier
0, // PreviousTargetId
- 0 // PreviousLun
+ 0, // PreviousLun
+ NULL, // Timer event
+ { // NonBlocking TaskList
+ NULL,
+ NULL
+ }
};
ATAPI_DEVICE_PATH mAtapiDevicePathTemplate = {
@@ -133,11 +138,303 @@ UINT8 mScsiId[TARGET_MAX_BYTES] = { };
/**
+ Sends an ATA command to an ATA device that is attached to the ATA controller. This function
+ supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required,
+ and the non-blocking I/O functionality is optional.
+
+ @param[in] Port The port number of the ATA device to send the command.
+ @param[in] PortMultiplierPort The port multiplier port number of the ATA device to send the command.
+ If there is no port multiplier, then specify 0.
+ @param[in, out] Packet A pointer to the ATA command to send to the ATA device specified by Port
+ and PortMultiplierPort.
+ @param[in] Instance Pointer to the ATA_ATAPI_PASS_THRU_INSTANCE.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
+
+ @retval EFI_SUCCESS The ATA command was sent by the host. For
+ bi-directional commands, InTransferLength bytes
+ were transferred from InDataBuffer. For
+ write and bi-directional commands, OutTransferLength
+ bytes were transferred by OutDataBuffer.
+ @retval EFI_BAD_BUFFER_SIZE The ATA command was not executed. The number
+ of bytes that could be transferred is returned
+ in InTransferLength. For write and bi-directional
+ commands, OutTransferLength bytes were transferred
+ by OutDataBuffer.
+ @retval EFI_NOT_READY The ATA command could not be sent because
+ there are too many ATA commands already
+ queued. The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting
+ to send the ATA command.
+ @retval EFI_INVALID_PARAMETER Port, PortMultiplierPort, or the contents
+ of Acb are invalid. The ATA command was
+ not sent, so no additional status information
+ is available.
+
+**/
+EFI_STATUS
+EFIAPI
+AtaPassThruPassThruExecute (
+ IN UINT16 Port,
+ IN UINT16 PortMultiplierPort,
+ IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
+ IN ATA_NONBLOCK_TASK *Task OPTIONAL
+ )
+{
+ EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol;
+ EFI_ATA_HC_WORK_MODE Mode;
+ EFI_STATUS Status;
+
+ Protocol = Packet->Protocol;
+
+ Mode = Instance->Mode;
+ switch (Mode) {
+ case EfiAtaIdeMode:
+ //
+ // Reassign IDE mode io port registers' base addresses
+ //
+ Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Protocol) {
+ case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
+ Status = AtaNonDataCommandIn (
+ Instance->PciIo,
+ &Instance->IdeRegisters[Port],
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
+ Status = AtaPioDataInOut (
+ Instance->PciIo,
+ &Instance->IdeRegisters[Port],
+ Packet->InDataBuffer,
+ Packet->InTransferLength,
+ TRUE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
+ Status = AtaPioDataInOut (
+ Instance->PciIo,
+ &Instance->IdeRegisters[Port],
+ Packet->OutDataBuffer,
+ Packet->OutTransferLength,
+ FALSE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
+ Status = AtaUdmaInOut (
+ Instance,
+ &Instance->IdeRegisters[Port],
+ TRUE,
+ Packet->InDataBuffer,
+ Packet->InTransferLength,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
+ Status = AtaUdmaInOut (
+ Instance,
+ &Instance->IdeRegisters[Port],
+ FALSE,
+ Packet->OutDataBuffer,
+ Packet->OutTransferLength,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ default :
+ return EFI_UNSUPPORTED;
+ }
+ break;
+ case EfiAtaAhciMode :
+ switch (Protocol) {
+ case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
+ Status = AhciNonDataTransfer (
+ Instance->PciIo,
+ &Instance->AhciRegisters,
+ (UINT8)Port,
+ (UINT8)PortMultiplierPort,
+ NULL,
+ 0,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
+ Status = AhciPioTransfer (
+ Instance->PciIo,
+ &Instance->AhciRegisters,
+ (UINT8)Port,
+ (UINT8)PortMultiplierPort,
+ NULL,
+ 0,
+ TRUE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->InDataBuffer,
+ Packet->InTransferLength,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
+ Status = AhciPioTransfer (
+ Instance->PciIo,
+ &Instance->AhciRegisters,
+ (UINT8)Port,
+ (UINT8)PortMultiplierPort,
+ NULL,
+ 0,
+ FALSE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->OutDataBuffer,
+ Packet->OutTransferLength,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
+ Status = AhciDmaTransfer (
+ Instance,
+ &Instance->AhciRegisters,
+ (UINT8)Port,
+ (UINT8)PortMultiplierPort,
+ NULL,
+ 0,
+ TRUE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->InDataBuffer,
+ Packet->InTransferLength,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
+ Status = AhciDmaTransfer (
+ Instance,
+ &Instance->AhciRegisters,
+ (UINT8)Port,
+ (UINT8)PortMultiplierPort,
+ NULL,
+ 0,
+ FALSE,
+ Packet->Acb,
+ Packet->Asb,
+ Packet->OutDataBuffer,
+ Packet->OutTransferLength,
+ Packet->Timeout,
+ Task
+ );
+ break;
+ default :
+ return EFI_UNSUPPORTED;
+ }
+ break;
+
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Call back function when the timer event is signaled.
+
+ @param[in] Event The Event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the
+ Event.
+
+**/
+VOID
+EFIAPI
+AsyncNonBlockingTransferRoutine (
+ EFI_EVENT Event,
+ VOID* Context
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *EntryHeader;
+ ATA_NONBLOCK_TASK *Task;
+ EFI_STATUS Status;
+ ATA_ATAPI_PASS_THRU_INSTANCE *Instance;
+
+ Instance = (ATA_ATAPI_PASS_THRU_INSTANCE *) Context;
+ EntryHeader = &Instance->NonBlockingTaskList;
+ //
+ // Get the Taks from the Taks List and execute it, until there is
+ // no task in the list or the device is busy with task (EFI_NOT_READY).
+ //
+ while (TRUE) {
+ if (!IsListEmpty (EntryHeader)) {
+ Entry = GetFirstNode (EntryHeader);
+ Task = ATA_NON_BLOCK_TASK_FROM_ENTRY (Entry);
+ } else {
+ return;
+ }
+
+ Status = AtaPassThruPassThruExecute (
+ Task->Port,
+ Task->PortMultiplier,
+ Task->Packet,
+ Instance,
+ Task
+ );
+
+ //
+ // If the data transfer meet a error which is not dumped into the status block
+ // set the Status block related bit.
+ //
+ if ((Status != EFI_NOT_READY) && (Status != EFI_SUCCESS)) {
+ Task->Packet->Asb->AtaStatus = 0x01;
+ }
+ //
+ // For Non blocking mode, the Status of EFI_NOT_READY means the operation
+ // is not finished yet. Other Status indicate the operation is either
+ // successful or failed.
+ //
+ if (Status != EFI_NOT_READY) {
+ RemoveEntryList (&Task->Link);
+ gBS->SignalEvent (Task->Event);
+ FreePool (Task);
+ } else {
+ break;
+ }
+ }
+}
+
+/**
The Entry Point of module.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
-
+
@retval EFI_SUCCESS The entry point is executed successfully.
@retval other Some error occurs when executing this entry point.
@@ -266,7 +563,7 @@ AtaAtapiPassThruSupported ( //
return Status;
}
-
+
//
// Close the I/O Abstraction(s) used to perform the supported test
//
@@ -324,7 +621,7 @@ AtaAtapiPassThruSupported ( 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
EFI_DEVICE_PATH_PROTOCOL.
3. Prior to calling Start(), the Supported() function for the driver specified by This must
- have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
@param[in] ControllerHandle The handle of the controller to start. This handle
@@ -333,7 +630,7 @@ AtaAtapiPassThruSupported ( @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
parameter is ignored by device drivers, and is optional for bus
drivers. For a bus driver, if this parameter is NULL, then handles
- for all the children of Controller are created by this driver.
+ for all the children of Controller are created by this driver.
If this parameter is not NULL and the first Device Path Node is
not the End of Device Path Node, then only the handle for the
child device specified by the first Device Path Node of
@@ -446,6 +743,28 @@ AtaAtapiPassThruStart ( Instance->AtaPassThru.Mode = &Instance->AtaPassThruMode;
Instance->ExtScsiPassThru.Mode = &Instance->ExtScsiPassThruMode;
InitializeListHead(&Instance->DeviceList);
+ InitializeListHead(&Instance->NonBlockingTaskList);
+
+ Instance->TimerEvent = NULL;
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ AsyncNonBlockingTransferRoutine,
+ Instance,
+ &Instance->TimerEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Set 1ms timer.
+ //
+ Status = gBS->SetTimer (Instance->TimerEvent, TimerPeriodic, 10000);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
//
// Enumerate all inserted ATA devices.
@@ -475,6 +794,10 @@ ErrorExit: );
}
+ if (Instance->TimerEvent != NULL) {
+ gBS->CloseEvent (Instance->TimerEvent);
+ }
+
//
// Remove all inserted ATA devices.
//
@@ -542,13 +865,22 @@ AtaAtapiPassThruStop ( if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
-
- Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS(AtaPassThru);
- PciIo = Instance->PciIo;
+
+ Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (AtaPassThru);
+
+ //
+ // Close Non-Blocking timer and free Task list.
+ //
+ if (Instance->TimerEvent != NULL) {
+ gBS->CloseEvent (Instance->TimerEvent);
+ Instance->TimerEvent = NULL;
+ }
+ DestroyAsynTaskList (Instance);
//
// Disable this ATA host controller.
//
+ PciIo = Instance->PciIo;
Status = PciIo->Attributes (
PciIo,
EfiPciIoAttributeOperationSupported,
@@ -672,7 +1004,7 @@ SearchDeviceInfoList ( }
Node = GetNextNode (&Instance->DeviceList, Node);
- }
+ }
return NULL;
}
@@ -758,6 +1090,42 @@ DestroyDeviceInfoList ( }
/**
+ Destroy all pending non blocking tasks.
+
+ @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
+
+**/
+VOID
+EFIAPI
+DestroyAsynTaskList (
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *DelEntry;
+ ATA_NONBLOCK_TASK *Task;
+ EFI_TPL OldTpl;
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ if (!IsListEmpty (&Instance->NonBlockingTaskList)) {
+ //
+ // Free the Subtask list.
+ //
+ for (Entry = (&Instance->NonBlockingTaskList)->ForwardLink;
+ Entry != (&Instance->NonBlockingTaskList);
+ ) {
+ DelEntry = Entry;
+ Entry = Entry->ForwardLink;
+ Task = ATA_NON_BLOCK_TASK_FROM_ENTRY (DelEntry);
+
+ RemoveEntryList (DelEntry);
+ FreePool (Task);
+ }
+ }
+ gBS->RestoreTPL (OldTpl);
+}
+
+/**
Enumerate all attached ATA devices at IDE mode or AHCI mode separately.
The function is designed to enumerate all attached ATA devices.
@@ -863,17 +1231,16 @@ AtaPassThruPassThru ( IN UINT16 PortMultiplierPort,
IN OUT EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet,
IN EFI_EVENT Event OPTIONAL
- )
+ )
{
- EFI_STATUS Status;
ATA_ATAPI_PASS_THRU_INSTANCE *Instance;
- EFI_ATA_PASS_THRU_CMD_PROTOCOL Protocol;
- EFI_ATA_HC_WORK_MODE Mode;
LIST_ENTRY *Node;
EFI_ATA_DEVICE_INFO *DeviceInfo;
EFI_IDENTIFY_DATA *IdentifyData;
UINT64 Capacity;
UINT32 MaxSectorCount;
+ ATA_NONBLOCK_TASK *Task;
+ EFI_TPL OldTpl;
Instance = ATA_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
@@ -940,173 +1307,37 @@ AtaPassThruPassThru ( return EFI_BAD_BUFFER_SIZE;
}
- Status = EFI_UNSUPPORTED;
- Protocol = Packet->Protocol;
-
- Mode = Instance->Mode;
- switch (Mode) {
- case EfiAtaIdeMode:
- //
- // Reassign IDE mode io port registers' base addresses
- //
- Status = GetIdeRegisterIoAddr (Instance->PciIo, Instance->IdeRegisters);
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- switch (Protocol) {
- case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
- Status = AtaNonDataCommandIn(
- Instance->PciIo,
- &Instance->IdeRegisters[Port],
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
- Status = AtaPioDataInOut(
- Instance->PciIo,
- &Instance->IdeRegisters[Port],
- Packet->InDataBuffer,
- Packet->InTransferLength,
- TRUE,
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
- Status = AtaPioDataInOut(
- Instance->PciIo,
- &Instance->IdeRegisters[Port],
- Packet->OutDataBuffer,
- Packet->OutTransferLength,
- FALSE,
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
- Status = AtaUdmaInOut(
- Instance->PciIo,
- &Instance->IdeRegisters[Port],
- TRUE,
- Packet->InDataBuffer,
- Packet->InTransferLength,
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
- Status = AtaUdmaInOut(
- Instance->PciIo,
- &Instance->IdeRegisters[Port],
- FALSE,
- Packet->OutDataBuffer,
- Packet->OutTransferLength,
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- default :
- return EFI_UNSUPPORTED;
- }
- break;
- case EfiAtaAhciMode :
- switch (Protocol) {
- case EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA:
- Status = AhciNonDataTransfer(
- Instance->PciIo,
- &Instance->AhciRegisters,
- (UINT8)Port,
- (UINT8)PortMultiplierPort,
- NULL,
- 0,
- Packet->Acb,
- Packet->Asb,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN:
- Status = AhciPioTransfer(
- Instance->PciIo,
- &Instance->AhciRegisters,
- (UINT8)Port,
- (UINT8)PortMultiplierPort,
- NULL,
- 0,
- TRUE,
- Packet->Acb,
- Packet->Asb,
- Packet->InDataBuffer,
- Packet->InTransferLength,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT:
- Status = AhciPioTransfer(
- Instance->PciIo,
- &Instance->AhciRegisters,
- (UINT8)Port,
- (UINT8)PortMultiplierPort,
- NULL,
- 0,
- FALSE,
- Packet->Acb,
- Packet->Asb,
- Packet->OutDataBuffer,
- Packet->OutTransferLength,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_IN:
- Status = AhciDmaTransfer(
- Instance->PciIo,
- &Instance->AhciRegisters,
- (UINT8)Port,
- (UINT8)PortMultiplierPort,
- NULL,
- 0,
- TRUE,
- Packet->Acb,
- Packet->Asb,
- Packet->InDataBuffer,
- Packet->InTransferLength,
- Packet->Timeout
- );
- break;
- case EFI_ATA_PASS_THRU_PROTOCOL_UDMA_DATA_OUT:
- Status = AhciDmaTransfer(
- Instance->PciIo,
- &Instance->AhciRegisters,
- (UINT8)Port,
- (UINT8)PortMultiplierPort,
- NULL,
- 0,
- FALSE,
- Packet->Acb,
- Packet->Asb,
- Packet->OutDataBuffer,
- Packet->OutTransferLength,
- Packet->Timeout
- );
- break;
- default :
- return EFI_UNSUPPORTED;
- }
- break;
+ //
+ // For non-blocking mode, queue the Task into the list.
+ //
+ if (Event != NULL) {
+ Task = AllocateZeroPool (sizeof (ATA_NONBLOCK_TASK));
+ if (Task == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Task->Signature = ATA_NONBLOCKING_TASK_SIGNATURE;
+ Task->Port = Port;
+ Task->PortMultiplier = PortMultiplierPort;
+ Task->Packet = Packet;
+ Task->Event = Event;
+ Task->IsStart = FALSE;
+ Task->RetryTimes = 0;
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);
+ gBS->RestoreTPL (OldTpl);
- default:
- Status = EFI_DEVICE_ERROR;
- break;
+ return EFI_SUCCESS;
+ } else {
+ return AtaPassThruPassThruExecute (
+ Port,
+ PortMultiplierPort,
+ Packet,
+ Instance,
+ NULL
+ );
}
-
- return Status;
}
/**
@@ -1197,7 +1428,7 @@ AtaPassThruGetNextPort ( //
return EFI_INVALID_PARAMETER;
}
-
+
Exit:
//
// Update the PreviousPort and PreviousPortMultiplier.
@@ -1216,20 +1447,20 @@ Exit: The GetNextDevice() function retrieves the port multiplier port number of an ATA device
present on a port of an ATA controller.
-
+
If PortMultiplierPort points to a port multiplier port number value that was returned on a
previous call to GetNextDevice(), then the port multiplier port number of the next ATA device
on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is
returned.
-
+
If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first
ATA device on port of the ATA controller is returned in PortMultiplierPort and
EFI_SUCCESS is returned.
-
+
If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort
was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER
is returned.
-
+
If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of
the ATA controller, then EFI_NOT_FOUND is returned.
@@ -1309,7 +1540,7 @@ AtaPassThruGetNextDevice ( //
return EFI_INVALID_PARAMETER;
}
-
+
Exit:
//
// Update the PreviousPort and PreviousPortMultiplier.
@@ -1377,7 +1608,7 @@ AtaPassThruBuildDevicePath ( if (Node == NULL) {
return EFI_NOT_FOUND;
}
-
+
if (Instance->Mode == EfiAtaIdeMode) {
DevicePathNode = AllocateCopyPool (sizeof (ATAPI_DEVICE_PATH), &mAtapiDevicePathTemplate);
if (DevicePathNode == NULL) {
@@ -1719,7 +1950,7 @@ ExtScsiPassThruPassThru ( can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
- channel.
+ channel.
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
@param Target On input, a pointer to the Target ID (an array of size
@@ -1840,7 +2071,7 @@ Exit: Instance->PreviousLun = *Lun;
return EFI_SUCCESS;
-}
+}
/**
Used to allocate and build a device path node for a SCSI device on a SCSI channel.
@@ -2031,8 +2262,8 @@ ExtScsiPassThruResetChannel ( )
{
return EFI_UNSUPPORTED;
-}
-
+}
+
/**
Resets a SCSI logical unit that is connected to a SCSI channel.
@@ -2061,7 +2292,7 @@ ExtScsiPassThruResetTargetLun ( )
{
return EFI_UNSUPPORTED;
-}
+}
/**
Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
@@ -2176,5 +2407,5 @@ Exit: Instance->PreviousTargetId = *Target16;
return EFI_SUCCESS;
-}
+}
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h index e1401867bb..0987478564 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h @@ -1,7 +1,7 @@ /** @file Header file for ATA/ATAPI PASS THRU driver. - Copyright (c) 2010, Intel Corporation. All rights reserved.<BR> + Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -47,6 +47,9 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gAtaAtapiPassThruComponentName2; #define ATA_ATAPI_PASS_THRU_SIGNATURE SIGNATURE_32 ('a', 'a', 'p', 't') #define ATA_ATAPI_DEVICE_SIGNATURE SIGNATURE_32 ('a', 'd', 'e', 'v') +#define ATA_NONBLOCKING_TASK_SIGNATURE SIGNATURE_32 ('a', 't', 's', 'k') + +typedef struct _ATA_NONBLOCK_TASK ATA_NONBLOCK_TASK; typedef enum { EfiAtaIdeMode, @@ -111,10 +114,34 @@ typedef struct { // UINT16 PreviousTargetId; UINT64 PreviousLun; - + + // + // For Non-blocking. + // + EFI_EVENT TimerEvent; + LIST_ENTRY NonBlockingTaskList; } ATA_ATAPI_PASS_THRU_INSTANCE; // +// Task for Non-blocking mode. +// +struct _ATA_NONBLOCK_TASK { + UINT32 Signature; + LIST_ENTRY Link; + + UINT16 Port; + UINT16 PortMultiplier; + EFI_ATA_PASS_THRU_COMMAND_PACKET *Packet; + BOOLEAN IsStart; + EFI_EVENT Event; + UINT64 RetryTimes; + VOID *Map; // Pointer to map. + VOID *TableMap;// Pointer to PRD table map. + EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map. + UINTN PageCount; // The page numbers used by PCIO freebuffer. +}; + +// // Timeout value which uses 100ns as a unit. // It means 3 second span. // @@ -142,6 +169,14 @@ typedef struct { Link, \ ATA_ATAPI_DEVICE_SIGNATURE \ ); + +#define ATA_NON_BLOCK_TASK_FROM_ENTRY(a) \ + CR (a, \ + ATA_NONBLOCK_TASK, \ + Link, \ + ATA_NONBLOCKING_TASK_SIGNATURE \ + ); + /** Retrieves a Unicode string that is the user readable name of the driver. @@ -454,6 +489,18 @@ DestroyDeviceInfoList ( ); /** + Destroy all pending non blocking tasks. + + @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance. + +**/ +VOID +EFIAPI +DestroyAsynTaskList ( + IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance + ); + +/** Enumerate all attached ATA devices at IDE mode or AHCI mode separately. The function is designed to enumerate all attached ATA devices. @@ -471,6 +518,21 @@ EnumerateAttachedDevice ( ); /** + Call back funtion when the timer event is signaled. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the + Event. + +**/ +VOID +EFIAPI +AsyncNonBlockingTransferRoutine ( + EFI_EVENT Event, + VOID* Context + ); + +/** Sends an ATA command to an ATA device that is attached to the ATA controller. This function supports both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking I/O functionality is optional. @@ -556,16 +618,16 @@ AtaPassThruGetNextPort ( The GetNextDevice() function retrieves the port multiplier port number of an ATA device present on a port of an ATA controller. - + If PortMultiplierPort points to a port multiplier port number value that was returned on a previous call to GetNextDevice(), then the port multiplier port number of the next ATA device on the port of the ATA controller is returned in PortMultiplierPort, and EFI_SUCCESS is returned. - + If PortMultiplierPort points to 0xFFFF, then the port multiplier port number of the first ATA device on port of the ATA controller is returned in PortMultiplierPort and EFI_SUCCESS is returned. - + If PortMultiplierPort is not 0xFFFF and the value pointed to by PortMultiplierPort was not returned on a previous call to GetNextDevice(), then EFI_INVALID_PARAMETER is returned. @@ -673,6 +735,7 @@ AtaPassThruBuildDevicePath ( @retval EFI_UNSUPPORTED This driver does not support the device path node type in DevicePath. @retval EFI_NOT_FOUND A valid translation from DevicePath to a port number and port multiplier port number does not exist. + **/ EFI_STATUS EFIAPI @@ -809,7 +872,7 @@ ExtScsiPassThruPassThru ( can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI - channel. + channel. @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. @param Target On input, a pointer to the Target ID (an array of size @@ -918,7 +981,7 @@ EFIAPI ExtScsiPassThruResetChannel ( IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This ); - + /** Resets a SCSI logical unit that is connected to a SCSI channel. @@ -1003,5 +1066,231 @@ AhciModeInitialization ( IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance ); +/** + Start a non data transfer on specific port. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS. + @param[in] Port The number of port. + @param[in] PortMultiplier The timeout value of stop. + @param[in] AtapiCommand The atapi command will be used for the + transfer. + @param[in] AtapiCommandLength The length of the atapi command. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in] Timeout The timeout value of non data transfer. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_SUCCESS The non data transfer executes successfully. + +**/ +EFI_STATUS +EFIAPI +AhciNonDataTransfer ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_AHCI_REGISTERS *AhciRegisters, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL, + IN UINT8 AtapiCommandLength, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + +/** + Start a DMA data transfer on specific port + + @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance. + @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS. + @param[in] Port The number of port. + @param[in] PortMultiplier The timeout value of stop. + @param[in] AtapiCommand The atapi command will be used for the + transfer. + @param[in] AtapiCommandLength The length of the atapi command. + @param[in] Read The transfer direction. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in, out] MemoryAddr The pointer to the data buffer. + @param[in] DataCount The data count to be transferred. + @param[in] Timeout The timeout value of non data transfer. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_SUCCESS The DMA data transfer executes successfully. + +**/ +EFI_STATUS +EFIAPI +AhciDmaTransfer ( + IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance, + IN EFI_AHCI_REGISTERS *AhciRegisters, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL, + IN UINT8 AtapiCommandLength, + IN BOOLEAN Read, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN OUT VOID *MemoryAddr, + IN UINTN DataCount, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + +/** + Start a PIO data transfer on specific port. + + @param[in] PciIo The PCI IO protocol instance. + @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS. + @param[in] Port The number of port. + @param[in] PortMultiplier The timeout value of stop. + @param[in] AtapiCommand The atapi command will be used for the + transfer. + @param[in] AtapiCommandLength The length of the atapi command. + @param[in] Read The transfer direction. + @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data. + @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data. + @param[in, out] MemoryAddr The pointer to the data buffer. + @param[in] DataCount The data count to be transferred. + @param[in] Timeout The timeout value of non data transfer. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs. + @retval EFI_TIMEOUT The operation is time out. + @retval EFI_UNSUPPORTED The device is not ready for transfer. + @retval EFI_SUCCESS The PIO data transfer executes successfully. + +**/ +EFI_STATUS +EFIAPI +AhciPioTransfer ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_AHCI_REGISTERS *AhciRegisters, + IN UINT8 Port, + IN UINT8 PortMultiplier, + IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL, + IN UINT8 AtapiCommandLength, + IN BOOLEAN Read, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN OUT VOID *MemoryAddr, + IN UINT32 DataCount, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + +/** + Send ATA command into device with NON_DATA protocol + + @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE + data structure. + @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. + @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data + structure. + @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. + @param[in] Timeout The time to complete the command. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_SUCCESS Reading succeed + @retval EFI_ABORTED Command failed + @retval EFI_DEVICE_ERROR Device status error. + +**/ +EFI_STATUS +EFIAPI +AtaNonDataCommandIn ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_IDE_REGISTERS *IdeRegisters, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + +/** + Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt). + + @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data + structure. + @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. + @param[in] Read Flag used to determine the data transfer + direction. Read equals 1, means data transferred + from device to host;Read equals 0, means data + transferred from host to device. + @param[in] DataBuffer A pointer to the source buffer for the data. + @param[in] DataLength The length of the data. + @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure. + @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. + @param[in] Timeout The time to complete the command. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_SUCCESS the operation is successful. + @retval EFI_OUT_OF_RESOURCES Build PRD table failed + @retval EFI_UNSUPPORTED Unknown channel or operations command + @retval EFI_DEVICE_ERROR Ata command execute failed + +**/ +EFI_STATUS +EFIAPI +AtaUdmaInOut ( + IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance, + IN EFI_IDE_REGISTERS *IdeRegisters, + IN BOOLEAN Read, + IN VOID *DataBuffer, + IN UINT64 DataLength, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + +/** + This function is used to send out ATA commands conforms to the PIO Data In Protocol. + + @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data + structure. + @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. + @param[in, out] Buffer A pointer to the source buffer for the data. + @param[in] ByteCount The length of the data. + @param[in] Read Flag used to determine the data transfer direction. + Read equals 1, means data transferred from device + to host;Read equals 0, means data transferred + from host to device. + @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure. + @param[in] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. + @param[in] Timeout The time to complete the command. + @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK + used by non-blocking mode. + + @retval EFI_SUCCESS send out the ATA command and device send required data successfully. + @retval EFI_DEVICE_ERROR command sent failed. + +**/ +EFI_STATUS +EFIAPI +AtaPioDataInOut ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_IDE_REGISTERS *IdeRegisters, + IN OUT VOID *Buffer, + IN UINT64 ByteCount, + IN BOOLEAN Read, + IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, + IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, + IN UINT64 Timeout, + IN ATA_NONBLOCK_TASK *Task + ); + #endif diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c index 50b95a6713..915e4bb296 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c @@ -1,7 +1,7 @@ /** @file
Header file for AHCI mode of ATA host controller.
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -1123,16 +1123,20 @@ AtaIssueCommand ( /**
This function is used to send out ATA commands conforms to the PIO Data In Protocol.
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param Buffer A pointer to the source buffer for the data.
- @param ByteCount The length of the data.
- @param Read Flag used to determine the data transfer direction.
- Read equals 1, means data transferred from device to host;
- Read equals 0, means data transferred from host to device.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
+ structure.
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
+ @param[in, out] Buffer A pointer to the source buffer for the data.
+ @param[in] ByteCount The length of the data.
+ @param[in] Read Flag used to determine the data transfer direction.
+ Read equals 1, means data transferred from device
+ to host;Read equals 0, means data transferred
+ from host to device.
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
+ @param[in] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
+ @param[in] Timeout The time to complete the command.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.
@retval EFI_DEVICE_ERROR command sent failed.
@@ -1148,7 +1152,8 @@ AtaPioDataInOut ( IN BOOLEAN Read,
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
)
{
UINTN WordCount;
@@ -1248,17 +1253,24 @@ Exit: //
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
+ //
+ // Not support the Non-blocking now,just do the blocking process.
+ //
return Status;
}
/**
Send ATA command into device with NON_DATA protocol
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE
+ data structure.
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data
+ structure.
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
+ @param[in] Timeout The time to complete the command.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_SUCCESS Reading succeed
@retval EFI_ABORTED Command failed
@@ -1272,7 +1284,8 @@ AtaNonDataCommandIn ( IN EFI_IDE_REGISTERS *IdeRegisters,
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
)
{
EFI_STATUS Status;
@@ -1310,24 +1323,123 @@ Exit: // Dump All Ide registers to ATA_STATUS_BLOCK
//
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
+
+ //
+ // Not support the Non-blocking now,just do the blocking process.
+ //
+ return Status;
+}
+
+/**
+ Wait for memory to be set.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] PortNum The IDE Port number.
+
+ @retval EFI_DEVICE_ERROR The memory is not set.
+ @retval EFI_TIMEOUT The memory setting is time out.
+ @retval EFI_SUCCESS The memory is correct set.
+
+**/
+EFI_STATUS
+AtaUdmStatusWait (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 PortNum
+ )
+{
+ UINT8 RegisterValue;
+ EFI_STATUS Status;
+ UINT64 Timeout;
+
+ Timeout = 2000;
+
+ while (TRUE) {
+ RegisterValue = IdeReadPortB (PciIo, PortNum);
+
+ if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Timeout));
+ break;
+ }
+ //
+ // Stall for 1 milliseconds.
+ //
+ MicroSecondDelay (1000);
+ Timeout--;
+ }
return Status;
}
+/**
+ Check if the memory to be set.
+
+ @param[in] PciIo The PCI IO protocol instance.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
+ @param[in] PortForBit The bit to be checked.
+
+ @retval EFI_DEVICE_ERROR The memory setting met a issue.
+ @retval EFI_NOT_READY The memory is not set.
+ @retval EFI_TIMEOUT The memory setting is time out.
+ @retval EFI_SUCCESS The memory is correct set.
+
+**/
+EFI_STATUS
+AtaUdmStatusCheck (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN ATA_NONBLOCK_TASK *Task,
+ IN UINT16 PortForBit
+ )
+{
+ UINT8 RegisterValue;
+
+ Task->RetryTimes--;
+ RegisterValue = IdeReadPortB(PciIo, PortForBit);
+
+ if ((RegisterValue & BMIS_ERROR) != 0) {
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {
+ DEBUG ((DEBUG_INFO, "Task->RetryTimes = %x\n", Task->RetryTimes));
+ return EFI_SUCCESS;
+ }
+
+ if (Task->RetryTimes == 0) {
+ return EFI_TIMEOUT;
+ } else {
+ //
+ // The memory is not set.
+ //
+ return EFI_NOT_READY;
+ }
+}
/**
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param Read Flag used to determine the data transfer direction.
- Read equals 1, means data transferred from device to host;
- Read equals 0, means data transferred from host to device.
- @param DataBuffer A pointer to the source buffer for the data.
- @param DataLength The length of the data.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
+ @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data
+ structure.
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
+ @param[in] Read Flag used to determine the data transfer
+ direction. Read equals 1, means data transferred
+ from device to host;Read equals 0, means data
+ transferred from host to device.
+ @param[in] DataBuffer A pointer to the source buffer for the data.
+ @param[in] DataLength The length of the data.
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
+ @param[in] Timeout The time to complete the command.
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
+ used by non-blocking mode.
@retval EFI_SUCCESS the operation is successful.
@retval EFI_OUT_OF_RESOURCES Build PRD table failed
@@ -1338,14 +1450,15 @@ Exit: EFI_STATUS
EFIAPI
AtaUdmaInOut (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN BOOLEAN Read,
- IN VOID *DataBuffer,
- IN UINT64 DataLength,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
+ IN EFI_IDE_REGISTERS *IdeRegisters,
+ IN BOOLEAN Read,
+ IN VOID *DataBuffer,
+ IN UINT64 DataLength,
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
+ IN UINT64 Timeout,
+ IN ATA_NONBLOCK_TASK *Task
)
{
EFI_STATUS Status;
@@ -1353,18 +1466,16 @@ AtaUdmaInOut ( UINT16 IoPortForBmis;
UINT16 IoPortForBmid;
- UINT8 RegisterValue;
-
- EFI_ATA_DMA_PRD *PrdBaseAddr;
- UINTN PrdTableNum;
UINTN PrdTableSize;
EFI_PHYSICAL_ADDRESS PrdTableMapAddr;
VOID *PrdTableMap;
+ EFI_ATA_DMA_PRD *PrdBaseAddr;
+ UINTN PrdTableNum;
+ UINT8 RegisterValue;
UINTN PageCount;
UINTN ByteCount;
UINTN ByteRemaining;
-
UINT8 DeviceControl;
VOID *BufferMap;
@@ -1373,15 +1484,37 @@ AtaUdmaInOut ( UINT8 DeviceHead;
UINT8 AtaCommand;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_TPL OldTpl;
- Status = EFI_SUCCESS;
- PrdBaseAddr = NULL;
+
+ Status = EFI_SUCCESS;
+ PrdBaseAddr = NULL;
+ PrdTableMap = NULL;
+ BufferMap = NULL;
+ PageCount = 0;
+ PciIo = Instance->PciIo;
if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking
+ // BlockIO tasks.
+ // Delay 1ms to simulate the blocking time out checking.
+ //
+ while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ AsyncNonBlockingTransferRoutine (NULL, Instance);
+ gBS->RestoreTPL (OldTpl);
+ //
+ // Stall for 1 milliseconds.
+ //
+ MicroSecondDelay (1000);
+ }
+
+ //
// The data buffer should be even alignment
//
if (((UINTN)DataBuffer & 0x1) != 0) {
@@ -1389,234 +1522,260 @@ AtaUdmaInOut ( }
//
- // Calculate the number of PRD entry.
- // Every entry in PRD table can specify a 64K memory region.
+ // Set relevant IO Port address.
//
- PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);
+ IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);
+ IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);
+ IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);
//
- // Make sure that the memory region of PRD table is not cross 64K boundary
- //
- PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);
- if (PrdTableSize > 0x10000) {
- return EFI_INVALID_PARAMETER;
- }
+ // For Blocking mode, start the command.
+ // For non-blocking mode, when the command is not started, start it, otherwise
+ // go to check the status.
+ //
+ if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {
+ //
+ // Calculate the number of PRD entry.
+ // Every entry in PRD table can specify a 64K memory region.
+ //
+ PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);
- //
- // Allocate buffer for PRD table initialization.
- //
- PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);
- Status = PciIo->AllocateBuffer (
- PciIo,
- AllocateAnyPages,
- EfiBootServicesData,
- PageCount,
- (VOID **)&PrdBaseAddr,
- 0
- );
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
+ //
+ // Make sure that the memory region of PRD table is not cross 64K boundary
+ //
+ PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);
+ if (PrdTableSize > 0x10000) {
+ return EFI_INVALID_PARAMETER;
+ }
- ByteCount = EFI_PAGES_TO_SIZE (PageCount);
- Status = PciIo->Map (
- PciIo,
- EfiPciIoOperationBusMasterCommonBuffer,
- PrdBaseAddr,
- &ByteCount,
- &PrdTableMapAddr,
- &PrdTableMap
- );
- if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {
- //
- // If the data length actually mapped is not equal to the requested amount,
- // it means the DMA operation may be broken into several discontinuous smaller chunks.
- // Can't handle this case.
- //
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
- return EFI_OUT_OF_RESOURCES;
- }
+ //
+ // Allocate buffer for PRD table initialization.
+ //
+ PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);
+ Status = PciIo->AllocateBuffer (
+ PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ PageCount,
+ (VOID **)&PrdBaseAddr,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);
+ ByteCount = EFI_PAGES_TO_SIZE (PageCount);
+ Status = PciIo->Map (
+ PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ PrdBaseAddr,
+ &ByteCount,
+ &PrdTableMapAddr,
+ &PrdTableMap
+ );
+ if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {
+ //
+ // If the data length actually mapped is not equal to the requested amount,
+ // it means the DMA operation may be broken into several discontinuous smaller chunks.
+ // Can't handle this case.
+ //
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
+ return EFI_OUT_OF_RESOURCES;
+ }
- //
- // Map the host address of DataBuffer to DMA master address.
- //
- if (Read) {
- PciIoOperation = EfiPciIoOperationBusMasterWrite;
- } else {
- PciIoOperation = EfiPciIoOperationBusMasterRead;
- }
+ ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);
- ByteCount = (UINTN)DataLength;
- Status = PciIo->Map (
- PciIo,
- PciIoOperation,
- DataBuffer,
- &ByteCount,
- &BufferMapAddress,
- &BufferMap
- );
- if (EFI_ERROR (Status) || (ByteCount != DataLength)) {
- PciIo->Unmap (PciIo, PrdTableMap);
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
- return EFI_OUT_OF_RESOURCES;
- }
+ //
+ // Map the host address of DataBuffer to DMA master address.
+ //
+ if (Read) {
+ PciIoOperation = EfiPciIoOperationBusMasterWrite;
+ } else {
+ PciIoOperation = EfiPciIoOperationBusMasterRead;
+ }
- //
- // According to Ata spec, it requires the buffer address and size to be even.
- //
- ASSERT ((BufferMapAddress & 0x1) == 0);
- ASSERT ((ByteCount & 0x1) == 0);
+ ByteCount = (UINTN)DataLength;
+ Status = PciIo->Map (
+ PciIo,
+ PciIoOperation,
+ DataBuffer,
+ &ByteCount,
+ &BufferMapAddress,
+ &BufferMap
+ );
+ if (EFI_ERROR (Status) || (ByteCount != DataLength)) {
+ PciIo->Unmap (PciIo, PrdTableMap);
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // According to Ata spec, it requires the buffer address and size to be even.
+ //
+ ASSERT ((BufferMapAddress & 0x1) == 0);
+ ASSERT ((ByteCount & 0x1) == 0);
+
+ //
+ // Fill the PRD table with appropriate bus master address of data buffer and data length.
+ //
+ ByteRemaining = ByteCount;
+ while (ByteRemaining != 0) {
+ if (ByteRemaining <= 0x10000) {
+ PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);
+ PrdBaseAddr->ByteCount = (UINT16) ByteRemaining;
+ PrdBaseAddr->EndOfTable = 0x8000;
+ break;
+ }
- //
- // Fill the PRD table with appropriate bus master address of data buffer and data length.
- //
- ByteRemaining = ByteCount;
- while (ByteRemaining != 0) {
- if (ByteRemaining <= 0x10000) {
PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);
- PrdBaseAddr->ByteCount = (UINT16) ByteRemaining;
- PrdBaseAddr->EndOfTable = 0x8000;
- break;
- }
+ PrdBaseAddr->ByteCount = (UINT16) 0x0;
- PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);
- PrdBaseAddr->ByteCount = (UINT16) 0x0;
+ ByteRemaining -= 0x10000;
+ BufferMapAddress += 0x10000;
+ PrdBaseAddr++;
+ }
- ByteRemaining -= 0x10000;
- BufferMapAddress += 0x10000;
- PrdBaseAddr++;
- }
+ //
+ // Start to enable the DMA operation
+ //
+ DeviceHead = AtaCommandBlock->AtaDeviceHead;
+ AtaCommand = AtaCommandBlock->AtaCommand;
- //
- // Start to enable the DMA operation
- //
- DeviceHead = AtaCommandBlock->AtaDeviceHead;
- AtaCommand = AtaCommandBlock->AtaCommand;
+ IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));
- IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));
+ //
+ // Enable interrupt to support UDMA
+ //
+ DeviceControl = 0;
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);
- //
- // Enable interrupt to support UDMA
- //
- DeviceControl = 0;
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+ IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);
- IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);
- IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);
- IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);
+ //
+ // Set the base address to BMID register
+ //
+ IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);
- //
- // Read BMIS register and clear ERROR and INTR bit
- //
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
+ if (Read) {
+ RegisterValue |= BMIC_NREAD;
+ } else {
+ RegisterValue &= ~((UINT8) BMIC_NREAD);
+ }
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);
- //
- // Set the base address to BMID register
- //
- IdeWritePortDW(PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);
+ //
+ // Issue ATA command
+ //
+ Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);
- //
- // Set BMIC register to identify the operation direction
- //
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
- if (Read) {
- RegisterValue |= BMIC_NREAD;
- } else {
- RegisterValue &= ~((UINT8) BMIC_NREAD);
- }
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
- //
- // Issue ATA command
- //
- Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);
+ //
+ // Set START bit of BMIC register
+ //
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
+ RegisterValue |= BMIC_START;
+ IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
- if (EFI_ERROR (Status)) {
- Status = EFI_DEVICE_ERROR;
- goto Exit;
+ if (Task != NULL) {
+ //
+ // Max transfer number of sectors for one command is 65536(32Mbyte),
+ // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
+ // So set the variable Count to 2000, for about 2 second Timeout time.
+ //
+ Task->RetryTimes = 2000;
+ Task->Map = BufferMap;
+ Task->TableMap = PrdTableMap;
+ Task->MapBaseAddress = PrdBaseAddr;
+ Task->PageCount = PageCount;
+ Task->IsStart = TRUE;
+ }
}
//
- // Set START bit of BMIC register
- //
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
- RegisterValue |= BMIC_START;
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
-
- //
// Check the INTERRUPT and ERROR bit of BMIS
// Max transfer number of sectors for one command is 65536(32Mbyte),
// it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).
// So set the variable Count to 2000, for about 2 second Timeout time.
//
- Timeout = 2000;
- while (TRUE) {
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
-
- if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {
- DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));
- Status = EFI_DEVICE_ERROR;
- break;
- }
-
- if ((RegisterValue & BMIS_INTERRUPT) != 0) {
- Status = EFI_SUCCESS;
- break;
- }
- //
- // Stall for 1 milliseconds.
- //
- MicroSecondDelay (1000);
- Timeout--;
+ if (Task != NULL) {
+ Status = AtaUdmStatusCheck (PciIo, Task, IoPortForBmis);
+ } else {
+ Status = AtaUdmStatusWait (PciIo, IoPortForBmis);
}
//
- // Read BMIS register and clear ERROR and INTR bit
+ // For blocking mode, clear registers and free buffers.
+ // For non blocking mode, when the related registers have been set or time
+ // out, or a error has been happened, it needs to clear the register and free
+ // buffer.
//
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);
+ if ((Task == NULL) || Status != EFI_NOT_READY) {
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+ IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);
- //
- // Read Status Register of IDE device to clear interrupt
- //
- RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);
+ //
+ // Read Status Register of IDE device to clear interrupt
+ //
+ RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);
- //
- // Clear START bit of BMIC register
- //
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
- RegisterValue &= ~((UINT8) BMIC_START);
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);
+ //
+ // Clear START bit of BMIC register
+ //
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);
+ RegisterValue &= ~((UINT8) BMIC_START);
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);
- //
- // Disable interrupt of Select device
- //
- DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);
- DeviceControl |= ATA_CTLREG_IEN_L;
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);
- //
- // Stall for 10 milliseconds.
- //
- MicroSecondDelay (10000);
+ //
+ // Disable interrupt of Select device
+ //
+ DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);
+ DeviceControl |= ATA_CTLREG_IEN_L;
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);
+ //
+ // Stall for 10 milliseconds.
+ //
+ MicroSecondDelay (10000);
+
+ }
Exit:
//
// Free all allocated resource
//
- PciIo->Unmap (PciIo, PrdTableMap);
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
- PciIo->Unmap (PciIo, BufferMap);
-
- //
- // Dump All Ide registers to ATA_STATUS_BLOCK
- //
- DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
+ if ((Task == NULL) || Status != EFI_NOT_READY) {
+ if (Task != NULL) {
+ PciIo->Unmap (PciIo, Task->TableMap);
+ PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);
+ PciIo->Unmap (PciIo, Task->Map);
+ } else {
+ PciIo->Unmap (PciIo, PrdTableMap);
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);
+ PciIo->Unmap (PciIo, BufferMap);
+ }
+ //
+ // Dump All Ide registers to ATA_STATUS_BLOCK
+ //
+ DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);
+ }
+
return Status;
}
@@ -2021,7 +2180,8 @@ SetDeviceTransferMode ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -2069,7 +2229,8 @@ SetDriveParameters ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
//
@@ -2084,7 +2245,8 @@ SetDriveParameters ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -2132,7 +2294,8 @@ IdeAtaSmartReturnStatusCheck ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
if (EFI_ERROR (Status)) {
@@ -2212,7 +2375,8 @@ IdeAtaSmartSupport ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
if (!EFI_ERROR (Status)) {
@@ -2233,7 +2397,8 @@ IdeAtaSmartSupport ( &Instance->IdeRegisters[Channel],
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
if (!EFI_ERROR (Status)) {
Status = IdeAtaSmartReturnStatusCheck (
@@ -2254,6 +2419,7 @@ IdeAtaSmartSupport ( return ;
}
+
/**
Sends out an ATA Identify Command to the specified device.
@@ -2274,6 +2440,7 @@ IdeAtaSmartSupport ( @retval EFI_SUCCESS Identify ATA device successfully.
@retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.
+
**/
EFI_STATUS
EFIAPI
@@ -2286,10 +2453,10 @@ AtaIdentify ( )
{
EFI_STATUS Status;
- EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
+ EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
-
+
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);
@@ -2301,7 +2468,8 @@ AtaIdentify ( TRUE,
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -2368,7 +2536,8 @@ AtaIdentifyPacket ( TRUE,
&AtaCommandBlock,
AtaStatusBlock,
- ATA_ATAPI_TIMEOUT
+ ATA_ATAPI_TIMEOUT,
+ NULL
);
return Status;
@@ -2425,7 +2594,7 @@ DetectAndConfigIdeDevice ( IdeInit = Instance->IdeControllerInit;
PciIo = Instance->PciIo;
- for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {
+ for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {
//
// Send ATA Device Execut Diagnostic command.
// This command should work no matter DRDY is ready or not
@@ -2483,7 +2652,7 @@ DetectAndConfigIdeDevice ( if (EFI_ERROR (Status)) {
DeviceType = EfiIdeHarddisk;
Status = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);
- }
+ }
}
if (EFI_ERROR (Status)) {
@@ -2491,12 +2660,11 @@ DetectAndConfigIdeDevice ( // No device is found at this port
//
continue;
- }
-
+ }
+
DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n",
(IdeChannel == 1) ? "secondary" : "primary ", (IdeDevice == 1) ? "slave " : "master",
DeviceType == EfiIdeCdrom ? "cdrom " : "harddisk"));
-
//
// If the device is a hard disk, then try to enable S.M.A.R.T feature
//
@@ -2548,7 +2716,7 @@ DetectAndConfigIdeDevice ( continue;
}
}
-
+
//
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
// be set together. Only one DMA mode can be set to a device. If setting
@@ -2559,7 +2727,7 @@ DetectAndConfigIdeDevice ( TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);
-
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
continue;
@@ -2568,13 +2736,13 @@ DetectAndConfigIdeDevice ( TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);
-
+
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
continue;
}
}
-
+
//
// Set Parameters for the device:
// 1) Init
@@ -2587,10 +2755,10 @@ DetectAndConfigIdeDevice ( DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->sectors_per_track;
DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->heads - 1);
DriveParameters.MultipleSector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->multi_sector_cmd_max_sct_cnt;
-
+
Status = SetDriveParameters (Instance, IdeChannel, IdeDevice, &DriveParameters, NULL);
}
-
+
//
// Set IDE controller Timing Blocks in the PCI Configuration Space
//
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h index b9c58c6341..67fff64658 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.h @@ -1,7 +1,7 @@ /** @file
Header file for IDE mode of ATA host controller.
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -200,94 +200,5 @@ AtaPacketCommandExecute ( IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
);
-/**
- Send ATA command into device with NON_DATA protocol
-
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
-
- @retval EFI_SUCCESS Reading succeed
- @retval EFI_ABORTED Command failed
- @retval EFI_DEVICE_ERROR Device status error.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaNonDataCommandIn (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
- );
-
-/**
- Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).
-
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param Read Flag used to determine the data transfer direction.
- Read equals 1, means data transferred from device to host;
- Read equals 0, means data transferred from host to device.
- @param DataBuffer A pointer to the source buffer for the data.
- @param DataLength The length of the data.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
-
- @retval EFI_SUCCESS the operation is successful.
- @retval EFI_OUT_OF_RESOURCES Build PRD table failed
- @retval EFI_UNSUPPORTED Unknown channel or operations command
- @retval EFI_DEVICE_ERROR Ata command execute failed
-
-**/
-EFI_STATUS
-EFIAPI
-AtaUdmaInOut (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN BOOLEAN Read,
- IN VOID *DataBuffer,
- IN UINT64 DataLength,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
- );
-
-/**
- This function is used to send out ATA commands conforms to the PIO Data In Protocol.
-
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
- @param Buffer A pointer to the source buffer for the data.
- @param ByteCount The length of the data.
- @param Read Flag used to determine the data transfer direction.
- Read equals 1, means data transferred from device to host;
- Read equals 0, means data transferred from host to device.
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
- @param Timeout The time to complete the command.
-
- @retval EFI_SUCCESS send out the ATA command and device send required data successfully.
- @retval EFI_DEVICE_ERROR command sent failed.
-
-**/
-EFI_STATUS
-EFIAPI
-AtaPioDataInOut (
- IN EFI_PCI_IO_PROTOCOL *PciIo,
- IN EFI_IDE_REGISTERS *IdeRegisters,
- IN OUT VOID *Buffer,
- IN UINT64 ByteCount,
- IN BOOLEAN Read,
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
- IN UINT64 Timeout
- );
-
-
#endif
|