]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.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 / ata.c
index 9a1542d0ea649f1efac2f92d5790336fce762e26..10240bf7b335321ea0c71114b22335f0504ae478 100644 (file)
@@ -1,12 +1,12 @@
 /** @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
+  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
   @par Revision Reference:\r
   2002-6: Add Atapi6 enhancement, support >120GB hard disk, including\r
 \r
 #include "idebus.h"\r
 \r
-\r
-EFI_STATUS\r
-AtaReadSectorsExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  OUT VOID        *DataBuffer,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINTN           NumberOfBlocks\r
-  );\r
-\r
-EFI_STATUS\r
-AtaWriteSectorsExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  VOID            *DataBuffer,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINTN           NumberOfBlocks\r
-  );\r
-\r
-EFI_STATUS\r
-AtaPioDataInExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  OUT VOID        *Buffer,\r
-  IN  UINT32          ByteCount,\r
-  IN  UINT8           AtaCommand,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINT16          SectorCount\r
-  );\r
-\r
-EFI_STATUS\r
-AtaPioDataOutExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  VOID            *Buffer,\r
-  IN  UINT32          ByteCount,\r
-  IN  UINT8           AtaCommand,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINT16          SectorCount\r
-  );\r
-\r
 /**\r
   Sends out an ATA Identify Command to the specified device.\r
 \r
   This function is called by DiscoverIdeDevice() during its device\r
-  identification. It sends out the ATA Identify Command to the \r
-  specified device. Only ATA device responses to this command. If \r
-  the command succeeds, it returns the Identify data structure which \r
-  contains information about the device. This function extracts the \r
-  information it needs to fill the IDE_BLK_IO_DEV data structure, \r
+  identification. It sends out the ATA Identify Command to the\r
+  specified device. Only ATA device responses to this command. If\r
+  the command succeeds, it returns the Identify data structure which\r
+  contains information about the device. This function extracts the\r
+  information it needs to fill the IDE_BLK_IO_DEV data structure,\r
   including device type, media block size, media capacity, and etc.\r
 \r
   @param[in] *IdeDev\r
@@ -76,7 +39,7 @@ AtaPioDataOutExt (
   to record all the information of the IDE device.\r
 \r
   @retval EFI_SUCCESS Identify ATA device successfully.\r
-  \r
+\r
   @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or\r
   device is not ATA device.\r
 \r
@@ -203,13 +166,13 @@ ATAIdentify (
 \r
   @retval  EFI_SUCCESS The disk specified by IdeDev is a Atapi6 supported one\r
   and 48-bit addressing must be used\r
-  \r
+\r
   @retval  EFI_UNSUPPORTED The disk dosn't not support Atapi6 or it supports but\r
   the capacity is below 120G, 48bit addressing is not\r
   needed\r
 \r
   @note\r
-  This function must be called after DEVICE_IDENTITY command has been \r
+  This function must be called after DEVICE_IDENTITY command has been\r
   successfully returned\r
 \r
 **/\r
