}\r
}\r
\r
-/**\r
- Check if the device is still on port. It also checks if the AHCI controller\r
- supports the address and data count will be transferred.\r
-\r
- @param PciIo The PCI IO protocol instance.\r
- @param Port The number of port.\r
-\r
- @retval EFI_SUCCESS The device is attached to port and the transfer data is\r
- supported by AHCI controller.\r
- @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI\r
- controller.\r
- @retval EFI_NOT_READY The physical communication between AHCI controller and device\r
- is not ready.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciCheckDeviceStatus (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 Port\r
- )\r
-{\r
- UINT32 Data;\r
- UINT32 Offset;\r
-\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
-\r
- Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;\r
-\r
- if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return EFI_NOT_READY;\r
-}\r
\r
/**\r
\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Do AHCI port reset.\r
-\r
- @param PciIo The PCI IO protocol instance.\r
- @param Port The number of port.\r
- @param Timeout The timeout value of reset, uses 100ns as a unit.\r
-\r
- @retval EFI_DEVICE_ERROR The port reset unsuccessfully\r
- @retval EFI_TIMEOUT The reset operation is time out.\r
- @retval EFI_SUCCESS The port reset successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciPortReset (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN UINT8 Port,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT32 Offset;\r
-\r
- AhciClearPortStatus (PciIo, Port);\r
-\r
- AhciStopCommand (PciIo, Port, Timeout);\r
-\r
- AhciDisableFisReceive (PciIo, Port, Timeout);\r
-\r
- AhciEnableFisReceive (PciIo, Port, Timeout);\r
-\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;\r
-\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);\r
-\r
- //\r
- // wait 5 millisecond before de-assert DET\r
- //\r
- MicroSecondDelay (5000);\r
-\r
- AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);\r
-\r
- //\r
- // wait 5 millisecond before de-assert DET\r
- //\r
- MicroSecondDelay (5000);\r
-\r
- //\r
- // Wait for communication to be re-established\r
- //\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;\r
- Status = AhciWaitMmioSet (\r
- PciIo,\r
- Offset,\r
- EFI_AHCI_PORT_SSTS_DET_MASK,\r
- EFI_AHCI_PORT_SSTS_DET_PCE,\r
- Timeout\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Port %d COMRESET failed: %r\n", Port, Status));\r
- return Status;\r
- }\r
-\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
- AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_ERR_CLEAR);\r
-\r
- return EFI_SUCCESS;\r
-}\r
\r
/**\r
Do AHCI HBA reset.\r
return EFI_TIMEOUT;\r
}\r
\r
-/**\r
- This function is used to poll for the DRDY bit set in the Status Register. DRDY\r
- bit is set when the device is ready to accept command. Most ATA commands must be\r
- sent after DRDY set except the ATAPI Packet Command.\r
-\r
- @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Timeout The time to complete the command, uses 100ns as a unit.\r
-\r
- @retval EFI_SUCCESS DRDY bit set within the time out.\r
- @retval EFI_TIMEOUT DRDY bit not set within the time out.\r
-\r
- @note Read Status Register will clear interrupt status.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-DRDYReady (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- UINT64 Delay;\r
- UINT8 StatusRegister;\r
- UINT8 ErrorRegister;\r
- BOOLEAN InfiniteWait;\r
-\r
- ASSERT (PciIo != NULL);\r
- ASSERT (IdeRegisters != NULL);\r
-\r
- if (Timeout == 0) {\r
- InfiniteWait = TRUE;\r
- } else {\r
- InfiniteWait = FALSE;\r
- }\r
-\r
- Delay = DivU64x32(Timeout, 1000) + 1;\r
- do {\r
- StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
- //\r
- // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
- //\r
- if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
- if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
-\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
- }\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((StatusRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- //\r
- // Stall for 100 microseconds.\r
- //\r
- MicroSecondDelay (100);\r
-\r
- Delay--;\r
- } while (InfiniteWait || (Delay > 0));\r
-\r
- return EFI_TIMEOUT;\r
-}\r
-\r
-/**\r
- This function is used to poll for the DRDY bit set in the Alternate Status Register.\r
- DRDY bit is set when the device is ready to accept command. Most ATA commands must\r
- be sent after DRDY set except the ATAPI Packet Command.\r
-\r
- @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Timeout The time to complete the command, uses 100ns as a unit.\r
-\r
- @retval EFI_SUCCESS DRDY bit set within the time out.\r
- @retval EFI_TIMEOUT DRDY bit not set within the time out.\r
-\r
- @note Read Alternate Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-DRDYReady2 (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- UINT64 Delay;\r
- UINT8 AltRegister;\r
- UINT8 ErrorRegister;\r
- BOOLEAN InfiniteWait;\r
-\r
- ASSERT (PciIo != NULL);\r
- ASSERT (IdeRegisters != NULL);\r
-\r
- if (Timeout == 0) {\r
- InfiniteWait = TRUE;\r
- } else {\r
- InfiniteWait = FALSE;\r
- }\r
-\r
- Delay = DivU64x32(Timeout, 1000) + 1;\r
- do {\r
- AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
- //\r
- // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
- //\r
- if ((AltRegister & ATA_STSREG_BSY) == 0) {\r
- if ((AltRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
-\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
- }\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if ((AltRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
- return EFI_SUCCESS;\r
- } else {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- }\r
-\r
- //\r
- // Stall for 100 microseconds.\r
- //\r
- MicroSecondDelay (100);\r
\r
- Delay--;\r
- } while (InfiniteWait || (Delay > 0));\r
\r
- return EFI_TIMEOUT;\r
-}\r
\r
/**\r
This function is used to poll for the BSY bit clear in the Status Register. BSY\r
return EFI_TIMEOUT;\r
}\r
\r
-/**\r
- This function is used to poll for the BSY bit clear in the Status Register. BSY\r
- is clear when the device is not busy. Every command must be sent after device is not busy.\r
-\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Timeout The time to complete the command, uses 100ns as a unit.\r
-\r
- @retval EFI_SUCCESS BSY bit clear within the time out.\r
- @retval EFI_TIMEOUT BSY bit not clear within the time out.\r
-\r
- @note Read Status Register will clear interrupt status.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-WaitForBSYClear2 (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- UINT64 Delay;\r
- UINT8 AltStatusRegister;\r
- BOOLEAN InfiniteWait;\r
-\r
- ASSERT (PciIo != NULL);\r
- ASSERT (IdeRegisters != NULL);\r
-\r
- if (Timeout == 0) {\r
- InfiniteWait = TRUE;\r
- } else {\r
- InfiniteWait = FALSE;\r
- }\r
-\r
- Delay = DivU64x32(Timeout, 1000) + 1;\r
- do {\r
- AltStatusRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
-\r
- if ((AltStatusRegister & ATA_STSREG_BSY) == 0x00) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Stall for 100 microseconds.\r
- //\r
- MicroSecondDelay (100);\r
-\r
- Delay--;\r
-\r
- } while (InfiniteWait || (Delay > 0));\r
-\r
- return EFI_TIMEOUT;\r
-}\r
\r
/**\r
Get IDE i/o port registers' base addresses by mode.\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- This function is used to implement the Soft Reset on the specified device. But,\r
- the ATA Soft Reset mechanism is so strong a reset method that it will force\r
- resetting on both devices connected to the same cable.\r
-\r
- It is called by IdeBlkIoReset(), a interface function of Block\r
- I/O protocol.\r
-\r
- This function can also be used by the ATAPI device to perform reset when\r
- ATAPI Reset command is failed.\r
-\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
- @param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
- @param Timeout The time to complete the command, uses 100ns as a unit.\r
-\r
- @retval EFI_SUCCESS Soft reset completes successfully.\r
- @retval EFI_DEVICE_ERROR Any step during the reset process is failed.\r
-\r
- @note The registers initial values after ATA soft reset are different\r
- to the ATA device and ATAPI device.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AtaSoftReset (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- UINT8 DeviceControl;\r
-\r
- DeviceControl = 0;\r
- //\r
- // disable Interrupt and set SRST bit to initiate soft reset\r
- //\r
- DeviceControl = ATA_CTLREG_SRST | ATA_CTLREG_IEN_L;\r
-\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
-\r
- //\r
- // SRST should assert for at least 5 us, we use 10 us for\r
- // better compatibility\r
- //\r
- MicroSecondDelay (10);\r
-\r
- //\r
- // Enable interrupt to support UDMA, and clear SRST bit\r
- //\r
- DeviceControl = 0;\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
-\r
- //\r
- // Wait for at least 10 ms to check BSY status, we use 10 ms\r
- // for better compatibility\r
- //\r
- MicroSecondDelay (10000);\r
-\r
- //\r
- // slave device needs at most 31ms to clear BSY\r
- //\r
- if (WaitForBSYClear (PciIo, IdeRegisters, Timeout) == EFI_TIMEOUT) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
\r
/**\r
Send ATA Ext command into device with NON_DATA protocol.\r