From 8536cc4b37e12d11af9432d6e73e3c8c84c68b79 Mon Sep 17 00:00:00 2001 From: erictian Date: Thu, 3 Nov 2011 12:38:21 +0000 Subject: [PATCH] MdeModulePkg: ATA performance tuning. 1. Boost IDE mode boot when slave device is absent. 2. Use D2H FIS to check if the PIO OUT/DMA IN/DMA OUT transfer is finished or error happened. ATA PIO IN has special check as it may just receive PIO SETUP FIS for success case. 3. Add command status register check for IDE DMA transfer. 4. ScsiDiskReadCapacity() in ScsiDisk should return EFI_SUCCESS if SENSE Data request is success. Signed-off-by: erictian Reviewed-by: rsun3 Reviewed-by: xdu2 Reviewed-by: mdkinney git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12658 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Bus/Ata/AtaAtapiPassThru/AhciMode.c | 350 +++++++++--------- .../Bus/Ata/AtaAtapiPassThru/AhciMode.h | 4 +- .../Ata/AtaAtapiPassThru/AtaAtapiPassThru.h | 16 +- .../Bus/Ata/AtaAtapiPassThru/IdeMode.c | 298 ++++++++------- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c | 2 +- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 5 +- 6 files changed, 341 insertions(+), 334 deletions(-) diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c index 0bc54abbf7..a9b126acfa 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c @@ -133,24 +133,23 @@ AhciOrReg ( } /** - Wait for memory set to the test value. + Wait for the value of the specified MMIO register set to the test value. @param PciIo The PCI IO protocol instance. - @param Offset The memory address to test. + @param Offset The MMIO address to test. @param MaskValue The mask value of memory. @param TestValue The test value of memory. - @param Timeout The time out value for wait memory set. + @param Timeout The time out value for wait memory set, uses 100ns as a unit. - @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. + @retval EFI_TIMEOUT The MMIO setting is time out. + @retval EFI_SUCCESS The MMIO is correct set. **/ EFI_STATUS EFIAPI -AhciWaitMemSet ( +AhciWaitMmioSet ( IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT32 Offset, + IN UINTN Offset, IN UINT32 MaskValue, IN UINT32 TestValue, IN UINT64 Timeout @@ -159,10 +158,13 @@ AhciWaitMemSet ( UINT32 Value; UINT32 Delay; - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); + Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); do { - Value = AhciReadReg (PciIo, Offset) & MaskValue; + // + // Access PCI MMIO space to see if the value is the tested one. + // + Value = AhciReadReg (PciIo, (UINT32) Offset) & MaskValue; if (Value == TestValue) { return EFI_SUCCESS; @@ -177,21 +179,70 @@ AhciWaitMemSet ( } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } + return EFI_TIMEOUT; +} + +/** + Wait for the value of the specified system memory set to the test value. + + @param Address The system memory address to test. + @param MaskValue The mask value of memory. + @param TestValue The test value of memory. + @param Timeout The time out value for wait memory set, uses 100ns as a unit. + + @retval EFI_TIMEOUT The system memory setting is time out. + @retval EFI_SUCCESS The system memory is correct set. + +**/ +EFI_STATUS +EFIAPI +AhciWaitMemSet ( + IN EFI_PHYSICAL_ADDRESS Address, + IN UINT32 MaskValue, + IN UINT32 TestValue, + IN UINT64 Timeout + ) +{ + UINT32 Value; + UINT32 Delay; + + Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); + + do { + // + // Access sytem memory to see if the value is the tested one. + // + // The system memory pointed by Address will be updated by the + // SATA Host Controller, "volatile" is introduced to prevent + // compiler from optimizing the access to the memory address + // to only read once. + // + Value = *(volatile UINT32 *) (UINTN) Address; + Value &= MaskValue; + + if (Value == TestValue) { + return EFI_SUCCESS; + } + + // + // Stall for 100 microseconds. + // + MicroSecondDelay (100); + + Delay--; - return EFI_DEVICE_ERROR; + } while (Delay > 0); + + return EFI_TIMEOUT; } /** 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] 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. + @param[in, out] RetryTimes The retry times value for waitting memory set. If 0, then just try once. @retval EFI_NOTREADY The memory is not set. @retval EFI_TIMEOUT The memory setting retry times out. @@ -201,24 +252,26 @@ AhciWaitMemSet ( EFI_STATUS EFIAPI AhciCheckMemSet ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT32 Offset, + IN UINTN Address, IN UINT32 MaskValue, IN UINT32 TestValue, - IN OUT UINTN *RetryTimes + IN OUT UINTN *RetryTimes OPTIONAL ) { UINT32 Value; - (*RetryTimes) --; - - Value = AhciReadReg (PciIo, Offset) & MaskValue; + if (RetryTimes != NULL) { + (*RetryTimes)--; + } + + Value = *(volatile UINT32 *) Address; + Value &= MaskValue; if (Value == TestValue) { return EFI_SUCCESS; } - if ((*RetryTimes) == 0) { + if ((RetryTimes != NULL) && (*RetryTimes == 0)) { return EFI_TIMEOUT; } else { return EFI_NOT_READY; @@ -338,7 +391,7 @@ AhciDumpPortStatus ( @param PciIo The PCI IO protocol instance. @param Port The number of port. - @param Timeout The timeout value of enabling FIS. + @param Timeout The timeout value of enabling FIS, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The FIS enable setting fails. @retval EFI_TIMEOUT The FIS enable setting is time out. @@ -358,7 +411,7 @@ AhciEnableFisReceive ( Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD; AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE); - return AhciWaitMemSet ( + return AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_CMD_FR, @@ -372,7 +425,7 @@ AhciEnableFisReceive ( @param PciIo The PCI IO protocol instance. @param Port The number of port. - @param Timeout The timeout value of disabling FIS. + @param Timeout The timeout value of disabling FIS, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The FIS disable setting fails. @retval EFI_TIMEOUT The FIS disable setting is time out. @@ -410,7 +463,7 @@ AhciDisableFisReceive ( AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE)); - return AhciWaitMemSet ( + return AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_CMD_FR, @@ -596,7 +649,7 @@ AhciBuildCommandFis ( @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -626,15 +679,16 @@ AhciPioTransfer ( { EFI_STATUS Status; UINTN FisBaseAddr; - UINT32 Offset; - UINT32 Value; + UINTN Offset; EFI_PHYSICAL_ADDRESS PhyAddr; VOID *Map; UINTN MapLength; EFI_PCI_IO_PROTOCOL_OPERATION Flag; UINT32 Delay; EFI_AHCI_COMMAND_FIS CFis; - EFI_AHCI_COMMAND_LIST CmdList; + EFI_AHCI_COMMAND_LIST CmdList; + UINT32 PortTfd; + UINT32 PrdCount; if (Read) { Flag = EfiPciIoOperationBusMasterWrite; @@ -697,56 +751,66 @@ AhciPioTransfer ( // Check the status and wait the driver sending data // FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS); - // - // Wait device sends the PIO setup fis before data transfer - // - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); - do { - Value = *(volatile UINT32 *) (FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET); - - if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_PIO_SETUP) { - break; - } + if (Read && (AtapiCommand == 0)) { // - // Stall for 100 microseconds. + // Wait device sends the PIO setup fis before data transfer // - MicroSecondDelay(100); + Status = EFI_TIMEOUT; + Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1); + do { + Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; + PortTfd = AhciReadReg (PciIo, (UINT32) Offset); + + if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + break; + } + Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET; - Delay--; - } while (Delay > 0); + Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0); + if (!EFI_ERROR (Status)) { + PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc)); + if (PrdCount == DataCount) { + break; + } + } - if (Delay == 0) { - Status = EFI_TIMEOUT; - goto Exit; - } + Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; + Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0); + if (!EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + break; + } - // - // 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 - ); + // + // Stall for 100 microseconds. + // + MicroSecondDelay(100); - if (EFI_ERROR (Status)) { - goto Exit; - } + Delay--; + } while (Delay > 0); + } else { + // + // Wait for D2H Fis is received + // + Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; + Status = AhciWaitMemSet ( + Offset, + EFI_AHCI_FIS_TYPE_MASK, + EFI_AHCI_FIS_REGISTER_D2H, + Timeout + ); - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS; - Status = AhciWaitMemSet ( - PciIo, - Offset, - EFI_AHCI_PORT_IS_PSS, - EFI_AHCI_PORT_IS_PSS, - Timeout - ); - if (EFI_ERROR (Status)) { - goto Exit; + if (EFI_ERROR (Status)) { + goto Exit; + } + + Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; + PortTfd = AhciReadReg (PciIo, (UINT32) Offset); + if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + } } Exit: @@ -787,7 +851,7 @@ Exit: @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -810,22 +874,24 @@ AhciDmaTransfer ( IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN OUT VOID *MemoryAddr, - IN UINTN DataCount, + IN UINT32 DataCount, IN UINT64 Timeout, IN ATA_NONBLOCK_TASK *Task ) { EFI_STATUS Status; - UINT32 Offset; + UINTN Offset; EFI_PHYSICAL_ADDRESS PhyAddr; VOID *Map; UINTN MapLength; EFI_PCI_IO_PROTOCOL_OPERATION Flag; EFI_AHCI_COMMAND_FIS CFis; EFI_AHCI_COMMAND_LIST CmdList; + UINTN FisBaseAddr; + UINT32 PortTfd; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_TPL OldTpl; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_TPL OldTpl; Map = NULL; PciIo = Instance->PciIo; @@ -916,45 +982,28 @@ AhciDmaTransfer ( 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; + FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS); + Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; if (Task != NULL) { // // For Non-blocking // Status = AhciCheckMemSet ( - PciIo, Offset, - 0xFFFFFFFF, - 0, + EFI_AHCI_FIS_TYPE_MASK, + EFI_AHCI_FIS_REGISTER_D2H, (UINTN *) (&Task->RetryTimes) ); } else { Status = AhciWaitMemSet ( - PciIo, Offset, - 0xFFFFFFFF, - 0, + EFI_AHCI_FIS_TYPE_MASK, + EFI_AHCI_FIS_REGISTER_D2H, Timeout ); } @@ -963,31 +1012,10 @@ AhciDmaTransfer ( goto Exit; } - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS; - - 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; + Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; + PortTfd = AhciReadReg (PciIo, (UINT32) Offset); + if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; } Exit: @@ -1039,7 +1067,7 @@ Exit: @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1066,10 +1094,8 @@ AhciNonDataTransfer ( { EFI_STATUS Status; UINTN FisBaseAddr; - UINT32 Offset; - UINT32 Value; - UINT32 Delay; - + UINTN Offset; + UINT32 PortTfd; EFI_AHCI_COMMAND_FIS CFis; EFI_AHCI_COMMAND_LIST CmdList; @@ -1110,39 +1136,23 @@ AhciNonDataTransfer ( // Wait device sends the Response Fis // FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS); - // - // Wait device sends the PIO setup fis before data transfer - // - Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); - do { - Value = *(volatile UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET); - - if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) { - break; - } + Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET; + Status = AhciWaitMemSet ( + Offset, + EFI_AHCI_FIS_TYPE_MASK, + EFI_AHCI_FIS_REGISTER_D2H, + Timeout + ); - // - // Stall for 100 microseconds. - // - MicroSecondDelay(100); - - Delay --; - } while (Delay > 0); - - if (Delay == 0) { - Status = EFI_TIMEOUT; + if (EFI_ERROR (Status)) { goto Exit; } - Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI; - - Status = AhciWaitMemSet ( - PciIo, - Offset, - 0xFFFFFFFF, - 0, - Timeout - ); + Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD; + PortTfd = AhciReadReg (PciIo, (UINT32) Offset); + if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) { + Status = EFI_DEVICE_ERROR; + } Exit: AhciStopCommand ( @@ -1167,7 +1177,7 @@ Exit: @param PciIo The PCI IO protocol instance. @param Port The number of port. - @param Timeout The timeout value of stop. + @param Timeout The timeout value of stop, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command stop unsuccessfully. @retval EFI_TIMEOUT The operation is time out. @@ -1196,7 +1206,7 @@ AhciStopCommand ( AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST)); } - return AhciWaitMemSet ( + return AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_CMD_CR, @@ -1211,7 +1221,7 @@ AhciStopCommand ( @param PciIo The PCI IO protocol instance. @param Port The number of port. @param CommandSlot The number of Command Slot. - @param Timeout The timeout value of start. + @param Timeout The timeout value of start, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command start unsuccessfully. @retval EFI_TIMEOUT The operation is time out. @@ -1275,7 +1285,7 @@ AhciStartCommand ( Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD; AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO); - AhciWaitMemSet ( + AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_CMD_CLO, @@ -1307,7 +1317,7 @@ AhciStartCommand ( @param PciIo The PCI IO protocol instance. @param Port The number of port. - @param Timeout The timeout value of reset. + @param Timeout The timeout value of reset, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The port reset unsuccessfully @retval EFI_TIMEOUT The reset operation is time out. @@ -1353,7 +1363,7 @@ AhciPortReset ( // Wait for communication to be re-established // Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS; - Status = AhciWaitMemSet ( + Status = AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_SSTS_DET_MASK, @@ -1375,7 +1385,7 @@ AhciPortReset ( Do AHCI HBA reset. @param PciIo The PCI IO protocol instance. - @param Timeout The timeout value of reset. + @param Timeout The timeout value of reset, uses 100ns as a unit. @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset. @retval EFI_TIMEOUT The reset operation is time out. @@ -2238,7 +2248,7 @@ AhciModeInitialization ( // Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD; AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE); - Status = AhciWaitMemSet ( + Status = AhciWaitMmioSet ( PciIo, Offset, EFI_AHCI_PORT_CMD_FR, @@ -2301,7 +2311,7 @@ AhciModeInitialization ( // When the first D2H register FIS is received, the content of PxSIG register is updated. // Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG; - Status = AhciWaitMemSet ( + Status = AhciWaitMmioSet ( PciIo, Offset, 0x0000FFFF, diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h index 032b97cd2f..052e7837f5 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h @@ -327,7 +327,7 @@ AhciPacketCommandExecute ( @param PciIo The PCI IO protocol instance. @param Port The number of port. @param CommandSlot The number of CommandSlot. - @param Timeout The timeout value of start. + @param Timeout The timeout value of start, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command start unsuccessfully. @retval EFI_TIMEOUT The operation is time out. @@ -348,7 +348,7 @@ AhciStartCommand ( @param PciIo The PCI IO protocol instance. @param Port The number of port. - @param Timeout The timeout value of stop. + @param Timeout The timeout value of stop, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command stop unsuccessfully. @retval EFI_TIMEOUT The operation is time out. diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h index 0bbad0a01a..5be8d24bd7 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.h @@ -101,7 +101,7 @@ typedef struct { // LIST_ENTRY DeviceList; UINT64 OriginalPciAttributes; - + // // For AtaPassThru protocol, using the following bytes to record the previous call in // GetNextPort()/GetNextDevice(). @@ -1078,7 +1078,7 @@ AhciModeInitialization ( @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1118,7 +1118,7 @@ AhciNonDataTransfer ( @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1141,7 +1141,7 @@ AhciDmaTransfer ( IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN OUT VOID *MemoryAddr, - IN UINTN DataCount, + IN UINT32 DataCount, IN UINT64 Timeout, IN ATA_NONBLOCK_TASK *Task ); @@ -1161,7 +1161,7 @@ AhciDmaTransfer ( @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] Timeout The timeout value of non data transfer, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1198,7 +1198,7 @@ AhciPioTransfer ( @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1232,7 +1232,7 @@ AtaNonDataCommandIn ( @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1270,7 +1270,7 @@ AtaUdmaInOut ( from host to device. @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c index 79310fcb49..0604a9d4c3 100644 --- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c +++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/IdeMode.c @@ -17,7 +17,7 @@ /** read a one-byte data from a IDE port. - @param PciIo The PCI IO protocol instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port The IDE Port number @return the one-byte data read from IDE port @@ -51,7 +51,7 @@ IdeReadPortB ( /** write a 1-byte data to a specific IDE port. - @param PciIo The PCI IO protocol instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port The IDE port to be writen @param Data The data to write to the port **/ @@ -81,7 +81,7 @@ IdeWritePortB ( /** write a 1-word data to a specific IDE port. - @param PciIo PCI IO protocol instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port The IDE port to be writen @param Data The data to write to the port **/ @@ -111,7 +111,7 @@ IdeWritePortW ( /** write a 2-word data to a specific IDE port. - @param PciIo PCI IO protocol instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port The IDE port to be writen @param Data The data to write to the port **/ @@ -143,7 +143,7 @@ IdeWritePortDW ( Call the IO abstraction once to do the complete read, not one word at a time - @param PciIo Pointer to the EFI_PCI_IO instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port IO port to read @param Count No. of UINT16's to read @param Buffer Pointer to the data buffer for read @@ -180,7 +180,7 @@ IdeWritePortWMultiple ( Call the IO abstraction once to do the complete read, not one word at a time - @param PciIo Pointer to the EFI_PCI_IO instance + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure @param Port IO port to read @param Count Number of UINT16's to read @param Buffer Pointer to the data buffer for read @@ -217,7 +217,7 @@ IdeReadPortWMultiple ( some debug information and if there is ERR bit set in the Status Register, the Error Register's value is also be parsed and print out. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure. @@ -294,11 +294,10 @@ DumpAllIdeRegisters ( } /** - This function is used to analyze the Status Register and print out - some debug information and if there is ERR bit set in the Status - Register, the Error Register's value is also be parsed and print out. + This function is used to analyze the Status Register at the condition that BSY is zero. + if there is ERR bit set in the Status Register, then return error. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. @retval EFI_SUCCESS No err information in the Status Register. @@ -312,7 +311,6 @@ CheckStatusRegister ( IN EFI_IDE_REGISTERS *IdeRegisters ) { - EFI_STATUS Status; UINT8 StatusRegister; ASSERT (PciIo != NULL); @@ -320,13 +318,14 @@ CheckStatusRegister ( StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); - if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) { - Status = EFI_SUCCESS; - } else { - Status = EFI_DEVICE_ERROR; + if ((StatusRegister & ATA_STSREG_BSY) == 0) { + if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } } - - return Status; + return EFI_SUCCESS; } /** @@ -334,9 +333,9 @@ CheckStatusRegister ( Register. DRQ is cleared when the device is finished transferring data. So this function is called after data transfer is finished. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRQ bit clear within the time out. @@ -356,7 +355,6 @@ DRQClear ( { UINT32 Delay; UINT8 StatusRegister; - UINT8 ErrorRegister; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); @@ -366,22 +364,18 @@ DRQClear ( StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); // - // wait for BSY == 0 and DRQ == 0 + // Wait for BSY == 0, then judge if DRQ is clear // - if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { - break; - } - - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((StatusRegister & ATA_STSREG_BSY) == 0) { + if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; } } // - // Stall for 100 microseconds. + // Stall for 100 microseconds. // MicroSecondDelay (100); @@ -389,11 +383,7 @@ DRQClear ( } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** This function is used to poll for the DRQ bit clear in the Alternate @@ -401,9 +391,9 @@ DRQClear ( transferring data. So this function is called after data transfer is finished. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRQ bit clear within the time out. @@ -421,7 +411,6 @@ DRQClear2 ( { UINT32 Delay; UINT8 AltRegister; - UINT8 ErrorRegister; ASSERT (PciIo != NULL); ASSERT (IdeRegisters != NULL); @@ -431,17 +420,13 @@ DRQClear2 ( AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); // - // wait for BSY == 0 and DRQ == 0 + // Wait for BSY == 0, then judge if DRQ is clear // - if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) { - break; - } - - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((AltRegister & ATA_STSREG_BSY) == 0) { + if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; } } @@ -454,11 +439,7 @@ DRQClear2 ( } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -468,9 +449,9 @@ DRQClear2 ( is called after the command is sent to the device and before required data is transferred. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRQ bit set within the time out. @retval EFI_TIMEOUT DRQ bit not set within the time out. @@ -497,22 +478,27 @@ DRQReady ( Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1); do { // - // read Status Register will clear interrupt + // Read Status Register will clear interrupt // StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); // - // BSY==0,DRQ==1 + // Wait for BSY == 0, then judge if DRQ is clear or ERR is set // - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - break; - } + if ((StatusRegister & ATA_STSREG_BSY) == 0) { + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + return EFI_DEVICE_ERROR; + } - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; } } @@ -524,20 +510,16 @@ DRQReady ( Delay--; } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** This function is used to poll for the DRQ bit set in the Alternate Status Register. DRQ is set when the device is ready to transfer data. So this function is called after the command is sent to the device and before required data is transferred. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRQ bit set within the time out. @retval EFI_TIMEOUT DRQ bit not set within the time out. @@ -564,21 +546,26 @@ DRQReady2 ( do { // - // Read Alternate Status Register will not clear interrupt status + // Read Alternate Status Register will not clear interrupt status // AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); // - // BSY == 0 , DRQ == 1 + // Wait for BSY == 0, then judge if DRQ is clear or ERR is set // - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) { - break; - } + if ((AltRegister & ATA_STSREG_BSY) == 0) { + if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + return EFI_DEVICE_ERROR; + } - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; } } @@ -590,11 +577,7 @@ DRQReady2 ( Delay--; } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -602,9 +585,9 @@ DRQReady2 ( bit is set when the device is ready to accept command. Most ATA commands must be sent after DRDY set except the ATAPI Packet Command. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRDY bit set within the time out. @retval EFI_TIMEOUT DRDY bit not set within the time out. @@ -630,17 +613,22 @@ DRDYReady ( do { StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); // - // BSY == 0 , DRDY == 1 + // Wait for BSY == 0, then judge if DRDY is set or ERR is set // - if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { - break; - } + if ((StatusRegister & ATA_STSREG_BSY) == 0) { + if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + return EFI_DEVICE_ERROR; + } - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((StatusRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; } } @@ -652,11 +640,7 @@ DRDYReady ( Delay--; } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -664,9 +648,9 @@ DRDYReady ( DRDY bit is set when the device is ready to accept command. Most ATA commands must be sent after DRDY set except the ATAPI Packet Command. - @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. + @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS DRDY bit set within the time out. @retval EFI_TIMEOUT DRDY bit not set within the time out. @@ -693,17 +677,22 @@ DRDYReady2 ( do { AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); // - // BSY == 0 , DRDY == 1 + // Wait for BSY == 0, then judge if DRDY is set or ERR is set // - if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) { - break; - } + if ((AltRegister & ATA_STSREG_BSY) == 0) { + if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) { + ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); - if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) { - ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature); + if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { + return EFI_ABORTED; + } + return EFI_DEVICE_ERROR; + } - if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) { - return EFI_ABORTED; + if ((AltRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; } } @@ -715,11 +704,7 @@ DRDYReady2 ( Delay--; } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -728,7 +713,7 @@ DRDYReady2 ( @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS BSY bit clear within the time out. @retval EFI_TIMEOUT BSY bit not clear within the time out. @@ -754,7 +739,7 @@ WaitForBSYClear ( StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus); if ((StatusRegister & ATA_STSREG_BSY) == 0x00) { - break; + return EFI_SUCCESS; } // @@ -766,11 +751,7 @@ WaitForBSYClear ( } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -779,7 +760,7 @@ WaitForBSYClear ( @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS BSY bit clear within the time out. @retval EFI_TIMEOUT BSY bit not clear within the time out. @@ -805,7 +786,7 @@ WaitForBSYClear2 ( AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev); if ((AltStatusRegister & ATA_STSREG_BSY) == 0x00) { - break; + return EFI_SUCCESS; } // @@ -817,11 +798,7 @@ WaitForBSYClear2 ( } while (Delay > 0); - if (Delay == 0) { - return EFI_TIMEOUT; - } - - return EFI_SUCCESS; + return EFI_TIMEOUT; } /** @@ -978,7 +955,7 @@ GetIdeRegisterIoAddr ( @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure. @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. - @param Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS Soft reset completes successfully. @retval EFI_DEVICE_ERROR Any step during the reset process is failed. @@ -1038,7 +1015,7 @@ AtaSoftReset ( @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 Timeout The time to complete the command. + @param Timeout The time to complete the command, uses 100ns as a unit. @retval EFI_SUCCESS Reading succeed @retval EFI_DEVICE_ERROR Error executing commands on this device. @@ -1134,7 +1111,7 @@ AtaIssueCommand ( from host to device. @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1268,7 +1245,7 @@ Exit: @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1334,7 +1311,7 @@ Exit: Wait for memory to be set. @param[in] PciIo The PCI IO protocol instance. - @param[in] PortNum The IDE Port number. + @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. @retval EFI_DEVICE_ERROR The memory is not set. @retval EFI_TIMEOUT The memory setting is time out. @@ -1344,18 +1321,25 @@ Exit: EFI_STATUS AtaUdmStatusWait ( IN EFI_PCI_IO_PROTOCOL *PciIo, - IN UINT16 PortNum + IN EFI_IDE_REGISTERS *IdeRegisters ) { UINT8 RegisterValue; EFI_STATUS Status; + UINT16 IoPortForBmis; UINT64 Timeout; Timeout = 2000; while (TRUE) { - RegisterValue = IdeReadPortB (PciIo, PortNum); + Status = CheckStatusRegister (PciIo, IdeRegisters); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + break; + } + IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET); + RegisterValue = IdeReadPortB (PciIo, IoPortForBmis); if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) { DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n")); Status = EFI_DEVICE_ERROR; @@ -1382,7 +1366,7 @@ AtaUdmStatusWait ( @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. + @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure. @retval EFI_DEVICE_ERROR The memory setting met a issue. @retval EFI_NOT_READY The memory is not set. @@ -1394,13 +1378,22 @@ EFI_STATUS AtaUdmStatusCheck ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN ATA_NONBLOCK_TASK *Task, - IN UINT16 PortForBit + IN EFI_IDE_REGISTERS *IdeRegisters ) { - UINT8 RegisterValue; + UINT8 RegisterValue; + UINT16 IoPortForBmis; + EFI_STATUS Status; Task->RetryTimes--; - RegisterValue = IdeReadPortB(PciIo, PortForBit); + + Status = CheckStatusRegister (PciIo, IdeRegisters); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET); + RegisterValue = IdeReadPortB (PciIo, IoPortForBmis); if ((RegisterValue & BMIS_ERROR) != 0) { DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n")); @@ -1435,7 +1428,7 @@ AtaUdmStatusCheck ( @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] Timeout The time to complete the command, uses 100ns as a unit. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by non-blocking mode. @@ -1652,7 +1645,7 @@ AtaUdmaInOut ( // RegisterValue = IdeReadPortB(PciIo, IoPortForBmis); RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); - IdeWritePortB(PciIo, IoPortForBmis, RegisterValue); + IdeWritePortB (PciIo, IoPortForBmis, RegisterValue); // // Set the base address to BMID register @@ -1680,6 +1673,11 @@ AtaUdmaInOut ( goto Exit; } + Status = CheckStatusRegister (PciIo, IdeRegisters); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Exit; + } // // Set START bit of BMIC register // @@ -1709,9 +1707,9 @@ AtaUdmaInOut ( // So set the variable Count to 2000, for about 2 second Timeout time. // if (Task != NULL) { - Status = AtaUdmStatusCheck (PciIo, Task, IoPortForBmis); + Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters); } else { - Status = AtaUdmStatusWait (PciIo, IoPortForBmis); + Status = AtaUdmStatusWait (PciIo, IdeRegisters); } // @@ -1829,7 +1827,8 @@ AtaPacketReadPendingData ( @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 Timeout Timeout value for wait DRQ ready before each data stream's transfer. + @param Timeout Timeout value for wait DRQ ready before each data stream's transfer + , uses 100ns as a unit. @retval EFI_SUCCESS data is transferred successfully. @retval EFI_DEVICE_ERROR the device failed to transfer data. @@ -1933,7 +1932,7 @@ AtaPacketReadWrite ( // // After data transfer is completed, normally, DRQ bit should clear. // - Status = DRQClear2 (PciIo, IdeRegisters, Timeout); + Status = DRQClear (PciIo, IdeRegisters, Timeout); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } @@ -1951,7 +1950,7 @@ AtaPacketReadWrite ( @param[in] Device The device number of device. @param[in] SenseData A pointer to store sense data. @param[in] SenseDataLength The sense data length. - @param[in] Timeout The timeout value to execute this cmd. + @param[in] Timeout The timeout value to execute this cmd, uses 100ns as a unit. @retval EFI_SUCCESS Send out the ATAPI packet command successfully. @retval EFI_DEVICE_ERROR The device failed to send data. @@ -2207,7 +2206,6 @@ SetDriveParameters ( IN UINT8 Device, IN EFI_ATA_DRIVE_PARMS *DriveParameters, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock - ) { EFI_STATUS Status; diff --git a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c index eb65022986..27d0a1c3db 100644 --- a/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c +++ b/MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBus.c @@ -506,7 +506,7 @@ UnregisterAtaDevice ( } ReleaseAtaResources (AtaDevice); - return EFI_SUCCESS; + return Status; } diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c index e8c8ee7a4b..0e8aa34ad6 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -1265,7 +1265,7 @@ DetectMediaParsingSenseKeys ( @param NumberOfSenseKeys The number of sense key @retval EFI_DEVICE_ERROR Indicates that error occurs - @retval EFI_SUCCESS Successfully to read capacity + @retval EFI_SUCCESS Successfully to read capacity or sense data is received. **/ EFI_STATUS @@ -1402,8 +1402,7 @@ ScsiDiskReadCapacity ( TRUE ); if (!EFI_ERROR (Status)) { - *NeedRetry = TRUE; - return EFI_DEVICE_ERROR; + return EFI_SUCCESS; } if (!*NeedRetry) { -- 2.39.2