In IdeBus driver block I/O read/write interface, it will always try to use UDMA mode...
authorklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 2 Mar 2007 08:21:43 +0000 (08:21 +0000)
committerklu2 <klu2@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 2 Mar 2007 08:21:43 +0000 (08:21 +0000)
This may cause side effects if disk does not support UDMA mode and also let bad performance.
The modification is to record supported mode and only try supported mode when do disk read/write.
Also this patch combines the code for read/readex/write/writex to reduce code size.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2412 6f19259b-4bc3-4df7-8a09-765794883524

EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h

index aea126b3e689e28ca5da8a86548469f9e32f3b92..10240bf7b335321ea0c71114b22335f0504ae478 100644 (file)
@@ -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
@@ -2440,1098 +2627,4 @@ AtaUdmaReadExt (
   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\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
-  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
+}
\ No newline at end of file
index b83a82a9fb52cfb3e4727045bd11f66b671a5c95..f382279ab54f0bf4fb83eb0b63d23325631938cd 100644 (file)
@@ -1097,6 +1097,42 @@ AtaUdmaWriteExt (
   )\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
+\r
+\r
 /**\r
   TODO: Add function description\r
 \r
index 52c1f266b1ea0893a161b7bbaa8065bc7ed94a25..78c79d7665dacc22f14871d6588e20da94b93923 100644 (file)
@@ -65,7 +65,7 @@ typedef struct {
   INQUIRY_DATA                *pInquiryData;\r
   EFI_IDENTIFY_DATA           *pIdData;\r
   ATA_PIO_MODE                PioMode;\r
-  ATA_UDMA_MODE               UDma_Mode;\r
+  EFI_ATA_MODE                UdmaMode;\r
   CHAR8                       ModelName[41];\r
   REQUEST_SENSE_DATA          *SenseData;\r
   UINT8                       SenseDataNumber;\r
index ec088dcfa6356b968d36f6d3e0cd4eb4ef5a93d8..0c3831119abdca80793a70db414fe64613b18c7c 100644 (file)
@@ -86,6 +86,13 @@ typedef enum {
   SenseOtherSense\r
 } SENSE_RESULT;\r
 \r
+typedef enum {\r
+  AtaUdmaReadOp,\r
+  AtaUdmaReadExtOp,\r
+  AtaUdmaWriteOp,\r
+  AtaUdmaWriteExtOp\r
+} ATA_UDMA_OPERATION;\r
+\r
 //\r
 // IDE Registers\r
 //\r