@@ -274,7 +237,7 @@ AtaAtapi6Identify (
 \r
 /**\r
   This function is called by ATAIdentify() or ATAPIIdentify()\r
-  to print device's module name. \r
+  to print device's module name.\r
 \r
   @param[in] *IdeDev\r
   pointer pointing to IDE_BLK_IO_DEV data structure, used\r
@@ -295,7 +258,7 @@ PrintAtaModuleName (
 }\r
 \r
 /**\r
-  This function is used to send out ATA commands conforms to the \r
+  This function is used to send out ATA commands conforms to the\r
   PIO Data In Protocol.\r
 \r
   @param[in] *IdeDev\r
@@ -328,7 +291,7 @@ PrintAtaModuleName (
 \r
   @retval EFI_SUCCESS send out the ATA command and device send required\r
   data successfully.\r
-  \r
+\r
   @retval EFI_DEVICE_ERROR command sent failed.\r
 \r
 **/\r
@@ -462,7 +425,7 @@ AtaPioDataIn (
 }\r
 \r
 /**\r
-  This function is used to send out ATA commands conforms to the \r
+  This function is used to send out ATA commands conforms to the\r
   PIO Data Out Protocol.\r
 \r
   @param *IdeDev\r
@@ -480,7 +443,7 @@ AtaPioDataIn (
 \r
   @retval EFI_SUCCESS send out the ATA command and device received required\r
   data successfully.\r
-  \r
+\r
   @retval EFI_DEVICE_ERROR command sent failed.\r
 \r
 **/\r
@@ -571,7 +534,7 @@ AtaPioDataOut (
   WordCount = 0;\r
 \r
   while (WordCount < ByteCount / 2) {\r
-    \r
+\r
     //\r
     // DRQReady2-- read Alternate Status Register to determine the DRQ bit\r
     // data transfer can be performed only when DRQ is ready.\r
@@ -595,7 +558,7 @@ AtaPioDataOut (
     //\r
     // perform a series of write without check DRQ ready\r
     //\r
-    \r
+\r
     IDEWritePortWMultiple (\r
       IdeDev->PciIo,\r
       IdeDev->IoPort->Data,\r
@@ -613,7 +576,7 @@ AtaPioDataOut (
 }\r
 \r
 /**\r
-  This function is used to analyze the Status Register and print out \r
+  This function is used to analyze the Status Register and print out\r
   some debug information and if there is ERR bit set in the Status\r
   Register, the Error Register's value is also be parsed and print out.\r
 \r
@@ -640,77 +603,77 @@ CheckErrorStatus (
 \r
   StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
 \r
-  DEBUG_CODE (\r
+  DEBUG_CODE_BEGIN ();\r
 \r
     if (StatusRegister & DWF) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
-      StatusRegister)\r
-      );\r
-  }\r
+      DEBUG (\r
+        (EFI_D_BLKIO,\r
+        "CheckErrorStatus()-- %02x : Error : Write Fault\n",\r
+        StatusRegister)\r
+        );\r
+    }\r
 \r
-  if (StatusRegister & CORR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
-      StatusRegister)\r
-      );\r
-  }\r
+    if (StatusRegister & CORR) {\r
+      DEBUG (\r
+        (EFI_D_BLKIO,\r
+        "CheckErrorStatus()-- %02x : Error : Corrected Data\n",\r
+        StatusRegister)\r
+        );\r
+    }\r
 \r
-  if (StatusRegister & ERR) {\r
-    ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+    if (StatusRegister & ERR) {\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
 \r
-    if (ErrorRegister & BBK_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & BBK_ERR) {\r
+      DEBUG (\r
+        (EFI_D_BLKIO,\r
+        "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",\r
+        ErrorRegister)\r
+        );\r
+      }\r
 \r
-  if (ErrorRegister & UNC_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & UNC_ERR) {\r
+        DEBUG (\r
+          (EFI_D_BLKIO,\r
+          "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",\r
+          ErrorRegister)\r
+          );\r
+      }\r
 \r
-  if (ErrorRegister & MC_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & MC_ERR) {\r
+        DEBUG (\r
+          (EFI_D_BLKIO,\r
+          "CheckErrorStatus()-- %02x : Error : Media Change\n",\r
+          ErrorRegister)\r
+          );\r
+      }\r
 \r
-  if (ErrorRegister & ABRT_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Abort\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & ABRT_ERR) {\r
+        DEBUG (\r
+          (EFI_D_BLKIO,\r
+          "CheckErrorStatus()-- %02x : Error : Abort\n",\r
+          ErrorRegister)\r
+          );\r
+      }\r
 \r
-  if (ErrorRegister & TK0NF_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & TK0NF_ERR) {\r
+        DEBUG (\r
+          (EFI_D_BLKIO,\r
+          "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",\r
+          ErrorRegister)\r
+          );\r
+      }\r
 \r
-  if (ErrorRegister & AMNF_ERR) {\r
-    DEBUG (\r
-      (EFI_D_BLKIO,\r
-      "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
-      ErrorRegister)\r
-      );\r
-  }\r
+      if (ErrorRegister & AMNF_ERR) {\r
+        DEBUG (\r
+          (EFI_D_BLKIO,\r
+          "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",\r
+          ErrorRegister)\r
+          );\r
+      }\r
+    }\r
 \r
-  }\r
-  );\r
+  DEBUG_CODE_END ();\r
 \r
   if ((StatusRegister & (ERR | DWF | CORR)) == 0) {\r
     return EFI_SUCCESS;\r
@@ -729,10 +692,10 @@ CheckErrorStatus (
   to record all the information of the IDE device.\r
 \r
   @param[in] *DataBuffer\r
-  A pointer to the destination buffer for the data. \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
+  The starting logical block address to read from\r
   on the device media.\r
 \r
   @param[in] NumberOfBlocks\r
@@ -770,7 +733,7 @@ AtaReadSectors (
   //\r
   AtaCommand      = READ_SECTORS_CMD;\r
 \r
-  \r
+\r
   BlocksRemaining = NumberOfBlocks;\r
 \r
   Lba32           = (UINT32) Lba;\r
@@ -778,7 +741,7 @@ AtaReadSectors (
   Status          = EFI_SUCCESS;\r
 \r
   while (BlocksRemaining > 0) {\r
-    \r
+\r
     //\r
     // in ATA-3 spec, LBA is in 28 bit width\r
     //\r
@@ -791,7 +754,7 @@ AtaReadSectors (
     Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);\r
 \r
     if (BlocksRemaining >= 0x100) {\r
-      \r
+\r
       //\r
       //  SectorCount8 is sent to Sector Count register, 0x00 means 256\r
       //  sectors to be read\r
@@ -847,10 +810,10 @@ AtaReadSectors (
   to record all the information of the IDE device.\r
 \r
   @param[in] *BufferData\r
-  A pointer to the source buffer for the data. \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 starting logical block address to write onto\r
   the device media.\r
 \r
   @param[in] NumberOfBlocks\r
@@ -902,7 +865,7 @@ AtaWriteSectors (
     Lba3  = (UINT8) ((Lba32 >> 24) & 0x0f);\r
 \r
     if (BlocksRemaining >= 0x100) {\r
-      \r
+\r
       //\r
       //  SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors\r
       //  to be written\r
@@ -945,8 +908,8 @@ AtaWriteSectors (
 \r
 /**\r
   This function is used to implement the Soft Reset on the specified\r
-  device. But, the ATA Soft Reset mechanism is so strong a reset method \r
-  that it will force resetting on both devices connected to the \r
+  device. But, the ATA Soft Reset mechanism is so strong a reset method\r
+  that it will force resetting on both devices connected to the\r
   same cable.\r
 \r
   It is called by IdeBlkIoReset(), a interface function of Block\r
@@ -988,6 +951,10 @@ AtaSoftReset (
 \r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
 \r
+  //\r
+  // SRST should assert for at least 5 us, we use 10 us for\r
+  // better compatibility\r
+  //\r
   gBS->Stall (10);\r
 \r
   //\r
@@ -996,6 +963,11 @@ AtaSoftReset (
   DeviceControl = 0;\r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
 \r
+  //\r
+  // Wait for at least 2 ms to check BSY status, we use 10 ms\r
+  // for better compatibility\r
+  //\r
+  gBS->Stall(10000);\r
   //\r
   // slave device needs at most 31s to clear BSY\r
   //\r
@@ -1017,7 +989,7 @@ AtaSoftReset (
   The media id that the read request is for.\r
 \r
   @param[in] LBA\r
-  The starting logical block address to read from \r
+  The starting logical block address to read from\r
   on the device.\r
 \r
   @param[in] BufferSize\r
@@ -1025,7 +997,7 @@ AtaSoftReset (
   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
+  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
@@ -1033,11 +1005,11 @@ AtaSoftReset (
   @retval EFI_DEVICE_ERROR  Read Blocks failed.\r
   @retval EFI_NO_MEDIA      There is no media in the device.\r
   @retval EFI_MEDIA_CHANGE  The MediaId is not for the current media.\r
-  \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
+\r
   @retval EFI_INVALID_PARAMETER\r
   The read request contains LBAs that are not valid,\r
   or the data buffer is not valid.\r
@@ -1103,24 +1075,23 @@ AtaBlkIoReadBlocks (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  Status = EFI_SUCCESS;\r
   if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
     //\r
     // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism\r
     //\r
-    Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
-    if (EFI_ERROR (Status)) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
+      Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
+    } else {\r
       Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   } else {\r
     //\r
     // For ATA-3 compatible device, use ATA-3 read block mechanism\r
-    // Notice DMA operation can only handle 32bit address\r
     //\r
-    if ((UINTN) Buffer <= 0xFFFFFFFF) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
       Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
-    }\r
-\r
-    if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) {\r
+    } else {\r
       Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   }\r
@@ -1145,7 +1116,7 @@ AtaBlkIoReadBlocks (
   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 starting logical block address to write onto\r
   the device.\r
 \r
   @param[in] BufferSize\r
@@ -1153,20 +1124,20 @@ AtaBlkIoReadBlocks (
   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
+  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
+  or explicit ownership of the memory that data is\r
   written from.\r
 \r
   @retval EFI_SUCCESS       Write Blocks successfully.\r
   @retval EFI_DEVICE_ERROR  Write Blocks failed.\r
   @retval EFI_NO_MEDIA      There is no media in the device.\r
   @retval EFI_MEDIA_CHANGE  The MediaId is not for the current media.\r
-  \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
+\r
   @retval EFI_INVALID_PARAMETER\r
   The write request contains LBAs that are not valid,\r
   or the data buffer is not valid.\r
@@ -1228,20 +1199,23 @@ AtaBlkIoWriteBlocks (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  Status = EFI_SUCCESS;\r
   if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
     //\r
     // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism\r
     //\r
-    Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
-    if (EFI_ERROR (Status)) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
+      Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
+    } else {\r
       Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   } else {\r
     //\r
     // For ATA-3 compatible device, use ATA-3 write block mechanism\r
     //\r
-    Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
-    if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
+      Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
+    } else {\r
       Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   }\r
@@ -1256,15 +1230,15 @@ AtaBlkIoWriteBlocks (
 \r
 /**\r
   This function is called by the AtaBlkIoReadBlocks() to perform\r
-  reading from media in block unit. The function has been enhanced to \r
+  reading from media in block unit. The function has been enhanced to\r
   support >120GB access and transfer at most 65536 blocks per 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] *DataBuffer    A pointer to the destination buffer for the data. \r
-  @param[in] StartLba       The starting logical block address to read from \r
+  @param[in] *DataBuffer    A pointer to the destination buffer for the data.\r
+  @param[in] StartLba       The starting logical block address to read from\r
   on the device media.\r
   @param[in] NumberOfBlocks The number of transfer data blocks.\r
 \r
@@ -1339,7 +1313,7 @@ AtaReadSectorsExt (
 \r
 /**\r
   This function is called by the AtaBlkIoWriteBlocks() to perform\r
-  writing onto media in block unit. The function has been enhanced to \r
+  writing onto media in block unit. The function has been enhanced to\r
   support >120GB access and transfer at most 65536 blocks per command\r
 \r
   @param[in] *IdeDev\r
@@ -1347,10 +1321,10 @@ AtaReadSectorsExt (
   to record all the information of the IDE device.\r
 \r
   @param[in] *DataBuffer\r
-  A pointer to the source buffer for the data. \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 starting logical block address to write onto\r
   the device media.\r
 \r
   @param[in] NumberOfBlocks\r
@@ -1427,14 +1401,14 @@ AtaWriteSectorsExt (
 }\r
 \r
 /**\r
-  This function is used to send out ATA commands conforms to the \r
+  This function is used to send out ATA commands conforms to the\r
   PIO Data In Protocol, supporting ATA/ATAPI-6 standard\r
 \r
   Comparing with ATA-3 data in protocol, we have two differents here:<BR>\r
   1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
   wait will frequently fail... cause writing function return error)\r
 \r
-  2. Do NOT wait for DRQ clear after all data readed.(the wait greatly \r
+  2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
   slow down writing performance by 100 times!)\r
 \r
   @param[in] *IdeDev pointer pointing to IDE_BLK_IO_DEV data structure, used\r
@@ -1448,7 +1422,7 @@ AtaWriteSectorsExt (
 \r
   @retval EFI_SUCCESS send out the ATA command and device send required\r
   data successfully.\r
-  \r
+\r
   @retval EFI_DEVICE_ERROR command sent failed.\r
 \r
 **/\r
@@ -1544,7 +1518,7 @@ AtaPioDataInExt (
   // According to PIO data in protocol, host can perform a series of reads to\r
   // the data register after each time device set DRQ ready;\r
   //\r
-  \r
+\r
   //\r
   // 256 words\r
   //\r
@@ -1592,14 +1566,14 @@ AtaPioDataInExt (
 }\r
 \r
 /**\r
-  This function is used to send out ATA commands conforms to the \r
+  This function is used to send out ATA commands conforms to the\r
   PIO Data Out Protocol, supporting ATA/ATAPI-6 standard\r
 \r
   Comparing with ATA-3 data out protocol, we have two differents here:<BR>\r
   1. Do NOT wait for DRQ clear before sending command into IDE device.(the\r
   wait will frequently fail... cause writing function return error)\r
 \r
-  2. Do NOT wait for DRQ clear after all data readed.(the wait greatly \r
+  2. Do NOT wait for DRQ clear after all data readed.(the wait greatly\r
   slow down writing performance by 100 times!)\r
 \r
   @param[in] *IdeDev\r
@@ -1614,7 +1588,7 @@ AtaPioDataInExt (
 \r
   @retval EFI_SUCCESS send out the ATA command and device receive required\r
   data successfully.\r
-  \r
+\r
   @retval EFI_DEVICE_ERROR command sent failed.\r
 \r
 **/\r
@@ -1661,7 +1635,7 @@ AtaPioDataOutExt (
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
-     \r
+\r
   //\r
   // Fill feature register if needed\r
   //\r
@@ -2068,7 +2042,7 @@ AtaCommandIssue (
   Lba1  = (UINT8) RShiftU64 (LbaAddress, 8);\r
   Lba2  = (UINT8) RShiftU64 (LbaAddress, 16);\r
   Lba3  = (UINT8) RShiftU64 (LbaAddress, 24);\r
-  Device |= Lba3;\r
+  Device = (UINT8) (Device | Lba3);\r
 \r
   //\r
   // Pass parameter into device register block\r
@@ -2090,7 +2064,7 @@ AtaCommandIssue (
   //\r
   // Fill the start LBA registers, which are also two-byte FIFO\r
   //\r
-  \r
+\r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);\r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);\r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);\r
@@ -2110,15 +2084,15 @@ AtaCommandIssue (
 \r
 /**\r
   This function is called by the AtaBlkIoReadBlocks() to perform\r
-  reading from media in block unit. The function has been enhanced to \r
+  reading from media in block unit. The function has been enhanced to\r
   support >120GB access and transfer at most 65536 blocks per command\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
 \r
-  @param[in] *DataBuffer A pointer to the destination buffer for the data. \r
+  @param[in] *DataBuffer A pointer to the destination buffer for the data.\r
 \r
-  @param[in] StartLba The starting logical block address to read from \r
+  @param[in] StartLba The starting logical block address to read from\r
   on the device media.\r
 \r
   @param[in] NumberOfBlocks The number of transfer data blocks.\r
@@ -2139,24 +2113,198 @@ AtaUdmaReadExt (
   IN  UINTN           NumberOfBlocks\r
   )\r
 {\r
-  IDE_DMA_PRD *PrdAddr;\r
-  IDE_DMA_PRD *UsedPrdAddr;\r
-  IDE_DMA_PRD *TempPrdAddr;\r
-  UINT8       RegisterValue;\r
-  UINT8       Device;\r
-  UINT64      IoPortForBmic;\r
-  UINT64      IoPortForBmis;\r
-  UINT64      IoPortForBmid;\r
-  EFI_STATUS  Status;\r
-  UINTN       PrdTableNum;\r
-  UINTN       ByteCount;\r
-  UINTN       ByteAvailable;\r
-  UINT8       *PrdBuffer;\r
-  UINTN       RemainBlockNum;\r
-  UINT8       DeviceControl;\r
+  return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadExtOp);\r
+}\r
+\r
+/**\r
+  This function is called by the AtaBlkIoReadBlocks() to perform\r
+  reading from media in block unit. The function has been enhanced to\r
+  support >120GB access and transfer at most 65536 blocks per 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] *DataBuffer    A pointer to the destination buffer for the data.\r
+  @param[in] StartLba       The starting logical block address to read from\r
+  on the device media.\r
+  @param[in] NumberOfBlocks The number of transfer data blocks.\r
+\r
+  @return The device status of UDMA operation. If the operation is\r
+  successful, return EFI_SUCCESS.\r
+\r
+  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+**/\r
+EFI_STATUS\r
+AtaUdmaRead (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  VOID            *DataBuffer,\r
+  IN  EFI_LBA         StartLba,\r
+  IN  UINTN           NumberOfBlocks\r
+  )\r
+{\r
+  return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaReadOp);\r
+}\r
+\r
+/**\r
+  This function is called by the AtaBlkIoWriteBlocks() to perform\r
+  writing to media in block unit. The function has been enhanced to\r
+  support >120GB access and transfer at most 65536 blocks per command\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
+\r
+  @param[in] *DataBuffer A pointer to the source buffer for the data.\r
+\r
+  @param[in] StartLba The starting logical block address to write to\r
+  on the device media.\r
+\r
+  @param[in] NumberOfBlocks The number of transfer data blocks.\r
+\r
+  @return The device status of UDMA operation. If the operation is\r
+  successful, return EFI_SUCCESS.\r
+\r
+  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+**/\r
+EFI_STATUS\r
+AtaUdmaWriteExt (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  VOID            *DataBuffer,\r
+  IN  EFI_LBA         StartLba,\r
+  IN  UINTN           NumberOfBlocks\r
+  )\r
+{\r
+  return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteExtOp);\r
+}\r
+\r
+/**\r
+  This function is called by the AtaBlkIoWriteBlocks() to perform\r
+  writing to media in block unit. The function has been enhanced to\r
+  support >120GB access and transfer at most 65536 blocks per 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] *DataBuffer\r
+  A pointer to the source buffer for the data.\r
+\r
+  @param[in] StartLba\r
+  The starting logical block address to write to\r
+  on the device media.\r
+\r
+  @param[in] NumberOfBlocks\r
+  The number of transfer data blocks.\r
+\r
+  @return The device status of UDMA operation. If the operation is\r
+  successful, return EFI_SUCCESS.\r
+\r
+  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+**/\r
+EFI_STATUS\r
+AtaUdmaWrite (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  VOID            *DataBuffer,\r
+  IN  EFI_LBA         StartLba,\r
+  IN  UINTN           NumberOfBlocks\r
+  )\r
+{\r
+  return DoAtaUdma (IdeDev, DataBuffer, StartLba, NumberOfBlocks, AtaUdmaWriteOp);\r
+}\r
+\r
+/**\r
+  Perform an ATA Udma operation (Read, ReadExt, Write, WriteExt).\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] *DataBuffer\r
+  A pointer to the source buffer for the data.\r
+\r
+  @param[in] StartLba\r
+  The starting logical block address to write to\r
+  on the device media.\r
+\r
+  @param[in] NumberOfBlocks\r
+  The number of transfer data blocks.\r
+  \r
+  @param[in] UdmaOp\r
+  The perform operations could be AtaUdmaReadOp, AtaUdmaReadExOp,\r
+  AtaUdmaWriteOp, AtaUdmaWriteExOp\r
+\r
+  @return The device status of UDMA operation. If the operation is\r
+  successful, return EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+DoAtaUdma (\r
+  IN  IDE_BLK_IO_DEV      *IdeDev,\r
+  IN  VOID                *DataBuffer,\r
+  IN  EFI_LBA             StartLba,\r
+  IN  UINTN               NumberOfBlocks,\r
+  IN  ATA_UDMA_OPERATION  UdmaOp\r
+  )\r
+{\r
+  IDE_DMA_PRD                   *PrdAddr;\r
+  IDE_DMA_PRD                   *UsedPrdAddr;\r
+  IDE_DMA_PRD                   *TempPrdAddr;\r
+  UINT8                         RegisterValue;\r
+  UINT8                         Device;\r
+  UINT64                        IoPortForBmic;\r
+  UINT64                        IoPortForBmis;\r
+  UINT64                        IoPortForBmid;\r
+  EFI_STATUS                    Status;\r
+  UINTN                         PrdTableNum;\r
+  UINTN                         ByteCount;\r
+  UINTN                         ByteAvailable;\r
+  UINT8                         *PrdBuffer;\r
+  UINTN                         RemainBlockNum;\r
+  UINT8                         DeviceControl;\r
+  UINT32                        Count;\r
+  UINTN                         PageCount;\r
+  VOID                          *Map;\r
+  VOID                          *MemPage;\r
+  EFI_PHYSICAL_ADDRESS          DeviceAddress;\r
+  UINTN                         MaxDmaCommandSectors;\r
+  EFI_PCI_IO_PROTOCOL_OPERATION PciIoProtocolOp;\r
+  UINT8                         AtaCommand;\r
+\r
+  switch (UdmaOp) {\r
+  case AtaUdmaReadOp:\r
+    MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;\r
+    PciIoProtocolOp      = EfiPciIoOperationBusMasterWrite;\r
+    AtaCommand           = READ_DMA_CMD;\r
+    break;\r
+  case AtaUdmaReadExtOp:\r
+    MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;\r
+    PciIoProtocolOp      = EfiPciIoOperationBusMasterWrite;\r
+    AtaCommand           = READ_DMA_EXT_CMD;\r
+    break;\r
+  case AtaUdmaWriteOp:\r
+    MaxDmaCommandSectors = MAX_DMA_COMMAND_SECTORS;\r
+    PciIoProtocolOp      = EfiPciIoOperationBusMasterRead;\r
+    AtaCommand           = WRITE_DMA_CMD;\r
+    break;\r
+  case AtaUdmaWriteExtOp:\r
+    MaxDmaCommandSectors = MAX_DMA_EXT_COMMAND_SECTORS;\r
+    PciIoProtocolOp      = EfiPciIoOperationBusMasterRead;\r
+    AtaCommand           = WRITE_DMA_EXT_CMD;\r
+    break;\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+    break;\r
+  }\r
 \r
   //\r
-  // Channel and device differential. Select device.\r
+  // Channel and device differential\r
   //\r
   Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
 \r
@@ -2185,13 +2333,13 @@ AtaUdmaReadExt (
   RemainBlockNum = NumberOfBlocks;\r
   while (RemainBlockNum > 0) {\r
 \r
-    if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {\r
+    if (RemainBlockNum >= MaxDmaCommandSectors) {\r
       //\r
       //  SectorCount is used to record the number of sectors to be read\r
       //  Max 65536 sectors can be transfered at a time.\r
       //\r
-      NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;\r
-      RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;\r
+      NumberOfBlocks = MaxDmaCommandSectors;\r
+      RemainBlockNum -= MaxDmaCommandSectors;\r
     } else {\r
       NumberOfBlocks  = (UINT16) RemainBlockNum;\r
       RemainBlockNum  = 0;\r
@@ -2207,8 +2355,21 @@ AtaUdmaReadExt (
     //\r
     // Build PRD table\r
     //\r
-    PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));\r
-\r
+    PageCount = EFI_SIZE_TO_PAGES (2 * PrdTableNum * sizeof (IDE_DMA_PRD));\r
+    Status = IdeDev->PciIo->AllocateBuffer (\r
+                    IdeDev->PciIo,\r
+                    AllocateAnyPages,\r
+                    EfiBootServicesData,\r
+                    PageCount,\r
+                    &MemPage,\r
+                    0\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    ZeroMem ((VOID *) ((UINTN) MemPage), EFI_PAGES_TO_SIZE (PageCount));\r
+    \r
+    PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
     //\r
     // To make sure PRD is allocated in one 64K page\r
     //\r
@@ -2225,7 +2386,19 @@ AtaUdmaReadExt (
     //\r
     // Build the PRD table\r
     //\r
-    PrdBuffer   = DataBuffer;\r
+    Status = IdeDev->PciIo->Map (\r
+                       IdeDev->PciIo, \r
+                       PciIoProtocolOp, \r
+                       DataBuffer, \r
+                       &ByteCount, \r
+                       &DeviceAddress,\r
+                       &Map\r
+                       );\r
+    if (EFI_ERROR (Status)) {\r
+      IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }    \r
+    PrdBuffer   = (VOID *) ((UINTN) DeviceAddress);\r
     TempPrdAddr = UsedPrdAddr;\r
     while (TRUE) {\r
 \r
@@ -2245,7 +2418,7 @@ AtaUdmaReadExt (
       PrdBuffer += ByteAvailable;\r
       TempPrdAddr++;\r
     }\r
-  \r
+\r
     //\r
     // Set the base address to BMID register\r
     //\r
@@ -2270,7 +2443,11 @@ AtaUdmaReadExt (
                         &RegisterValue\r
                         );\r
 \r
-    RegisterValue |= BMIC_nREAD;\r
+    if (UdmaOp == AtaUdmaReadExtOp || UdmaOp == AtaUdmaReadOp) {\r
+      RegisterValue |= BMIC_nREAD;\r
+    } else {\r
+      RegisterValue &= ~((UINT8) BMIC_nREAD);\r
+    }\r
 \r
     IdeDev->PciIo->Io.Write (\r
                         IdeDev->PciIo,\r
@@ -2293,7 +2470,7 @@ AtaUdmaReadExt (
                         &RegisterValue\r
                         );\r
 \r
-    RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR;\r
+    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
 \r
     IdeDev->PciIo->Io.Write (\r
                         IdeDev->PciIo,\r
@@ -2304,19 +2481,29 @@ AtaUdmaReadExt (
                         &RegisterValue\r
                         );\r
 \r
-    //\r
-    // Issue READ DMA EXT command\r
-    //\r
-    Status = AtaCommandIssueExt (\r
-              IdeDev,\r
-              READ_DMA_EXT_CMD,\r
-              Device,\r
-              0,\r
-              (UINT16) NumberOfBlocks,\r
-              StartLba\r
-              );\r
+    if (UdmaOp == AtaUdmaWriteExtOp || UdmaOp == AtaUdmaReadExtOp) {\r
+      Status = AtaCommandIssueExt (\r
+                 IdeDev,\r
+                 AtaCommand,\r
+                 Device,\r
+                 0,\r
+                 (UINT16) NumberOfBlocks,\r
+                 StartLba\r
+                 );\r
+    } else {\r
+      Status = AtaCommandIssue (\r
+                 IdeDev,\r
+                 AtaCommand,\r
+                 Device,\r
+                 0,\r
+                 (UINT16) NumberOfBlocks,\r
+                 StartLba\r
+                 );\r
+    }\r
+\r
     if (EFI_ERROR (Status)) {\r
-      gBS->FreePool (PrdAddr);\r
+      IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
+      IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
       return EFI_DEVICE_ERROR;\r
     }\r
 \r
@@ -2345,7 +2532,11 @@ AtaUdmaReadExt (
 \r
     //\r
     // Check the INTERRUPT and ERROR bit of BMIS\r
+    // Max transfer number of sectors for one command is 65536(32Mbyte),\r
+    // it will cost 1 second to transfer these data in UDMA mode 2(33.3MBps).\r
+    // So set the variable Count to 2000, for about 2 second timeout time.\r
     //\r
+    Count = 2000;\r
     while (TRUE) {\r
 \r
       IdeDev->PciIo->Io.Read (\r
@@ -2356,21 +2547,49 @@ AtaUdmaReadExt (
                           1,\r
                           &RegisterValue\r
                           );\r
-      if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {\r
-        if (RegisterValue & BMIS_ERROR) {\r
-          gBS->FreePool (PrdAddr);\r
+      if ((RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) || (Count == 0)) {\r
+        if ((RegisterValue & BMIS_ERROR) || (Count == 0)) {\r
+          //\r
+          // Clear START bit of BMIC register before return EFI_DEVICE_ERROR\r
+          //\r
+          IdeDev->PciIo->Io.Read (\r
+                              IdeDev->PciIo,\r
+                              EfiPciIoWidthUint8,\r
+                              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                              IoPortForBmic,\r
+                              1,\r
+                              &RegisterValue\r
+                              );\r
+\r
+          RegisterValue &= ~((UINT8)BMIC_START);\r
+\r
+          IdeDev->PciIo->Io.Write (\r
+                              IdeDev->PciIo,\r
+                              EfiPciIoWidthUint8,\r
+                              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+                              IoPortForBmic,\r
+                              1,\r
+                              &RegisterValue\r
+                              );\r
+          IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
+          IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
           return EFI_DEVICE_ERROR;\r
         }\r
         break;\r
       }\r
 \r
       gBS->Stall (1000);\r
+      Count --;\r
     }\r
 \r
-    gBS->FreePool (PrdAddr);\r
-\r
+    IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
+    IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
     //\r
-    // Set START bit of BMIC register\r
+    // Read Status Register of IDE device to clear interrupt\r
+    //\r
+    RegisterValue = IDEReadPortB(IdeDev->PciIo,IdeDev->IoPort->Reg.Status);\r
+    //\r
+    // Clear START bit of BMIC register\r
     //\r
     IdeDev->PciIo->Io.Read (\r
                         IdeDev->PciIo,\r
@@ -2400,885 +2619,12 @@ AtaUdmaReadExt (
     StartLba += NumberOfBlocks;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is called by the AtaBlkIoReadBlocks() to perform\r
-  reading from media in block unit. The function has been enhanced to \r
-  support >120GB access and transfer at most 65536 blocks per 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] *DataBuffer    A pointer to the destination buffer for the data. \r
-  @param[in] StartLba       The starting logical block address to read from \r
-  on the device media.\r
-  @param[in] NumberOfBlocks The number of transfer data blocks.\r
-\r
-  @return The device status of UDMA operation. If the operation is\r
-  successful, return EFI_SUCCESS.\r
-\r
-  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-**/\r
-EFI_STATUS\r
-AtaUdmaRead (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  VOID            *DataBuffer,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINTN           NumberOfBlocks\r
-  )\r
-{\r
-  IDE_DMA_PRD *PrdAddr;\r
-  IDE_DMA_PRD *UsedPrdAddr;\r
-  IDE_DMA_PRD *TempPrdAddr;\r
-  UINT8       RegisterValue;\r
-  UINT8       Device;\r
-  UINT64      IoPortForBmic;\r
-  UINT64      IoPortForBmis;\r
-  UINT64      IoPortForBmid;\r
-  EFI_STATUS  Status;\r
-  UINTN       PrdTableNum;\r
-  UINTN       ByteCount;\r
-  UINTN       ByteAvailable;\r
-  UINT8       *PrdBuffer;\r
-  UINTN       RemainBlockNum;\r
-  UINT8       DeviceControl;\r
-\r
-  //\r
-  // Channel and device differential\r
-  //\r
-  Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
-\r
-  //\r
-  // Enable interrupt to support UDMA and Select device\r
-  //\r
-  DeviceControl = 0;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
-\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-\r
-  if (IdePrimary == IdeDev->Channel) {\r
-    IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
-    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
-    IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
-  } else {\r
-    if (IdeSecondary == IdeDev->Channel) {\r
-      IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
-      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
-      IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
-    } else {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  RemainBlockNum = NumberOfBlocks;\r
-  while (RemainBlockNum > 0) {\r
-\r
-    if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {\r
-      //\r
-      //  SectorCount is used to record the number of sectors to be read\r
-      //  Max 256 sectors can be transfered at a time.\r
-      //\r
-      NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;\r
-      RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;\r
-    } else {\r
-      NumberOfBlocks  = (UINT16) RemainBlockNum;\r
-      RemainBlockNum  = 0;\r
-    }\r
-\r
-    //\r
-    // Calculate the number of PRD table to make sure the memory region\r
-    // not cross 64K boundary\r
-    //\r
-    ByteCount   = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
-\r
-    //\r
-    // Build PRD table\r
-    //\r
-    PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));\r
-    //\r
-    // To make sure PRD is allocated in one 64K page\r
-    //\r
-    if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
-      UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
-    } else {\r
-      if ((UINTN) PrdAddr & 0x03) {\r
-        UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
-      } else {\r
-        UsedPrdAddr = PrdAddr;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Build the PRD table\r
-    //\r
-    PrdBuffer   = DataBuffer;\r
-    TempPrdAddr = UsedPrdAddr;\r
-    while (TRUE) {\r
-\r
-      ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
-\r
-      if (ByteCount <= ByteAvailable) {\r
-        TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-        TempPrdAddr->ByteCount      = (UINT16) ByteCount;\r
-        TempPrdAddr->EndOfTable     = 0x8000;\r
-        break;\r
-      }\r
-\r
-      TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-      TempPrdAddr->ByteCount      = (UINT16) ByteAvailable;\r
-\r
-      ByteCount -= ByteAvailable;\r
-      PrdBuffer += ByteAvailable;\r
-      TempPrdAddr++;\r
-    }\r
-\r
-    //\r
-    // Set the base address to BMID register\r
-    //\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint32,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmid,\r
-                        1,\r
-                        &UsedPrdAddr\r
-                        );\r
-\r
-    //\r
-    // Set BMIC register to identify the operation direction\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= BMIC_nREAD;\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Read BMIS register and clear ERROR and INTR bit\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Issue READ DMA command\r
-    //\r
-    Status = AtaCommandIssue (\r
-              IdeDev,\r
-              READ_DMA_CMD,\r
-              Device,\r
-              0,\r
-              (UINT16) NumberOfBlocks,\r
-              StartLba\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->FreePool (PrdAddr);\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= BMIC_START;\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Check the INTERRUPT and ERROR bit of BMIS\r
-    //\r
-    while (TRUE) {\r
-\r
-      IdeDev->PciIo->Io.Read (\r
-                          IdeDev->PciIo,\r
-                          EfiPciIoWidthUint8,\r
-                          EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                          IoPortForBmis,\r
-                          1,\r
-                          &RegisterValue\r
-                          );\r
-      if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {\r
-        if (RegisterValue & BMIS_ERROR) {\r
-          gBS->FreePool (PrdAddr);\r
-          return EFI_DEVICE_ERROR;\r
-        }\r
-        break;\r
-      }\r
-\r
-      gBS->Stall (1000);\r
-    }\r
-\r
-    gBS->FreePool (PrdAddr);\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue &= ~((UINT8) BMIC_START);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    if (RegisterValue & BMIS_ERROR) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    StartLba += NumberOfBlocks;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is called by the AtaBlkIoWriteBlocks() to perform\r
-  writing to media in block unit. The function has been enhanced to \r
-  support >120GB access and transfer at most 65536 blocks per command\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
-\r
-  @param[in] *DataBuffer A pointer to the source buffer for the data. \r
-\r
-  @param[in] StartLba The starting logical block address to write to \r
-  on the device media.\r
-\r
-  @param[in] NumberOfBlocks The number of transfer data blocks.\r
-\r
-  @return The device status of UDMA operation. If the operation is\r
-  successful, return EFI_SUCCESS.\r
-\r
-  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-**/\r
-EFI_STATUS\r
-AtaUdmaWriteExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  VOID            *DataBuffer,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINTN           NumberOfBlocks\r
-  )\r
-{\r
-  IDE_DMA_PRD *PrdAddr;\r
-  IDE_DMA_PRD *UsedPrdAddr;\r
-  IDE_DMA_PRD *TempPrdAddr;\r
-  UINT8       RegisterValue;\r
-  UINT8       Device;\r
-  UINT64      IoPortForBmic;\r
-  UINT64      IoPortForBmis;\r
-  UINT64      IoPortForBmid;\r
-  EFI_STATUS  Status;\r
-  UINTN       PrdTableNum;\r
-  UINTN       ByteCount;\r
-  UINTN       ByteAvailable;\r
-  UINT8       *PrdBuffer;\r
-  UINTN       RemainBlockNum;\r
-  UINT8       DeviceControl;\r
-\r
-  //\r
-  // Channel and device differential\r
-  //\r
-  Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
-\r
-  //\r
-  // Enable interrupt to support UDMA and Select device\r
-  //\r
-  DeviceControl = 0;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
-\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-\r
-  if (IdePrimary == IdeDev->Channel) {\r
-    IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
-    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
-    IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
-  } else {\r
-    if (IdeSecondary == IdeDev->Channel) {\r
-      IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
-      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
-      IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
-    } else {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  RemainBlockNum = NumberOfBlocks;\r
-  while (RemainBlockNum > 0) {\r
-\r
-    if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {\r
-      //\r
-      //  SectorCount is used to record the number of sectors to be read\r
-      //  Max 65536 sectors can be transfered at a time.\r
-      //\r
-      NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;\r
-      RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;\r
-    } else {\r
-      NumberOfBlocks  = (UINT16) RemainBlockNum;\r
-      RemainBlockNum  = 0;\r
-    }\r
-\r
-    //\r
-    // Calculate the number of PRD table to make sure the memory region\r
-    // not cross 64K boundary\r
-    //\r
-    ByteCount   = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
-\r
-    //\r
-    // Build PRD table\r
-    //\r
-    PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));\r
-    //\r
-    // To make sure PRD is allocated in one 64K page\r
-    //\r
-    if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
-      UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
-    } else {\r
-      if ((UINTN) PrdAddr & 0x03) {\r
-        UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
-      } else {\r
-        UsedPrdAddr = PrdAddr;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Build the PRD table\r
-    //\r
-    PrdBuffer   = DataBuffer;\r
-    TempPrdAddr = UsedPrdAddr;\r
-    while (TRUE) {\r
-\r
-      ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
-\r
-      if (ByteCount <= ByteAvailable) {\r
-        TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-        TempPrdAddr->ByteCount      = (UINT16) ByteCount;\r
-        TempPrdAddr->EndOfTable     = 0x8000;\r
-        break;\r
-      }\r
-\r
-      TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-      TempPrdAddr->ByteCount      = (UINT16) ByteAvailable;\r
-\r
-      ByteCount -= ByteAvailable;\r
-      PrdBuffer += ByteAvailable;\r
-      TempPrdAddr++;\r
-    }\r
-  \r
-    //\r
-    // Set the base address to BMID register\r
-    //\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint32,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmid,\r
-                        1,\r
-                        &UsedPrdAddr\r
-                        );\r
-\r
-    //\r
-    // Set BMIC register to identify the operation direction\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-    //\r
-    // 0000 1000\r
-    //\r
-    RegisterValue &= ~((UINT8) BMIC_nREAD);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Read BMIS register and clear ERROR and INTR bit\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Issue WRITE DMA EXT command\r
-    //\r
-    Status = AtaCommandIssueExt (\r
-              IdeDev,\r
-              WRITE_DMA_EXT_CMD,\r
-              Device,\r
-              0,\r
-              (UINT16) NumberOfBlocks,\r
-              StartLba\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->FreePool (PrdAddr);\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= BMIC_START;\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Check the INTERRUPT and ERROR bit of BMIS\r
-    //\r
-    while (TRUE) {\r
-\r
-      IdeDev->PciIo->Io.Read (\r
-                          IdeDev->PciIo,\r
-                          EfiPciIoWidthUint8,\r
-                          EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                          IoPortForBmis,\r
-                          1,\r
-                          &RegisterValue\r
-                          );\r
-      if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {\r
-        if (RegisterValue & BMIS_ERROR) {\r
-          gBS->FreePool (PrdAddr);\r
-          return EFI_DEVICE_ERROR;\r
-        }\r
-        break;\r
-      }\r
-\r
-      gBS->Stall (1000);\r
-    }\r
-\r
-    gBS->FreePool (PrdAddr);\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue &= ~((UINT8) BMIC_START);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    StartLba += NumberOfBlocks;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is called by the AtaBlkIoWriteBlocks() to perform\r
-  writing to media in block unit. The function has been enhanced to \r
-  support >120GB access and transfer at most 65536 blocks per 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] *DataBuffer\r
-  A pointer to the source buffer for the data. \r
-\r
-  @param[in] StartLba\r
-  The starting logical block address to write to \r
-  on the device media.\r
-\r
-  @param[in] NumberOfBlocks\r
-  The number of transfer data blocks.\r
-\r
-  @return The device status of UDMA operation. If the operation is\r
-  successful, return EFI_SUCCESS.\r
-\r
-  TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-  TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-**/\r
-EFI_STATUS\r
-AtaUdmaWrite (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  VOID            *DataBuffer,\r
-  IN  EFI_LBA         StartLba,\r
-  IN  UINTN           NumberOfBlocks\r
-  )\r
-{\r
-  IDE_DMA_PRD *PrdAddr;\r
-  IDE_DMA_PRD *UsedPrdAddr;\r
-  IDE_DMA_PRD *TempPrdAddr;\r
-  UINT8       RegisterValue;\r
-  UINT8       Device;\r
-  UINT64      IoPortForBmic;\r
-  UINT64      IoPortForBmis;\r
-  UINT64      IoPortForBmid;\r
-  EFI_STATUS  Status;\r
-  UINTN       PrdTableNum;\r
-  UINTN       ByteCount;\r
-  UINTN       ByteAvailable;\r
-  UINT8       *PrdBuffer;\r
-  UINTN       RemainBlockNum;\r
-  UINT8       DeviceControl;\r
-\r
-  //\r
-  // Channel and device differential\r
-  //\r
-  Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
-\r
   //\r
-  // Enable interrupt to support UDMA\r
+  // Disable interrupt of Select device\r
   //\r
-  DeviceControl = 0;\r
+  IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
+  DeviceControl |= IEN_L;\r
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
 \r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-\r
-  if (IdePrimary == IdeDev->Channel) {\r
-    IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;\r
-    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
-    IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;\r
-  } else {\r
-    if (IdeSecondary == IdeDev->Channel) {\r
-      IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;\r
-      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
-      IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;\r
-    } else {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  RemainBlockNum = NumberOfBlocks;\r
-  while (RemainBlockNum > 0) {\r
-\r
-    if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {\r
-      //\r
-      //  SectorCount is used to record the number of sectors to be read\r
-      //  Max 256 sectors can be transfered at a time.\r
-      //\r
-      NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;\r
-      RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;\r
-    } else {\r
-      NumberOfBlocks  = (UINT16) RemainBlockNum;\r
-      RemainBlockNum  = 0;\r
-    }\r
-\r
-    //\r
-    // Calculate the number of PRD table to make sure the memory region\r
-    // not cross 64K boundary\r
-    //\r
-    ByteCount   = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    PrdTableNum = ((ByteCount >> 16) + 1) + 1;\r
-\r
-    //\r
-    // Build PRD table\r
-    //\r
-    PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));\r
-\r
-    //\r
-    // To make sure PRD is allocated in one 64K page\r
-    //\r
-    if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {\r
-      UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);\r
-    } else {\r
-      if ((UINTN) PrdAddr & 0x03) {\r
-        UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);\r
-      } else {\r
-        UsedPrdAddr = PrdAddr;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Build the PRD table\r
-    //\r
-    PrdBuffer   = DataBuffer;\r
-    TempPrdAddr = UsedPrdAddr;\r
-    while (TRUE) {\r
-\r
-      ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);\r
-\r
-      if (ByteCount <= ByteAvailable) {\r
-        TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-        TempPrdAddr->ByteCount      = (UINT16) ByteCount;\r
-        TempPrdAddr->EndOfTable     = 0x8000;\r
-        break;\r
-      }\r
-\r
-      TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);\r
-      TempPrdAddr->ByteCount      = (UINT16) ByteAvailable;\r
-\r
-      ByteCount -= ByteAvailable;\r
-      PrdBuffer += ByteAvailable;\r
-      TempPrdAddr++;\r
-    }\r
-  \r
-    //\r
-    // Set the base address to BMID register\r
-    //\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint32,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmid,\r
-                        1,\r
-                        &UsedPrdAddr\r
-                        );\r
-\r
-    //\r
-    // Set BMIC register to identify the operation direction\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-    //\r
-    // 0000 1000\r
-    //\r
-    RegisterValue &= ~((UINT8) BMIC_nREAD);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Read BMIS register and clear ERROR and INTR bit\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmis,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Issue WRITE DMA command\r
-    //\r
-    Status = AtaCommandIssue (\r
-              IdeDev,\r
-              WRITE_DMA_CMD,\r
-              Device,\r
-              0,\r
-              (UINT16) NumberOfBlocks,\r
-              StartLba\r
-              );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->FreePool (PrdAddr);\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue |= BMIC_START;\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    //\r
-    // Check the INTERRUPT and ERROR bit of BMIS\r
-    //\r
-    while (TRUE) {\r
-\r
-      IdeDev->PciIo->Io.Read (\r
-                          IdeDev->PciIo,\r
-                          EfiPciIoWidthUint8,\r
-                          EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                          IoPortForBmis,\r
-                          1,\r
-                          &RegisterValue\r
-                          );\r
-      if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {\r
-        if (RegisterValue & BMIS_ERROR) {\r
-          gBS->FreePool (PrdAddr);\r
-          return EFI_DEVICE_ERROR;\r
-        }\r
-        break;\r
-      }\r
-\r
-      gBS->Stall (1000);\r
-    }\r
-\r
-    gBS->FreePool (PrdAddr);\r
-\r
-    //\r
-    // Set START bit of BMIC register\r
-    //\r
-    IdeDev->PciIo->Io.Read (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    RegisterValue &= ~((UINT8) BMIC_START);\r
-\r
-    IdeDev->PciIo->Io.Write (\r
-                        IdeDev->PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        EFI_PCI_IO_PASS_THROUGH_BAR,\r
-                        IoPortForBmic,\r
-                        1,\r
-                        &RegisterValue\r
-                        );\r
-\r
-    DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;\r
-    StartLba += NumberOfBlocks;\r
-  }\r
-\r
   return EFI_SUCCESS;\r
-}\r
+}
\ No newline at end of file