]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
The latest IPF boot failure is found and is not caused by this fixing, so check-in...
[mirror_edk2.git] / EdkModulePkg / Bus / Pci / IdeBus / Dxe / ata.c
index aea126b3e689e28ca5da8a86548469f9e32f3b92..382c0691ba9ab98bca57ff984a723a080750d77b 100644 (file)
@@ -1,5 +1,5 @@
 /** @file\r
-  Copyright (c) 2006, Intel Corporation\r
+  Copyright (c) 2006 - 2007 Intel Corporation. <BR>\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
@@ -1075,20 +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
     //\r
-    Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
-    if (EFI_ERROR (Status)) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
+      Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
+    } else {\r
       Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   }\r
@@ -1196,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)) {\r
+    if (IdeBlkIoDevice->UdmaMode.Valid) {\r
+      Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
+    } else {\r
       Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);\r
     }\r
   }\r
@@ -2107,29 +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
-  UINT32                     Count;\r
-  UINTN                      PageCount;\r
-  VOID                       *Map;\r
-  VOID                       *MemPage;\r
-  EFI_PHYSICAL_ADDRESS       DeviceAddress;\r
-\r
-  //\r
-  // Channel and device differential. Select device.\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\r
   //\r
   Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
 \r
@@ -2158,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
@@ -2182,20 +2357,19 @@ AtaUdmaReadExt (
     //\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
+                    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
+    \r
     PrdAddr = (IDE_DMA_PRD *) ((UINTN) MemPage);\r
-\r
     //\r
     // To make sure PRD is allocated in one 64K page\r
     //\r
@@ -2213,17 +2387,17 @@ AtaUdmaReadExt (
     // Build the PRD table\r
     //\r
     Status = IdeDev->PciIo->Map (\r
-                       IdeDev->PciIo,\r
-                       EfiPciIoOperationBusMasterWrite,\r
-                       DataBuffer,\r
-                       &ByteCount,\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
+    }    \r
     PrdBuffer   = (VOID *) ((UINTN) DeviceAddress);\r
     TempPrdAddr = UsedPrdAddr;\r
     while (TRUE) {\r
@@ -2269,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
@@ -2292,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
@@ -2303,17 +2481,26 @@ 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
       IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
       IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
@@ -2441,1097 +2628,3 @@ AtaUdmaReadExt (
 \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
-  UINT32                     Count;\r
-  UINTN                      PageCount;\r
-  VOID                       *Map;\r
-  VOID                       *MemPage;\r
-  EFI_PHYSICAL_ADDRESS       DeviceAddress;\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
-    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
-    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
-    Status = IdeDev->PciIo->Map (\r
-                       IdeDev->PciIo,\r
-                       EfiPciIoOperationBusMasterWrite,\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   = (UINT8 *) ((UINTN) DeviceAddress);\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
-      IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-      IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\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
-    // 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
-                          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)) || (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
-    IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-    IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
-    //\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
-                        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
-  //\r
-  // Disable interrupt of Select device\r
-  //\r
-  IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
-  DeviceControl |= IEN_L;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\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
-  UINT32                     Count;\r
-  UINTN                      PageCount;\r
-  VOID                       *Map;\r
-  VOID                       *MemPage;\r
-  EFI_PHYSICAL_ADDRESS       DeviceAddress;\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
-    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
-    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
-    Status = IdeDev->PciIo->Map (\r
-                       IdeDev->PciIo,\r
-                       EfiPciIoOperationBusMasterRead,\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   = (UINT8 *) ((UINTN) DeviceAddress);\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
-      IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-      IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\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
-    // 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
-                          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)) || (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
-    IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-    IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
-    //\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
-                        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
-  //\r
-  // Disable interrupt of Select device\r
-  //\r
-  IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
-  DeviceControl |= IEN_L;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\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
-  UINT32                     Count;\r
-  UINTN                      PageCount;\r
-  VOID                       *Map;\r
-  VOID                       *MemPage;\r
-  EFI_PHYSICAL_ADDRESS       DeviceAddress;\r
-\r
-  //\r
-  // Channel and device differential\r
-  //\r
-  Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);\r
-\r
-  //\r
-  // Enable interrupt to support UDMA\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
-    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
-    //\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
-    Status = IdeDev->PciIo->Map (\r
-                       IdeDev->PciIo,\r
-                       EfiPciIoOperationBusMasterRead,\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   = (UINT8 *) ((UINTN) DeviceAddress);\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
-      IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-      IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\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
-    // 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
-                          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)) || (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
-    IdeDev->PciIo->FreeBuffer (IdeDev->PciIo, PageCount, MemPage);\r
-    IdeDev->PciIo->Unmap (IdeDev->PciIo, Map);\r
-\r
-    //\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
-                        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
-  //\r
-  // Disable interrupt of Select device\r
-  //\r
-  IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl);\r
-  DeviceControl |= IEN_L;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
-\r
-  return EFI_SUCCESS;\r
-}\r