]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c
1. Changed device detect method to use ATA/ATAPI device signature;
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / atapi.c
index 70433066420bba4c74dafc4e683ae8033fc7b286..a54acf6994f3a1130f772de78a4181414d19dc99 100644 (file)
@@ -783,6 +783,15 @@ PioReadWriteData (
     PtrBuffer += WordCount;\r
     ActualWordCount += WordCount;\r
   }\r
     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
 \r
   //\r
   // After data transfer is completed, normally, DRQ bit should clear.\r
@@ -802,25 +811,25 @@ PioReadWriteData (
   Sends out ATAPI Test Unit Ready Packet Command to the specified device\r
   to find out whether device is accessible.\r
 \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
 \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
 \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
   )\r
 {\r
   ATAPI_PACKET_COMMAND  Packet;\r
   EFI_STATUS            Status;\r
 \r
+  *SenseCount = 0;\r
+\r
   //\r
   // fill command packet\r
   //\r
   //\r
   // fill command packet\r
   //\r
@@ -831,7 +840,17 @@ AtapiTestUnitReady (
   // send command packet\r
   //\r
   Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);\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
 \r
 /**\r
@@ -927,7 +946,7 @@ AtapiRequestSense (
       //\r
       // Ptr is word-based pointer\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
 \r
     } else {\r
       //\r
@@ -951,30 +970,28 @@ AtapiRequestSense (
   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
   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
 \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
 \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
 \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
   )\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
   ATAPI_PACKET_COMMAND      Packet;\r
 \r
   //\r
@@ -983,6 +1000,8 @@ AtapiReadCapacity (
   READ_CAPACITY_DATA        Data;\r
   READ_FORMAT_CAPACITY_DATA FormatData;\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 (&Data, sizeof (Data));\r
   ZeroMem (&FormatData, sizeof (FormatData));\r
 \r
@@ -991,12 +1010,12 @@ AtapiReadCapacity (
     ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));\r
     Packet.Inquiry.opcode = READ_CAPACITY;\r
     Status = AtapiPacketCommandIn (\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
 \r
   } else {\r
     //\r
@@ -1006,81 +1025,91 @@ AtapiReadCapacity (
     Packet.ReadFormatCapacity.opcode                = READ_FORMAT_CAPACITY;\r
     Packet.ReadFormatCapacity.allocation_length_lo  = 12;\r
     Status = AtapiPacketCommandIn (\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
   }\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
 \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
 \r
-      IdeDev->BlkIo.Media->ReadOnly = TRUE;\r
+  if (!EFI_ERROR (SenseStatus)) {\r
 \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
 \r
-    if (IdeDev->Type == IdeMagnetic) {\r
+      if (IdeDev->Type == IdeCdRom) {\r
 \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
 \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
         if (IdeDev->BlkIo.Media->LastBlock != 0) {\r
-          IdeDev->BlkIo.Media->LastBlock--;\r
 \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
           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
         }\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
 \r
     return EFI_SUCCESS;\r
 \r
   } else {\r
       }\r
     }\r
 \r
     return EFI_SUCCESS;\r
 \r
   } else {\r
-\r
+    *SenseCount = 0;\r
     return EFI_DEVICE_ERROR;\r
   }\r
 }\r
     return EFI_DEVICE_ERROR;\r
   }\r
 }\r
@@ -1119,240 +1148,158 @@ AtapiDetectMedia (
   OUT BOOLEAN         *MediaChange\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
 \r
+  CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (EFI_BLOCK_IO_MEDIA));\r
+  *MediaChange  = FALSE;\r
   //\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
   //\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
 \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
-\r
+ DoTUR:\r
   //\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
   //\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
 \r
-    Status = AtapiSoftReset (IdeDev);\r
+    Status = AtapiTestUnitReady (IdeDev, &SenseCount);\r
 \r
     if (EFI_ERROR (Status)) {\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
       //\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
       //\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
         //\r
-        // No Media\r
+        // Busy wait failed, try again\r
         //\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
         } 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
           //\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
         }\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
       }\r
-    } else {\r
-      //\r
-      // retry once more, if request sense command met errors.\r
-      //\r
-      RetryTimes++;\r
     }\r
   }\r
 \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
 \r
-      ReadCapacityStatus  = AtapiReadCapacity (IdeDev);\r
+  //\r
+  // Do Read Capacity\r
+  //\r
+ DoRC:\r
+    RetryTimes = 5;\r
 \r
 \r
-      SenseCounts         = 0;\r
+    while (RetryTimes != 0) {\r
 \r
 \r
-      if (!EFI_ERROR (ReadCapacityStatus)) {\r
-        //\r
-        // Read Capacity succeeded\r
-        //\r
-        break;\r
+      Status = AtapiReadCapacity (IdeDev, &SenseCount);\r
 \r
 \r
+      if (EFI_ERROR (Status)) {\r
+        RetryTimes--;\r
+        continue;\r
       } else {\r
 \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
 \r
-          Status = AtapiSoftReset (IdeDev);\r
+        switch (SResult) {\r
+        case SenseNoSenseKey:\r
+          goto Done;\r
+          break;\r
 \r
 \r
+        case SenseDeviceNotReadyNeedRetry:\r
           //\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
           //\r
-          RetryTimes++;\r
-          continue;\r
-        }\r
-        \r
-        //\r
-        // No Media\r
-        //\r
-        if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {\r
+          goto DoTUR;\r
+          break;\r
 \r
 \r
+        case SenseNoMedia:\r
           IdeDev->BlkIo.Media->MediaPresent = FALSE;\r
           IdeDev->BlkIo.Media->LastBlock    = 0;\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
 \r
-        if (IsMediaError (IdeDev->SenseData, SenseCounts)) {\r
+        case SenseDeviceNotReadyNoRetry:\r
+        case SenseMediaError:\r
           return EFI_DEVICE_ERROR;\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
           IdeDev->BlkIo.Media->MediaId++;\r
-        }\r
+          continue;\r
+          break;\r
 \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
-        //\r
-        // if read capacity fail not for above reasons, retry once more\r
-        //\r
-        RetryTimes++;\r
       }\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
 \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
   // the following code is to check the write-protected for LS120 media\r
   //\r
@@ -1423,8 +1370,11 @@ AtapiDetectMedia (
           );\r
   }\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
 \r
 /**\r
@@ -1490,7 +1440,7 @@ AtapiReadSectors (
   //\r
   // limit the data bytes that can be transferred by one Read(10) Command\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
   BlocksRemaining = NumberOfBlocks;\r
 \r
@@ -2037,259 +1987,114 @@ AtapiBlkIoWriteBlocks (
 \r
 }\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
 /**\r
-  TODO: Add function description\r
+  This function is used to parse sense data. Only the first\r
+  sense data is honoured.\r
 \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
 \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
 \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
   )\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
 \r
-    SensePointer++;\r
+  if (SenseCount == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \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
 \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
       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
       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
       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
-\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
       break;\r
     }\r
-\r
-    SensePointer++;\r
+    break;\r
+  default:\r
+    break;\r
   }\r
 \r
   }\r
 \r
-  return IsReady;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  TODO: Add function description\r
+  This function reads the pending data in the device.\r
 \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
 \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
 \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
   )\r
 {\r
-  BOOLEAN Have;\r
+  UINT8     AltRegister;\r
+  UINT16    TempWordBuffer;\r
 \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
-\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
 }\r
 \r
 /**\r