From ab82122dfebb90751b478b7c3cab9ed42051dbf4 Mon Sep 17 00:00:00 2001 From: "Tian, Feng" Date: Thu, 15 May 2014 07:09:14 +0000 Subject: [PATCH] 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 Reviewed-by: Li, Elvin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15534 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Bus/Ata/AtaAtapiPassThru/AhciMode.c | 61 +++++--- .../Ata/AtaAtapiPassThru/AtaAtapiPassThru.c | 7 +- .../Ata/AtaAtapiPassThru/AtaAtapiPassThru.h | 7 +- .../Bus/Ata/AtaAtapiPassThru/IdeMode.c | 144 ++++++++++++------ 4 files changed, 151 insertions(+), 68 deletions(-) diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c index 950b5da038..df22d517fd 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c @@ -156,9 +156,16 @@ AhciWaitMmioSet ( ) { 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 { // @@ -177,7 +184,7 @@ AhciWaitMmioSet ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -204,9 +211,16 @@ AhciWaitMemSet ( ) { UINT32 Value; - UINT32 Delay; + UINT64 Delay; + BOOLEAN InfiniteWait; + + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } - Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); + Delay = DivU64x32 (Timeout, 1000) + 1; do { // @@ -231,7 +245,7 @@ AhciWaitMemSet ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -242,7 +256,8 @@ AhciWaitMemSet ( @param[in] Address 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. 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_TIMEOUT The memory setting retry times out. @@ -255,13 +270,13 @@ AhciCheckMemSet ( IN UINTN Address, IN UINT32 MaskValue, IN UINT32 TestValue, - IN OUT UINTN *RetryTimes OPTIONAL + IN OUT ATA_NONBLOCK_TASK *Task ) { UINT32 Value; - if (RetryTimes != NULL) { - (*RetryTimes)--; + if (Task != NULL) { + Task->RetryTimes--; } Value = *(volatile UINT32 *) Address; @@ -271,7 +286,7 @@ AhciCheckMemSet ( return EFI_SUCCESS; } - if ((RetryTimes != NULL) && (*RetryTimes == 0)) { + if ((Task != NULL) && !Task->InfiniteWait && (Task->RetryTimes == 0)) { return EFI_TIMEOUT; } else { return EFI_NOT_READY; @@ -683,11 +698,18 @@ AhciPioTransfer ( VOID *Map; UINTN MapLength; EFI_PCI_IO_PROTOCOL_OPERATION Flag; - UINT32 Delay; + UINT64 Delay; EFI_AHCI_COMMAND_FIS CFis; EFI_AHCI_COMMAND_LIST CmdList; UINT32 PortTfd; UINT32 PrdCount; + BOOLEAN InfiniteWait; + + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } if (Read) { Flag = EfiPciIoOperationBusMasterWrite; @@ -756,11 +778,11 @@ AhciPioTransfer ( // Wait device sends the PIO setup fis before data transfer // Status = EFI_TIMEOUT; - Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); + Delay = DivU64x32 (Timeout, 1000) + 1; do { 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)) { Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; PortTfd = AhciReadReg (PciIo, (UINT32) Offset); @@ -780,7 +802,7 @@ AhciPioTransfer ( } 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)) { Status = EFI_DEVICE_ERROR; break; @@ -792,7 +814,7 @@ AhciPioTransfer ( MicroSecondDelay(100); Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); } else { // // Wait for D2H Fis is received @@ -924,7 +946,6 @@ AhciDmaTransfer ( // if (Task != NULL) { Task->IsStart = TRUE; - Task->RetryTimes = (UINT32) (DivU64x32(Timeout, 1000) + 1); } if (Read) { Flag = EfiPciIoOperationBusMasterWrite; @@ -1000,7 +1021,7 @@ AhciDmaTransfer ( Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, - (UINTN *) (&Task->RetryTimes) + Task ); } else { Status = AhciWaitMemSet ( @@ -1402,14 +1423,14 @@ AhciReset ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT32 Value; AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE); AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + Delay = DivU64x32(Timeout, 1000) + 1; do { Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET); diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c index a3b9ccd484..12a40d413e 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c @@ -1339,7 +1339,12 @@ AtaPassThruPassThru ( Task->Packet = Packet; Task->Event = Event; 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); InsertTailList (&Instance->NonBlockingTaskList, &Task->Link); diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h index 0d93e54467..6f3407c01a 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h @@ -135,10 +135,11 @@ struct _ATA_NONBLOCK_TASK { BOOLEAN IsStart; EFI_EVENT Event; UINT64 RetryTimes; - VOID *Map; // Pointer to map. - VOID *TableMap;// Pointer to PRD table map. + BOOLEAN InfiniteWait; + 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. + UINTN PageCount; // The page numbers used by PCIO freebuffer. }; // diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c index 5f362d1e15..e5beea65a2 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c @@ -353,13 +353,20 @@ DRQClear ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 StatusRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); @@ -381,7 +388,7 @@ DRQClear ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -409,13 +416,20 @@ DRQClear2 ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 AltRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); @@ -437,7 +451,7 @@ DRQClear2 ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -468,14 +482,21 @@ DRQReady ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 StatusRegister; UINT8 ErrorRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { // // Read Status Register will clear interrupt @@ -508,7 +529,7 @@ DRQReady ( MicroSecondDelay (100); Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -535,14 +556,21 @@ DRQReady2 ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 AltRegister; UINT8 ErrorRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { // @@ -575,7 +603,7 @@ DRQReady2 ( MicroSecondDelay (100); Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -602,14 +630,21 @@ DRDYReady ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 StatusRegister; UINT8 ErrorRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); // @@ -638,7 +673,7 @@ DRDYReady ( MicroSecondDelay (100); Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -666,14 +701,21 @@ DRDYReady2 ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 AltRegister; UINT8 ErrorRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); // @@ -702,7 +744,7 @@ DRDYReady2 ( MicroSecondDelay (100); Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -728,13 +770,20 @@ WaitForBSYClear ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 StatusRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); @@ -749,7 +798,7 @@ WaitForBSYClear ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -775,13 +824,20 @@ WaitForBSYClear2 ( IN UINT64 Timeout ) { - UINT32 Delay; + UINT64 Delay; UINT8 AltStatusRegister; + BOOLEAN InfiniteWait; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } + + Delay = DivU64x32(Timeout, 1000) + 1; do { AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); @@ -796,7 +852,7 @@ WaitForBSYClear2 ( Delay--; - } while (Delay > 0); + } while (InfiniteWait || (Delay > 0)); return EFI_TIMEOUT; } @@ -1312,6 +1368,7 @@ Exit: @param[in] PciIo The PCI IO protocol instance. @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_TIMEOUT The memory setting is time out. @@ -1320,18 +1377,26 @@ Exit: **/ EFI_STATUS AtaUdmStatusWait ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN EFI_IDE_REGISTERS *IdeRegisters + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_IDE_REGISTERS *IdeRegisters, + IN UINT64 Timeout ) { UINT8 RegisterValue; EFI_STATUS Status; UINT16 IoPortForBmis; - UINT64 Timeout; + UINT64 Delay; + BOOLEAN InfiniteWait; + + if (Timeout == 0) { + InfiniteWait = TRUE; + } else { + InfiniteWait = FALSE; + } - Timeout = 2000; + Delay = DivU64x32 (Timeout, 1000) + 1; - while (TRUE) { + do { Status = CheckStatusRegister (PciIo, IdeRegisters); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; @@ -1351,11 +1416,11 @@ AtaUdmStatusWait ( break; } // - // Stall for 1 milliseconds. + // Stall for 100 microseconds. // - MicroSecondDelay (1000); - Timeout--; - } + MicroSecondDelay (100); + Delay--; + } while (InfiniteWait || (Delay > 0)); return Status; } @@ -1404,7 +1469,7 @@ AtaUdmStatusCheck ( return EFI_SUCCESS; } - if (Task->RetryTimes == 0) { + if (!Task->InfiniteWait && (Task->RetryTimes == 0)) { return EFI_TIMEOUT; } else { // @@ -1664,12 +1729,6 @@ AtaUdmaInOut ( IdeWritePortB (PciIo, IoPortForBmic, RegisterValue); 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; @@ -1703,14 +1762,11 @@ AtaUdmaInOut ( // // 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) { Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters); } else { - Status = AtaUdmStatusWait (PciIo, IdeRegisters); + Status = AtaUdmStatusWait (PciIo, IdeRegisters, Timeout); } // -- 2.39.2