MdeModulePkg/AtaAtapiPassThru: Handle timeout 0 as indefinitely wait to strictly comply with UEFI spec

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tian, Feng <feng.tian@intel.com>
Reviewed-by: Li, Elvin <elvin.li@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15534 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Tian, Feng 2014-05-15 07:09:14 +00:00 committed by erictian
parent 129ff94661
commit ab82122dfe
4 changed files with 151 additions and 68 deletions

View File

@ -156,9 +156,16 @@ AhciWaitMmioSet (
) )
{ {
UINT32 Value; UINT32 Value;
UINT32 Delay; UINT64 Delay;
BOOLEAN InfiniteWait;
Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32 (Timeout, 1000) + 1;
do { do {
// //
@ -177,7 +184,7 @@ AhciWaitMmioSet (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -204,9 +211,16 @@ AhciWaitMemSet (
) )
{ {
UINT32 Value; UINT32 Value;
UINT32 Delay; UINT64 Delay;
BOOLEAN InfiniteWait;
Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32 (Timeout, 1000) + 1;
do { do {
// //
@ -231,7 +245,7 @@ AhciWaitMemSet (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -242,7 +256,8 @@ AhciWaitMemSet (
@param[in] Address The memory address to test. @param[in] Address The memory address to test.
@param[in] MaskValue The mask value of memory. @param[in] MaskValue The mask value of memory.
@param[in] TestValue The test value of memory. @param[in] TestValue The test value of memory.
@param[in, out] RetryTimes The retry times value for waitting memory set. If 0, then just try once. @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
non-blocking mode. If NULL, then just try once.
@retval EFI_NOTREADY The memory is not set. @retval EFI_NOTREADY The memory is not set.
@retval EFI_TIMEOUT The memory setting retry times out. @retval EFI_TIMEOUT The memory setting retry times out.
@ -255,13 +270,13 @@ AhciCheckMemSet (
IN UINTN Address, IN UINTN Address,
IN UINT32 MaskValue, IN UINT32 MaskValue,
IN UINT32 TestValue, IN UINT32 TestValue,
IN OUT UINTN *RetryTimes OPTIONAL IN OUT ATA_NONBLOCK_TASK *Task
) )
{ {
UINT32 Value; UINT32 Value;
if (RetryTimes != NULL) { if (Task != NULL) {
(*RetryTimes)--; Task->RetryTimes--;
} }
Value = *(volatile UINT32 *) Address; Value = *(volatile UINT32 *) Address;
@ -271,7 +286,7 @@ AhciCheckMemSet (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
if ((RetryTimes != NULL) && (*RetryTimes == 0)) { if ((Task != NULL) && !Task->InfiniteWait && (Task->RetryTimes == 0)) {
return EFI_TIMEOUT; return EFI_TIMEOUT;
} else { } else {
return EFI_NOT_READY; return EFI_NOT_READY;
@ -683,11 +698,18 @@ AhciPioTransfer (
VOID *Map; VOID *Map;
UINTN MapLength; UINTN MapLength;
EFI_PCI_IO_PROTOCOL_OPERATION Flag; EFI_PCI_IO_PROTOCOL_OPERATION Flag;
UINT32 Delay; UINT64 Delay;
EFI_AHCI_COMMAND_FIS CFis; EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList; EFI_AHCI_COMMAND_LIST CmdList;
UINT32 PortTfd; UINT32 PortTfd;
UINT32 PrdCount; UINT32 PrdCount;
BOOLEAN InfiniteWait;
if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
if (Read) { if (Read) {
Flag = EfiPciIoOperationBusMasterWrite; Flag = EfiPciIoOperationBusMasterWrite;
@ -756,11 +778,11 @@ AhciPioTransfer (
// Wait device sends the PIO setup fis before data transfer // Wait device sends the PIO setup fis before data transfer
// //
Status = EFI_TIMEOUT; Status = EFI_TIMEOUT;
Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); Delay = DivU64x32 (Timeout, 1000) + 1;
do { do {
Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET; Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0); Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
PortTfd = AhciReadReg (PciIo, (UINT32) Offset); PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
@ -780,7 +802,7 @@ AhciPioTransfer (
} }
Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0); Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
break; break;
@ -792,7 +814,7 @@ AhciPioTransfer (
MicroSecondDelay(100); MicroSecondDelay(100);
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
} else { } else {
// //
// Wait for D2H Fis is received // Wait for D2H Fis is received
@ -924,7 +946,6 @@ AhciDmaTransfer (
// //
if (Task != NULL) { if (Task != NULL) {
Task->IsStart = TRUE; Task->IsStart = TRUE;
Task->RetryTimes = (UINT32) (DivU64x32(Timeout, 1000) + 1);
} }
if (Read) { if (Read) {
Flag = EfiPciIoOperationBusMasterWrite; Flag = EfiPciIoOperationBusMasterWrite;
@ -1000,7 +1021,7 @@ AhciDmaTransfer (
Offset, Offset,
EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_TYPE_MASK,
EFI_AHCI_FIS_REGISTER_D2H, EFI_AHCI_FIS_REGISTER_D2H,
(UINTN *) (&Task->RetryTimes) Task
); );
} else { } else {
Status = AhciWaitMemSet ( Status = AhciWaitMemSet (
@ -1402,14 +1423,14 @@ AhciReset (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT32 Value; UINT32 Value;
AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE); AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET); AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET); Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);

View File

@ -1339,7 +1339,12 @@ AtaPassThruPassThru (
Task->Packet = Packet; Task->Packet = Packet;
Task->Event = Event; Task->Event = Event;
Task->IsStart = FALSE; Task->IsStart = FALSE;
Task->RetryTimes = 0; Task->RetryTimes = DivU64x32(Packet->Timeout, 1000) + 1;
if (Packet->Timeout == 0) {
Task->InfiniteWait = TRUE;
} else {
Task->InfiniteWait = FALSE;
}
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
InsertTailList (&Instance->NonBlockingTaskList, &Task->Link); InsertTailList (&Instance->NonBlockingTaskList, &Task->Link);

View File

@ -135,10 +135,11 @@ struct _ATA_NONBLOCK_TASK {
BOOLEAN IsStart; BOOLEAN IsStart;
EFI_EVENT Event; EFI_EVENT Event;
UINT64 RetryTimes; UINT64 RetryTimes;
VOID *Map; // Pointer to map. BOOLEAN InfiniteWait;
VOID *TableMap;// Pointer to PRD table map. VOID *Map; // Pointer to map.
VOID *TableMap; // Pointer to PRD table map.
EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map. EFI_ATA_DMA_PRD *MapBaseAddress; // Pointer to range Base address for Map.
UINTN PageCount; // The page numbers used by PCIO freebuffer. UINTN PageCount; // The page numbers used by PCIO freebuffer.
}; };
// //

View File

@ -353,13 +353,20 @@ DRQClear (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 StatusRegister; UINT8 StatusRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);
@ -381,7 +388,7 @@ DRQClear (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -409,13 +416,20 @@ DRQClear2 (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 AltRegister; UINT8 AltRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);
@ -437,7 +451,7 @@ DRQClear2 (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -468,14 +482,21 @@ DRQReady (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 StatusRegister; UINT8 StatusRegister;
UINT8 ErrorRegister; UINT8 ErrorRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
// //
// Read Status Register will clear interrupt // Read Status Register will clear interrupt
@ -508,7 +529,7 @@ DRQReady (
MicroSecondDelay (100); MicroSecondDelay (100);
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -535,14 +556,21 @@ DRQReady2 (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 AltRegister; UINT8 AltRegister;
UINT8 ErrorRegister; UINT8 ErrorRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
// //
@ -575,7 +603,7 @@ DRQReady2 (
MicroSecondDelay (100); MicroSecondDelay (100);
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -602,14 +630,21 @@ DRDYReady (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 StatusRegister; UINT8 StatusRegister;
UINT8 ErrorRegister; UINT8 ErrorRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);
// //
@ -638,7 +673,7 @@ DRDYReady (
MicroSecondDelay (100); MicroSecondDelay (100);
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -666,14 +701,21 @@ DRDYReady2 (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 AltRegister; UINT8 AltRegister;
UINT8 ErrorRegister; UINT8 ErrorRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);
// //
@ -702,7 +744,7 @@ DRDYReady2 (
MicroSecondDelay (100); MicroSecondDelay (100);
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -728,13 +770,20 @@ WaitForBSYClear (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 StatusRegister; UINT8 StatusRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);
@ -749,7 +798,7 @@ WaitForBSYClear (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -775,13 +824,20 @@ WaitForBSYClear2 (
IN UINT64 Timeout IN UINT64 Timeout
) )
{ {
UINT32 Delay; UINT64 Delay;
UINT8 AltStatusRegister; UINT8 AltStatusRegister;
BOOLEAN InfiniteWait;
ASSERT (PciIo != NULL); ASSERT (PciIo != NULL);
ASSERT (IdeRegisters != NULL); ASSERT (IdeRegisters != NULL);
Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
Delay = DivU64x32(Timeout, 1000) + 1;
do { do {
AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);
@ -796,7 +852,7 @@ WaitForBSYClear2 (
Delay--; Delay--;
} while (Delay > 0); } while (InfiniteWait || (Delay > 0));
return EFI_TIMEOUT; return EFI_TIMEOUT;
} }
@ -1312,6 +1368,7 @@ Exit:
@param[in] PciIo The PCI IO protocol instance. @param[in] PciIo The PCI IO protocol instance.
@param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.
@param[in] Timeout The time to complete the command, uses 100ns as a unit.
@retval EFI_DEVICE_ERROR The memory is not set. @retval EFI_DEVICE_ERROR The memory is not set.
@retval EFI_TIMEOUT The memory setting is time out. @retval EFI_TIMEOUT The memory setting is time out.
@ -1320,18 +1377,26 @@ Exit:
**/ **/
EFI_STATUS EFI_STATUS
AtaUdmStatusWait ( AtaUdmStatusWait (
IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PCI_IO_PROTOCOL *PciIo,
IN EFI_IDE_REGISTERS *IdeRegisters IN EFI_IDE_REGISTERS *IdeRegisters,
IN UINT64 Timeout
) )
{ {
UINT8 RegisterValue; UINT8 RegisterValue;
EFI_STATUS Status; EFI_STATUS Status;
UINT16 IoPortForBmis; UINT16 IoPortForBmis;
UINT64 Timeout; UINT64 Delay;
BOOLEAN InfiniteWait;
Timeout = 2000; if (Timeout == 0) {
InfiniteWait = TRUE;
} else {
InfiniteWait = FALSE;
}
while (TRUE) { Delay = DivU64x32 (Timeout, 1000) + 1;
do {
Status = CheckStatusRegister (PciIo, IdeRegisters); Status = CheckStatusRegister (PciIo, IdeRegisters);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
@ -1351,11 +1416,11 @@ AtaUdmStatusWait (
break; break;
} }
// //
// Stall for 1 milliseconds. // Stall for 100 microseconds.
// //
MicroSecondDelay (1000); MicroSecondDelay (100);
Timeout--; Delay--;
} } while (InfiniteWait || (Delay > 0));
return Status; return Status;
} }
@ -1404,7 +1469,7 @@ AtaUdmStatusCheck (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
if (Task->RetryTimes == 0) { if (!Task->InfiniteWait && (Task->RetryTimes == 0)) {
return EFI_TIMEOUT; return EFI_TIMEOUT;
} else { } else {
// //
@ -1664,12 +1729,6 @@ AtaUdmaInOut (
IdeWritePortB (PciIo, IoPortForBmic, RegisterValue); IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);
if (Task != NULL) { 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->Map = BufferMap;
Task->TableMap = PrdTableMap; Task->TableMap = PrdTableMap;
Task->MapBaseAddress = PrdBaseAddr; Task->MapBaseAddress = PrdBaseAddr;
@ -1703,14 +1762,11 @@ AtaUdmaInOut (
// //
// Check the INTERRUPT and ERROR bit of BMIS // 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.
// //
if (Task != NULL) { if (Task != NULL) {
Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters); Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters);
} else { } else {
Status = AtaUdmStatusWait (PciIo, IdeRegisters); Status = AtaUdmStatusWait (PciIo, IdeRegisters, Timeout);
} }
// //