]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c
In IdeBus driver block I/O read/write interface, it will always try to use UDMA mode...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / atapi.c
index fa004e3d7f999e286f63869bbbae190d3e980a3c..93f7081516172a3fa7c0b9810eb602d988f6d443 100644 (file)
@@ -1,67 +1,50 @@
-/*++\r
+/** @file\r
+  Copyright (c) 2006, Intel Corporation                                                         \r
+  All rights reserved. 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
-Copyright (c) 2006, Intel Corporation                                                         \r
-All rights reserved. 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
+  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
-Module Name:\r
+**/\r
 \r
-  atapi.c\r
-    \r
-Abstract: \r
-    \r
+#include "idebus.h"\r
 \r
-Revision History\r
---*/\r
+/**\r
+  This function is used to get the current status of the media residing\r
+  in the LS-120 drive or ZIP drive. The media status is returned in the \r
+  Error Status.\r
 \r
-#include "idebus.h"\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
+\r
+  @retval EFI_SUCCESS\r
+  The media status is achieved successfully and the media\r
+  can be read/written.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Get Media Status Command is failed.\r
+  \r
+  @retval EFI_NO_MEDIA\r
+  There is no media in the drive.\r
+  \r
+  @retval EFI_WRITE_PROTECTED\r
+  The media is writing protected.\r
 \r
+  @note\r
+  This function must be called after the LS120EnableMediaStatus() \r
+  with second parameter set to TRUE \r
+  (means enable media status notification) is called.\r
+\r
+**/\r
 STATIC\r
 EFI_STATUS\r
 LS120GetMediaStatus (\r
   IN  IDE_BLK_IO_DEV  *IdeDev\r
   )\r
-/*++\r
-  Name:\r
-        LS120GetMediaStatus\r
-\r
-  Purpose: \r
-        This function is used to get the current status of the media residing\r
-        in the LS-120 drive or ZIP drive. The media status is returned in the \r
-        Error Status.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          The media status is achieved successfully and the media\r
-          can be read/written.             \r
-    \r
-        EFI_DEVICE_ERROR\r
-          Get Media Status Command is failed.\r
-\r
-        EFI_NO_MEDIA\r
-          There is no media in the drive.\r
-\r
-        EFI_WRITE_PROTECTED\r
-          The media is writing protected. \r
-\r
-  Notes:                \r
-        This function must be called after the LS120EnableMediaStatus() \r
-        with second parameter set to TRUE \r
-        (means enable media status notification) is called.\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
 {\r
   UINT8       DeviceSelect;\r
   UINT8       StatusValue;\r
@@ -119,43 +102,31 @@ LS120GetMediaStatus (
   }\r
 }\r
 \r
+/**\r
+  This function is used to send Enable Media Status Notification Command\r
+  or Disable Media Status Notification Command.\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
+\r
+  @param[in] Enable\r
+  a flag that indicates whether enable or disable media\r
+  status notification.\r
+\r
+  @retval EFI_SUCCESS\r
+  If command completes successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  If command failed.\r
+\r
+**/\r
 STATIC\r
 EFI_STATUS\r
 LS120EnableMediaStatus (\r
   IN  IDE_BLK_IO_DEV  *IdeDev,\r
   IN  BOOLEAN         Enable\r
   )\r
-/*++\r
-  Name:\r
-        LS120EnableMediaStatus\r
-\r
-  Purpose: \r
-        This function is used to send Enable Media Status Notification Command\r
-        or Disable Media Status Notification Command.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        BOOLEAN     IN    Enable\r
-          a flag that indicates whether enable or disable media\r
-          status notification.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          If command completes successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          If command failed.\r
-\r
-\r
-  Notes:                \r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Enable - add argument and description to function comment\r
 {\r
   UINT8       DeviceSelect;\r
   EFI_STATUS  Status;\r
@@ -211,60 +182,51 @@ LS120EnableMediaStatus (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function is called by DiscoverIdeDevice() during its device\r
+  identification.\r
+\r
+  Its main purpose is to get enough information for the device media\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
+\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
+  the only meaningful information is the device module name.\r
+\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
+\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
+  media is present. The media detection will be performed just before\r
+  each BLK_IO read/write\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
+\r
+  @retval EFI_SUCCESS\r
+  Identify ATAPI device successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  ATAPI Identify Device Command failed or device type\r
+  is not supported by this IDE driver.\r
+\r
+  @note\r
+  Parameter "IdeDev" will be updated in this function.\r
+\r
+  TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+  TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+**/\r
 EFI_STATUS\r
 ATAPIIdentify (\r
   IN  IDE_BLK_IO_DEV  *IdeDev\r
   )\r
