)\r
{\r
EFI_STATUS Status;\r
- EFI_STATUS ReadCapacityStatus;\r
EFI_SCSI_SENSE_DATA *SenseData;\r
UINTN NumberOfSenseKeys;\r
BOOLEAN NeedRetry;\r
BOOLEAN NeedReadCapacity;\r
- UINT8 Index;\r
+ UINT8 Retry;\r
UINT8 MaxRetry;\r
EFI_BLOCK_IO_MEDIA OldMedia;\r
UINTN Action;\r
+ EFI_EVENT TimeoutEvt;\r
\r
Status = EFI_SUCCESS;\r
- ReadCapacityStatus = EFI_SUCCESS;\r
SenseData = NULL;\r
NumberOfSenseKeys = 0;\r
- NeedReadCapacity = FALSE;\r
- CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));\r
- *MediaChange = FALSE;\r
+ Retry = 0;\r
MaxRetry = 3;\r
Action = ACTION_NO_ACTION;\r
+ NeedReadCapacity = FALSE;\r
+ *MediaChange = FALSE;\r
+ TimeoutEvt = NULL;\r
\r
- for (Index = 0; Index < MaxRetry; Index++) {\r
+ CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia));\r
+\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &TimeoutEvt\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->SetTimer (TimeoutEvt, TimerRelative, EFI_TIMER_PERIOD_SECONDS(120));\r
+ if (EFI_ERROR (Status)) {\r
+ goto EXIT;\r
+ }\r
+\r
+ //\r
+ // Sending Test_Unit cmd to poll device status.\r
+ // If the sense data shows the drive is not ready or reset before, we need poll the device status again.\r
+ // We limit the upper boundary to 120 seconds.\r
+ //\r
+ while (EFI_ERROR (gBS->CheckEvent (TimeoutEvt))) {\r
Status = ScsiDiskTestUnitReady (\r
ScsiDiskDevice,\r
&NeedRetry,\r
&Action\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto EXIT;\r
} else if (Action == ACTION_RETRY_COMMAND_LATER) {\r
continue;\r
} else {\r
break;\r
}\r
- }\r
-\r
- if (!NeedRetry) {\r
- return Status;\r
+ } else {\r
+ Retry++;\r
+ if (!NeedRetry || (Retry >= MaxRetry)) {\r
+ goto EXIT;\r
+ }\r
}\r
}\r
\r
- if ((Index == MaxRetry) && EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
+ if (EFI_ERROR (Status)) {\r
+ goto EXIT;\r
}\r
\r
//\r
//\r
// retrieve media information\r
//\r
- MaxRetry = 3;\r
- for (Index = 0; Index < MaxRetry; Index++) {\r
-\r
- ReadCapacityStatus = ScsiDiskReadCapacity (\r
- ScsiDiskDevice,\r
- &NeedRetry,\r
- &SenseData,\r
- &NumberOfSenseKeys\r
- );\r
- if (EFI_ERROR (ReadCapacityStatus) && !NeedRetry) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // analyze sense key to action\r
- //\r
- Status = DetectMediaParsingSenseKeys (\r
- ScsiDiskDevice,\r
- SenseData,\r
- NumberOfSenseKeys,\r
- &Action\r
- );\r
- //\r
- // if Status is error, it may indicate crisis error,\r
- // so return without retry.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- switch (Action) {\r
- case ACTION_NO_ACTION:\r
- //\r
- // no retry\r
- //\r
- Index = MaxRetry;\r
- break;\r
-\r
- case ACTION_RETRY_COMMAND_LATER:\r
- //\r
- // retry the ReadCapacity later and continuously, until the condition\r
- // no longer emerges.\r
- // stall time is 100000us, or say 0.1 second.\r
- //\r
- gBS->Stall (100000);\r
- Index = 0;\r
- break;\r
-\r
- default:\r
+ for (Retry = 0; Retry < MaxRetry; Retry++) {\r
+ Status = ScsiDiskReadCapacity (\r
+ ScsiDiskDevice,\r
+ &NeedRetry,\r
+ &SenseData,\r
+ &NumberOfSenseKeys\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
//\r
- // other cases, just retry the command\r
+ // analyze sense key to action\r
//\r
- break;\r
+ Status = DetectMediaParsingSenseKeys (\r
+ ScsiDiskDevice,\r
+ SenseData,\r
+ NumberOfSenseKeys,\r
+ &Action\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // if Status is error, it may indicate crisis error,\r
+ // so return without retry.\r
+ //\r
+ goto EXIT;\r
+ } else if (Action == ACTION_RETRY_COMMAND_LATER) {\r
+ Retry = 0;\r
+ continue;\r
+ } else {\r
+ break;\r
+ }\r
+ } else { \r
+ Retry++;\r
+ if (!NeedRetry || (Retry >= MaxRetry)) {\r
+ goto EXIT;\r
+ }\r
}\r
}\r
\r
- if ((Index == MaxRetry) && EFI_ERROR (ReadCapacityStatus)) {\r
- return EFI_DEVICE_ERROR;\r
+ if (EFI_ERROR (Status)) {\r
+ goto EXIT;\r
}\r
}\r
\r
*MediaChange = TRUE;\r
}\r
\r
- return EFI_SUCCESS;\r
+EXIT:\r
+ if (TimeoutEvt != NULL) {\r
+ gBS->CloseEvent (TimeoutEvt);\r
+ }\r
+ return Status;\r
}\r
\r
\r
*Action = ACTION_READ_CAPACITY;\r
\r
if (NumberOfSenseKeys == 0) {\r
- *Action = ACTION_NO_ACTION;\r
+ if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {\r
+ *Action = ACTION_NO_ACTION;\r
+ }\r
return EFI_SUCCESS;\r
}\r
\r
//\r
// No Sense Key returned from last submitted command\r
//\r
- *Action = ACTION_NO_ACTION;\r
+ if (ScsiDiskDevice->BlkIo.Media->MediaPresent == TRUE) {\r
+ *Action = ACTION_NO_ACTION;\r
+ }\r
return EFI_SUCCESS;\r
}\r
\r
if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {\r
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;\r
ScsiDiskDevice->BlkIo.Media->LastBlock = 0;\r
+ *Action = ACTION_NO_ACTION;\r
return EFI_DEVICE_ERROR;\r
}\r
\r
if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) {\r
+ *Action = ACTION_NO_ACTION;\r
return EFI_DEVICE_ERROR;\r
}\r
\r
*Action = ACTION_RETRY_COMMAND_LATER;\r
return EFI_SUCCESS;\r
}\r
-\r
+ *Action = ACTION_NO_ACTION;\r
return EFI_DEVICE_ERROR;\r
}\r
\r