]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Media detection logic is enhanced to be more robust.
authorerictian <erictian@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 7 Sep 2011 08:11:42 +0000 (08:11 +0000)
committererictian <erictian@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 7 Sep 2011 08:11:42 +0000 (08:11 +0000)
Signed-off-by: erictian
Reviewed-by: hhuan13
Reviewed-by: mdkinney
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12289 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c

index e9a7788faf862dbf4b31adaf8524e171659f6712..e8c8ee7a4b064d81ed32facf860170340f9681cc 100644 (file)
@@ -697,27 +697,50 @@ ScsiDiskDetectMedia (
   )\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
@@ -732,21 +755,22 @@ ScsiDiskDetectMedia (
                  &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
@@ -765,63 +789,45 @@ ScsiDiskDetectMedia (
     //\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
@@ -863,7 +869,11 @@ ScsiDiskDetectMedia (
     *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
@@ -1188,7 +1198,9 @@ DetectMediaParsingSenseKeys (
   *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
@@ -1196,7 +1208,9 @@ DetectMediaParsingSenseKeys (
     //\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
@@ -1220,10 +1234,12 @@ DetectMediaParsingSenseKeys (
   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
@@ -1232,7 +1248,7 @@ DetectMediaParsingSenseKeys (
       *Action = ACTION_RETRY_COMMAND_LATER;\r
       return EFI_SUCCESS;\r
     }\r
-\r
+    *Action = ACTION_NO_ACTION;\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r