-/*++\r
-  Name:\r
-        ATAPIIdentify\r
-\r
-\r
-  Purpose: \r
-        This function is called by DiscoverIdeDevice() during its device\r
-        identification.\r
-\r
-        Its main purpose is to get enough information for the device media\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
-\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
-           the only meaningful information is the device module name.\r
-\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
-\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
-           media is present. The media detection will be performed just before\r
-           each BLK_IO read/write\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          Identify ATAPI device successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          ATAPI Identify Device Command failed or device type \r
-          is not supported by this IDE driver.\r
-\r
-  Notes:\r
-        Parameter "IdeDev" will be updated in this function.\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
-// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
 {\r
   EFI_IDENTIFY_DATA *AtapiIdentifyPointer;\r
   UINT8             DeviceSelect;\r
@@ -409,35 +371,28 @@ ATAPIIdentify (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Sends out ATAPI Inquiry Packet Command to the specified device.\r
+  This command will return INQUIRY data of the device.\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
+\r
+  @retval EFI_SUCCESS\r
+  Inquiry command completes successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Inquiry command failed.\r
+\r
+  @note\r
+  Parameter "IdeDev" will be updated in this function.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiInquiry (\r
   IN  IDE_BLK_IO_DEV  *IdeDev\r
   )\r
-/*++\r
-  Name:\r
-        AtapiInquiry\r
-\r
-  Purpose: \r
-        Sends out ATAPI Inquiry Packet Command to the specified device.\r
-        This command will return INQUIRY data of the device.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          Inquiry command completes successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          Inquiry command failed.\r
-  Notes:\r
-        Parameter "IdeDev" will be updated in this function.\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
 {\r
   ATAPI_PACKET_COMMAND  Packet;\r
   EFI_STATUS            Status;\r
@@ -476,6 +431,36 @@ AtapiInquiry (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function is used to send out ATAPI commands conforms to the \r
+  Packet Command with PIO Data In Protocol.\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
+\r
+  @param[in] *Packet\r
+  pointer pointing to ATAPI_PACKET_COMMAND data structure\r
+  which contains the contents of the command.     \r
+\r
+  @param[in] *Buffer\r
+  buffer contained data transferred from device to host.\r
+\r
+  @param[in] ByteCount\r
+  data size in byte unit of the buffer.\r
+\r
+  @param[in] TimeOut\r
+  this parameter is used to specify the timeout \r
+  value for the PioReadWriteData() function. \r
+\r
+  @retval EFI_SUCCESS\r
+  send out the ATAPI packet command successfully\r
+  and device sends data successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  the device failed to send data.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiPacketCommandIn (\r
   IN  IDE_BLK_IO_DEV        *IdeDev,\r
@@ -484,50 +469,6 @@ AtapiPacketCommandIn (
   IN  UINT32                ByteCount,\r
   IN  UINTN                 TimeOut\r
   )\r
-/*++\r
-  Name:\r
-        AtapiPacketCommandIn\r
-\r
-  Purpose: \r
-        This function is used to send out ATAPI commands conforms to the \r
-        Packet Command with PIO Data In Protocol.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        ATAPI_PACKET_COMMAND  IN  *Packet\r
-          pointer pointing to ATAPI_PACKET_COMMAND data structure\r
-          which contains the contents of the command.     \r
-              \r
-        UINT16      IN    *Buffer\r
-          buffer contained data transferred from device to host.\r
-\r
-        UINT32      IN    ByteCount\r
-          data size in byte unit of the buffer.\r
-\r
-        UINTN     IN    TimeOut\r
-          this parameter is used to specify the timeout \r
-          value for the PioReadWriteData() function. \r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          send out the ATAPI packet command successfully \r
-          and device sends data successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          the device failed to send data.                 \r
-\r
-  Notes:\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Packet - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    ByteCount - add argument and description to function comment\r
-// TODO:    TimeOut - add argument and description to function comment\r
 {\r
   UINT16      *CommandIndex;\r
   EFI_STATUS  Status;\r
@@ -605,6 +546,36 @@ AtapiPacketCommandIn (
   return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut);\r
 }\r
 \r
+/**\r
+  This function is used to send out ATAPI commands conforms to the \r
+  Packet Command with PIO Data Out Protocol.\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
+\r
+  @param[in] *Packet\r
+  pointer pointing to ATAPI_PACKET_COMMAND data structure\r
+  which contains the contents of the command.\r
+\r
+  @param[in] *Buffer\r
+  buffer contained data transferred from host to device.\r
+\r
+  @param[in] ByteCount\r
+  data size in byte unit of the buffer.\r
+\r
+  @param[in] TimeOut\r
+  this parameter is used to specify the timeout \r
+  value for the PioReadWriteData() function. \r
+\r
+  @retval EFI_SUCCESS\r
+  send out the ATAPI packet command successfully\r
+  and device received data successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  the device failed to send data.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiPacketCommandOut (\r
   IN  IDE_BLK_IO_DEV        *IdeDev,\r
@@ -613,51 +584,6 @@ AtapiPacketCommandOut (
   IN  UINT32                ByteCount,\r
   IN  UINTN                 TimeOut\r
   )\r
-/*++\r
-  Name:\r
-        AtapiPacketCommandOut\r
-\r
-  Purpose: \r
-        This function is used to send out ATAPI commands conforms to the \r
-        Packet Command with PIO Data Out Protocol.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        ATAPI_PACKET_COMMAND  IN  *Packet\r
-          pointer pointing to ATAPI_PACKET_COMMAND data structure\r
-          which contains the contents of the command.\r
-\r
-        VOID      IN    *Buffer\r
-          buffer contained data transferred from host to device.\r
-\r
-        UINT32      IN    ByteCount\r
-          data size in byte unit of the buffer.\r
-\r
-        UINTN     IN    TimeOut\r
-          this parameter is used to specify the timeout \r
-          value for the PioReadWriteData() function. \r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          send out the ATAPI packet command successfully \r
-          and device received data successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          the device failed to send data. \r
-\r
-  Notes:\r
-  \r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Packet - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    ByteCount - add argument and description to function comment\r
-// TODO:    TimeOut - add argument and description to function comment\r
 {\r
   UINT16      *CommandIndex;\r
   EFI_STATUS  Status;\r
@@ -733,6 +659,38 @@ AtapiPacketCommandOut (
   return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut);\r
 }\r
 \r
+/**\r
+  This function is called by either AtapiPacketCommandIn() or \r
+  AtapiPacketCommandOut(). It is used to transfer data between\r
+  host and device. The data direction is specified by the fourth\r
+  parameter.\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
+\r
+  @param[in] *Buffer\r
+  buffer contained data transferred between host and device.\r
+\r
+  @param[in] ByteCount\r
+  data size in byte unit of the buffer.\r
+\r
+  @param[in] Read\r
+  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
+\r
+  @param[in] TimeOut\r
+  timeout value for wait DRQ ready before each data \r
+  stream's transfer.\r
+\r
+  @retval EFI_SUCCESS\r
+  data is transferred successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  the device failed to transfer data.\r
+\r
+**/\r
 EFI_STATUS\r
 PioReadWriteData (\r
   IN  IDE_BLK_IO_DEV  *IdeDev,\r
@@ -741,54 +699,6 @@ PioReadWriteData (
   IN  BOOLEAN         Read,\r
   IN  UINTN           TimeOut\r
   )\r
-/*++\r
-  Name:\r
-        PioReadWriteData\r
-\r
-  Purpose: \r
-        This function is called by either AtapiPacketCommandIn() or \r
-        AtapiPacketCommandOut(). It is used to transfer data between\r
-        host and device. The data direction is specified by the fourth\r
-        parameter.\r
-\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        VOID      IN    *Buffer\r
-          buffer contained data transferred between host and device.\r
-\r
-        UINT32      IN    ByteCount\r
-          data size in byte unit of the buffer.\r
-\r
-        BOOLEAN     IN    Read\r
-          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
-\r
-        UINTN     IN    TimeOut\r
-          timeout value for wait DRQ ready before each data \r
-          stream's transfer.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          data is transferred successfully.  \r
-\r
-        EFI_DEVICE_ERROR\r
-          the device failed to transfer data.                 \r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    ByteCount - add argument and description to function comment\r
-// TODO:    Read - add argument and description to function comment\r
-// TODO:    TimeOut - add argument and description to function comment\r
 {\r
   //\r
   // required transfer data in word unit.\r
@@ -803,11 +713,6 @@ PioReadWriteData (
   EFI_STATUS  Status;\r
   UINT16      *PtrBuffer;\r
 \r
-  //\r
-  // containing status byte read from Status Register.\r
-  //\r
-  UINT8       StatusRegister;\r
-\r
   //\r
   // No data transfer is premitted.\r
   //\r
@@ -840,16 +745,14 @@ PioReadWriteData (
     //\r
     // read Status Register will clear interrupt\r
     //\r
-    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+    IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
 \r
     //\r
     // get current data transfer size from Cylinder Registers.\r
     //\r
-    WordCount =\r
-      (\r
-        (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8) |\r
-        IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb)\r
-      ) & 0xffff;\r
+    WordCount = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8;\r
+    WordCount = WordCount | IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);\r
+    WordCount = WordCount & 0xffff;\r
     WordCount /= 2;\r
 \r
     WordCount = EFI_MIN (WordCount, (RequiredWordCount - ActualWordCount));\r
@@ -873,6 +776,15 @@ PioReadWriteData (
     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
@@ -888,40 +800,29 @@ PioReadWriteData (
   return CheckErrorStatus (IdeDev);\r
 }\r
 \r
-EFI_STATUS\r
-AtapiTestUnitReady (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev\r
-  )\r
-/*++\r
-  Name:\r
-        AtapiTestUnitReady\r
-\r
-  Purpose: \r
-        Sends out ATAPI Test Unit Ready Packet Command to the specified device\r
-        to find out whether device is accessible.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
+/**\r
+  Sends out ATAPI Test Unit Ready Packet Command to the specified device\r
+  to find out whether device is accessible.\r
 \r
-  Returns:  \r
-        EFI_SUCCESS\r
-          device is accessible.\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
-        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
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
+**/\r
+EFI_STATUS\r
+AtapiTestUnitReady (\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
@@ -932,53 +833,51 @@ AtapiTestUnitReady (
   // send command packet\r
   //\r
   Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);\r
-  return Status;\r
-}\r
-\r
-EFI_STATUS\r
-AtapiRequestSense (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  OUT UINTN           *SenseCounts\r
-  )\r
-/*++\r
-  Name:\r
-        AtapiRequestSense\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  Purpose: \r
-        Sends out ATAPI Request Sense Packet Command to the specified device.\r
-        This command will return all the current Sense data in the device. \r
-        This function will pack all the Sense data in one single buffer.\r
+  Status = AtapiRequestSense (IdeDev, SenseCount);\r
+  if (EFI_ERROR (Status)) {\r
+    *SenseCount = 0;\r
+    return Status;\r
+  }\r
 \r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
+  return EFI_SUCCESS;\r
+}\r
 \r
-        UINT16      OUT   **SenseBuffers\r
-          allocated in this function, and freed by the calling function.\r
-          This buffer is used to accommodate all the sense data returned \r
-          by the device.\r
+/**\r
+  Sends out ATAPI Request Sense Packet Command to the specified device.\r
+  This command will return all the current Sense data in the device. \r
+  This function will pack all the Sense data in one single buffer.\r
 \r
-        UINTN     OUT   *BufUnit\r
-          record the unit size of the sense data block in the SenseBuffers,\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
 \r
-        UINTN     OUT   *BufNumbers\r
-          record the number of units in the SenseBuffers.\r
+  @param[out] **SenseBuffers\r
+  allocated in this function, and freed by the calling function.\r
+  This buffer is used to accommodate all the sense data returned \r
+  by the device.\r
 \r
-  Returns:  \r
-        EFI_SUCCESS\r
-          Request Sense command completes successfully.\r
+  @param[out] *BufUnit\r
+  record the unit size of the sense data block in the SenseBuffers,\r
 \r
-        EFI_DEVICE_ERROR\r
-          Request Sense command failed.\r
+  @param[out] *BufNumbers\r
+  record the number of units in the SenseBuffers.\r
 \r
-  Notes:\r
+  @retval EFI_SUCCESS\r
+  Request Sense command completes successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Request Sense command failed.\r
 \r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    SenseCounts - add argument and description to function comment\r
+**/\r
+EFI_STATUS\r
+AtapiRequestSense (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  OUT UINTN           *SenseCounts\r
+  )\r
 {\r
   EFI_STATUS            Status;\r
   REQUEST_SENSE_DATA    *Sense;\r
@@ -1040,7 +939,7 @@ AtapiRequestSense (
       //\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
@@ -1053,50 +952,39 @@ AtapiRequestSense (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Sends out ATAPI Read Capacity Packet Command to the specified device.\r
+  This command will return the information regarding the capacity of the\r
+  media in the device.\r
+\r
+  Current device status will impact device's response to the Read Capacity\r
+  Command. For example, if the device once reset, the Read Capacity\r
+  Command will fail. The Sense data record the current device status, so \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    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      Read Capacity Command finally completes successfully.\r
+  @retval EFI_DEVICE_ERROR Read Capacity Command failed because of device error.\r
+\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
-  Name:\r
-        AtapiReadCapacity\r
-\r
-  Purpose: \r
-        Sends out ATAPI Read Capacity Packet Command to the specified device.\r
-        This command will return the information regarding the capacity of the\r
-        media in the device.\r
-\r
-        Current device status will impact device's response to the Read Capacity\r
-        Command. For example, if the device once reset, the Read Capacity\r
-        Command will fail. The Sense data record the current device status, so \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
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          Read Capacity Command finally completes successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          Read Capacity Command failed because of device error.\r
-\r
-  Notes:\r
-        parameter "IdeDev" will be updated in this function.\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    EFI_NOT_READY - add return value to function comment\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
@@ -1105,6 +993,8 @@ AtapiReadCapacity (
   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
@@ -1113,12 +1003,12 @@ AtapiReadCapacity (
     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
@@ -1128,362 +1018,281 @@ AtapiReadCapacity (
     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
 \r
+/**\r
+  Used before read/write blocks from/to ATAPI device media. \r
+  Since ATAPI device media is removable, it is necessary to detect\r
+  whether media is present and get current present media's\r
+  information, and if media has been changed, Block I/O Protocol\r
+  need to be reinstalled.\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
+\r
+  @param[out] *MediaChange\r
+  return value that indicates if the media of the device has been\r
+  changed.\r
+\r
+  @retval EFI_SUCCESS\r
+  media found successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  any error encounters during media detection.\r
+  \r
+  @retval EFI_NO_MEDIA\r
+  media not found.\r
+\r
+  @note\r
+  parameter IdeDev may be updated in this function.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiDetectMedia (\r
   IN  IDE_BLK_IO_DEV  *IdeDev,\r
   OUT BOOLEAN         *MediaChange\r
   )\r
-/*++\r
-  Name:\r
-        AtapiDetectMedia\r
-\r
-  Purpose: \r
-        Used before read/write blocks from/to ATAPI device media. \r
-        Since ATAPI device media is removable, it is necessary to detect\r
-        whether media is present and get current present media's\r
-        information, and if media has been changed, Block I/O Protocol\r
-        need to be reinstalled.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        BOOLEAN         OUT   *MediaChange\r
-          return value that indicates if the media of the device has been\r
-          changed.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          media found successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          any error encounters during media detection.\r
-          \r
-        EFI_NO_MEDIA\r
-          media not found.\r
-\r
-  Notes:\r
-        parameter IdeDev may be updated in this function.\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    MediaChange - add argument and description to function comment\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
+        ParseSenseData (IdeDev, SenseCount, &SResult);\r
 \r
-        //\r
-        // If Request Sense data failed, reset the device and retry.\r
-        //\r
-        if (EFI_ERROR (Status)) {\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
+          // We use Test Unit Ready to retry which\r
+          // is faster.\r
           //\r
-          if (EFI_ERROR (Status)) {\r
-            AtaSoftReset (IdeDev);\r
-          }\r
-          //\r
-          // retry once more\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
@@ -1554,10 +1363,42 @@ AtapiDetectMedia (
           );\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
+  This function is called by the AtapiBlkIoReadBlocks() to perform\r
+  read from media in block unit.\r
+\r
+  The main command used to access media here is READ(10) Command. \r
+  READ(10) Command requests that the ATAPI device media transfer \r
+  specified data to the host. Data is transferred in block(sector) \r
+  unit. The maximum number of blocks that can be transferred once is\r
+  65536. This is the main difference between READ(10) and READ(12) \r
+  Command. The maximum number of blocks in READ(12) is 2 power 32.\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
+\r
+  @param[in] *Buffer\r
+  A pointer to the destination buffer for the data. \r
+\r
+  @param[in] Lba\r
+  The starting logical block address to read from \r
+  on the device media.\r
+\r
+  @param[in] NumberOfBlocks\r
+  The number of transfer data blocks.\r
+\r
+  @return status is fully dependent on the return status\r
+  of AtapiPacketCommandIn() function.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiReadSectors (\r
   IN  IDE_BLK_IO_DEV  *IdeDev,\r
@@ -1565,49 +1406,6 @@ AtapiReadSectors (
   IN  EFI_LBA         Lba,\r
   IN  UINTN           NumberOfBlocks\r
   )\r
-/*++\r
-  Name:\r
-        AtapiReadSectors\r
-\r
-  Purpose: \r
-        This function is called by the AtapiBlkIoReadBlocks() to perform\r
-        read from media in block unit.\r
-\r
-        The main command used to access media here is READ(10) Command. \r
-        READ(10) Command requests that the ATAPI device media transfer \r
-        specified data to the host. Data is transferred in block(sector) \r
-        unit. The maximum number of blocks that can be transferred once is\r
-        65536. This is the main difference between READ(10) and READ(12) \r
-        Command. The maximum number of blocks in READ(12) is 2 power 32.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        VOID      IN    *Buffer\r
-          A pointer to the destination buffer for the data. \r
-\r
-        EFI_LBA     IN    Lba\r
-          The starting logical block address to read from \r
-          on the device media.\r
-\r
-        UINTN     IN    NumberOfBlocks\r
-          The number of transfer data blocks.\r
-\r
-  Returns:  \r
-        return status is fully dependent on the return status\r
-        of AtapiPacketCommandIn() function.\r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    Lba - add argument and description to function comment\r
-// TODO:    NumberOfBlocks - add argument and description to function comment\r
 {\r
 \r
   ATAPI_PACKET_COMMAND  Packet;\r
@@ -1635,7 +1433,7 @@ AtapiReadSectors (
   //\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
@@ -1699,6 +1497,33 @@ AtapiReadSectors (
   return Status;\r
 }\r
 \r
+/**\r
+  This function is called by the AtapiBlkIoWriteBlocks() to perform\r
+  write onto media in block unit.\r
+  The main command used to access media here is Write(10) Command. \r
+  Write(10) Command requests that the ATAPI device media transfer \r
+  specified data to the host. Data is transferred in block (sector) \r
+  unit. The maximum number of blocks that can be transferred once is\r
+  65536. \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
+\r
+  @param[in] *Buffer\r
+  A pointer to the source buffer for the data. \r
+\r
+  @param[in] Lba\r
+  The starting logical block address to write onto \r
+  the device media.\r
+\r
+  @param[in] NumberOfBlocks\r
+  The number of transfer data blocks.\r
+\r
+  @return status is fully dependent on the return status\r
+  of AtapiPacketCommandOut() function.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiWriteSectors (\r
   IN  IDE_BLK_IO_DEV  *IdeDev,\r
@@ -1706,47 +1531,6 @@ AtapiWriteSectors (
   IN  EFI_LBA         Lba,\r
   IN  UINTN           NumberOfBlocks\r
   )\r
-/*++\r
-  Name:\r
-        AtapiWriteSectors\r
-\r
-  Purpose: \r
-        This function is called by the AtapiBlkIoWriteBlocks() to perform\r
-        write onto media in block unit.\r
-        The main command used to access media here is Write(10) Command. \r
-        Write(10) Command requests that the ATAPI device media transfer \r
-        specified data to the host. Data is transferred in block (sector) \r
-        unit. The maximum number of blocks that can be transferred once is\r
-        65536. \r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-        VOID      IN    *Buffer\r
-          A pointer to the source buffer for the data. \r
-\r
-        EFI_LBA     IN    Lba\r
-          The starting logical block address to write onto \r
-          the device media.\r
-\r
-        UINTN     IN    NumberOfBlocks\r
-          The number of transfer data blocks.\r
-\r
-  Returns:  \r
-        return status is fully dependent on the return status\r
-        of AtapiPacketCommandOut() function.\r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    Lba - add argument and description to function comment\r
-// TODO:    NumberOfBlocks - add argument and description to function comment\r
 {\r
 \r
   ATAPI_PACKET_COMMAND  Packet;\r
@@ -1834,45 +1618,33 @@ AtapiWriteSectors (
   return Status;\r
 }\r
 \r
+/**\r
+  This function is used to implement the Soft Reset on the specified\r
+  ATAPI device. Different from the AtaSoftReset(), here reset is a ATA\r
+  Soft Reset Command special for ATAPI device, and it only take effects\r
+  on the specified ATAPI device, not on the whole IDE bus.\r
+  Since the ATAPI soft reset is needed when device is in exceptional\r
+  condition (such as BSY bit is always set ), I think the Soft Reset\r
+  command should be sent without waiting for the BSY clear and DRDY\r
+  set.\r
+  This function is called by IdeBlkIoReset(), \r
+  a interface function of Block I/O protocol.\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
+\r
+  @retval EFI_SUCCESS\r
+  Soft reset completes successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Any step during the reset process is failed.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiSoftReset (\r
   IN  IDE_BLK_IO_DEV  *IdeDev\r
   )\r
-/*++\r
-  Name:\r
-        AtapiSoftReset\r
-\r
-  Purpose: \r
-        This function is used to implement the Soft Reset on the specified\r
-        ATAPI device. Different from the AtaSoftReset(), here reset is a ATA\r
-        Soft Reset Command special for ATAPI device, and it only take effects\r
-        on the specified ATAPI device, not on the whole IDE bus.\r
-        Since the ATAPI soft reset is needed when device is in exceptional\r
-        condition (such as BSY bit is always set ), I think the Soft Reset\r
-        command should be sent without waiting for the BSY clear and DRDY\r
-        set.\r
-        This function is called by IdeBlkIoReset(), \r
-        a interface function of Block I/O protocol.\r
-\r
-            \r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeDev\r
-          pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-          to record all the information of the IDE device.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS\r
-          Soft reset completes successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          Any step during the reset process is failed.\r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
 {\r
   UINT8       Command;\r
   UINT8       DeviceSelect;\r
@@ -1906,6 +1678,50 @@ AtapiSoftReset (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function is the ATAPI implementation for ReadBlocks in the\r
+  Block I/O Protocol interface.\r
+\r
+  @param[in] *IdeBlkIoDev\r
+  Indicates the calling context.\r
+\r
+  @param[in] MediaId\r
+  The media id that the read request is for.\r
+\r
+  @param[in] LBA\r
+  The starting logical block address to read from \r
+  on the device.\r
+\r
+  @param[in] BufferSize\r
+  The size of the Buffer in bytes. This must be a\r
+  multiple of the intrinsic block size of the device.\r
+\r
+  @param[out] *Buffer\r
+  A pointer to the destination buffer for the data. \r
+  The caller is responsible for either having implicit\r
+  or explicit ownership of the memory that data is read into.\r
+\r
+  @retval EFI_SUCCESS\r
+  Read Blocks successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Read Blocks failed.\r
+  \r
+  @retval EFI_NO_MEDIA\r
+  There is no media in the device.\r
+  \r
+  @retval EFI_MEDIA_CHANGED\r
+  The MediaId is not for the current media.\r
+  \r
+  @retval EFI_BAD_BUFFER_SIZE\r
+  The BufferSize parameter is not a multiple of the\r
+  intrinsic block size of the device.\r
+  \r
+  @retval EFI_INVALID_PARAMETER\r
+  The read request contains LBAs that are not valid,\r
+  or the data buffer is not valid.\r
+\r
+**/\r
 EFI_STATUS\r
 AtapiBlkIoReadBlocks (\r
   IN IDE_BLK_IO_DEV   *IdeBlkIoDevice,\r
@@ -1914,65 +1730,6 @@ AtapiBlkIoReadBlocks (
   IN UINTN            BufferSize,\r
   OUT VOID            *Buffer\r
   )\r
-/*++\r
-  Name:\r
-        AtapiBlkIoReadBlocks\r
-\r
-  Purpose: \r
-        This function is the ATAPI implementation for ReadBlocks in the\r
-        Block I/O Protocol interface.\r
-\r
-  Parameters:\r
-        IDE_BLK_IO_DEV  IN    *IdeBlkIoDev\r
-          Indicates the calling context.\r
-\r
-        UINT32      IN    MediaId\r
-          The media id that the read request is for.\r
-\r
-        EFI_LBA     IN    LBA\r
-          The starting logical block address to read from \r
-          on the device.\r
-\r
-        UINTN     IN    BufferSize\r
-          The size of the Buffer in bytes. This must be a\r
-          multiple of the intrinsic block size of the device.\r
-\r
-        VOID      OUT   *Buffer\r
-          A pointer to the destination buffer for the data. \r
-          The caller is responsible for either having implicit\r
-          or explicit ownership of the memory that data is read into.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS \r
-          Read Blocks successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          Read Blocks failed.\r
-\r
-        EFI_NO_MEDIA\r
-          There is no media in the device.\r
-\r
-        EFI_MEDIA_CHANGED\r
-          The MediaId is not for the current media.\r
-\r
-        EFI_BAD_BUFFER_SIZE\r
-          The BufferSize parameter is not a multiple of the \r
-          intrinsic block size of the device.\r
-\r
-        EFI_INVALID_PARAMETER\r
-          The read request contains LBAs that are not valid,\r
-          or the data buffer is not valid.\r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeBlkIoDevice - add argument and description to function comment\r
-// TODO:    MediaId - add argument and description to function comment\r
-// TODO:    LBA - add argument and description to function comment\r
-// TODO:    BufferSize - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
 {\r
   EFI_BLOCK_IO_MEDIA  *Media;\r
   UINTN               BlockSize;\r
@@ -2074,6 +1831,53 @@ AtapiBlkIoReadBlocks (
 \r
 }\r
 \r
+/**\r
+  This function is the ATAPI implementation for WriteBlocks in the\r
+  Block I/O Protocol interface.\r
+\r
+  @param[in] *This\r
+  Indicates the calling context.\r
+\r
+  @param[in] MediaId\r
+  The media id that the write request is for.\r
+\r
+  @param[in] LBA\r
+  The starting logical block address to write onto \r
+  the device.\r
+\r
+  @param[in] BufferSize\r
+  The size of the Buffer in bytes. This must be a\r
+  multiple of the intrinsic block size of the device.\r
+\r
+  @param[out] *Buffer\r
+  A pointer to the source buffer for the data. \r
+  The caller is responsible for either having implicit\r
+  or explicit ownership of the memory that data is \r
+  written from.\r
+\r
+  @retval EFI_SUCCESS\r
+  Write Blocks successfully.\r
+  \r
+  @retval EFI_DEVICE_ERROR\r
+  Write Blocks failed.\r
+  \r
+  @retval EFI_NO_MEDIA\r
+  There is no media in the device.\r
+  \r
+  @retval EFI_MEDIA_CHANGE\r
+  The MediaId is not for the current media.\r
+  \r
+  @retval EFI_BAD_BUFFER_SIZE\r
+  The BufferSize parameter is not a multiple of the\r
+  intrinsic block size of the device.\r
+  \r
+  @retval EFI_INVALID_PARAMETER\r
+  The write request contains LBAs that are not valid,\r
+  or the data buffer is not valid.\r
+\r
+  TODO:    EFI_MEDIA_CHANGED - add return value to function comment\r
+  TODO:    EFI_WRITE_PROTECTED - add return value to function comment\r
+**/\r
 EFI_STATUS\r
 AtapiBlkIoWriteBlocks (\r
   IN IDE_BLK_IO_DEV   *IdeBlkIoDevice,\r
@@ -2082,68 +1886,6 @@ AtapiBlkIoWriteBlocks (
   IN UINTN            BufferSize,\r
   OUT VOID            *Buffer\r
   )\r
-/*++\r
-  Name:\r
-        AtapiBlkIoWriteBlocks\r
-\r
-  Purpose: \r
-        This function is the ATAPI implementation for WriteBlocks in the\r
-        Block I/O Protocol interface.\r
-\r
-  Parameters:\r
-        EFI_BLOCK_IO  IN    *This\r
-          Indicates the calling context.\r
-\r
-        UINT32      IN    MediaId\r
-          The media id that the write request is for.\r
-\r
-        EFI_LBA     IN    LBA\r
-          The starting logical block address to write onto \r
-          the device.\r
-\r
-        UINTN     IN    BufferSize\r
-          The size of the Buffer in bytes. This must be a\r
-          multiple of the intrinsic block size of the device.\r
-\r
-        VOID      OUT   *Buffer\r
-          A pointer to the source buffer for the data. \r
-          The caller is responsible for either having implicit\r
-          or explicit ownership of the memory that data is \r
-          written from.\r
-\r
-  Returns:  \r
-        EFI_SUCCESS \r
-          Write Blocks successfully.\r
-\r
-        EFI_DEVICE_ERROR\r
-          Write Blocks failed.\r
-\r
-        EFI_NO_MEDIA\r
-          There is no media in the device.\r
-\r
-        EFI_MEDIA_CHANGE\r
-          The MediaId is not for the current media.\r
-\r
-        EFI_BAD_BUFFER_SIZE\r
-          The BufferSize parameter is not a multiple of the \r
-          intrinsic block size of the device.\r
-\r
-        EFI_INVALID_PARAMETER\r
-          The write request contains LBAs that are not valid,\r
-          or the data buffer is not valid. \r
-\r
-  Notes:\r
-\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeBlkIoDevice - add argument and description to function comment\r
-// TODO:    MediaId - add argument and description to function comment\r
-// TODO:    LBA - add argument and description to function comment\r
-// TODO:    BufferSize - add argument and description to function comment\r
-// TODO:    Buffer - add argument and description to function comment\r
-// TODO:    EFI_MEDIA_CHANGED - add return value to function comment\r
-// TODO:    EFI_WRITE_PROTECTED - add return value to function comment\r
 {\r
 \r
   EFI_BLOCK_IO_MEDIA  *Media;\r
@@ -2238,324 +1980,132 @@ AtapiBlkIoWriteBlocks (
 \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
-BOOLEAN\r
-IsNoMedia (\r
-  IN  REQUEST_SENSE_DATA    *SenseData,\r
-  IN  UINTN                 SenseCounts\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  TODO: Add function description\r
-\r
-Arguments:\r
+/**\r
+  This function is used to parse sense data. Only the first\r
+  sense data is honoured.\r
 \r
-  SenseData   - TODO: add argument description\r
-  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
-Returns:\r
-\r
-  TODO: add return values\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
+  @retval EFI_SUCCESS           Successfully parsed.\r
+  @retval EFI_INVALID_PARAMETER Count of sense data is zero.\r
 \r
-      NoMedia = TRUE;\r
-    }\r
-\r
-    SensePointer++;\r
-  }\r
-\r
-  return NoMedia;\r
-}\r
-\r
-BOOLEAN\r
-IsMediaError (\r
-  IN  REQUEST_SENSE_DATA    *SenseData,\r
-  IN  UINTN                 SenseCounts\r
+**/\r
+EFI_STATUS\r
+ParseSenseData (\r
+  IN IDE_BLK_IO_DEV     *IdeDev,\r
+  IN UINTN              SenseCount,\r
+  OUT SENSE_RESULT      *Result\r
   )\r
-/*++\r
-  Name:\r
-        IsMediaError\r
-\r
-  Purpose: \r
-        Test if the device meets a media error after media changed\r
-\r
-  Parameters:\r
-        EQUEST_SENSE_DATA   IN  *SenseData\r
-          pointer pointing to ATAPI device sense data list.\r
-        UINTN               IN  SenseCounts\r
-          sense data number of the list          \r
-\r
-  Returns:  \r
-        TRUE\r
-          Device meets a media error\r
-\r
-        FALSE\r
-          No media error\r
---*/\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    SenseData - add argument and description to function comment\r
-// TODO:    SenseCounts - add argument and description to function comment\r
 {\r
-  REQUEST_SENSE_DATA  *SensePointer;\r
-  UINTN               Index;\r
-  BOOLEAN             IsError;\r
-\r
-  IsError       = FALSE;\r
-  SensePointer  = SenseData;\r
+  REQUEST_SENSE_DATA      *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
+  if (SenseCount == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\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
+    case ASC_MEDIA_UPSIDE_DOWN:\r
+      *Result = SenseMediaError;\r
+      break;\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
-    default:\r
+    }\r
+    break;\r
+  case SK_UNIT_ATTENTION:\r
+    if (SenseData->addnl_sense_code == ASC_MEDIA_CHANGE) {\r
+      *Result = SenseMediaChange;\r
+    }\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 IsError;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
-BOOLEAN\r
-IsMediaChange (\r
-  IN  REQUEST_SENSE_DATA    *SenseData,\r
-  IN  UINTN                 SenseCounts\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  TODO: Add function description\r
-\r
-Arguments:\r
-\r
-  SenseData   - TODO: add argument description\r
-  SenseCounts - TODO: add argument description\r
-\r
-Returns:\r
+/**\r
+  This function reads the pending data in the device.\r
 \r
-  TODO: add return values\r
+  @param[in] IdeDev   Indicates the calling context.\r
 \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
-    }\r
-\r
-    SensePointer++;\r
-  }\r
-\r
-  return IsMediaChange;\r
-}\r
+  @retval EFI_SUCCESS   Successfully read.\r
+  @retval EFI_NOT_READY The BSY is set avoiding reading.\r
 \r
-BOOLEAN\r
-IsDriveReady (\r
-  IN  REQUEST_SENSE_DATA    *SenseData,\r
-  IN  UINTN                 SenseCounts,\r
-  OUT BOOLEAN               *NeedRetry\r
+**/\r
+EFI_STATUS\r
+AtapiReadPendingData (\r
+  IN IDE_BLK_IO_DEV     *IdeDev\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  TODO: Add function description\r
-\r
-Arguments:\r
-\r
-  SenseData   - TODO: add argument description\r
-  SenseCounts - TODO: add argument description\r
-  NeedRetry   - TODO: add argument description\r
-\r
-Returns:\r
-\r
-  TODO: add return values\r
-\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
+  UINT8     AltRegister;\r
+  UINT16    TempWordBuffer;\r
 \r
-    default:\r
-      break;\r
+  AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+  if ((AltRegister & BSY) == BSY) {\r
+    return EFI_NOT_READY;\r
+  }\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
-    SensePointer++;\r
   }\r
-\r
-  return IsReady;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
-BOOLEAN\r
-HaveSenseKey (\r
-  IN  REQUEST_SENSE_DATA    *SenseData,\r
-  IN  UINTN                 SenseCounts\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
+/**\r
   TODO: Add function description\r
 \r
-Arguments:\r
-\r
-  SenseData   - TODO: add argument description\r
-  SenseCounts - TODO: add argument description\r
-\r
-Returns:\r
-\r
-  TODO: add return values\r
-\r
---*/\r
-{\r
-  BOOLEAN Have;\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
-  }\r
+  @param  IdeDev TODO: add argument description\r
+  @param  WriteProtected TODO: add argument description\r
 \r
-  return Have;\r
-}\r
+  @retval  EFI_DEVICE_ERROR TODO: Add description for return value\r
+  @retval  EFI_DEVICE_ERROR TODO: Add description for return value\r
+  @retval  EFI_SUCCESS TODO: Add description for return value\r
 \r
+**/\r
 EFI_STATUS\r
 IsLS120orZipWriteProtected (\r
   IN  IDE_BLK_IO_DEV    *IdeDev,\r
   OUT BOOLEAN           *WriteProtected\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  TODO: Add function description\r
-\r
-Arguments:\r
-\r
-  IdeDev          - TODO: add argument description\r
-  WriteProtected  - TODO: add argument description\r
-\r
-Returns:\r
-\r
-  EFI_DEVICE_ERROR - TODO: Add description for return value\r
-  EFI_DEVICE_ERROR - TODO: Add description for return value\r
-  EFI_SUCCESS - TODO: Add description for return value\r
-\r
---*/\r
 {\r
   EFI_STATUS  Status;\r
 \r