/** @file\r
Header file for AHCI mode of ATA host controller.\r
- \r
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials \r
- are licensed and made available under the terms and conditions of the BSD License \r
- which accompanies this distribution. The full text of the license may be found at \r
- http://opensource.org/licenses/bsd-license.php \r
\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
**/\r
\r
/**\r
read a one-byte data from a IDE port.\r
\r
- @param PciIo The PCI IO protocol instance\r
- @param Port The IDE Port number \r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
+ @param Port The IDE Port number\r
\r
@return the one-byte data read from IDE port\r
**/\r
/**\r
write a 1-byte data to a specific IDE port.\r
\r
- @param PciIo The PCI IO protocol instance\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
@param Port The IDE port to be writen\r
@param Data The data to write to the port\r
**/\r
/**\r
write a 1-word data to a specific IDE port.\r
\r
- @param PciIo PCI IO protocol instance\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
@param Port The IDE port to be writen\r
@param Data The data to write to the port\r
**/\r
/**\r
write a 2-word data to a specific IDE port.\r
\r
- @param PciIo PCI IO protocol instance\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
@param Port The IDE port to be writen\r
@param Data The data to write to the port\r
**/\r
Call the IO abstraction once to do the complete read,\r
not one word at a time\r
\r
- @param PciIo Pointer to the EFI_PCI_IO instance\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
@param Port IO port to read\r
@param Count No. of UINT16's to read\r
@param Buffer Pointer to the data buffer for read\r
Call the IO abstraction once to do the complete read,\r
not one word at a time\r
\r
- @param PciIo Pointer to the EFI_PCI_IO instance\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure\r
@param Port IO port to read\r
@param Count Number of UINT16's to read\r
@param Buffer Pointer to the data buffer for read\r
some debug information and if there is ERR bit set in the Status\r
Register, the Error Register's value is also be parsed and print out.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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 AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
\r
}\r
\r
/**\r
- This function is used to analyze the Status Register and print out\r
- some debug information and if there is ERR bit set in the Status\r
- Register, the Error Register's value is also be parsed and print out.\r
+ This function is used to analyze the Status Register at the condition that BSY is zero.\r
+ if there is ERR bit set in the Status Register, then return error.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
+ @param PciIo A pointer to EFI_PCI_IO_PROTOCOL data structure.\r
@param IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
\r
@retval EFI_SUCCESS No err information in the Status Register.\r
IN EFI_IDE_REGISTERS *IdeRegisters\r
)\r
{\r
- EFI_STATUS Status;\r
UINT8 StatusRegister;\r
\r
ASSERT (PciIo != NULL);\r
\r
StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
\r
- if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
+ if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
+ if ((StatusRegister & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
}\r
-\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
Register. DRQ is cleared when the device is finished transferring data.\r
So this function is called after data transfer is finished.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\r
+ @param Timeout The time to complete the command, uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS DRQ bit clear within the time out.\r
\r
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 StatusRegister;\r
- UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
//\r
- // wait for BSY == 0 and DRQ == 0\r
+ // Wait for BSY == 0, then judge if DRQ is clear\r
//\r
- if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
- break;\r
- }\r
-\r
- if ((StatusRegister & (ATA_STSREG_BSY | 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
+ if ((StatusRegister & ATA_STSREG_BSY) == 0) {\r
+ if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
//\r
- // Stall for 100 microseconds.\r
+ // Stall for 100 microseconds.\r
//\r
MicroSecondDelay (100);\r
\r
Delay--;\r
\r
- } while (Delay > 0);\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
/**\r
This function is used to poll for the DRQ bit clear in the Alternate\r
transferring data. So this function is called after data transfer\r
is finished.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\r
+ @param Timeout The time to complete the command, uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS DRQ bit clear within the time out.\r
\r
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 AltRegister;\r
- UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
//\r
- // wait for BSY == 0 and DRQ == 0\r
+ // Wait for BSY == 0, then judge if DRQ is clear\r
//\r
- if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
- break;\r
- }\r
-\r
- if ((AltRegister & (ATA_STSREG_BSY | 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
+ if ((AltRegister & ATA_STSREG_BSY) == 0) {\r
+ if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
\r
Delay--;\r
\r
- } while (Delay > 0);\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\r
is called after the command is sent to the device and before required\r
data is transferred.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\r
+ @param Timeout The time to complete the command, uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS DRQ bit set within the time out.\r
@retval EFI_TIMEOUT DRQ bit not set within the time out.\r
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 StatusRegister;\r
UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
+ if (Timeout == 0) {\r
+ InfiniteWait = TRUE;\r
+ } else {\r
+ InfiniteWait = FALSE;\r
+ }\r
+\r
+ Delay = DivU64x32(Timeout, 1000) + 1;\r
do {\r
//\r
- // read Status Register will clear interrupt\r
+ // Read Status Register will clear interrupt\r
//\r
StatusRegister = IdeReadPortB (PciIo, IdeRegisters->CmdOrStatus);\r
\r
//\r
- // BSY==0,DRQ==1\r
+ // Wait for BSY == 0, then judge if DRQ is clear or ERR is set\r
//\r
- if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
- break;\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 ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
+ if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+ return EFI_ABORTED;\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
+ if ((StatusRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
}\r
}\r
\r
MicroSecondDelay (100);\r
\r
Delay--;\r
- } while (Delay > 0);\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
/**\r
This function is used to poll for the DRQ bit set in the Alternate Status Register.\r
- DRQ is set when the device is ready to transfer data. So this function is called after \r
+ DRQ is set when the device is ready to transfer data. So this function is called after\r
the command is sent to the device and before required data is transferred.\r
\r
- @param PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\r
+ @param Timeout The time to complete the command, uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS DRQ bit set within the time out.\r
@retval EFI_TIMEOUT DRQ bit not set within the time out.\r
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 AltRegister;\r
UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
+ if (Timeout == 0) {\r
+ InfiniteWait = TRUE;\r
+ } else {\r
+ InfiniteWait = FALSE;\r
+ }\r
+\r
+ Delay = DivU64x32(Timeout, 1000) + 1;\r
\r
do {\r
//\r
- // Read Alternate Status Register will not clear interrupt status\r
+ // Read Alternate Status Register will not clear interrupt status\r
//\r
AltRegister = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
//\r
- // BSY == 0 , DRQ == 1\r
+ // Wait for BSY == 0, then judge if DRQ is clear or ERR is set\r
//\r
- if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
- break;\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 ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
+ if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+ return EFI_ABORTED;\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
+ if ((AltRegister & ATA_STSREG_DRQ) == ATA_STSREG_DRQ) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
}\r
}\r
\r
MicroSecondDelay (100);\r
\r
Delay--;\r
- } while (Delay > 0);\r
-\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- return EFI_SUCCESS;\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
+ 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 ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\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
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 StatusRegister;\r
UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
- // BSY == 0 , DRDY == 1\r
+ // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
//\r
- if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
- break;\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 ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
+ if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+ return EFI_ABORTED;\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
+ if ((StatusRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_DEVICE_ERROR;\r
}\r
}\r
\r
MicroSecondDelay (100);\r
\r
Delay--;\r
- } while (Delay > 0);\r
-\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- return EFI_SUCCESS;\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
+ 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 ATA_ATAPI_PASS_THRU_INSTANCE data structure.\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.\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
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 AltRegister;\r
UINT8 ErrorRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
- // BSY == 0 , DRDY == 1\r
+ // Wait for BSY == 0, then judge if DRDY is set or ERR is set\r
//\r
- if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
- break;\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 ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
- ErrorRegister = IdeReadPortB (PciIo, IdeRegisters->ErrOrFeature);\r
+ if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+ return EFI_ABORTED;\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
\r
- if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
- return EFI_ABORTED;\r
+ if ((AltRegister & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_DEVICE_ERROR;\r
}\r
}\r
\r
MicroSecondDelay (100);\r
\r
Delay--;\r
- } while (Delay > 0);\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\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.\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
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 StatusRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {\r
- break;\r
+ return EFI_SUCCESS;\r
}\r
\r
//\r
\r
Delay--;\r
\r
- } while (Delay > 0);\r
-\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\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.\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
IN UINT64 Timeout\r
)\r
{\r
- UINT32 Delay;\r
+ UINT64 Delay;\r
UINT8 AltStatusRegister;\r
+ BOOLEAN InfiniteWait;\r
\r
ASSERT (PciIo != NULL);\r
ASSERT (IdeRegisters != NULL);\r
\r
- Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\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
- break;\r
+ return EFI_SUCCESS;\r
}\r
\r
//\r
\r
Delay--;\r
\r
- } while (Delay > 0);\r
+ } while (InfiniteWait || (Delay > 0));\r
\r
- if (Delay == 0) {\r
- return EFI_TIMEOUT;\r
- }\r
-\r
- return EFI_SUCCESS;\r
+ return EFI_TIMEOUT;\r
}\r
\r
/**\r
- Get IDE i/o port registers' base addresses by mode. \r
+ Get IDE i/o port registers' base addresses by mode.\r
\r
In 'Compatibility' mode, use fixed addresses.\r
In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's\r
|___________|_______________|_______________|\r
\r
Table 1. Compatibility resource mappings\r
- \r
+\r
b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs\r
in IDE controller's PCI Configuration Space, shown in the Table 2 below.\r
___________________________________________________\r
@param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
@param[in, out] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to\r
store the IDE i/o port registers' base addresses\r
- \r
+\r
@retval EFI_UNSUPPORTED Return this value when the BARs is not IO type\r
@retval EFI_SUCCESS Get the Base address successfully\r
@retval Other Read the pci configureation data error\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
+ 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
\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.\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
// Wait for at least 10 ms to check BSY status, we use 10 ms\r
// for better compatibility\r
- // \r
+ //\r
MicroSecondDelay (10000);\r
\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 AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param Timeout The time to complete the command, uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS Reading succeed\r
@retval EFI_DEVICE_ERROR Error executing commands on this device.\r
/**\r
This function is used to send out ATA commands conforms to the PIO Data In Protocol.\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 Buffer A pointer to the source buffer for the data.\r
- @param ByteCount The length of the data.\r
- @param Read Flag used to determine the data transfer direction.\r
- Read equals 1, means data transferred from device to host;\r
- Read equals 0, means data transferred from host to device. \r
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
- \r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in, out] Buffer A pointer to the source buffer for the data.\r
+ @param[in] ByteCount The length of the data.\r
+ @param[in] Read Flag used to determine the data transfer direction.\r
+ Read equals 1, means data transferred from device\r
+ to host;Read equals 0, means data transferred\r
+ from host to device.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+\r
@retval EFI_SUCCESS send out the ATA command and device send required data successfully.\r
@retval EFI_DEVICE_ERROR command sent failed.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-AtaPioDataInOut ( \r
+AtaPioDataInOut (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN EFI_IDE_REGISTERS *IdeRegisters,\r
IN OUT VOID *Buffer,\r
IN BOOLEAN Read,\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
UINTN WordCount;\r
// Poll DRQ bit set, data transfer can be performed only when DRQ is ready\r
//\r
Status = DRQReady2 (PciIo, IdeRegisters, Timeout);\r
- if (EFI_ERROR (Status)) { \r
+ if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
//\r
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
\r
+ //\r
+ // Not support the Non-blocking now,just do the blocking process.\r
+ //\r
return Status;\r
}\r
\r
/**\r
Send ATA command into device with NON_DATA protocol\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 AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param[in] PciIo A pointer to ATA_ATAPI_PASS_THRU_INSTANCE\r
+ data structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data\r
+ structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_SUCCESS Reading succeed\r
@retval EFI_ABORTED Command failed\r
**/\r
EFI_STATUS\r
EFIAPI\r
-AtaNonDataCommandIn ( \r
+AtaNonDataCommandIn (\r
IN EFI_PCI_IO_PROTOCOL *PciIo,\r
IN EFI_IDE_REGISTERS *IdeRegisters,\r
IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
- \r
+\r
Status = CheckStatusRegister (PciIo, IdeRegisters);\r
if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
//\r
DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
\r
+ //\r
+ // Not support the Non-blocking now,just do the blocking process.\r
+ //\r
return Status;\r
}\r
\r
+/**\r
+ Wait for memory to be set.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+\r
+ @retval EFI_DEVICE_ERROR The memory is not set.\r
+ @retval EFI_TIMEOUT The memory setting is time out.\r
+ @retval EFI_SUCCESS The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusWait (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN UINT64 Timeout\r
+ )\r
+{\r
+ UINT8 RegisterValue;\r
+ EFI_STATUS Status;\r
+ UINT16 IoPortForBmis;\r
+ UINT64 Delay;\r
+ BOOLEAN InfiniteWait;\r
+\r
+ if (Timeout == 0) {\r
+ InfiniteWait = TRUE;\r
+ } else {\r
+ InfiniteWait = FALSE;\r
+ }\r
+\r
+ Delay = DivU64x32 (Timeout, 1000) + 1;\r
+\r
+ do {\r
+ Status = CheckStatusRegister (PciIo, IdeRegisters);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
+ RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
+ if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+ Status = EFI_SUCCESS;\r
+ break;\r
+ }\r
+ //\r
+ // Stall for 100 microseconds.\r
+ //\r
+ MicroSecondDelay (100);\r
+ Delay--;\r
+ } while (InfiniteWait || (Delay > 0));\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Check if the memory to be set.\r
+\r
+ @param[in] PciIo The PCI IO protocol instance.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+\r
+ @retval EFI_DEVICE_ERROR The memory setting met a issue.\r
+ @retval EFI_NOT_READY The memory is not set.\r
+ @retval EFI_TIMEOUT The memory setting is time out.\r
+ @retval EFI_SUCCESS The memory is correct set.\r
+\r
+**/\r
+EFI_STATUS\r
+AtaUdmStatusCheck (\r
+ IN EFI_PCI_IO_PROTOCOL *PciIo,\r
+ IN ATA_NONBLOCK_TASK *Task,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters\r
+ )\r
+{\r
+ UINT8 RegisterValue;\r
+ UINT16 IoPortForBmis;\r
+ EFI_STATUS Status;\r
+\r
+ Task->RetryTimes--;\r
+\r
+ Status = CheckStatusRegister (PciIo, IdeRegisters);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
+ RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
+\r
+ if ((RegisterValue & BMIS_ERROR) != 0) {\r
+ DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (!Task->InfiniteWait && (Task->RetryTimes == 0)) {\r
+ return EFI_TIMEOUT;\r
+ } else {\r
+ //\r
+ // The memory is not set.\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+}\r
\r
/**\r
Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\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 Read Flag used to determine the data transfer direction.\r
- Read equals 1, means data transferred from device to host;\r
- Read equals 0, means data transferred from host to device.\r
- @param DataBuffer A pointer to the source buffer for the data.\r
- @param DataLength The length of the data.\r
- @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
- @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
- @param Timeout The time to complete the command.\r
+ @param[in] Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data\r
+ structure.\r
+ @param[in] IdeRegisters A pointer to EFI_IDE_REGISTERS data structure.\r
+ @param[in] Read Flag used to determine the data transfer\r
+ direction. Read equals 1, means data transferred\r
+ from device to host;Read equals 0, means data\r
+ transferred from host to device.\r
+ @param[in] DataBuffer A pointer to the source buffer for the data.\r
+ @param[in] DataLength The length of the data.\r
+ @param[in] AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK data structure.\r
+ @param[in, out] AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.\r
+ @param[in] Timeout The time to complete the command, uses 100ns as a unit.\r
+ @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK\r
+ used by non-blocking mode.\r
\r
@retval EFI_SUCCESS the operation is successful.\r
@retval EFI_OUT_OF_RESOURCES Build PRD table failed\r
EFI_STATUS\r
EFIAPI\r
AtaUdmaInOut (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN BOOLEAN Read,\r
- IN VOID *DataBuffer,\r
- IN UINT64 DataLength,\r
- IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
- IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
- IN UINT64 Timeout\r
+ IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,\r
+ IN EFI_IDE_REGISTERS *IdeRegisters,\r
+ IN BOOLEAN Read,\r
+ IN VOID *DataBuffer,\r
+ IN UINT64 DataLength,\r
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,\r
+ IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,\r
+ IN UINT64 Timeout,\r
+ IN ATA_NONBLOCK_TASK *Task\r
)\r
{\r
EFI_STATUS Status;\r
UINT16 IoPortForBmis;\r
UINT16 IoPortForBmid;\r
\r
- UINT8 RegisterValue;\r
-\r
- EFI_ATA_DMA_PRD *PrdBaseAddr;\r
- UINTN PrdTableNum;\r
UINTN PrdTableSize;\r
EFI_PHYSICAL_ADDRESS PrdTableMapAddr;\r
VOID *PrdTableMap;\r
+ EFI_ATA_DMA_PRD *PrdBaseAddr;\r
+ EFI_ATA_DMA_PRD *TempPrdBaseAddr;\r
+ UINTN PrdTableNum;\r
\r
+ UINT8 RegisterValue;\r
UINTN PageCount;\r
UINTN ByteCount;\r
UINTN ByteRemaining;\r
-\r
UINT8 DeviceControl;\r
\r
VOID *BufferMap;\r
EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;\r
\r
UINT8 DeviceHead;\r
- UINT8 AtaCommand;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_TPL OldTpl;\r
+\r
\r
- Status = EFI_SUCCESS;\r
- PrdBaseAddr = NULL;\r
+ Status = EFI_SUCCESS;\r
+ PrdBaseAddr = NULL;\r
+ PrdTableMap = NULL;\r
+ BufferMap = NULL;\r
+ PageCount = 0;\r
+ PciIo = Instance->PciIo;\r
\r
if ((PciIo == NULL) || (IdeRegisters == NULL) || (DataBuffer == NULL) || (AtaCommandBlock == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // The data buffer should be even alignment\r
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking\r
+ // BlockIO tasks.\r
+ // Delay 1ms to simulate the blocking time out checking.\r
//\r
- if (((UINTN)DataBuffer & 0x1) != 0) {\r
- return EFI_INVALID_PARAMETER;\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {\r
+ AsyncNonBlockingTransferRoutine (NULL, Instance);\r
+ //\r
+ // Stall for 1 milliseconds.\r
+ //\r
+ MicroSecondDelay (1000);\r
}\r
+ gBS->RestoreTPL (OldTpl);\r
\r
//\r
- // Calculate the number of PRD entry.\r
- // Every entry in PRD table can specify a 64K memory region.\r
- //\r
- PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
-\r
- //\r
- // Make sure that the memory region of PRD table is not cross 64K boundary\r
+ // The data buffer should be even alignment\r
//\r
- PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
- if (PrdTableSize > 0x10000) {\r
+ if (((UINTN)DataBuffer & 0x1) != 0) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
- // Allocate buffer for PRD table initialization.\r
+ // Set relevant IO Port address.\r
//\r
- PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
- Status = PciIo->AllocateBuffer (\r
- PciIo,\r
- AllocateAnyPages,\r
- EfiBootServicesData,\r
- PageCount,\r
- (VOID **)&PrdBaseAddr,\r
- 0\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
- Status = PciIo->Map (\r
- PciIo,\r
- EfiPciIoOperationBusMasterCommonBuffer,\r
- PrdBaseAddr,\r
- &ByteCount,\r
- &PrdTableMapAddr,\r
- &PrdTableMap\r
- );\r
- if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
- //\r
- // If the data length actually mapped is not equal to the requested amount,\r
- // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
- // Can't handle this case.\r
- //\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
+ IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
+ IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
+ IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
\r
//\r
- // Map the host address of DataBuffer to DMA master address.\r
+ // For Blocking mode, start the command.\r
+ // For non-blocking mode, when the command is not started, start it, otherwise\r
+ // go to check the status.\r
//\r
- if (Read) {\r
- PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- PciIoOperation = EfiPciIoOperationBusMasterRead;\r
- }\r
+ if (((Task != NULL) && (!Task->IsStart)) || (Task == NULL)) {\r
+ //\r
+ // Calculate the number of PRD entry.\r
+ // Every entry in PRD table can specify a 64K memory region.\r
+ //\r
+ PrdTableNum = (UINTN)(RShiftU64(DataLength, 16) + 1);\r
\r
- ByteCount = (UINTN)DataLength;\r
- Status = PciIo->Map (\r
- PciIo,\r
- PciIoOperation,\r
- DataBuffer,\r
- &ByteCount,\r
- &BufferMapAddress,\r
- &BufferMap\r
- );\r
- if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
- PciIo->Unmap (PciIo, PrdTableMap);\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ //\r
+ // Make sure that the memory region of PRD table is not cross 64K boundary\r
+ //\r
+ PrdTableSize = PrdTableNum * sizeof (EFI_ATA_DMA_PRD);\r
+ if (PrdTableSize > 0x10000) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- //\r
- // According to Ata spec, it requires the buffer address and size to be even.\r
- //\r
- ASSERT ((BufferMapAddress & 0x1) == 0);\r
- ASSERT ((ByteCount & 0x1) == 0);\r
+ //\r
+ // Allocate buffer for PRD table initialization.\r
+ //\r
+ PageCount = EFI_SIZE_TO_PAGES (PrdTableSize);\r
+ Status = PciIo->AllocateBuffer (\r
+ PciIo,\r
+ AllocateAnyPages,\r
+ EfiBootServicesData,\r
+ PageCount,\r
+ (VOID **)&PrdBaseAddr,\r
+ 0\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- //\r
- // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
- //\r
- ByteRemaining = ByteCount;\r
- while (ByteRemaining != 0) {\r
- if (ByteRemaining <= 0x10000) {\r
- PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
- PrdBaseAddr->ByteCount = (UINT16) ByteRemaining;\r
- PrdBaseAddr->EndOfTable = 0x8000;\r
- break;\r
+ ByteCount = EFI_PAGES_TO_SIZE (PageCount);\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ EfiPciIoOperationBusMasterCommonBuffer,\r
+ PrdBaseAddr,\r
+ &ByteCount,\r
+ &PrdTableMapAddr,\r
+ &PrdTableMap\r
+ );\r
+ if (EFI_ERROR (Status) || (ByteCount != EFI_PAGES_TO_SIZE (PageCount))) {\r
+ //\r
+ // If the data length actually mapped is not equal to the requested amount,\r
+ // it means the DMA operation may be broken into several discontinuous smaller chunks.\r
+ // Can't handle this case.\r
+ //\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- PrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
- PrdBaseAddr->ByteCount = (UINT16) 0x0;\r
+ ZeroMem ((VOID *) ((UINTN) PrdBaseAddr), ByteCount);\r
\r
- ByteRemaining -= 0x10000;\r
- BufferMapAddress += 0x10000;\r
- PrdBaseAddr++;\r
- }\r
+ //\r
+ // Map the host address of DataBuffer to DMA master address.\r
+ //\r
+ if (Read) {\r
+ PciIoOperation = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ PciIoOperation = EfiPciIoOperationBusMasterRead;\r
+ }\r
\r
- //\r
- // Start to enable the DMA operation\r
- //\r
- DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
- AtaCommand = AtaCommandBlock->AtaCommand;\r
+ ByteCount = (UINTN)DataLength;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ PciIoOperation,\r
+ DataBuffer,\r
+ &ByteCount,\r
+ &BufferMapAddress,\r
+ &BufferMap\r
+ );\r
+ if (EFI_ERROR (Status) || (ByteCount != DataLength)) {\r
+ PciIo->Unmap (PciIo, PrdTableMap);\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
+ //\r
+ // According to Ata spec, it requires the buffer address and size to be even.\r
+ //\r
+ ASSERT ((BufferMapAddress & 0x1) == 0);\r
+ ASSERT ((ByteCount & 0x1) == 0);\r
\r
- //\r
- // Enable interrupt to support UDMA\r
- //\r
- DeviceControl = 0;\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+ //\r
+ // Fill the PRD table with appropriate bus master address of data buffer and data length.\r
+ //\r
+ ByteRemaining = ByteCount;\r
+ TempPrdBaseAddr = PrdBaseAddr;\r
+ while (ByteRemaining != 0) {\r
+ if (ByteRemaining <= 0x10000) {\r
+ TempPrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
+ TempPrdBaseAddr->ByteCount = (UINT16) ByteRemaining;\r
+ TempPrdBaseAddr->EndOfTable = 0x8000;\r
+ break;\r
+ }\r
\r
- IoPortForBmic = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIC_OFFSET);\r
- IoPortForBmis = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMIS_OFFSET);\r
- IoPortForBmid = (UINT16) (IdeRegisters->BusMasterBaseAddr + BMID_OFFSET);\r
+ TempPrdBaseAddr->RegionBaseAddr = (UINT32) ((UINTN) BufferMapAddress);\r
+ TempPrdBaseAddr->ByteCount = (UINT16) 0x0;\r
\r
- //\r
- // Read BMIS register and clear ERROR and INTR bit\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+ ByteRemaining -= 0x10000;\r
+ BufferMapAddress += 0x10000;\r
+ TempPrdBaseAddr++;\r
+ }\r
\r
- //\r
- // Set the base address to BMID register\r
- //\r
- IdeWritePortDW(PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
+ //\r
+ // Start to enable the DMA operation\r
+ //\r
+ DeviceHead = AtaCommandBlock->AtaDeviceHead;\r
\r
- //\r
- // Set BMIC register to identify the operation direction\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- if (Read) {\r
- RegisterValue |= BMIC_NREAD;\r
- } else {\r
- RegisterValue &= ~((UINT8) BMIC_NREAD);\r
- }\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+ IdeWritePortB (PciIo, IdeRegisters->Head, (UINT8)(0xe0 | DeviceHead));\r
\r
- //\r
- // Issue ATA command\r
- //\r
- Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
+ //\r
+ // Enable interrupt to support UDMA\r
+ //\r
+ DeviceControl = 0;\r
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
\r
- if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
- }\r
+ //\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+ IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
\r
- //\r
- // Set START bit of BMIC register\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- RegisterValue |= BMIC_START;\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+ //\r
+ // Set the base address to BMID register\r
+ //\r
+ IdeWritePortDW (PciIo, IoPortForBmid, (UINT32)PrdTableMapAddr);\r
\r
- //\r
- // Check the INTERRUPT and ERROR bit of BMIS\r
- // Max transfer number of sectors for one command is 65536(32Mbyte),\r
- // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
- // So set the variable Count to 2000, for about 2 second Timeout time.\r
- //\r
- Timeout = 2000;\r
- while (TRUE) {\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
+ //\r
+ // Set BMIC register to identify the operation direction\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ if (Read) {\r
+ RegisterValue |= BMIC_NREAD;\r
+ } else {\r
+ RegisterValue &= ~((UINT8) BMIC_NREAD);\r
+ }\r
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
+\r
+ if (Task != NULL) {\r
+ Task->Map = BufferMap;\r
+ Task->TableMap = PrdTableMap;\r
+ Task->MapBaseAddress = PrdBaseAddr;\r
+ Task->PageCount = PageCount;\r
+ Task->IsStart = TRUE;\r
+ }\r
\r
- if (((RegisterValue & BMIS_ERROR) != 0) || (Timeout == 0)) {\r
- DEBUG ((EFI_D_ERROR, "ATA UDMA operation fails\n"));\r
+ //\r
+ // Issue ATA command\r
+ //\r
+ Status = AtaIssueCommand (PciIo, IdeRegisters, AtaCommandBlock, Timeout);\r
+\r
+ if (EFI_ERROR (Status)) {\r
Status = EFI_DEVICE_ERROR;\r
- break;\r
+ goto Exit;\r
}\r
\r
- if ((RegisterValue & BMIS_INTERRUPT) != 0) {\r
- Status = EFI_SUCCESS;\r
- break;\r
+ Status = CheckStatusRegister (PciIo, IdeRegisters);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
}\r
//\r
- // Stall for 1 milliseconds.\r
+ // Set START bit of BMIC register\r
//\r
- MicroSecondDelay (1000);\r
- Timeout--;\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ RegisterValue |= BMIC_START;\r
+ IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+\r
}\r
\r
//\r
- // Read BMIS register and clear ERROR and INTR bit\r
+ // Check the INTERRUPT and ERROR bit of BMIS\r
//\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmis);\r
- RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
- IdeWritePortB(PciIo, IoPortForBmis, RegisterValue);\r
+ if (Task != NULL) {\r
+ Status = AtaUdmStatusCheck (PciIo, Task, IdeRegisters);\r
+ } else {\r
+ Status = AtaUdmStatusWait (PciIo, IdeRegisters, Timeout);\r
+ }\r
\r
//\r
- // Read Status Register of IDE device to clear interrupt\r
+ // For blocking mode, clear registers and free buffers.\r
+ // For non blocking mode, when the related registers have been set or time\r
+ // out, or a error has been happened, it needs to clear the register and free\r
+ // buffer.\r
//\r
- RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
+ if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+ //\r
+ // Read BMIS register and clear ERROR and INTR bit\r
+ //\r
+ RegisterValue = IdeReadPortB (PciIo, IoPortForBmis);\r
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
+ IdeWritePortB (PciIo, IoPortForBmis, RegisterValue);\r
\r
- //\r
- // Clear START bit of BMIC register\r
- //\r
- RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
- RegisterValue &= ~((UINT8) BMIC_START);\r
- IdeWritePortB(PciIo, IoPortForBmic, RegisterValue);\r
+ //\r
+ // Read Status Register of IDE device to clear interrupt\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IdeRegisters->CmdOrStatus);\r
\r
- //\r
- // Disable interrupt of Select device\r
- //\r
- DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
- DeviceControl |= ATA_CTLREG_IEN_L;\r
- IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
- //\r
- // Stall for 10 milliseconds.\r
- //\r
- MicroSecondDelay (10000);\r
+ //\r
+ // Clear START bit of BMIC register\r
+ //\r
+ RegisterValue = IdeReadPortB(PciIo, IoPortForBmic);\r
+ RegisterValue &= ~((UINT8) BMIC_START);\r
+ IdeWritePortB (PciIo, IoPortForBmic, RegisterValue);\r
+\r
+ //\r
+ // Disable interrupt of Select device\r
+ //\r
+ DeviceControl = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
+ DeviceControl |= ATA_CTLREG_IEN_L;\r
+ IdeWritePortB (PciIo, IdeRegisters->AltOrDev, DeviceControl);\r
+ //\r
+ // Stall for 10 milliseconds.\r
+ //\r
+ MicroSecondDelay (10000);\r
+\r
+ }\r
\r
Exit:\r
//\r
// Free all allocated resource\r
//\r
- PciIo->Unmap (PciIo, PrdTableMap);\r
- PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
- PciIo->Unmap (PciIo, BufferMap);\r
+ if ((Task == NULL) || Status != EFI_NOT_READY) {\r
+ if (Task != NULL) {\r
+ PciIo->Unmap (PciIo, Task->TableMap);\r
+ PciIo->FreeBuffer (PciIo, Task->PageCount, Task->MapBaseAddress);\r
+ PciIo->Unmap (PciIo, Task->Map);\r
+ } else {\r
+ PciIo->Unmap (PciIo, PrdTableMap);\r
+ PciIo->FreeBuffer (PciIo, PageCount, PrdBaseAddr);\r
+ PciIo->Unmap (PciIo, BufferMap);\r
+ }\r
\r
- //\r
- // Dump All Ide registers to ATA_STATUS_BLOCK\r
- //\r
- DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+ //\r
+ // Dump All Ide registers to ATA_STATUS_BLOCK\r
+ //\r
+ DumpAllIdeRegisters (PciIo, IdeRegisters, AtaStatusBlock);\r
+ }\r
\r
return Status;\r
}\r
while ((TempWordBuffer & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
IdeReadPortWMultiple (\r
PciIo,\r
- IdeRegisters->Data, \r
- 1, \r
+ IdeRegisters->Data,\r
+ 1,\r
&TempWordBuffer\r
);\r
TempWordBuffer = IdeReadPortB (PciIo, IdeRegisters->AltOrDev);\r
}\r
\r
/**\r
- This function is called by AtaPacketCommandExecute(). \r
+ This function is called by AtaPacketCommandExecute().\r
It is used to transfer data between host and device. The data direction is specified\r
by the fourth parameter.\r
\r
@param Read Flag used to determine the data transfer direction.\r
Read equals 1, means data transferred from device to host;\r
Read equals 0, means data transferred from host to device.\r
- @param Timeout Timeout value for wait DRQ ready before each data stream's transfer.\r
+ @param Timeout Timeout value for wait DRQ ready before each data stream's transfer\r
+ , uses 100ns as a unit.\r
\r
@retval EFI_SUCCESS data is transferred successfully.\r
@retval EFI_DEVICE_ERROR the device failed to transfer data.\r
if (ByteCount == 0) {\r
return EFI_SUCCESS;\r
}\r
- \r
+\r
PtrBuffer = Buffer;\r
RequiredWordCount = (UINT32)RShiftU64(ByteCount, 1);\r
//\r
PtrBuffer += WordCount;\r
ActualWordCount += WordCount;\r
}\r
- \r
+\r
if (Read) {\r
//\r
// In the case where the drive wants to send more data than we need to read,\r
//\r
// After data transfer is completed, normally, DRQ bit should clear.\r
//\r
- Status = DRQClear2 (PciIo, IdeRegisters, Timeout);\r
+ Status = DRQClear (PciIo, IdeRegisters, Timeout);\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
}\r
- \r
- return Status;\r
-}\r
-\r
-/**\r
- Sumbit ATAPI request sense command.\r
-\r
- @param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
- @param[in] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to\r
- store the IDE i/o port registers' base addresses\r
- @param[in] Channel The channel number of device.\r
- @param[in] Device The device number of device.\r
- @param[in] SenseData A pointer to store sense data.\r
- @param[in] SenseDataLength The sense data length.\r
- @param[in] Timeout The timeout value to execute this cmd.\r
-\r
- @retval EFI_SUCCESS Send out the ATAPI packet command successfully.\r
- @retval EFI_DEVICE_ERROR The device failed to send data.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AtaPacketRequestSense (\r
- IN EFI_PCI_IO_PROTOCOL *PciIo,\r
- IN EFI_IDE_REGISTERS *IdeRegisters,\r
- IN UINT8 Channel,\r
- IN UINT8 Device,\r
- IN VOID *SenseData,\r
- IN UINT8 SenseDataLength,\r
- IN UINT64 Timeout\r
- )\r
-{\r
- EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet;\r
- UINT8 Cdb[12];\r
- EFI_STATUS Status;\r
-\r
- ZeroMem (&Packet, sizeof (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
- ZeroMem (Cdb, 12);\r
-\r
- Cdb[0] = ATA_CMD_REQUEST_SENSE;\r
- Cdb[4] = SenseDataLength;\r
-\r
- Packet.Timeout = Timeout;\r
- Packet.Cdb = Cdb;\r
- Packet.CdbLength = 12;\r
- Packet.DataDirection = EFI_EXT_SCSI_DATA_DIRECTION_READ;\r
- Packet.InDataBuffer = SenseData;\r
- Packet.InTransferLength = SenseDataLength;\r
-\r
- Status = AtaPacketCommandExecute (PciIo, IdeRegisters, Channel, Device, &Packet);\r
\r
return Status;\r
}\r
\r
/**\r
- This function is used to send out ATAPI commands conforms to the Packet Command \r
+ This function is used to send out ATAPI commands conforms to the Packet Command\r
with PIO Data In Protocol.\r
\r
@param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
)\r
{\r
- EFI_STATUS PacketCommandStatus;\r
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
EFI_STATUS Status;\r
UINT8 Count;\r
// Send out ATAPI command packet\r
//\r
for (Count = 0; Count < 6; Count++) {\r
- IdeWritePortW (PciIo, IdeRegisters->Data, *((UINT16*)PacketCommand + Count)); \r
+ IdeWritePortW (PciIo, IdeRegisters->Data, *((UINT16*)PacketCommand + Count));\r
//\r
// Stall for 10 microseconds.\r
//\r
// Read/Write the data of ATAPI Command\r
//\r
if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
- PacketCommandStatus = AtaPacketReadWrite (\r
- PciIo,\r
- IdeRegisters,\r
- Packet->InDataBuffer,\r
- Packet->InTransferLength,\r
- TRUE,\r
- Packet->Timeout\r
- );\r
+ Status = AtaPacketReadWrite (\r
+ PciIo,\r
+ IdeRegisters,\r
+ Packet->InDataBuffer,\r
+ Packet->InTransferLength,\r
+ TRUE,\r
+ Packet->Timeout\r
+ );\r
} else {\r
- PacketCommandStatus = AtaPacketReadWrite (\r
- PciIo,\r
- IdeRegisters,\r
- Packet->OutDataBuffer,\r
- Packet->OutTransferLength,\r
- FALSE,\r
- Packet->Timeout\r
- );\r
+ Status = AtaPacketReadWrite (\r
+ PciIo,\r
+ IdeRegisters,\r
+ Packet->OutDataBuffer,\r
+ Packet->OutTransferLength,\r
+ FALSE,\r
+ Packet->Timeout\r
+ );\r
}\r
\r
- if (!EFI_ERROR (PacketCommandStatus)) {\r
- return PacketCommandStatus;\r
- }\r
-\r
- //\r
- // Return SenseData if PacketCommandStatus matches\r
- // the following return codes.\r
- //\r
- if ((PacketCommandStatus == EFI_BAD_BUFFER_SIZE) ||\r
- (PacketCommandStatus == EFI_DEVICE_ERROR) ||\r
- (PacketCommandStatus == EFI_TIMEOUT)) {\r
-\r
- //\r
- // avoid submit request sense command continuously.\r
- //\r
- if ((Packet->SenseData == NULL) || (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_REQUEST_SENSE)) {\r
- return PacketCommandStatus;\r
- }\r
-\r
- AtaPacketRequestSense (\r
- PciIo,\r
- IdeRegisters,\r
- Channel,\r
- Device,\r
- Packet->SenseData,\r
- Packet->SenseDataLength,\r
- Packet->Timeout\r
- );\r
- }\r
-\r
- return PacketCommandStatus;\r
+ return Status;\r
}\r
\r
\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
IN UINT8 Device,\r
IN EFI_ATA_DRIVE_PARMS *DriveParameters,\r
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock\r
- \r
)\r
{\r
EFI_STATUS Status;\r
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_INIT_DRIVE_PARAM;\r
AtaCommandBlock.AtaSectorCount = DriveParameters->Sector;\r
AtaCommandBlock.AtaDeviceHead = (UINT8) ((Device << 0x4) + DriveParameters->Heads);\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
//\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
+ );\r
return EFI_DEVICE_ERROR;\r
}\r
\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
+ );\r
+\r
LBAMid = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderLsb);\r
LBAHigh = IdeReadPortB (Instance->PciIo, Instance->IdeRegisters[Channel].CylinderMsb);\r
\r
// The threshold exceeded condition is not detected by the device\r
//\r
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));\r
-\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
+ );\r
} else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
//\r
// The threshold exceeded condition is detected by the device\r
//\r
DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
+ );\r
}\r
\r
return EFI_SUCCESS;\r
//\r
// S.M.A.R.T is not supported by the device\r
//\r
- DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at [%a] channel [%a] device!\n", \r
+ DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at [%a] channel [%a] device!\n",\r
(Channel == 1) ? "secondary" : "primary", (Device == 1) ? "slave" : "master"));\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
+ );\r
} else {\r
//\r
// Check if the feature is enabled. If not, then enable S.M.A.R.T.\r
//\r
if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {\r
\r
+ REPORT_STATUS_CODE (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)\r
+ );\r
+\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
\r
AtaCommandBlock.AtaCommand = ATA_CMD_SMART;\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
if (!EFI_ERROR (Status)) {\r
&Instance->IdeRegisters[Channel],\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
if (!EFI_ERROR (Status)) {\r
Status = IdeAtaSmartReturnStatusCheck (\r
}\r
}\r
\r
- DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at [%a] channel [%a] device!\n", \r
+ DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at [%a] channel [%a] device!\n",\r
(Channel == 1) ? "secondary" : "primary", (Device == 1) ? "slave" : "master"));\r
\r
}\r
return ;\r
}\r
\r
+\r
/**\r
Sends out an ATA Identify Command to the specified device.\r
\r
@retval EFI_SUCCESS Identify ATA device successfully.\r
@retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.\r
@retval EFI_OUT_OF_RESOURCES Allocate memory failed.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_ATA_COMMAND_BLOCK AtaCommandBlock; \r
+ EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;\r
AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
\r
TRUE,\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
to fill in the Media data structure of the Block I/O Protocol interface.\r
\r
There are 5 steps to reach such objective:\r
- 1. Sends out the ATAPI Identify Command to the specified device. \r
+ 1. Sends out the ATAPI Identify Command to the specified device.\r
Only ATAPI device responses to this command. If the command succeeds,\r
- it returns the Identify data structure which filled with information \r
- about the device. Since the ATAPI device contains removable media, \r
+ it returns the Identify data structure which filled with information\r
+ about the device. Since the ATAPI device contains removable media,\r
the only meaningful information is the device module name.\r
2. Sends out ATAPI Inquiry Packet Command to the specified device.\r
This command will return inquiry data of the device, which contains\r
the device type information.\r
3. Allocate sense data space for future use. We don't detect the media\r
- presence here to improvement boot performance, especially when CD \r
+ presence here to improvement boot performance, especially when CD\r
media is present. The media detection will be performed just before\r
each BLK_IO read/write\r
- \r
+\r
@param Instance A pointer to ATA_ATAPI_PASS_THRU_INSTANCE data structure.\r
@param Channel The channel number of device.\r
@param Device The device number of device.\r
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;\r
\r
ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
- \r
+\r
AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;\r
AtaCommandBlock.AtaDeviceHead = (UINT8)(Device << 0x4);\r
\r
TRUE,\r
&AtaCommandBlock,\r
AtaStatusBlock,\r
- ATA_ATAPI_TIMEOUT\r
+ ATA_ATAPI_TIMEOUT,\r
+ NULL\r
);\r
\r
return Status;\r
IdeInit = Instance->IdeControllerInit;\r
PciIo = Instance->PciIo;\r
\r
- for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) { \r
+ for (IdeDevice = 0; IdeDevice < EfiIdeMaxDevice; IdeDevice++) {\r
//\r
// Send ATA Device Execut Diagnostic command.\r
// This command should work no matter DRDY is ready or not\r
//\r
IdeWritePortB (PciIo, IdeRegisters->CmdOrStatus, ATA_CMD_EXEC_DRIVE_DIAG);\r
- \r
+\r
Status = WaitForBSYClear (PciIo, IdeRegisters, 350000000);\r
if (EFI_ERROR (Status)) {\r
DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));\r
// if identifying ata device is failure, then try to send identify packet cmd.\r
//\r
if (EFI_ERROR (Status)) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));\r
+\r
DeviceType = EfiIdeCdrom;\r
Status = AtaIdentifyPacket (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
}\r
if (EFI_ERROR (Status)) {\r
DeviceType = EfiIdeHarddisk;\r
Status = AtaIdentify (Instance, IdeChannel, IdeDevice, &Buffer, NULL);\r
- } \r
+ }\r
}\r
\r
if (EFI_ERROR (Status)) {\r
// No device is found at this port\r
//\r
continue;\r
- } \r
- \r
- DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n", \r
+ }\r
+\r
+ DEBUG ((EFI_D_INFO, "[%a] channel [%a] [%a] device\n",\r
(IdeChannel == 1) ? "secondary" : "primary ", (IdeDevice == 1) ? "slave " : "master",\r
DeviceType == EfiIdeCdrom ? "cdrom " : "harddisk"));\r
-\r
//\r
// If the device is a hard disk, then try to enable S.M.A.R.T feature\r
//\r
- if (DeviceType == EfiIdeHarddisk) {\r
+ if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {\r
IdeAtaSmartSupport (\r
Instance,\r
IdeChannel,\r
continue;\r
}\r
}\r
- \r
+\r
//\r
// Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
// be set together. Only one DMA mode can be set to a device. If setting\r
TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;\r
TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);\r
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
continue;\r
TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;\r
TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
Status = SetDeviceTransferMode (Instance, IdeChannel, IdeDevice, &TransferMode, NULL);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));\r
continue;\r
}\r
}\r
- \r
+\r
//\r
// Set Parameters for the device:\r
// 1) Init\r
DriveParameters.Sector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->sectors_per_track;\r
DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->heads - 1);\r
DriveParameters.MultipleSector = (UINT8) ((ATA5_IDENTIFY_DATA *)(&Buffer.AtaData))->multi_sector_cmd_max_sct_cnt;\r
- \r
+\r
Status = SetDriveParameters (Instance, IdeChannel, IdeDevice, &DriveParameters, NULL);\r
}\r
- \r
+\r
//\r
// Set IDE controller Timing Blocks in the PCI Configuration Space\r
//\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
+\r
+ if (DeviceType == EfiIdeHarddisk) {\r
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));\r
+ }\r
}\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
Initialize ATA host controller at IDE mode.\r
- \r
- The function is designed to initialize ATA host controller. \r
- \r
+\r
+ The function is designed to initialize ATA host controller.\r
+\r
@param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.\r
\r
**/\r
IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance\r
)\r
{\r
- BOOLEAN EnumAll;\r
EFI_STATUS Status;\r
EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;\r
EFI_PCI_IO_PROTOCOL *PciIo;\r
\r
IdeInit = Instance->IdeControllerInit;\r
PciIo = Instance->PciIo;\r
- EnumAll = IdeInit->EnumAll;\r
Channel = IdeInit->ChannelCount;\r
\r
//\r