PtrBuffer += WordCount;\r
ActualWordCount += WordCount;\r
}\r
+ \r
+ if (Read) {\r
+ //\r
+ // In the case where the drive wants to send more data than we need to read,\r
+ // the DRQ bit will be set and cause delays from DRQClear2().\r
+ // We need to read data from the drive until it clears DRQ so we can move on.\r
+ //\r
+ AtapiReadPendingData (IdeDev);\r
+ }\r
\r
//\r
// After data transfer is completed, normally, DRQ bit should clear.\r
Sends out ATAPI Test Unit Ready Packet Command to the specified device\r
to find out whether device is accessible.\r
\r
- @param[in] *IdeDev\r
- pointer pointing to IDE_BLK_IO_DEV data structure, used\r
- to record all the information of the IDE device.\r
+ @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+ to record all the information of the IDE device.\r
+ @param[in] *SenseCount Sense count for this packet command\r
\r
- @retval EFI_SUCCESS\r
- device is accessible.\r
- \r
- @retval EFI_DEVICE_ERROR\r
- device is not accessible.\r
+ @retval EFI_SUCCESS Device is accessible.\r
+ @retval EFI_DEVICE_ERROR Device is not accessible.\r
\r
**/\r
EFI_STATUS\r
AtapiTestUnitReady (\r
- IN IDE_BLK_IO_DEV *IdeDev\r
+ IN IDE_BLK_IO_DEV *IdeDev,\r
+ OUT UINTN *SenseCount\r
)\r
{\r
ATAPI_PACKET_COMMAND Packet;\r
EFI_STATUS Status;\r
\r
+ *SenseCount = 0;\r
+\r
//\r
// fill command packet\r
//\r
// send command packet\r
//\r
Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);\r
- return Status;\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = AtapiRequestSense (IdeDev, SenseCount);\r
+ if (EFI_ERROR (Status)) {\r
+ *SenseCount = 0;\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
//\r
// Ptr is word-based pointer\r
//\r
- Ptr += sizeof (REQUEST_SENSE_DATA) / 2;\r
+ Ptr += (sizeof (REQUEST_SENSE_DATA) + 1) >> 1;\r
\r
} else {\r
//\r
if the Read Capacity Command failed, the Sense data must be requested\r
and be analyzed to determine if the Read Capacity Command should retry.\r
\r
- @param[in] *IdeDev\r
- pointer pointing to IDE_BLK_IO_DEV data structure, used\r
- to record all the information of the IDE device.\r
+ @param[in] *IdeDev Pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+ to record all the information of the IDE device.\r
+ @param[in] SenseCount Sense count for this packet command\r
\r
- @retval EFI_SUCCESS\r
- Read Capacity Command finally completes successfully.\r
- \r
- @retval EFI_DEVICE_ERROR\r
- Read Capacity Command failed because of device error.\r
+ @retval EFI_SUCCESS Read Capacity Command finally completes successfully.\r
+ @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.\r
\r
- @note\r
- parameter "IdeDev" will be updated in this function.\r
+ @note Parameter "IdeDev" will be updated in this function.\r
\r
TODO: EFI_NOT_READY - add return value to function comment\r
**/\r
EFI_STATUS\r
AtapiReadCapacity (\r
- IN IDE_BLK_IO_DEV *IdeDev\r
+ IN IDE_BLK_IO_DEV *IdeDev,\r
+ OUT UINTN *SenseCount\r
)\r
{\r
//\r
// status returned by Read Capacity Packet Command\r
//\r
EFI_STATUS Status;\r
+ EFI_STATUS SenseStatus;\r
ATAPI_PACKET_COMMAND Packet;\r
\r
//\r
READ_CAPACITY_DATA Data;\r
READ_FORMAT_CAPACITY_DATA FormatData;\r
\r
+ *SenseCount = 0;\r
+\r
ZeroMem (&Data, sizeof (Data));\r
ZeroMem (&FormatData, sizeof (FormatData));\r
\r
ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
Packet.Inquiry.opcode = READ_CAPACITY;\r
Status = AtapiPacketCommandIn (\r
- IdeDev,\r
- &Packet,\r
- (UINT16 *) &Data,\r
- sizeof (READ_CAPACITY_DATA),\r
- ATAPITIMEOUT\r
- );\r
+ IdeDev,\r
+ &Packet,\r
+ (UINT16 *) &Data,\r
+ sizeof (READ_CAPACITY_DATA),\r
+ ATAPITIMEOUT\r
+ );\r
\r
} else {\r
//\r
Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;\r
Packet.ReadFormatCapacity.allocation_length_lo = 12;\r
Status = AtapiPacketCommandIn (\r
- IdeDev,\r
- &Packet,\r
- (UINT16 *) &FormatData,\r
- sizeof (READ_FORMAT_CAPACITY_DATA),\r
- ATAPITIMEOUT\r
- );\r
+ IdeDev,\r
+ &Packet,\r
+ (UINT16 *) &FormatData,\r
+ sizeof (READ_FORMAT_CAPACITY_DATA),\r
+ ATAPITIMEOUT\r
+ );\r
}\r
\r
- if (!EFI_ERROR (Status)) {\r
-\r
- if (IdeDev->Type == IdeCdRom) {\r
-\r
- IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |\r
- (Data.LastLba2 << 16) |\r
- (Data.LastLba1 << 8) |\r
- Data.LastLba0;\r
-\r
- if (IdeDev->BlkIo.Media->LastBlock != 0) {\r
-\r
- IdeDev->BlkIo.Media->BlockSize = (Data.BlockSize3 << 24) |\r
- (Data.BlockSize2 << 16) |\r
- (Data.BlockSize1 << 8) |\r
- Data.BlockSize0;\r
+ if (Status == EFI_TIMEOUT) {\r
+ *SenseCount = 0;\r
+ return Status;\r
+ }\r
\r
- IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
- } else {\r
- IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ SenseStatus = AtapiRequestSense (IdeDev, SenseCount);\r
\r
- IdeDev->BlkIo.Media->ReadOnly = TRUE;\r
+ if (!EFI_ERROR (SenseStatus)) {\r
\r
- //\r
- // Because the user data portion in the sector of the Data CD supported\r
- // is always 0x800\r
- //\r
- IdeDev->BlkIo.Media->BlockSize = 0x800;\r
- }\r
+ if (!EFI_ERROR (Status)) {\r
\r
- if (IdeDev->Type == IdeMagnetic) {\r
+ if (IdeDev->Type == IdeCdRom) {\r
\r
- if (FormatData.DesCode == 3) {\r
- IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
- IdeDev->BlkIo.Media->LastBlock = 0;\r
- } else {\r
+ IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |\r
+ (Data.LastLba2 << 16) |\r
+ (Data.LastLba1 << 8) |\r
+ Data.LastLba0;\r
\r
- IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |\r
- (FormatData.LastLba2 << 16) | \r
- (FormatData.LastLba1 << 8) |\r
- FormatData.LastLba0;\r
if (IdeDev->BlkIo.Media->LastBlock != 0) {\r
- IdeDev->BlkIo.Media->LastBlock--;\r
\r
- IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |\r
- (FormatData.BlockSize1 << 8) |\r
- FormatData.BlockSize0;\r
+ IdeDev->BlkIo.Media->BlockSize = (Data.BlockSize3 << 24) |\r
+ (Data.BlockSize2 << 16) |\r
+ (Data.BlockSize1 << 8) |\r
+ Data.BlockSize0;\r
\r
IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
} else {\r
IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
- //\r
- // Return EFI_NOT_READY operation succeeds but returned capacity is 0\r
- //\r
- return EFI_NOT_READY;\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- IdeDev->BlkIo.Media->BlockSize = 0x200;\r
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;\r
+\r
+ //\r
+ // Because the user data portion in the sector of the Data CD supported\r
+ // is always 0x800\r
+ //\r
+ IdeDev->BlkIo.Media->BlockSize = 0x800;\r
+ }\r
+\r
+ if (IdeDev->Type == IdeMagnetic) {\r
+\r
+ if (FormatData.DesCode == 3) {\r
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
+ IdeDev->BlkIo.Media->LastBlock = 0;\r
+ } else {\r
+\r
+ IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |\r
+ (FormatData.LastLba2 << 16) | \r
+ (FormatData.LastLba1 << 8) |\r
+ FormatData.LastLba0;\r
+ if (IdeDev->BlkIo.Media->LastBlock != 0) {\r
+ IdeDev->BlkIo.Media->LastBlock--;\r
+\r
+ IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |\r
+ (FormatData.BlockSize1 << 8) |\r
+ FormatData.BlockSize0;\r
+\r
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;\r
+ } else {\r
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
+ //\r
+ // Return EFI_NOT_READY operation succeeds but returned capacity is 0\r
+ //\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ IdeDev->BlkIo.Media->BlockSize = 0x200;\r
\r
+ }\r
}\r
}\r
\r
return EFI_SUCCESS;\r
\r
} else {\r
-\r
+ *SenseCount = 0;\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
OUT BOOLEAN *MediaChange\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_STATUS ReadCapacityStatus;\r
- EFI_BLOCK_IO_MEDIA OldMediaInfo;\r
- UINTN SenseCounts;\r
- UINTN RetryIndex;\r
- UINTN RetryTimes;\r
- UINTN MaximumRetryTimes;\r
- UINTN ReadyWaitFactor;\r
- BOOLEAN NeedRetry;\r
- //\r
- // a flag used to determine whether need to perform Read Capacity command.\r
- //\r
- BOOLEAN NeedReadCapacity;\r
- BOOLEAN WriteProtected;\r
+ EFI_STATUS Status;\r
+ EFI_STATUS CleanStateStatus;\r
+ EFI_BLOCK_IO_MEDIA OldMediaInfo;\r
+ UINTN RetryTimes;\r
+ UINTN RetryNotReady;\r
+ UINTN SenseCount;\r
+ SENSE_RESULT SResult;\r
+ BOOLEAN WriteProtected;\r
\r
+ CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
+ *MediaChange = FALSE;\r
//\r
- // init\r
+ // Retry for SenseDeviceNotReadyNeedRetry.\r
+ // Each retry takes 1s and we limit the upper boundary to\r
+ // 120 times about 2 min.\r
//\r
- CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (OldMediaInfo));\r
- // OldMediaInfo = *(IdeDev->BlkIo.Media);\r
- *MediaChange = FALSE;\r
- ReadCapacityStatus = EFI_DEVICE_ERROR;\r
+ RetryNotReady = 120;\r
\r
//\r
- // if there is no media, or media is not changed,\r
- // the request sense command will detect faster than read capacity command.\r
- // read capacity command can be bypassed, thus improve performance.\r
+ // Do Test Unit Ready\r
//\r
-\r
+ DoTUR:\r
//\r
- // Test Unit Ready command is used to detect whether device is accessible,\r
- // the device will produce corresponding Sense data.\r
+ // Retry 5 times\r
//\r
- for (RetryIndex = 0; RetryIndex < 2; RetryIndex++) {\r
-\r
- Status = AtapiTestUnitReady (IdeDev);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // skip the loop if test unit command succeeds.\r
- //\r
- break;\r
- }\r
+ RetryTimes = 5;\r
+ while (RetryTimes != 0) {\r
\r
- Status = AtapiSoftReset (IdeDev);\r
+ Status = AtapiTestUnitReady (IdeDev, &SenseCount);\r
\r
if (EFI_ERROR (Status)) {\r
- AtaSoftReset (IdeDev);\r
- }\r
- }\r
-\r
- SenseCounts = 0;\r
- NeedReadCapacity = TRUE;\r
-\r
- //\r
- // at most retry 5 times\r
- //\r
- MaximumRetryTimes = 5;\r
- RetryTimes = 1;\r
-\r
- for (RetryIndex = 0; \r
- (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);\r
- RetryIndex++) {\r
-\r
- Status = AtapiRequestSense (IdeDev, &SenseCounts);\r
-\r
- if (!EFI_ERROR (Status)) {\r
//\r
- // if first time there is no Sense Key, no need to read capacity any more\r
+ // Test Unit Ready error without sense data.\r
+ // For some devices, this means there's extra data\r
+ // that has not been read, so we read these extra\r
+ // data out before going on.\r
//\r
- if (!HaveSenseKey (IdeDev->SenseData, SenseCounts) &&\r
- (IdeDev->BlkIo.Media->MediaPresent)) {\r
-\r
- if (RetryIndex == 0) {\r
- NeedReadCapacity = FALSE;\r
- }\r
-\r
- } else {\r
+ CleanStateStatus = AtapiReadPendingData (IdeDev);\r
+ if (EFI_ERROR (CleanStateStatus)) {\r
//\r
- // No Media\r
+ // Busy wait failed, try again\r
//\r
- if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {\r
- NeedReadCapacity = FALSE;\r
- IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
- IdeDev->BlkIo.Media->LastBlock = 0;\r
+ RetryTimes--;\r
+ }\r
+ //\r
+ // Try again without counting down RetryTimes\r
+ //\r
+ continue;\r
+ } else {\r
+\r
+ ParseSenseData (IdeDev, SenseCount, &SResult);\r
+\r
+ switch (SResult) {\r
+ case SenseNoSenseKey:\r
+ if (IdeDev->BlkIo.Media->MediaPresent) {\r
+ goto Done;\r
} else {\r
//\r
- // Media Changed\r
- //\r
- if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {\r
- NeedReadCapacity = TRUE;\r
- IdeDev->BlkIo.Media->MediaId++;\r
- }\r
- //\r
- // Media Error\r
+ // Media present but the internal structure need refreshed.\r
+ // Try Read Capacity\r
//\r
- if (IsMediaError (IdeDev->SenseData, SenseCounts)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ goto DoRC;\r
+ }\r
+ break;\r
+\r
+ case SenseDeviceNotReadyNeedRetry:\r
+ if (--RetryNotReady == 0) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
+ gBS->Stall (1000 * STALL_1_MILLI_SECOND);\r
+ continue;\r
+ break;\r
+\r
+ case SenseNoMedia:\r
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
+ IdeDev->BlkIo.Media->LastBlock = 0;\r
+ goto Done;\r
+ break;\r
+\r
+ case SenseDeviceNotReadyNoRetry:\r
+ case SenseMediaError:\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ case SenseMediaChange:\r
+ IdeDev->BlkIo.Media->MediaId++;\r
+ goto DoRC;\r
+ break;\r
+\r
+ default:\r
+ RetryTimes--;\r
+ break;\r
}\r
- } else {\r
- //\r
- // retry once more, if request sense command met errors.\r
- //\r
- RetryTimes++;\r
}\r
}\r
\r
- if (NeedReadCapacity) {\r
- //\r
- // at most retry 5 times\r
- //\r
- MaximumRetryTimes = 5;\r
- //\r
- // initial retry twice\r
- //\r
- RetryTimes = 2;\r
- ReadyWaitFactor = 2;\r
-\r
- for (RetryIndex = 0;\r
- (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);\r
- RetryIndex++) {\r
+ return EFI_DEVICE_ERROR;\r
\r
- ReadCapacityStatus = AtapiReadCapacity (IdeDev);\r
+ //\r
+ // Do Read Capacity\r
+ //\r
+ DoRC:\r
+ RetryTimes = 5;\r
\r
- SenseCounts = 0;\r
+ while (RetryTimes != 0) {\r
\r
- if (!EFI_ERROR (ReadCapacityStatus)) {\r
- //\r
- // Read Capacity succeeded\r
- //\r
- break;\r
+ Status = AtapiReadCapacity (IdeDev, &SenseCount);\r
\r
+ if (EFI_ERROR (Status)) {\r
+ RetryTimes--;\r
+ continue;\r
} else {\r
\r
- if (ReadCapacityStatus == EFI_NOT_READY) {\r
- //\r
- // If device not ready, wait here... waiting time increases by retry\r
- // times.\r
- //\r
- gBS->Stall (ReadyWaitFactor * 2000 * STALL_1_MILLI_SECOND);\r
- ReadyWaitFactor++;\r
- //\r
- // retry once more\r
- //\r
- RetryTimes++;\r
- continue;\r
- }\r
- \r
- //\r
- // Other errors returned, requery sense data\r
- //\r
- Status = AtapiRequestSense (IdeDev, &SenseCounts);\r
-\r
- //\r
- // If Request Sense data failed, reset the device and retry.\r
- //\r
- if (EFI_ERROR (Status)) {\r
+ ParseSenseData (IdeDev, SenseCount, &SResult);\r
\r
- Status = AtapiSoftReset (IdeDev);\r
+ switch (SResult) {\r
+ case SenseNoSenseKey:\r
+ goto Done;\r
+ break;\r
\r
+ case SenseDeviceNotReadyNeedRetry:\r
//\r
- // if ATAPI soft reset fail,\r
- // use stronger reset mechanism -- ATA soft reset.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- AtaSoftReset (IdeDev);\r
- }\r
- //\r
- // retry once more\r
+ // We use Test Unit Ready to retry which\r
+ // is faster.\r
//\r
- RetryTimes++;\r
- continue;\r
- }\r
- \r
- //\r
- // No Media\r
- //\r
- if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {\r
+ goto DoTUR;\r
+ break;\r
\r
+ case SenseNoMedia:\r
IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
IdeDev->BlkIo.Media->LastBlock = 0;\r
- return EFI_NO_MEDIA;\r
- }\r
+ goto Done;\r
+ break;\r
\r
- if (IsMediaError (IdeDev->SenseData, SenseCounts)) {\r
+ case SenseDeviceNotReadyNoRetry:\r
+ case SenseMediaError:\r
return EFI_DEVICE_ERROR;\r
- }\r
- \r
- //\r
- // Media Changed\r
- //\r
- if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {\r
+\r
+ case SenseMediaChange:\r
IdeDev->BlkIo.Media->MediaId++;\r
- }\r
+ continue;\r
+ break;\r
\r
- if (!IsDriveReady (IdeDev->SenseData, SenseCounts, &NeedRetry)) {\r
- \r
- //\r
- // Drive not ready: if NeedRetry, then retry once more;\r
- // else return error\r
- //\r
- if (NeedRetry) {\r
- //\r
- // Stall 1 second to wait for drive becoming ready\r
- //\r
- gBS->Stall (1000 * STALL_1_MILLI_SECOND);\r
- //\r
- // reset retry variable to zero,\r
- // to make it retry for "drive in progress of becoming ready".\r
- //\r
- RetryIndex = 0;\r
- continue;\r
- } else {\r
- AtapiSoftReset (IdeDev);\r
- return EFI_DEVICE_ERROR;\r
- }\r
+ default:\r
+ RetryTimes--;\r
+ break;\r
}\r
- //\r
- // if read capacity fail not for above reasons, retry once more\r
- //\r
- RetryTimes++;\r
}\r
-\r
- }\r
- \r
- //\r
- // tell whether the readcapacity process is successful or not in the end\r
- //\r
- if (EFI_ERROR (ReadCapacityStatus)) {\r
- return EFI_DEVICE_ERROR;\r
}\r
- }\r
\r
+ return EFI_DEVICE_ERROR;\r
+\r
+ Done:\r
//\r
// the following code is to check the write-protected for LS120 media\r
//\r
);\r
}\r
\r
- return EFI_SUCCESS;\r
-\r
+ if (IdeDev->BlkIo.Media->MediaPresent) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NO_MEDIA;\r
+ }\r
}\r
\r
/**\r
//\r
// limit the data bytes that can be transferred by one Read(10) Command\r
//\r
- MaxBlock = (UINT16) (65536 / BlockSize);\r
+ MaxBlock = 65535;\r
\r
BlocksRemaining = NumberOfBlocks;\r
\r
\r
}\r
\r
-//\r
-// The following functions are a set of helper functions,\r
-// which are used to parse sense key returned by the device.\r
-//\r
-\r
/**\r
- TODO: Add function description\r
+ This function is used to parse sense data. Only the first\r
+ sense data is honoured.\r
\r
- @param SenseData TODO: add argument description\r
- @param SenseCounts TODO: add argument description\r
+ @param[in] IdeDev Indicates the calling context.\r
+ @param[in] SenseCount Count of sense data.\r
+ @param[out] Result The parsed result.\r
\r
- TODO: add return values\r
+ @retval EFI_SUCCESS Successfully parsed.\r
+ @retval EFI_INVALID_PARAMETER Count of sense data is zero.\r
\r
**/\r
-BOOLEAN\r
-IsNoMedia (\r
- IN REQUEST_SENSE_DATA *SenseData,\r
- IN UINTN SenseCounts\r
+EFI_STATUS\r
+ParseSenseData (\r
+ IN IDE_BLK_IO_DEV *IdeDev,\r
+ IN UINTN SenseCount,\r
+ OUT SENSE_RESULT *Result\r
)\r
{\r
- REQUEST_SENSE_DATA *SensePointer;\r
- UINTN Index;\r
- BOOLEAN NoMedia;\r
-\r
- NoMedia = FALSE;\r
- SensePointer = SenseData;\r
-\r
- for (Index = 0; Index < SenseCounts; Index++) {\r
- //\r
- // Sense Key is SK_NOT_READY (0x2),\r
- // Additional Sense Code is ASC_NO_MEDIA (0x3A)\r
- //\r
- if ((SensePointer->sense_key == SK_NOT_READY) &&\r
- (SensePointer->addnl_sense_code == ASC_NO_MEDIA)) {\r
-\r
- NoMedia = TRUE;\r
- }\r
+ REQUEST_SENSE_DATA *SenseData;\r
\r
- SensePointer++;\r
+ if (SenseCount == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- return NoMedia;\r
-}\r
-\r
-/**\r
- Test if the device meets a media error after media changed\r
-\r
- @param[in] *SenseData\r
- pointer pointing to ATAPI device sense data list.\r
- @param[in] SenseCounts\r
- sense data number of the list \r
-\r
- @retval TRUE Device meets a media error\r
- @retval FALSE No media error\r
-\r
-**/\r
-BOOLEAN\r
-IsMediaError (\r
- IN REQUEST_SENSE_DATA *SenseData,\r
- IN UINTN SenseCounts\r
- )\r
-{\r
- REQUEST_SENSE_DATA *SensePointer;\r
- UINTN Index;\r
- BOOLEAN IsError;\r
-\r
- IsError = FALSE;\r
- SensePointer = SenseData;\r
-\r
- for (Index = 0; Index < SenseCounts; Index++) {\r
-\r
- switch (SensePointer->sense_key) {\r
-\r
- case SK_MEDIUM_ERROR:\r
- //\r
- // Sense Key is SK_MEDIUM_ERROR (0x3)\r
- //\r
- switch (SensePointer->addnl_sense_code) {\r
- case ASC_MEDIA_ERR1:\r
- case ASC_MEDIA_ERR2:\r
- case ASC_MEDIA_ERR3:\r
- case ASC_MEDIA_ERR4:\r
- IsError = TRUE;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
+ //\r
+ // Only use the first sense data\r
+ //\r
+ SenseData = IdeDev->SenseData;\r
+ *Result = SenseOtherSense;\r
\r
+ switch (SenseData->sense_key) {\r
+ case SK_NO_SENSE:\r
+ *Result = SenseNoSenseKey;\r
+ break;\r
+ case SK_NOT_READY:\r
+ switch (SenseData->addnl_sense_code) {\r
+ case ASC_NO_MEDIA:\r
+ *Result = SenseNoMedia;\r
break;\r
-\r
- case SK_NOT_READY:\r
- //\r
- // Sense Key is SK_NOT_READY (0x2)\r
- //\r
- switch (SensePointer->addnl_sense_code) {\r
- //\r
- // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)\r
- //\r
- case ASC_MEDIA_UPSIDE_DOWN:\r
- IsError = TRUE;\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
+ case ASC_MEDIA_UPSIDE_DOWN:\r
+ *Result = SenseMediaError;\r
break;\r
-\r
- default:\r
+ case ASC_NOT_READY:\r
+ if (SenseData->addnl_sense_code_qualifier == ASCQ_IN_PROGRESS) {\r
+ *Result = SenseDeviceNotReadyNeedRetry;\r
+ } else {\r
+ *Result = SenseDeviceNotReadyNoRetry;\r
+ }\r
break;\r
}\r
-\r
- SensePointer++;\r
- }\r
-\r
- return IsError;\r
-}\r
-\r
-/**\r
- TODO: Add function description\r
-\r
- @param SenseData TODO: add argument description\r
- @param SenseCounts TODO: add argument description\r
-\r
- TODO: add return values\r
-\r
-**/\r
-BOOLEAN\r
-IsMediaChange (\r
- IN REQUEST_SENSE_DATA *SenseData,\r
- IN UINTN SenseCounts\r
- )\r
-{\r
- REQUEST_SENSE_DATA *SensePointer;\r
- UINTN Index;\r
- BOOLEAN IsMediaChange;\r
-\r
- IsMediaChange = FALSE;\r
- SensePointer = SenseData;\r
-\r
- for (Index = 0; Index < SenseCounts; Index++) {\r
- //\r
- // Sense Key is SK_UNIT_ATTENTION (0x6)\r
- //\r
- if ((SensePointer->sense_key == SK_UNIT_ATTENTION) &&\r
- (SensePointer->addnl_sense_code == ASC_MEDIA_CHANGE)) {\r
-\r
- IsMediaChange = TRUE;\r
+ break;\r
+ case SK_UNIT_ATTENTION:\r
+ if (SenseData->addnl_sense_code == ASC_MEDIA_CHANGE) {\r
+ *Result = SenseMediaChange;\r
}\r
-\r
- SensePointer++;\r
- }\r
-\r
- return IsMediaChange;\r
-}\r
-\r
-/**\r
- TODO: Add function description\r
-\r
- @param SenseData TODO: add argument description\r
- @param SenseCounts TODO: add argument description\r
- @param NeedRetry TODO: add argument description\r
-\r
- TODO: add return values\r
-\r
-**/\r
-BOOLEAN\r
-IsDriveReady (\r
- IN REQUEST_SENSE_DATA *SenseData,\r
- IN UINTN SenseCounts,\r
- OUT BOOLEAN *NeedRetry\r
- )\r
-{\r
- REQUEST_SENSE_DATA *SensePointer;\r
- UINTN Index;\r
- BOOLEAN IsReady;\r
-\r
- IsReady = TRUE;\r
- *NeedRetry = FALSE;\r
- SensePointer = SenseData;\r
-\r
- for (Index = 0; Index < SenseCounts; Index++) {\r
-\r
- switch (SensePointer->sense_key) {\r
-\r
- case SK_NOT_READY:\r
- //\r
- // Sense Key is SK_NOT_READY (0x2)\r
- //\r
- switch (SensePointer->addnl_sense_code) {\r
- case ASC_NOT_READY:\r
- //\r
- // Additional Sense Code is ASC_NOT_READY (0x4)\r
- //\r
- switch (SensePointer->addnl_sense_code_qualifier) {\r
- case ASCQ_IN_PROGRESS:\r
- //\r
- // Additional Sense Code Qualifier is ASCQ_IN_PROGRESS (0x1)\r
- //\r
- IsReady = FALSE;\r
- *NeedRetry = TRUE;\r
- break;\r
-\r
- default:\r
- IsReady = FALSE;\r
- *NeedRetry = FALSE;\r
- break;\r
- }\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- default:\r
+ break;\r
+ case SK_MEDIUM_ERROR:\r
+ switch (SenseData->addnl_sense_code) {\r
+ case ASC_MEDIA_ERR1:\r
+ case ASC_MEDIA_ERR2:\r
+ case ASC_MEDIA_ERR3:\r
+ case ASC_MEDIA_ERR4:\r
+ *Result = SenseMediaError;\r
break;\r
}\r
-\r
- SensePointer++;\r
+ break;\r
+ default:\r
+ break;\r
}\r
\r
- return IsReady;\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- TODO: Add function description\r
+ This function reads the pending data in the device.\r
\r
- @param SenseData TODO: add argument description\r
- @param SenseCounts TODO: add argument description\r
+ @param[in] IdeDev Indicates the calling context.\r
\r
- TODO: add return values\r
+ @retval EFI_SUCCESS Successfully read.\r
+ @retval EFI_NOT_READY The BSY is set avoiding reading.\r
\r
**/\r
-BOOLEAN\r
-HaveSenseKey (\r
- IN REQUEST_SENSE_DATA *SenseData,\r
- IN UINTN SenseCounts\r
+EFI_STATUS\r
+AtapiReadPendingData (\r
+ IN IDE_BLK_IO_DEV *IdeDev\r
)\r
{\r
- BOOLEAN Have;\r
+ UINT8 AltRegister;\r
+ UINT16 TempWordBuffer;\r
\r
- Have = TRUE;\r
-\r
- //\r
- // if first sense key in the Sense Data Array is SK_NO_SENSE,\r
- // it indicates there is no more sense key in the Sense Data Array.\r
- //\r
- if (SenseData->sense_key == SK_NO_SENSE) {\r
- Have = FALSE;\r
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+ if ((AltRegister & BSY) == BSY) {\r
+ return EFI_NOT_READY;\r
}\r
-\r
- return Have;\r
+ if ((AltRegister & (BSY | DRQ)) == DRQ) {\r
+ TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);\r
+ while ((TempWordBuffer & (BSY | DRQ)) == DRQ) {\r
+ IDEReadPortWMultiple (\r
+ IdeDev->PciIo,\r
+ IdeDev->IoPort->Data, \r
+ 1, \r
+ &TempWordBuffer\r
+ );\r
+ TempWordBuffer = IDEReadPortB (IdeDev->PciIo,IdeDev->IoPort->Alt.AltStatus);\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r