]> git.proxmox.com Git - mirror_edk2.git/commitdiff
rename to meet naming rules
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 2 Jul 2008 03:20:21 +0000 (03:20 +0000)
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 2 Jul 2008 03:20:21 +0000 (03:20 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5398 6f19259b-4bc3-4df7-8a09-765794883524

IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ide.c [deleted file]

diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/Ide.c
new file mode 100644 (file)
index 0000000..a69c72e
--- /dev/null
@@ -0,0 +1,1824 @@
+/** @file\r
+  Copyright (c) 2006, Intel Corporation\r
+  All rights reserved. This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "idebus.h"\r
+\r
+BOOLEAN ChannelDeviceDetected = FALSE;\r
+BOOLEAN SlaveDeviceExist      = FALSE;\r
+UINT8   SlaveDeviceType       = INVALID_DEVICE_TYPE;\r
+BOOLEAN MasterDeviceExist     = FALSE;\r
+UINT8   MasterDeviceType      = INVALID_DEVICE_TYPE;\r
+\r
+/**\r
+  TODO: Add function description\r
+\r
+  @param  PciIo TODO: add argument description\r
+  @param  Port TODO: add argument description\r
+\r
+  TODO: add return values\r
+\r
+**/\r
+UINT8\r
+IDEReadPortB (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT16                Port\r
+  )\r
+{\r
+  UINT8 Data;\r
+\r
+  Data = 0;\r
+  //\r
+  // perform 1-byte data read from register\r
+  //\r
+  PciIo->Io.Read (\r
+              PciIo,\r
+              EfiPciIoWidthUint8,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              (UINT64) Port,\r
+              1,\r
+              &Data\r
+              );\r
+  return Data;\r
+}\r
+\r
+/**\r
+  Reads multiple words of data from the IDE data port.\r
+  Call the IO abstraction once to do the complete read,\r
+  not one word at a time\r
+\r
+  @param  PciIo Pointer to the EFI_PCI_IO instance\r
+  @param  Port IO port to read\r
+  @param  Count No. of UINT16's to read\r
+  @param  Buffer Pointer to the data buffer for read\r
+\r
+**/\r
+VOID\r
+IDEReadPortWMultiple (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT16                Port,\r
+  IN  UINTN                 Count,\r
+  IN  VOID                  *Buffer\r
+  )\r
+{\r
+  UINT16  *AlignedBuffer;\r
+  UINT16  *WorkingBuffer;\r
+  UINTN   Size;\r
+\r
+  //\r
+  // Prepare an 16-bit alligned working buffer. CpuIo will return failure and\r
+  // not perform actual I/O operations if buffer pointer passed in is not at\r
+  // natural boundary. The "Buffer" argument is passed in by user and may not\r
+  // at 16-bit natural boundary.\r
+  //\r
+  Size = sizeof (UINT16) * Count;\r
+\r
+  gBS->AllocatePool (\r
+        EfiBootServicesData,\r
+        Size + 1,\r
+        (VOID**)&WorkingBuffer\r
+        );\r
+\r
+  AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));\r
+\r
+  //\r
+  // Perform UINT16 data read from FIFO\r
+  //\r
+  PciIo->Io.Read (\r
+              PciIo,\r
+              EfiPciIoWidthFifoUint16,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              (UINT64) Port,\r
+              Count,\r
+              (UINT16*)AlignedBuffer\r
+              );\r
+\r
+  //\r
+  // Copy data to user buffer\r
+  //\r
+  CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);\r
+  gBS->FreePool (WorkingBuffer);\r
+}\r
+\r
+/**\r
+  TODO: Add function description\r
+\r
+  @param  PciIo TODO: add argument description\r
+  @param  Port TODO: add argument description\r
+  @param  Data TODO: add argument description\r
+\r
+  TODO: add return values\r
+\r
+**/\r
+VOID\r
+IDEWritePortB (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT16                Port,\r
+  IN  UINT8                 Data\r
+  )\r
+{\r
+  //\r
+  // perform 1-byte data write to register\r
+  //\r
+  PciIo->Io.Write (\r
+              PciIo,\r
+              EfiPciIoWidthUint8,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              (UINT64) Port,\r
+              1,\r
+              &Data\r
+              );\r
+\r
+}\r
+\r
+/**\r
+  TODO: Add function description\r
+\r
+  @param  PciIo TODO: add argument description\r
+  @param  Port TODO: add argument description\r
+  @param  Data TODO: add argument description\r
+\r
+  TODO: add return values\r
+\r
+**/\r
+VOID\r
+IDEWritePortW (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT16                Port,\r
+  IN  UINT16                Data\r
+  )\r
+{\r
+  //\r
+  // perform 1-word data write to register\r
+  //\r
+  PciIo->Io.Write (\r
+              PciIo,\r
+              EfiPciIoWidthUint16,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              (UINT64) Port,\r
+              1,\r
+              &Data\r
+              );\r
+}\r
+\r
+/**\r
+  Write multiple words of data to the IDE data port.\r
+  Call the IO abstraction once to do the complete read,\r
+  not one word at a time\r
+\r
+  @param  PciIo Pointer to the EFI_PCI_IO instance\r
+  @param  Port IO port to read\r
+  @param  Count No. of UINT16's to read\r
+  @param  Buffer Pointer to the data buffer for read\r
+\r
+**/\r
+VOID\r
+IDEWritePortWMultiple (\r
+  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
+  IN  UINT16                Port,\r
+  IN  UINTN                 Count,\r
+  IN  VOID                  *Buffer\r
+  )\r
+{\r
+  UINT16  *AlignedBuffer;\r
+  UINT32  *WorkingBuffer;\r
+  UINTN   Size;\r
+\r
+  //\r
+  // Prepare an 16-bit alligned working buffer. CpuIo will return failure and\r
+  // not perform actual I/O operations if buffer pointer passed in is not at\r
+  // natural boundary. The "Buffer" argument is passed in by user and may not\r
+  // at 16-bit natural boundary.\r
+  //\r
+  Size = sizeof (UINT16) * Count;\r
+\r
+  gBS->AllocatePool (\r
+        EfiBootServicesData,\r
+        Size + 1,\r
+        (VOID **) &WorkingBuffer\r
+        );\r
+\r
+  AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));\r
+\r
+  //\r
+  // Copy data from user buffer to working buffer\r
+  //\r
+  CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);\r
+\r
+  //\r
+  // perform UINT16 data write to the FIFO\r
+  //\r
+  PciIo->Io.Write (\r
+              PciIo,\r
+              EfiPciIoWidthFifoUint16,\r
+              EFI_PCI_IO_PASS_THROUGH_BAR,\r
+              (UINT64) Port,\r
+              Count,\r
+              (UINT16 *) AlignedBuffer\r
+              );\r
+\r
+  gBS->FreePool (WorkingBuffer);\r
+}\r
+\r
+//\r
+// GetIdeRegistersBaseAddr\r
+//\r
+/**\r
+  Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,\r
+  use fixed addresses. In Native-PCI mode, get base addresses from BARs in\r
+  the PCI IDE controller's Configuration Space.\r
+\r
+  The steps to get IDE IO port registers' base addresses for each channel\r
+  as follows:\r
+\r
+  1. Examine the Programming Interface byte of the Class Code fields in PCI IDE\r
+  controller's Configuration Space to determine the operating mode.\r
+\r
+  2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.\r
+  <pre>\r
+  ___________________________________________\r
+  |           | Command Block | Control Block |\r
+  |  Channel  |   Registers   |   Registers   |\r
+  |___________|_______________|_______________|\r
+  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |\r
+  |___________|_______________|_______________|\r
+  | Secondary |  170h - 177h  |  376h - 377h  |\r
+  |___________|_______________|_______________|\r
+\r
+  Table 1. Compatibility resource mappings\r
+  </pre>\r
+\r
+  b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs\r
+  in IDE controller's PCI Configuration Space, shown in the Table 2 below.\r
+  <pre>\r
+  ___________________________________________________\r
+  |           |   Command Block   |   Control Block   |\r
+  |  Channel  |     Registers     |     Registers     |\r
+  |___________|___________________|___________________|\r
+  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|\r
+  |___________|___________________|___________________|\r
+  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|\r
+  |___________|___________________|___________________|\r
+\r
+  Table 2. BARs for Register Mapping\r
+  </pre>\r
+  @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for\r
+  primary, 0374h for secondary. So 2 bytes extra offset should be\r
+  added to the base addresses read from BARs.\r
+\r
+  For more details, please refer to PCI IDE Controller Specification and Intel\r
+  ICH4 Datasheet.\r
+\r
+  @param  PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
+  @param  IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to\r
+  receive IDE IO port registers' base addresses\r
+\r
+**/\r
+EFI_STATUS\r
+GetIdeRegistersBaseAddr (\r
+  IN  EFI_PCI_IO_PROTOCOL         *PciIo,\r
+  OUT IDE_REGISTERS_BASE_ADDR     *IdeRegsBaseAddr\r
+  )\r
+// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS  Status;\r
+  PCI_TYPE00  PciData;\r
+\r
+  Status = PciIo->Pci.Read (\r
+                        PciIo,\r
+                        EfiPciIoWidthUint8,\r
+                        0,\r
+                        sizeof (PciData),\r
+                        &PciData\r
+                        );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {\r
+    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  = 0x1f0;\r
+    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  = 0x3f6;\r
+    IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =\r
+    (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));\r
+  } else {\r
+    //\r
+    // The BARs should be of IO type\r
+    //\r
+    if ((PciData.Device.Bar[0] & BIT0) == 0 ||\r
+        (PciData.Device.Bar[1] & BIT0) == 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  =\r
+    (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);\r
+    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  =\r
+    (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);\r
+    IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =\r
+    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
+  }\r
+\r
+  if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {\r
+    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  = 0x170;\r
+    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  = 0x376;\r
+    IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =\r
+    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
+  } else {\r
+    //\r
+    // The BARs should be of IO type\r
+    //\r
+    if ((PciData.Device.Bar[2] & BIT0) == 0 ||\r
+        (PciData.Device.Bar[3] & BIT0) == 0) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  =\r
+    (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);\r
+    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  =\r
+    (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);\r
+    IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =\r
+    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to requery IDE resources. The IDE controller will\r
+  probably switch between native and legacy modes during the EFI->CSM->OS\r
+  transfer. We do this everytime before an BlkIo operation to ensure its\r
+  succeess.\r
+\r
+  @param  IdeDev The BLK_IO private data which specifies the IDE device\r
+\r
+**/\r
+EFI_STATUS\r
+ReassignIdeResources (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev\r
+  )\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS              Status;\r
+  IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];\r
+  UINT16                  CommandBlockBaseAddr;\r
+  UINT16                  ControlBlockBaseAddr;\r
+\r
+  //\r
+  // Requery IDE IO port registers' base addresses in case of the switch of\r
+  // native and legacy modes\r
+  //\r
+  Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));\r
+  CommandBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;\r
+  ControlBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;\r
+\r
+  IdeDev->IoPort->Data                = CommandBlockBaseAddr;\r
+  (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
+  IdeDev->IoPort->SectorCount         = (UINT16) (CommandBlockBaseAddr + 0x02);\r
+  IdeDev->IoPort->SectorNumber        = (UINT16) (CommandBlockBaseAddr + 0x03);\r
+  IdeDev->IoPort->CylinderLsb         = (UINT16) (CommandBlockBaseAddr + 0x04);\r
+  IdeDev->IoPort->CylinderMsb         = (UINT16) (CommandBlockBaseAddr + 0x05);\r
+  IdeDev->IoPort->Head                = (UINT16) (CommandBlockBaseAddr + 0x06);\r
+\r
+  (*(UINT16 *) &IdeDev->IoPort->Reg)  = (UINT16) (CommandBlockBaseAddr + 0x07);\r
+  (*(UINT16 *) &IdeDev->IoPort->Alt)  = ControlBlockBaseAddr;\r
+  IdeDev->IoPort->DriveAddress        = (UINT16) (ControlBlockBaseAddr + 0x01);\r
+  IdeDev->IoPort->MasterSlave         = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);\r
+\r
+  IdeDev->IoPort->BusMasterBaseAddr   = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// DiscoverIdeDevice\r
+//\r
+/**\r
+  Detect if there is disk connected to this port\r
+\r
+  @param  IdeDev The BLK_IO private data which specifies the IDE device\r
+\r
+**/\r
+EFI_STATUS\r
+DiscoverIdeDevice (\r
+  IN IDE_BLK_IO_DEV *IdeDev\r
+  )\r
+// TODO:    EFI_NOT_FOUND - add return value to function comment\r
+// TODO:    EFI_NOT_FOUND - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // If a channel has not been checked, check it now. Then set it to "checked" state\r
+  // After this step, all devices in this channel have been checked.\r
+  //\r
+  if (ChannelDeviceDetected == FALSE) {\r
+    Status = DetectIDEController (IdeDev);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  Status = EFI_NOT_FOUND;\r
+\r
+  //\r
+  // Device exists. test if it is an ATA device.\r
+  // Prefer the result from DetectIDEController,\r
+  // if failed, try another device type to handle\r
+  // devices that not follow the spec.\r
+  //\r
+  if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {\r
+    if (MasterDeviceType == ATA_DEVICE_TYPE) {\r
+      Status = ATAIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAPIIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          MasterDeviceType = ATAPI_DEVICE_TYPE;\r
+        }\r
+      }\r
+    } else {\r
+      Status = ATAPIIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          MasterDeviceType = ATA_DEVICE_TYPE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {\r
+    if (SlaveDeviceType == ATA_DEVICE_TYPE) {\r
+      Status = ATAIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAPIIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          SlaveDeviceType = ATAPI_DEVICE_TYPE;\r
+        }\r
+      }\r
+    } else {\r
+      Status = ATAPIIdentify (IdeDev);\r
+      if (EFI_ERROR (Status)) {\r
+        Status = ATAIdentify (IdeDev);\r
+        if (!EFI_ERROR (Status)) {\r
+          SlaveDeviceType = ATA_DEVICE_TYPE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  //\r
+  // Init Block I/O interface\r
+  //\r
+  IdeDev->BlkIo.Revision            = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+  IdeDev->BlkIo.Reset               = IDEBlkIoReset;\r
+  IdeDev->BlkIo.ReadBlocks          = IDEBlkIoReadBlocks;\r
+  IdeDev->BlkIo.WriteBlocks         = IDEBlkIoWriteBlocks;\r
+  IdeDev->BlkIo.FlushBlocks         = IDEBlkIoFlushBlocks;\r
+\r
+  IdeDev->BlkMedia.LogicalPartition = FALSE;\r
+  IdeDev->BlkMedia.WriteCaching     = FALSE;\r
+\r
+  //\r
+  // Init Disk Info interface\r
+  //\r
+  gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));\r
+  IdeDev->DiskInfo.Inquiry    = IDEDiskInfoInquiry;\r
+  IdeDev->DiskInfo.Identify   = IDEDiskInfoIdentify;\r
+  IdeDev->DiskInfo.SenseData  = IDEDiskInfoSenseData;\r
+  IdeDev->DiskInfo.WhichIde   = IDEDiskInfoWhichIde;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This interface is used to initialize all state data related to the detection of one\r
+  channel.\r
+\r
+  @retval EFI_SUCCESS Completed Successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InitializeIDEChannelData (\r
+  VOID\r
+  )\r
+{\r
+  ChannelDeviceDetected = FALSE;\r
+  MasterDeviceExist = FALSE;\r
+  MasterDeviceType  = 0xff;\r
+  SlaveDeviceExist  = FALSE;\r
+  SlaveDeviceType   = 0xff;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is called by DiscoverIdeDevice(). It is used for detect\r
+  whether the IDE device exists in the specified Channel as the specified\r
+  Device Number.\r
+\r
+  There is two IDE channels: one is Primary Channel, the other is\r
+  Secondary Channel.(Channel is the logical name for the physical "Cable".)\r
+  Different channel has different register group.\r
+\r
+  On each IDE channel, at most two IDE devices attach,\r
+  one is called Device 0 (Master device), the other is called Device 1\r
+  (Slave device). The devices on the same channel co-use the same register\r
+  group, so before sending out a command for a specified device via command\r
+  register, it is a must to select the current device to accept the command\r
+  by set the device number in the Head/Device Register.\r
+\r
+  @param[in] *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @retval TRUE\r
+  successfully detects device.\r
+\r
+  @retval FALSE\r
+  any failure during detection process will return this\r
+  value.\r
+\r
+  @note\r
+  TODO:    EFI_SUCCESS - add return value to function comment\r
+  TODO:    EFI_NOT_FOUND - add return value to function comment\r
+\r
+**/\r
+EFI_STATUS\r
+DetectIDEController (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       SectorCountReg;\r
+  UINT8       LBALowReg;\r
+  UINT8       LBAMidReg;\r
+  UINT8       LBAHighReg;\r
+  UINT8       InitStatusReg;\r
+  UINT8       StatusReg;\r
+\r
+  //\r
+  // Select slave device\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((1 << 4) | 0xe0)\r
+    );\r
+  gBS->Stall (100);\r
+\r
+  //\r
+  // Save the init slave status register\r
+  //\r
+  InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+\r
+  //\r
+  // Select Master back\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((0 << 4) | 0xe0)\r
+    );\r
+  gBS->Stall (100);\r
+\r
+  //\r
+  // Send ATA Device Execut Diagnostic command.\r
+  // This command should work no matter DRDY is ready or not\r
+  //\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);\r
+\r
+  Status    = WaitForBSYClear (IdeDev, 3500);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));\r
+    return Status;\r
+  }\r
+  //\r
+  // Read device signature\r
+  //\r
+  //\r
+  // Select Master\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((0 << 4) | 0xe0)\r
+    );\r
+  gBS->Stall (100);\r
+  SectorCountReg = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorCount\r
+                     );\r
+  LBALowReg      = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorNumber\r
+                     );\r
+  LBAMidReg      = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->CylinderLsb\r
+                     );\r
+  LBAHighReg     = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->CylinderMsb\r
+                     );\r
+  if ((SectorCountReg == 0x1) &&\r
+      (LBALowReg      == 0x1) &&\r
+      (LBAMidReg      == 0x0) &&\r
+      (LBAHighReg     == 0x0)) {\r
+    MasterDeviceExist = TRUE;\r
+    MasterDeviceType  = ATA_DEVICE_TYPE;\r
+  } else {\r
+    if ((LBAMidReg      == 0x14) &&\r
+        (LBAHighReg     == 0xeb)) {\r
+      MasterDeviceExist = TRUE;\r
+      MasterDeviceType  = ATAPI_DEVICE_TYPE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // For some Hard Drive, it takes some time to get\r
+  // the right signature when operating in single slave mode.\r
+  // We stall 20ms to work around this.\r
+  //\r
+  if (!MasterDeviceExist) {\r
+    gBS->Stall (20000);\r
+  }\r
+\r
+  //\r
+  // Select Slave\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((1 << 4) | 0xe0)\r
+    );\r
+  gBS->Stall (100);\r
+  SectorCountReg = IDEReadPortB (\r
+                     IdeDev->PciIo,\r
+                     IdeDev->IoPort->SectorCount\r
+                     );\r
+  LBALowReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->SectorNumber\r
+                 );\r
+  LBAMidReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->CylinderLsb\r
+                 );\r
+  LBAHighReg = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->CylinderMsb\r
+                 );\r
+  StatusReg  = IDEReadPortB (\r
+                 IdeDev->PciIo,\r
+                 IdeDev->IoPort->Reg.Status\r
+                 );\r
+  if ((SectorCountReg == 0x1) &&\r
+      (LBALowReg      == 0x1) &&\r
+      (LBAMidReg      == 0x0) &&\r
+      (LBAHighReg     == 0x0)) {\r
+    SlaveDeviceExist = TRUE;\r
+    SlaveDeviceType  = ATA_DEVICE_TYPE;\r
+  } else {\r
+    if ((LBAMidReg     == 0x14) &&\r
+        (LBAHighReg    == 0xeb)) {\r
+      SlaveDeviceExist = TRUE;\r
+      SlaveDeviceType  = ATAPI_DEVICE_TYPE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // When single master is plugged, slave device\r
+  // will be wrongly detected. Here's the workaround\r
+  // for ATA devices by detecting DRY bit in status\r
+  // register.\r
+  // NOTE: This workaround doesn't apply to ATAPI.\r
+  //\r
+  if (MasterDeviceExist && SlaveDeviceExist &&\r
+      (StatusReg & ATA_STSREG_DRDY) == 0               &&\r
+      (InitStatusReg & ATA_STSREG_DRDY) == 0           &&\r
+      MasterDeviceType == SlaveDeviceType   &&\r
+      SlaveDeviceType != ATAPI_DEVICE_TYPE) {\r
+    SlaveDeviceExist = FALSE;\r
+  }\r
+\r
+  //\r
+  // Indicate this channel has been detected\r
+  //\r
+  ChannelDeviceDetected = TRUE;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to poll for the DRQ bit clear in the Status\r
+  Register. DRQ is cleared when the device is finished transferring data.\r
+  So this function is called after data transfer is finished.\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] TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ clear.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRQ bit clear within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRQ bit not clear within the time out.\r
+\r
+  @note\r
+  Read Status Register will clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRQClear (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+// TODO:    EFI_ABORTED - add return value to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   StatusRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+\r
+    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+\r
+    //\r
+    // wait for BSY == 0 and DRQ == 0\r
+    //\r
+    if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
+      break;\r
+    }\r
+\r
+    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    //\r
+    //  Stall for 30 us\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to poll for the DRQ bit clear in the Alternate\r
+  Status Register. DRQ is cleared when the device is finished\r
+  transferring data. So this function is called after data transfer\r
+  is finished.\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] TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ clear.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRQ bit clear within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRQ bit not clear within the time out.\r
+\r
+  @note\r
+  Read Alternate Status Register will not clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRQClear2 (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+// TODO:    EFI_ABORTED - add return value to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   AltRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+\r
+    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+\r
+    //\r
+    //  wait for BSY == 0 and DRQ == 0\r
+    //\r
+    if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
+      break;\r
+    }\r
+\r
+    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Stall for 30 us\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to poll for the DRQ bit set in the\r
+  Status Register.\r
+  DRQ is set when the device is ready to transfer data. So this function\r
+  is called after the command is sent to the device and before required\r
+  data is transferred.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure,used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRQ bit set within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRQ bit not set within the time out.\r
+\r
+  @retval EFI_ABORTED\r
+  DRQ bit not set caused by the command abort.\r
+\r
+  @note\r
+  Read Status Register will clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRQReady (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   StatusRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+    //\r
+    //  read Status Register will clear interrupt\r
+    //\r
+    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+\r
+    //\r
+    //  BSY==0,DRQ==1\r
+    //\r
+    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
+      break;\r
+    }\r
+\r
+    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Stall for 30 us\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to poll for the DRQ bit set in the\r
+  Alternate Status Register. DRQ is set when the device is ready to\r
+  transfer data. So this function is called after the command\r
+  is sent to the device and before required data is transferred.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRQ bit set within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRQ bit not set within the time out.\r
+\r
+  @retval EFI_ABORTED\r
+  DRQ bit not set caused by the command abort.\r
+\r
+  @note\r
+  Read Alternate Status Register will not clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRQReady2 (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   AltRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+\r
+  do {\r
+    //\r
+    //  Read Alternate Status Register will not clear interrupt status\r
+    //\r
+    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+    //\r
+    // BSY == 0 , DRQ == 1\r
+    //\r
+    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
+      break;\r
+    }\r
+\r
+    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Stall for 30 us\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is used to poll for the BSY bit clear in the\r
+  Status Register. BSY is clear when the device is not busy.\r
+  Every command must be sent after device is not busy.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  BSY bit clear within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  BSY bit not clear within the time out.\r
+\r
+  @note\r
+  Read Status Register will clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForBSYClear (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   StatusRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+\r
+    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+    if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Stall for 30 us\r
+    //\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// WaitForBSYClear2\r
+//\r
+/**\r
+  This function is used to poll for the BSY bit clear in the\r
+  Alternate Status Register. BSY is clear when the device is not busy.\r
+  Every command must be sent after device is not busy.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  BSY bit clear within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  BSY bit not clear within the time out.\r
+\r
+  @note\r
+  Read Alternate Status Register will not clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+WaitForBSYClear2 (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           TimeoutInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   AltRegister;\r
+\r
+  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+    if ((AltRegister & ATA_STSREG_BSY) == 0x00) {\r
+      break;\r
+    }\r
+\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// DRDYReady\r
+//\r
+/**\r
+  This function is used to poll for the DRDY bit set in the\r
+  Status Register. DRDY bit is set when the device is ready\r
+  to accept command. Most ATA commands must be sent after\r
+  DRDY set except the ATAPI Packet Command.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRDY bit set within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRDY bit not set within the time out.\r
+\r
+  @note\r
+  Read Status Register will clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRDYReady (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           DelayInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    DelayInMilliSeconds - add argument and description to function comment\r
+// TODO:    EFI_ABORTED - add return value to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   StatusRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+    //\r
+    //  BSY == 0 , DRDY == 1\r
+    //\r
+    if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
+      break;\r
+    }\r
+\r
+    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// DRDYReady2\r
+//\r
+/**\r
+  This function is used to poll for the DRDY bit set in the\r
+  Alternate Status Register. DRDY bit is set when the device is ready\r
+  to accept command. Most ATA commands must be sent after\r
+  DRDY set except the ATAPI Packet Command.\r
+\r
+  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
+  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
+  to record all the information of the IDE device.\r
+\r
+  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
+  used to designate the timeout for the DRQ ready.\r
+\r
+  @retval EFI_SUCCESS\r
+  DRDY bit set within the time out.\r
+\r
+  @retval EFI_TIMEOUT\r
+  DRDY bit not set within the time out.\r
+\r
+  @note\r
+  Read Alternate Status Register will clear interrupt status.\r
+\r
+**/\r
+EFI_STATUS\r
+DRDYReady2 (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINTN           DelayInMilliSeconds\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+// TODO: function comment is missing 'Arguments:'\r
+// TODO:    IdeDev - add argument and description to function comment\r
+// TODO:    DelayInMilliSeconds - add argument and description to function comment\r
+// TODO:    EFI_ABORTED - add return value to function comment\r
+{\r
+  UINT32  Delay;\r
+  UINT8   AltRegister;\r
+  UINT8   ErrorRegister;\r
+\r
+  Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
+  do {\r
+    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
+    //\r
+    //  BSY == 0 , DRDY == 1\r
+    //\r
+    if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
+      break;\r
+    }\r
+\r
+    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
+\r
+      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
+      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
+        return EFI_ABORTED;\r
+      }\r
+    }\r
+\r
+    gBS->Stall (30);\r
+\r
+    Delay--;\r
+  } while (Delay);\r
+\r
+  if (Delay == 0) {\r
+    return EFI_TIMEOUT;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// SwapStringChars\r
+//\r
+/**\r
+  This function is a helper function used to change the char order in a\r
+  string. It is designed specially for the PrintAtaModuleName() function.\r
+  After the IDE device is detected, the IDE driver gets the device module\r
+  name by sending ATA command called ATA Identify Command or ATAPI\r
+  Identify Command to the specified IDE device. The module name returned\r
+  is a string of ASCII characters: the first character is bit8--bit15\r
+  of the first word, the second character is BIT0--bit7 of the first word\r
+  and so on. Thus the string can not be print directly before it is\r
+  preprocessed by this func to change the order of characters in\r
+  each word in the string.\r
+\r
+  @param[in] CHAR8 IN    *Destination\r
+  Indicates the destination string.\r
+\r
+  @param[in] CHAR8 IN    *Source\r
+  Indicates the source string.\r
+\r
+  @param[in] UINT8 IN    Size\r
+  the length of the string\r
+\r
+**/\r
+VOID\r
+SwapStringChars (\r
+  IN CHAR8  *Destination,\r
+  IN CHAR8  *Source,\r
+  IN UINT32 Size\r
+  )\r
+{\r
+  UINT32  Index;\r
+  CHAR8   Temp;\r
+\r
+  for (Index = 0; Index < Size; Index += 2) {\r
+\r
+    Temp                    = Source[Index + 1];\r
+    Destination[Index + 1]  = Source[Index];\r
+    Destination[Index]      = Temp;\r
+  }\r
+}\r
+\r
+//\r
+// ReleaseIdeResources\r
+//\r
+/**\r
+  Release resources of an IDE device before stopping it.\r
+\r
+  @param[in] *IdeBlkIoDevice  Standard IDE device private data structure\r
+\r
+**/\r
+VOID\r
+ReleaseIdeResources (\r
+  IN  IDE_BLK_IO_DEV  *IdeBlkIoDevice\r
+  )\r
+{\r
+  if (IdeBlkIoDevice == NULL) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // Release all the resourses occupied by the IDE_BLK_IO_DEV\r
+  //\r
+\r
+  if (IdeBlkIoDevice->SenseData != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->SenseData);\r
+    IdeBlkIoDevice->SenseData = NULL;\r
+  }\r
+\r
+  if (IdeBlkIoDevice->Cache != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->Cache);\r
+    IdeBlkIoDevice->Cache = NULL;\r
+  }\r
+\r
+  if (IdeBlkIoDevice->pIdData != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->pIdData);\r
+    IdeBlkIoDevice->pIdData = NULL;\r
+  }\r
+\r
+  if (IdeBlkIoDevice->pInquiryData != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->pInquiryData);\r
+    IdeBlkIoDevice->pInquiryData = NULL;\r
+  }\r
+\r
+  if (IdeBlkIoDevice->ControllerNameTable != NULL) {\r
+    FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);\r
+    IdeBlkIoDevice->ControllerNameTable = NULL;\r
+  }\r
+\r
+  if (IdeBlkIoDevice->IoPort != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->IoPort);\r
+  }\r
+\r
+  if (IdeBlkIoDevice->DevicePath != NULL) {\r
+    gBS->FreePool (IdeBlkIoDevice->DevicePath);\r
+  }\r
+\r
+  if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {\r
+    gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);\r
+    IdeBlkIoDevice->ExitBootServiceEvent = NULL;\r
+  }\r
+\r
+  gBS->FreePool (IdeBlkIoDevice);\r
+  IdeBlkIoDevice = NULL;\r
+\r
+  return ;\r
+}\r
+\r
+//\r
+// SetDeviceTransferMode\r
+//\r
+/**\r
+  Set the calculated Best transfer mode to a detected device\r
+\r
+  @param[in] *IdeDev       Standard IDE device private data structure\r
+  @param[in] *TransferMode The device transfer mode to be set\r
+\r
+  @return Set transfer mode Command execute status\r
+\r
+**/\r
+EFI_STATUS\r
+SetDeviceTransferMode (\r
+  IN IDE_BLK_IO_DEV       *IdeDev,\r
+  IN ATA_TRANSFER_MODE    *TransferMode\r
+  )\r
+// TODO: function comment is missing 'Routine Description:'\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       DeviceSelect;\r
+  UINT8       SectorCount;\r
+\r
+  DeviceSelect  = 0;\r
+  DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);\r
+  SectorCount   = *((UINT8 *) TransferMode);\r
+\r
+  //\r
+  // Send SET FEATURE command (sub command 0x03) to set pio mode.\r
+  //\r
+  Status = AtaNonDataCommandIn (\r
+            IdeDev,\r
+            ATA_CMD_SET_FEATURES,\r
+            DeviceSelect,\r
+            0x03,\r
+            SectorCount,\r
+            0,\r
+            0,\r
+            0\r
+            );\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send ATA command into device with NON_DATA protocol\r
+\r
+  @param  IdeDev Standard IDE device private data structure\r
+  @param  AtaCommand The ATA command to be sent\r
+  @param  Device The value in Device register\r
+  @param  Feature The value in Feature register\r
+  @param  SectorCount The value in SectorCount register\r
+  @param  LbaLow The value in LBA_LOW register\r
+  @param  LbaMiddle The value in LBA_MIDDLE register\r
+  @param  LbaHigh The value in LBA_HIGH register\r
+\r
+  @retval  EFI_SUCCESS Reading succeed\r
+  @retval  EFI_ABORTED Command failed\r
+  @retval  EFI_DEVICE_ERROR Device status error\r
+\r
+**/\r
+EFI_STATUS\r
+AtaNonDataCommandIn (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINT8           AtaCommand,\r
+  IN  UINT8           Device,\r
+  IN  UINT8           Feature,\r
+  IN  UINT8           SectorCount,\r
+  IN  UINT8           LbaLow,\r
+  IN  UINT8           LbaMiddle,\r
+  IN  UINT8           LbaHigh\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       StatusRegister;\r
+\r
+  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
+    );\r
+\r
+  //\r
+  // ATA commands for ATA device must be issued when DRDY is set\r
+  //\r
+  Status = DRDYReady (IdeDev, ATATIMEOUT);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Pass parameter into device register block\r
+  //\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
+\r
+  //\r
+  // Send command via Command Register\r
+  //\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
+\r
+  //\r
+  // Wait for command completion\r
+  // For ATAPI_SMART_CMD, we may need more timeout to let device\r
+  // adjust internal states.\r
+  //\r
+  if (AtaCommand == ATA_CMD_SMART) {\r
+    Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);\r
+  } else {\r
+    Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+  if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
+    //\r
+    // Failed to execute command, abort operation\r
+    //\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Send ATA Ext command into device with NON_DATA protocol\r
+\r
+  @param  IdeDev Standard IDE device private data structure\r
+  @param  AtaCommand The ATA command to be sent\r
+  @param  Device The value in Device register\r
+  @param  Feature The value in Feature register\r
+  @param  SectorCount The value in SectorCount register\r
+  @param  LbaAddress The LBA address in 48-bit mode\r
+\r
+  @retval  EFI_SUCCESS Reading succeed\r
+  @retval  EFI_ABORTED Command failed\r
+  @retval  EFI_DEVICE_ERROR Device status error\r
+\r
+**/\r
+EFI_STATUS\r
+AtaNonDataCommandInExt (\r
+  IN  IDE_BLK_IO_DEV  *IdeDev,\r
+  IN  UINT8           AtaCommand,\r
+  IN  UINT8           Device,\r
+  IN  UINT16          Feature,\r
+  IN  UINT16          SectorCount,\r
+  IN  EFI_LBA         LbaAddress\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       StatusRegister;\r
+  UINT8       SectorCount8;\r
+  UINT8       Feature8;\r
+  UINT8       LbaLow;\r
+  UINT8       LbaMid;\r
+  UINT8       LbaHigh;\r
+\r
+  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
+  //\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
+    );\r
+\r
+  //\r
+  // ATA commands for ATA device must be issued when DRDY is set\r
+  //\r
+  Status = DRDYReady (IdeDev, ATATIMEOUT);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Pass parameter into device register block\r
+  //\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
+\r
+  //\r
+  // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
+  //\r
+  Feature8 = (UINT8) (Feature >> 8);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
+\r
+  Feature8 = (UINT8) Feature;\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
+\r
+  //\r
+  // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
+  //\r
+  SectorCount8 = (UINT8) (SectorCount >> 8);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
+\r
+  SectorCount8 = (UINT8) SectorCount;\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
+\r
+  //\r
+  // Fill the start LBA registers, which are also two-byte FIFO\r
+  //\r
+  LbaLow  = (UINT8) RShiftU64 (LbaAddress, 24);\r
+  LbaMid  = (UINT8) RShiftU64 (LbaAddress, 32);\r
+  LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
+\r
+  LbaLow  = (UINT8) LbaAddress;\r
+  LbaMid  = (UINT8) RShiftU64 (LbaAddress, 8);\r
+  LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
+\r
+  //\r
+  // Send command via Command Register\r
+  //\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
+\r
+  //\r
+  // Wait for command completion\r
+  //\r
+  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
+  if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
+    //\r
+    // Failed to execute command, abort operation\r
+    //\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+//\r
+// SetDriveParameters\r
+//\r
+/**\r
+  Set drive parameters for devices not support PACKETS command\r
+\r
+  @param[in] IdeDev       Standard IDE device private data structure\r
+  @param[in] DriveParameters The device parameters to be set into the disk\r
+\r
+  @return SetParameters Command execute status\r
+\r
+**/\r
+EFI_STATUS\r
+SetDriveParameters (\r
+  IN IDE_BLK_IO_DEV       *IdeDev,\r
+  IN ATA_DRIVE_PARMS      *DriveParameters\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       DeviceSelect;\r
+\r
+  DeviceSelect  = 0;\r
+  DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);\r
+\r
+  //\r
+  // Send Init drive parameters\r
+  //\r
+  Status = AtaNonDataCommandIn (\r
+            IdeDev,\r
+            ATA_CMD_INIT_DRIVE_PARAM,\r
+            (UINT8) (DeviceSelect + DriveParameters->Heads),\r
+            0,\r
+            DriveParameters->Sector,\r
+            0,\r
+            0,\r
+            0\r
+            );\r
+\r
+  //\r
+  // Send Set Multiple parameters\r
+  //\r
+  Status = AtaNonDataCommandIn (\r
+            IdeDev,\r
+            ATA_CMD_SET_MULTIPLE_MODE,\r
+            DeviceSelect,\r
+            0,\r
+            DriveParameters->MultipleSector,\r
+            0,\r
+            0,\r
+            0\r
+            );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  TODO: Add function description\r
+\r
+  @param  IdeDev TODO: add argument description\r
+\r
+  @retval  EFI_SUCCESS TODO: Add description for return value\r
+\r
+**/\r
+EFI_STATUS\r
+EnableInterrupt (\r
+  IN IDE_BLK_IO_DEV       *IdeDev\r
+  )\r
+{\r
+  UINT8 DeviceControl;\r
+\r
+  //\r
+  // Enable interrupt for DMA operation\r
+  //\r
+  DeviceControl = 0;\r
+  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.\r
+\r
+  @param[in]  Event   Pointer to this event\r
+  @param[in]  Context Event hanlder private data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ClearInterrupt (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT64          IoPortForBmis;\r
+  UINT8           RegisterValue;\r
+  IDE_BLK_IO_DEV  *IdeDev;\r
+\r
+  //\r
+  // Get our context\r
+  //\r
+  IdeDev = (IDE_BLK_IO_DEV *) Context;\r
+\r
+  //\r
+  // Obtain IDE IO port registers' base addresses\r
+  //\r
+  Status = ReassignIdeResources (IdeDev);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Check whether interrupt is pending\r
+  //\r
+\r
+  //\r
+  // Reset IDE device to force it de-assert interrupt pin\r
+  // Note: this will reset all devices on this IDE channel\r
+  //\r
+  AtaSoftReset (IdeDev);\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Get base address of IDE Bus Master Status Regsiter\r
+  //\r
+  if (IdePrimary == IdeDev->Channel) {\r
+    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
+  } else {\r
+    if (IdeSecondary == IdeDev->Channel) {\r
+      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
+    } else {\r
+      return;\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
+  // Select the other device on this channel to ensure this device to release the interrupt pin\r
+  //\r
+  if (IdeDev->Device == 0) {\r
+    RegisterValue = (1 << 4) | 0xe0;\r
+  } else {\r
+    RegisterValue = (0 << 4) | 0xe0;\r
+  }\r
+  IDEWritePortB (\r
+    IdeDev->PciIo,\r
+    IdeDev->IoPort->Head,\r
+    RegisterValue\r
+    );\r
+\r
+}\r
diff --git a/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ide.c b/IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/ide.c
deleted file mode 100644 (file)
index a69c72e..0000000
+++ /dev/null
@@ -1,1824 +0,0 @@
-/** @file\r
-  Copyright (c) 2006, Intel Corporation\r
-  All rights reserved. This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "idebus.h"\r
-\r
-BOOLEAN ChannelDeviceDetected = FALSE;\r
-BOOLEAN SlaveDeviceExist      = FALSE;\r
-UINT8   SlaveDeviceType       = INVALID_DEVICE_TYPE;\r
-BOOLEAN MasterDeviceExist     = FALSE;\r
-UINT8   MasterDeviceType      = INVALID_DEVICE_TYPE;\r
-\r
-/**\r
-  TODO: Add function description\r
-\r
-  @param  PciIo TODO: add argument description\r
-  @param  Port TODO: add argument description\r
-\r
-  TODO: add return values\r
-\r
-**/\r
-UINT8\r
-IDEReadPortB (\r
-  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
-  IN  UINT16                Port\r
-  )\r
-{\r
-  UINT8 Data;\r
-\r
-  Data = 0;\r
-  //\r
-  // perform 1-byte data read from register\r
-  //\r
-  PciIo->Io.Read (\r
-              PciIo,\r
-              EfiPciIoWidthUint8,\r
-              EFI_PCI_IO_PASS_THROUGH_BAR,\r
-              (UINT64) Port,\r
-              1,\r
-              &Data\r
-              );\r
-  return Data;\r
-}\r
-\r
-/**\r
-  Reads multiple words of data from the IDE data port.\r
-  Call the IO abstraction once to do the complete read,\r
-  not one word at a time\r
-\r
-  @param  PciIo Pointer to the EFI_PCI_IO instance\r
-  @param  Port IO port to read\r
-  @param  Count No. of UINT16's to read\r
-  @param  Buffer Pointer to the data buffer for read\r
-\r
-**/\r
-VOID\r
-IDEReadPortWMultiple (\r
-  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
-  IN  UINT16                Port,\r
-  IN  UINTN                 Count,\r
-  IN  VOID                  *Buffer\r
-  )\r
-{\r
-  UINT16  *AlignedBuffer;\r
-  UINT16  *WorkingBuffer;\r
-  UINTN   Size;\r
-\r
-  //\r
-  // Prepare an 16-bit alligned working buffer. CpuIo will return failure and\r
-  // not perform actual I/O operations if buffer pointer passed in is not at\r
-  // natural boundary. The "Buffer" argument is passed in by user and may not\r
-  // at 16-bit natural boundary.\r
-  //\r
-  Size = sizeof (UINT16) * Count;\r
-\r
-  gBS->AllocatePool (\r
-        EfiBootServicesData,\r
-        Size + 1,\r
-        (VOID**)&WorkingBuffer\r
-        );\r
-\r
-  AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));\r
-\r
-  //\r
-  // Perform UINT16 data read from FIFO\r
-  //\r
-  PciIo->Io.Read (\r
-              PciIo,\r
-              EfiPciIoWidthFifoUint16,\r
-              EFI_PCI_IO_PASS_THROUGH_BAR,\r
-              (UINT64) Port,\r
-              Count,\r
-              (UINT16*)AlignedBuffer\r
-              );\r
-\r
-  //\r
-  // Copy data to user buffer\r
-  //\r
-  CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);\r
-  gBS->FreePool (WorkingBuffer);\r
-}\r
-\r
-/**\r
-  TODO: Add function description\r
-\r
-  @param  PciIo TODO: add argument description\r
-  @param  Port TODO: add argument description\r
-  @param  Data TODO: add argument description\r
-\r
-  TODO: add return values\r
-\r
-**/\r
-VOID\r
-IDEWritePortB (\r
-  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
-  IN  UINT16                Port,\r
-  IN  UINT8                 Data\r
-  )\r
-{\r
-  //\r
-  // perform 1-byte data write to register\r
-  //\r
-  PciIo->Io.Write (\r
-              PciIo,\r
-              EfiPciIoWidthUint8,\r
-              EFI_PCI_IO_PASS_THROUGH_BAR,\r
-              (UINT64) Port,\r
-              1,\r
-              &Data\r
-              );\r
-\r
-}\r
-\r
-/**\r
-  TODO: Add function description\r
-\r
-  @param  PciIo TODO: add argument description\r
-  @param  Port TODO: add argument description\r
-  @param  Data TODO: add argument description\r
-\r
-  TODO: add return values\r
-\r
-**/\r
-VOID\r
-IDEWritePortW (\r
-  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
-  IN  UINT16                Port,\r
-  IN  UINT16                Data\r
-  )\r
-{\r
-  //\r
-  // perform 1-word data write to register\r
-  //\r
-  PciIo->Io.Write (\r
-              PciIo,\r
-              EfiPciIoWidthUint16,\r
-              EFI_PCI_IO_PASS_THROUGH_BAR,\r
-              (UINT64) Port,\r
-              1,\r
-              &Data\r
-              );\r
-}\r
-\r
-/**\r
-  Write multiple words of data to the IDE data port.\r
-  Call the IO abstraction once to do the complete read,\r
-  not one word at a time\r
-\r
-  @param  PciIo Pointer to the EFI_PCI_IO instance\r
-  @param  Port IO port to read\r
-  @param  Count No. of UINT16's to read\r
-  @param  Buffer Pointer to the data buffer for read\r
-\r
-**/\r
-VOID\r
-IDEWritePortWMultiple (\r
-  IN  EFI_PCI_IO_PROTOCOL   *PciIo,\r
-  IN  UINT16                Port,\r
-  IN  UINTN                 Count,\r
-  IN  VOID                  *Buffer\r
-  )\r
-{\r
-  UINT16  *AlignedBuffer;\r
-  UINT32  *WorkingBuffer;\r
-  UINTN   Size;\r
-\r
-  //\r
-  // Prepare an 16-bit alligned working buffer. CpuIo will return failure and\r
-  // not perform actual I/O operations if buffer pointer passed in is not at\r
-  // natural boundary. The "Buffer" argument is passed in by user and may not\r
-  // at 16-bit natural boundary.\r
-  //\r
-  Size = sizeof (UINT16) * Count;\r
-\r
-  gBS->AllocatePool (\r
-        EfiBootServicesData,\r
-        Size + 1,\r
-        (VOID **) &WorkingBuffer\r
-        );\r
-\r
-  AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));\r
-\r
-  //\r
-  // Copy data from user buffer to working buffer\r
-  //\r
-  CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);\r
-\r
-  //\r
-  // perform UINT16 data write to the FIFO\r
-  //\r
-  PciIo->Io.Write (\r
-              PciIo,\r
-              EfiPciIoWidthFifoUint16,\r
-              EFI_PCI_IO_PASS_THROUGH_BAR,\r
-              (UINT64) Port,\r
-              Count,\r
-              (UINT16 *) AlignedBuffer\r
-              );\r
-\r
-  gBS->FreePool (WorkingBuffer);\r
-}\r
-\r
-//\r
-// GetIdeRegistersBaseAddr\r
-//\r
-/**\r
-  Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,\r
-  use fixed addresses. In Native-PCI mode, get base addresses from BARs in\r
-  the PCI IDE controller's Configuration Space.\r
-\r
-  The steps to get IDE IO port registers' base addresses for each channel\r
-  as follows:\r
-\r
-  1. Examine the Programming Interface byte of the Class Code fields in PCI IDE\r
-  controller's Configuration Space to determine the operating mode.\r
-\r
-  2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.\r
-  <pre>\r
-  ___________________________________________\r
-  |           | Command Block | Control Block |\r
-  |  Channel  |   Registers   |   Registers   |\r
-  |___________|_______________|_______________|\r
-  |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |\r
-  |___________|_______________|_______________|\r
-  | Secondary |  170h - 177h  |  376h - 377h  |\r
-  |___________|_______________|_______________|\r
-\r
-  Table 1. Compatibility resource mappings\r
-  </pre>\r
-\r
-  b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs\r
-  in IDE controller's PCI Configuration Space, shown in the Table 2 below.\r
-  <pre>\r
-  ___________________________________________________\r
-  |           |   Command Block   |   Control Block   |\r
-  |  Channel  |     Registers     |     Registers     |\r
-  |___________|___________________|___________________|\r
-  |  Primary  | BAR at offset 0x10| BAR at offset 0x14|\r
-  |___________|___________________|___________________|\r
-  | Secondary | BAR at offset 0x18| BAR at offset 0x1C|\r
-  |___________|___________________|___________________|\r
-\r
-  Table 2. BARs for Register Mapping\r
-  </pre>\r
-  @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for\r
-  primary, 0374h for secondary. So 2 bytes extra offset should be\r
-  added to the base addresses read from BARs.\r
-\r
-  For more details, please refer to PCI IDE Controller Specification and Intel\r
-  ICH4 Datasheet.\r
-\r
-  @param  PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance\r
-  @param  IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to\r
-  receive IDE IO port registers' base addresses\r
-\r
-**/\r
-EFI_STATUS\r
-GetIdeRegistersBaseAddr (\r
-  IN  EFI_PCI_IO_PROTOCOL         *PciIo,\r
-  OUT IDE_REGISTERS_BASE_ADDR     *IdeRegsBaseAddr\r
-  )\r
-// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
-{\r
-  EFI_STATUS  Status;\r
-  PCI_TYPE00  PciData;\r
-\r
-  Status = PciIo->Pci.Read (\r
-                        PciIo,\r
-                        EfiPciIoWidthUint8,\r
-                        0,\r
-                        sizeof (PciData),\r
-                        &PciData\r
-                        );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {\r
-    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  = 0x1f0;\r
-    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  = 0x3f6;\r
-    IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =\r
-    (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));\r
-  } else {\r
-    //\r
-    // The BARs should be of IO type\r
-    //\r
-    if ((PciData.Device.Bar[0] & BIT0) == 0 ||\r
-        (PciData.Device.Bar[1] & BIT0) == 0) {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-\r
-    IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  =\r
-    (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);\r
-    IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  =\r
-    (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);\r
-    IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =\r
-    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
-  }\r
-\r
-  if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {\r
-    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  = 0x170;\r
-    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  = 0x376;\r
-    IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =\r
-    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
-  } else {\r
-    //\r
-    // The BARs should be of IO type\r
-    //\r
-    if ((PciData.Device.Bar[2] & BIT0) == 0 ||\r
-        (PciData.Device.Bar[3] & BIT0) == 0) {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-\r
-    IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  =\r
-    (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);\r
-    IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  =\r
-    (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);\r
-    IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =\r
-    (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to requery IDE resources. The IDE controller will\r
-  probably switch between native and legacy modes during the EFI->CSM->OS\r
-  transfer. We do this everytime before an BlkIo operation to ensure its\r
-  succeess.\r
-\r
-  @param  IdeDev The BLK_IO private data which specifies the IDE device\r
-\r
-**/\r
-EFI_STATUS\r
-ReassignIdeResources (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev\r
-  )\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
-{\r
-  EFI_STATUS              Status;\r
-  IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];\r
-  UINT16                  CommandBlockBaseAddr;\r
-  UINT16                  ControlBlockBaseAddr;\r
-\r
-  //\r
-  // Requery IDE IO port registers' base addresses in case of the switch of\r
-  // native and legacy modes\r
-  //\r
-  Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));\r
-  CommandBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;\r
-  ControlBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;\r
-\r
-  IdeDev->IoPort->Data                = CommandBlockBaseAddr;\r
-  (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
-  IdeDev->IoPort->SectorCount         = (UINT16) (CommandBlockBaseAddr + 0x02);\r
-  IdeDev->IoPort->SectorNumber        = (UINT16) (CommandBlockBaseAddr + 0x03);\r
-  IdeDev->IoPort->CylinderLsb         = (UINT16) (CommandBlockBaseAddr + 0x04);\r
-  IdeDev->IoPort->CylinderMsb         = (UINT16) (CommandBlockBaseAddr + 0x05);\r
-  IdeDev->IoPort->Head                = (UINT16) (CommandBlockBaseAddr + 0x06);\r
-\r
-  (*(UINT16 *) &IdeDev->IoPort->Reg)  = (UINT16) (CommandBlockBaseAddr + 0x07);\r
-  (*(UINT16 *) &IdeDev->IoPort->Alt)  = ControlBlockBaseAddr;\r
-  IdeDev->IoPort->DriveAddress        = (UINT16) (ControlBlockBaseAddr + 0x01);\r
-  IdeDev->IoPort->MasterSlave         = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);\r
-\r
-  IdeDev->IoPort->BusMasterBaseAddr   = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// DiscoverIdeDevice\r
-//\r
-/**\r
-  Detect if there is disk connected to this port\r
-\r
-  @param  IdeDev The BLK_IO private data which specifies the IDE device\r
-\r
-**/\r
-EFI_STATUS\r
-DiscoverIdeDevice (\r
-  IN IDE_BLK_IO_DEV *IdeDev\r
-  )\r
-// TODO:    EFI_NOT_FOUND - add return value to function comment\r
-// TODO:    EFI_NOT_FOUND - add return value to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
-{\r
-  EFI_STATUS  Status;\r
-\r
-  //\r
-  // If a channel has not been checked, check it now. Then set it to "checked" state\r
-  // After this step, all devices in this channel have been checked.\r
-  //\r
-  if (ChannelDeviceDetected == FALSE) {\r
-    Status = DetectIDEController (IdeDev);\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_NOT_FOUND;\r
-    }\r
-  }\r
-\r
-  Status = EFI_NOT_FOUND;\r
-\r
-  //\r
-  // Device exists. test if it is an ATA device.\r
-  // Prefer the result from DetectIDEController,\r
-  // if failed, try another device type to handle\r
-  // devices that not follow the spec.\r
-  //\r
-  if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {\r
-    if (MasterDeviceType == ATA_DEVICE_TYPE) {\r
-      Status = ATAIdentify (IdeDev);\r
-      if (EFI_ERROR (Status)) {\r
-        Status = ATAPIIdentify (IdeDev);\r
-        if (!EFI_ERROR (Status)) {\r
-          MasterDeviceType = ATAPI_DEVICE_TYPE;\r
-        }\r
-      }\r
-    } else {\r
-      Status = ATAPIIdentify (IdeDev);\r
-      if (EFI_ERROR (Status)) {\r
-        Status = ATAIdentify (IdeDev);\r
-        if (!EFI_ERROR (Status)) {\r
-          MasterDeviceType = ATA_DEVICE_TYPE;\r
-        }\r
-      }\r
-    }\r
-  }\r
-  if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {\r
-    if (SlaveDeviceType == ATA_DEVICE_TYPE) {\r
-      Status = ATAIdentify (IdeDev);\r
-      if (EFI_ERROR (Status)) {\r
-        Status = ATAPIIdentify (IdeDev);\r
-        if (!EFI_ERROR (Status)) {\r
-          SlaveDeviceType = ATAPI_DEVICE_TYPE;\r
-        }\r
-      }\r
-    } else {\r
-      Status = ATAPIIdentify (IdeDev);\r
-      if (EFI_ERROR (Status)) {\r
-        Status = ATAIdentify (IdeDev);\r
-        if (!EFI_ERROR (Status)) {\r
-          SlaveDeviceType = ATA_DEVICE_TYPE;\r
-        }\r
-      }\r
-    }\r
-  }\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-  //\r
-  // Init Block I/O interface\r
-  //\r
-  IdeDev->BlkIo.Revision            = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
-  IdeDev->BlkIo.Reset               = IDEBlkIoReset;\r
-  IdeDev->BlkIo.ReadBlocks          = IDEBlkIoReadBlocks;\r
-  IdeDev->BlkIo.WriteBlocks         = IDEBlkIoWriteBlocks;\r
-  IdeDev->BlkIo.FlushBlocks         = IDEBlkIoFlushBlocks;\r
-\r
-  IdeDev->BlkMedia.LogicalPartition = FALSE;\r
-  IdeDev->BlkMedia.WriteCaching     = FALSE;\r
-\r
-  //\r
-  // Init Disk Info interface\r
-  //\r
-  gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));\r
-  IdeDev->DiskInfo.Inquiry    = IDEDiskInfoInquiry;\r
-  IdeDev->DiskInfo.Identify   = IDEDiskInfoIdentify;\r
-  IdeDev->DiskInfo.SenseData  = IDEDiskInfoSenseData;\r
-  IdeDev->DiskInfo.WhichIde   = IDEDiskInfoWhichIde;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This interface is used to initialize all state data related to the detection of one\r
-  channel.\r
-\r
-  @retval EFI_SUCCESS Completed Successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-InitializeIDEChannelData (\r
-  VOID\r
-  )\r
-{\r
-  ChannelDeviceDetected = FALSE;\r
-  MasterDeviceExist = FALSE;\r
-  MasterDeviceType  = 0xff;\r
-  SlaveDeviceExist  = FALSE;\r
-  SlaveDeviceType   = 0xff;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is called by DiscoverIdeDevice(). It is used for detect\r
-  whether the IDE device exists in the specified Channel as the specified\r
-  Device Number.\r
-\r
-  There is two IDE channels: one is Primary Channel, the other is\r
-  Secondary Channel.(Channel is the logical name for the physical "Cable".)\r
-  Different channel has different register group.\r
-\r
-  On each IDE channel, at most two IDE devices attach,\r
-  one is called Device 0 (Master device), the other is called Device 1\r
-  (Slave device). The devices on the same channel co-use the same register\r
-  group, so before sending out a command for a specified device via command\r
-  register, it is a must to select the current device to accept the command\r
-  by set the device number in the Head/Device Register.\r
-\r
-  @param[in] *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @retval TRUE\r
-  successfully detects device.\r
-\r
-  @retval FALSE\r
-  any failure during detection process will return this\r
-  value.\r
-\r
-  @note\r
-  TODO:    EFI_SUCCESS - add return value to function comment\r
-  TODO:    EFI_NOT_FOUND - add return value to function comment\r
-\r
-**/\r
-EFI_STATUS\r
-DetectIDEController (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       SectorCountReg;\r
-  UINT8       LBALowReg;\r
-  UINT8       LBAMidReg;\r
-  UINT8       LBAHighReg;\r
-  UINT8       InitStatusReg;\r
-  UINT8       StatusReg;\r
-\r
-  //\r
-  // Select slave device\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((1 << 4) | 0xe0)\r
-    );\r
-  gBS->Stall (100);\r
-\r
-  //\r
-  // Save the init slave status register\r
-  //\r
-  InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-\r
-  //\r
-  // Select Master back\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((0 << 4) | 0xe0)\r
-    );\r
-  gBS->Stall (100);\r
-\r
-  //\r
-  // Send ATA Device Execut Diagnostic command.\r
-  // This command should work no matter DRDY is ready or not\r
-  //\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);\r
-\r
-  Status    = WaitForBSYClear (IdeDev, 3500);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));\r
-    return Status;\r
-  }\r
-  //\r
-  // Read device signature\r
-  //\r
-  //\r
-  // Select Master\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((0 << 4) | 0xe0)\r
-    );\r
-  gBS->Stall (100);\r
-  SectorCountReg = IDEReadPortB (\r
-                     IdeDev->PciIo,\r
-                     IdeDev->IoPort->SectorCount\r
-                     );\r
-  LBALowReg      = IDEReadPortB (\r
-                     IdeDev->PciIo,\r
-                     IdeDev->IoPort->SectorNumber\r
-                     );\r
-  LBAMidReg      = IDEReadPortB (\r
-                     IdeDev->PciIo,\r
-                     IdeDev->IoPort->CylinderLsb\r
-                     );\r
-  LBAHighReg     = IDEReadPortB (\r
-                     IdeDev->PciIo,\r
-                     IdeDev->IoPort->CylinderMsb\r
-                     );\r
-  if ((SectorCountReg == 0x1) &&\r
-      (LBALowReg      == 0x1) &&\r
-      (LBAMidReg      == 0x0) &&\r
-      (LBAHighReg     == 0x0)) {\r
-    MasterDeviceExist = TRUE;\r
-    MasterDeviceType  = ATA_DEVICE_TYPE;\r
-  } else {\r
-    if ((LBAMidReg      == 0x14) &&\r
-        (LBAHighReg     == 0xeb)) {\r
-      MasterDeviceExist = TRUE;\r
-      MasterDeviceType  = ATAPI_DEVICE_TYPE;\r
-    }\r
-  }\r
-\r
-  //\r
-  // For some Hard Drive, it takes some time to get\r
-  // the right signature when operating in single slave mode.\r
-  // We stall 20ms to work around this.\r
-  //\r
-  if (!MasterDeviceExist) {\r
-    gBS->Stall (20000);\r
-  }\r
-\r
-  //\r
-  // Select Slave\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((1 << 4) | 0xe0)\r
-    );\r
-  gBS->Stall (100);\r
-  SectorCountReg = IDEReadPortB (\r
-                     IdeDev->PciIo,\r
-                     IdeDev->IoPort->SectorCount\r
-                     );\r
-  LBALowReg  = IDEReadPortB (\r
-                 IdeDev->PciIo,\r
-                 IdeDev->IoPort->SectorNumber\r
-                 );\r
-  LBAMidReg  = IDEReadPortB (\r
-                 IdeDev->PciIo,\r
-                 IdeDev->IoPort->CylinderLsb\r
-                 );\r
-  LBAHighReg = IDEReadPortB (\r
-                 IdeDev->PciIo,\r
-                 IdeDev->IoPort->CylinderMsb\r
-                 );\r
-  StatusReg  = IDEReadPortB (\r
-                 IdeDev->PciIo,\r
-                 IdeDev->IoPort->Reg.Status\r
-                 );\r
-  if ((SectorCountReg == 0x1) &&\r
-      (LBALowReg      == 0x1) &&\r
-      (LBAMidReg      == 0x0) &&\r
-      (LBAHighReg     == 0x0)) {\r
-    SlaveDeviceExist = TRUE;\r
-    SlaveDeviceType  = ATA_DEVICE_TYPE;\r
-  } else {\r
-    if ((LBAMidReg     == 0x14) &&\r
-        (LBAHighReg    == 0xeb)) {\r
-      SlaveDeviceExist = TRUE;\r
-      SlaveDeviceType  = ATAPI_DEVICE_TYPE;\r
-    }\r
-  }\r
-\r
-  //\r
-  // When single master is plugged, slave device\r
-  // will be wrongly detected. Here's the workaround\r
-  // for ATA devices by detecting DRY bit in status\r
-  // register.\r
-  // NOTE: This workaround doesn't apply to ATAPI.\r
-  //\r
-  if (MasterDeviceExist && SlaveDeviceExist &&\r
-      (StatusReg & ATA_STSREG_DRDY) == 0               &&\r
-      (InitStatusReg & ATA_STSREG_DRDY) == 0           &&\r
-      MasterDeviceType == SlaveDeviceType   &&\r
-      SlaveDeviceType != ATAPI_DEVICE_TYPE) {\r
-    SlaveDeviceExist = FALSE;\r
-  }\r
-\r
-  //\r
-  // Indicate this channel has been detected\r
-  //\r
-  ChannelDeviceDetected = TRUE;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to poll for the DRQ bit clear in the Status\r
-  Register. DRQ is cleared when the device is finished transferring data.\r
-  So this function is called after data transfer is finished.\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] TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ clear.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRQ bit clear within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRQ bit not clear within the time out.\r
-\r
-  @note\r
-  Read Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRQClear (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-// TODO:    EFI_ABORTED - add return value to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   StatusRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-\r
-    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-\r
-    //\r
-    // wait for BSY == 0 and DRQ == 0\r
-    //\r
-    if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
-      break;\r
-    }\r
-\r
-    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    //\r
-    //  Stall for 30 us\r
-    //\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to poll for the DRQ bit clear in the Alternate\r
-  Status Register. DRQ is cleared when the device is finished\r
-  transferring data. So this function is called after data transfer\r
-  is finished.\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] TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ clear.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRQ bit clear within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRQ bit not clear within the time out.\r
-\r
-  @note\r
-  Read Alternate Status Register will not clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRQClear2 (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-// TODO:    EFI_ABORTED - add return value to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   AltRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-\r
-    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
-\r
-    //\r
-    //  wait for BSY == 0 and DRQ == 0\r
-    //\r
-    if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {\r
-      break;\r
-    }\r
-\r
-    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Stall for 30 us\r
-    //\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to poll for the DRQ bit set in the\r
-  Status Register.\r
-  DRQ is set when the device is ready to transfer data. So this function\r
-  is called after the command is sent to the device and before required\r
-  data is transferred.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure,used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRQ bit set within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRQ bit not set within the time out.\r
-\r
-  @retval EFI_ABORTED\r
-  DRQ bit not set caused by the command abort.\r
-\r
-  @note\r
-  Read Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRQReady (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   StatusRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-    //\r
-    //  read Status Register will clear interrupt\r
-    //\r
-    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-\r
-    //\r
-    //  BSY==0,DRQ==1\r
-    //\r
-    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
-      break;\r
-    }\r
-\r
-    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Stall for 30 us\r
-    //\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to poll for the DRQ bit set in the\r
-  Alternate Status Register. DRQ is set when the device is ready to\r
-  transfer data. So this function is called after the command\r
-  is sent to the device and before required data is transferred.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRQ bit set within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRQ bit not set within the time out.\r
-\r
-  @retval EFI_ABORTED\r
-  DRQ bit not set caused by the command abort.\r
-\r
-  @note\r
-  Read Alternate Status Register will not clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRQReady2 (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   AltRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-\r
-  do {\r
-    //\r
-    //  Read Alternate Status Register will not clear interrupt status\r
-    //\r
-    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
-    //\r
-    // BSY == 0 , DRQ == 1\r
-    //\r
-    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {\r
-      break;\r
-    }\r
-\r
-    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Stall for 30 us\r
-    //\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to poll for the BSY bit clear in the\r
-  Status Register. BSY is clear when the device is not busy.\r
-  Every command must be sent after device is not busy.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  BSY bit clear within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  BSY bit not clear within the time out.\r
-\r
-  @note\r
-  Read Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-WaitForBSYClear (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   StatusRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-\r
-    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-    if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Stall for 30 us\r
-    //\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-//\r
-// WaitForBSYClear2\r
-//\r
-/**\r
-  This function is used to poll for the BSY bit clear in the\r
-  Alternate Status Register. BSY is clear when the device is not busy.\r
-  Every command must be sent after device is not busy.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  BSY bit clear within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  BSY bit not clear within the time out.\r
-\r
-  @note\r
-  Read Alternate Status Register will not clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-WaitForBSYClear2 (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           TimeoutInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    TimeoutInMilliSeconds - add argument and description to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   AltRegister;\r
-\r
-  Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
-    if ((AltRegister & ATA_STSREG_BSY) == 0x00) {\r
-      break;\r
-    }\r
-\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// DRDYReady\r
-//\r
-/**\r
-  This function is used to poll for the DRDY bit set in the\r
-  Status Register. DRDY bit is set when the device is ready\r
-  to accept command. Most ATA commands must be sent after\r
-  DRDY set except the ATAPI Packet Command.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRDY bit set within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRDY bit not set within the time out.\r
-\r
-  @note\r
-  Read Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRDYReady (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           DelayInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    DelayInMilliSeconds - add argument and description to function comment\r
-// TODO:    EFI_ABORTED - add return value to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   StatusRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-    StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-    //\r
-    //  BSY == 0 , DRDY == 1\r
-    //\r
-    if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
-      break;\r
-    }\r
-\r
-    if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// DRDYReady2\r
-//\r
-/**\r
-  This function is used to poll for the DRDY bit set in the\r
-  Alternate Status Register. DRDY bit is set when the device is ready\r
-  to accept command. Most ATA commands must be sent after\r
-  DRDY set except the ATAPI Packet Command.\r
-\r
-  @param[in] IDE_BLK_IO_DEV  IN    *IdeDev\r
-  pointer pointing to IDE_BLK_IO_DEV data structure, used\r
-  to record all the information of the IDE device.\r
-\r
-  @param[in] UINTN     IN    TimeoutInMilliSeconds\r
-  used to designate the timeout for the DRQ ready.\r
-\r
-  @retval EFI_SUCCESS\r
-  DRDY bit set within the time out.\r
-\r
-  @retval EFI_TIMEOUT\r
-  DRDY bit not set within the time out.\r
-\r
-  @note\r
-  Read Alternate Status Register will clear interrupt status.\r
-\r
-**/\r
-EFI_STATUS\r
-DRDYReady2 (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINTN           DelayInMilliSeconds\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-// TODO: function comment is missing 'Arguments:'\r
-// TODO:    IdeDev - add argument and description to function comment\r
-// TODO:    DelayInMilliSeconds - add argument and description to function comment\r
-// TODO:    EFI_ABORTED - add return value to function comment\r
-{\r
-  UINT32  Delay;\r
-  UINT8   AltRegister;\r
-  UINT8   ErrorRegister;\r
-\r
-  Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);\r
-  do {\r
-    AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);\r
-    //\r
-    //  BSY == 0 , DRDY == 1\r
-    //\r
-    if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {\r
-      break;\r
-    }\r
-\r
-    if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {\r
-\r
-      ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);\r
-      if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-\r
-    gBS->Stall (30);\r
-\r
-    Delay--;\r
-  } while (Delay);\r
-\r
-  if (Delay == 0) {\r
-    return EFI_TIMEOUT;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// SwapStringChars\r
-//\r
-/**\r
-  This function is a helper function used to change the char order in a\r
-  string. It is designed specially for the PrintAtaModuleName() function.\r
-  After the IDE device is detected, the IDE driver gets the device module\r
-  name by sending ATA command called ATA Identify Command or ATAPI\r
-  Identify Command to the specified IDE device. The module name returned\r
-  is a string of ASCII characters: the first character is bit8--bit15\r
-  of the first word, the second character is BIT0--bit7 of the first word\r
-  and so on. Thus the string can not be print directly before it is\r
-  preprocessed by this func to change the order of characters in\r
-  each word in the string.\r
-\r
-  @param[in] CHAR8 IN    *Destination\r
-  Indicates the destination string.\r
-\r
-  @param[in] CHAR8 IN    *Source\r
-  Indicates the source string.\r
-\r
-  @param[in] UINT8 IN    Size\r
-  the length of the string\r
-\r
-**/\r
-VOID\r
-SwapStringChars (\r
-  IN CHAR8  *Destination,\r
-  IN CHAR8  *Source,\r
-  IN UINT32 Size\r
-  )\r
-{\r
-  UINT32  Index;\r
-  CHAR8   Temp;\r
-\r
-  for (Index = 0; Index < Size; Index += 2) {\r
-\r
-    Temp                    = Source[Index + 1];\r
-    Destination[Index + 1]  = Source[Index];\r
-    Destination[Index]      = Temp;\r
-  }\r
-}\r
-\r
-//\r
-// ReleaseIdeResources\r
-//\r
-/**\r
-  Release resources of an IDE device before stopping it.\r
-\r
-  @param[in] *IdeBlkIoDevice  Standard IDE device private data structure\r
-\r
-**/\r
-VOID\r
-ReleaseIdeResources (\r
-  IN  IDE_BLK_IO_DEV  *IdeBlkIoDevice\r
-  )\r
-{\r
-  if (IdeBlkIoDevice == NULL) {\r
-    return ;\r
-  }\r
-\r
-  //\r
-  // Release all the resourses occupied by the IDE_BLK_IO_DEV\r
-  //\r
-\r
-  if (IdeBlkIoDevice->SenseData != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->SenseData);\r
-    IdeBlkIoDevice->SenseData = NULL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->Cache != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->Cache);\r
-    IdeBlkIoDevice->Cache = NULL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->pIdData != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->pIdData);\r
-    IdeBlkIoDevice->pIdData = NULL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->pInquiryData != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->pInquiryData);\r
-    IdeBlkIoDevice->pInquiryData = NULL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->ControllerNameTable != NULL) {\r
-    FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);\r
-    IdeBlkIoDevice->ControllerNameTable = NULL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->IoPort != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->IoPort);\r
-  }\r
-\r
-  if (IdeBlkIoDevice->DevicePath != NULL) {\r
-    gBS->FreePool (IdeBlkIoDevice->DevicePath);\r
-  }\r
-\r
-  if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {\r
-    gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);\r
-    IdeBlkIoDevice->ExitBootServiceEvent = NULL;\r
-  }\r
-\r
-  gBS->FreePool (IdeBlkIoDevice);\r
-  IdeBlkIoDevice = NULL;\r
-\r
-  return ;\r
-}\r
-\r
-//\r
-// SetDeviceTransferMode\r
-//\r
-/**\r
-  Set the calculated Best transfer mode to a detected device\r
-\r
-  @param[in] *IdeDev       Standard IDE device private data structure\r
-  @param[in] *TransferMode The device transfer mode to be set\r
-\r
-  @return Set transfer mode Command execute status\r
-\r
-**/\r
-EFI_STATUS\r
-SetDeviceTransferMode (\r
-  IN IDE_BLK_IO_DEV       *IdeDev,\r
-  IN ATA_TRANSFER_MODE    *TransferMode\r
-  )\r
-// TODO: function comment is missing 'Routine Description:'\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       DeviceSelect;\r
-  UINT8       SectorCount;\r
-\r
-  DeviceSelect  = 0;\r
-  DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);\r
-  SectorCount   = *((UINT8 *) TransferMode);\r
-\r
-  //\r
-  // Send SET FEATURE command (sub command 0x03) to set pio mode.\r
-  //\r
-  Status = AtaNonDataCommandIn (\r
-            IdeDev,\r
-            ATA_CMD_SET_FEATURES,\r
-            DeviceSelect,\r
-            0x03,\r
-            SectorCount,\r
-            0,\r
-            0,\r
-            0\r
-            );\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Send ATA command into device with NON_DATA protocol\r
-\r
-  @param  IdeDev Standard IDE device private data structure\r
-  @param  AtaCommand The ATA command to be sent\r
-  @param  Device The value in Device register\r
-  @param  Feature The value in Feature register\r
-  @param  SectorCount The value in SectorCount register\r
-  @param  LbaLow The value in LBA_LOW register\r
-  @param  LbaMiddle The value in LBA_MIDDLE register\r
-  @param  LbaHigh The value in LBA_HIGH register\r
-\r
-  @retval  EFI_SUCCESS Reading succeed\r
-  @retval  EFI_ABORTED Command failed\r
-  @retval  EFI_DEVICE_ERROR Device status error\r
-\r
-**/\r
-EFI_STATUS\r
-AtaNonDataCommandIn (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINT8           AtaCommand,\r
-  IN  UINT8           Device,\r
-  IN  UINT8           Feature,\r
-  IN  UINT8           SectorCount,\r
-  IN  UINT8           LbaLow,\r
-  IN  UINT8           LbaMiddle,\r
-  IN  UINT8           LbaHigh\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       StatusRegister;\r
-\r
-  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
-    );\r
-\r
-  //\r
-  // ATA commands for ATA device must be issued when DRDY is set\r
-  //\r
-  Status = DRDYReady (IdeDev, ATATIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Pass parameter into device register block\r
-  //\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
-\r
-  //\r
-  // Send command via Command Register\r
-  //\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
-\r
-  //\r
-  // Wait for command completion\r
-  // For ATAPI_SMART_CMD, we may need more timeout to let device\r
-  // adjust internal states.\r
-  //\r
-  if (AtaCommand == ATA_CMD_SMART) {\r
-    Status = WaitForBSYClear (IdeDev, ATASMARTTIMEOUT);\r
-  } else {\r
-    Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
-  }\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-  if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
-    //\r
-    // Failed to execute command, abort operation\r
-    //\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Send ATA Ext command into device with NON_DATA protocol\r
-\r
-  @param  IdeDev Standard IDE device private data structure\r
-  @param  AtaCommand The ATA command to be sent\r
-  @param  Device The value in Device register\r
-  @param  Feature The value in Feature register\r
-  @param  SectorCount The value in SectorCount register\r
-  @param  LbaAddress The LBA address in 48-bit mode\r
-\r
-  @retval  EFI_SUCCESS Reading succeed\r
-  @retval  EFI_ABORTED Command failed\r
-  @retval  EFI_DEVICE_ERROR Device status error\r
-\r
-**/\r
-EFI_STATUS\r
-AtaNonDataCommandInExt (\r
-  IN  IDE_BLK_IO_DEV  *IdeDev,\r
-  IN  UINT8           AtaCommand,\r
-  IN  UINT8           Device,\r
-  IN  UINT16          Feature,\r
-  IN  UINT16          SectorCount,\r
-  IN  EFI_LBA         LbaAddress\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       StatusRegister;\r
-  UINT8       SectorCount8;\r
-  UINT8       Feature8;\r
-  UINT8       LbaLow;\r
-  UINT8       LbaMid;\r
-  UINT8       LbaHigh;\r
-\r
-  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)\r
-  //\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    (UINT8) ((IdeDev->Device << 4) | 0xe0)\r
-    );\r
-\r
-  //\r
-  // ATA commands for ATA device must be issued when DRDY is set\r
-  //\r
-  Status = DRDYReady (IdeDev, ATATIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  //\r
-  // Pass parameter into device register block\r
-  //\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);\r
-\r
-  //\r
-  // Fill the feature register, which is a two-byte FIFO. Need write twice.\r
-  //\r
-  Feature8 = (UINT8) (Feature >> 8);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
-\r
-  Feature8 = (UINT8) Feature;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);\r
-\r
-  //\r
-  // Fill the sector count register, which is a two-byte FIFO. Need write twice.\r
-  //\r
-  SectorCount8 = (UINT8) (SectorCount >> 8);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
-\r
-  SectorCount8 = (UINT8) SectorCount;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);\r
-\r
-  //\r
-  // Fill the start LBA registers, which are also two-byte FIFO\r
-  //\r
-  LbaLow  = (UINT8) RShiftU64 (LbaAddress, 24);\r
-  LbaMid  = (UINT8) RShiftU64 (LbaAddress, 32);\r
-  LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
-\r
-  LbaLow  = (UINT8) LbaAddress;\r
-  LbaMid  = (UINT8) RShiftU64 (LbaAddress, 8);\r
-  LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);\r
-\r
-  //\r
-  // Send command via Command Register\r
-  //\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);\r
-\r
-  //\r
-  // Wait for command completion\r
-  //\r
-  Status = WaitForBSYClear (IdeDev, ATATIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);\r
-  if ((StatusRegister & ATA_STSREG_ERR) == ATA_STSREG_ERR) {\r
-    //\r
-    // Failed to execute command, abort operation\r
-    //\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-//\r
-// SetDriveParameters\r
-//\r
-/**\r
-  Set drive parameters for devices not support PACKETS command\r
-\r
-  @param[in] IdeDev       Standard IDE device private data structure\r
-  @param[in] DriveParameters The device parameters to be set into the disk\r
-\r
-  @return SetParameters Command execute status\r
-\r
-**/\r
-EFI_STATUS\r
-SetDriveParameters (\r
-  IN IDE_BLK_IO_DEV       *IdeDev,\r
-  IN ATA_DRIVE_PARMS      *DriveParameters\r
-  )\r
-{\r
-  EFI_STATUS  Status;\r
-  UINT8       DeviceSelect;\r
-\r
-  DeviceSelect  = 0;\r
-  DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);\r
-\r
-  //\r
-  // Send Init drive parameters\r
-  //\r
-  Status = AtaNonDataCommandIn (\r
-            IdeDev,\r
-            ATA_CMD_INIT_DRIVE_PARAM,\r
-            (UINT8) (DeviceSelect + DriveParameters->Heads),\r
-            0,\r
-            DriveParameters->Sector,\r
-            0,\r
-            0,\r
-            0\r
-            );\r
-\r
-  //\r
-  // Send Set Multiple parameters\r
-  //\r
-  Status = AtaNonDataCommandIn (\r
-            IdeDev,\r
-            ATA_CMD_SET_MULTIPLE_MODE,\r
-            DeviceSelect,\r
-            0,\r
-            DriveParameters->MultipleSector,\r
-            0,\r
-            0,\r
-            0\r
-            );\r
-  return Status;\r
-}\r
-\r
-/**\r
-  TODO: Add function description\r
-\r
-  @param  IdeDev TODO: add argument description\r
-\r
-  @retval  EFI_SUCCESS TODO: Add description for return value\r
-\r
-**/\r
-EFI_STATUS\r
-EnableInterrupt (\r
-  IN IDE_BLK_IO_DEV       *IdeDev\r
-  )\r
-{\r
-  UINT8 DeviceControl;\r
-\r
-  //\r
-  // Enable interrupt for DMA operation\r
-  //\r
-  DeviceControl = 0;\r
-  IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.\r
-\r
-  @param[in]  Event   Pointer to this event\r
-  @param[in]  Context Event hanlder private data\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ClearInterrupt (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  EFI_STATUS      Status;\r
-  UINT64          IoPortForBmis;\r
-  UINT8           RegisterValue;\r
-  IDE_BLK_IO_DEV  *IdeDev;\r
-\r
-  //\r
-  // Get our context\r
-  //\r
-  IdeDev = (IDE_BLK_IO_DEV *) Context;\r
-\r
-  //\r
-  // Obtain IDE IO port registers' base addresses\r
-  //\r
-  Status = ReassignIdeResources (IdeDev);\r
-  if (EFI_ERROR (Status)) {\r
-    return;\r
-  }\r
-\r
-  //\r
-  // Check whether interrupt is pending\r
-  //\r
-\r
-  //\r
-  // Reset IDE device to force it de-assert interrupt pin\r
-  // Note: this will reset all devices on this IDE channel\r
-  //\r
-  AtaSoftReset (IdeDev);\r
-  if (EFI_ERROR (Status)) {\r
-    return;\r
-  }\r
-\r
-  //\r
-  // Get base address of IDE Bus Master Status Regsiter\r
-  //\r
-  if (IdePrimary == IdeDev->Channel) {\r
-    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;\r
-  } else {\r
-    if (IdeSecondary == IdeDev->Channel) {\r
-      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;\r
-    } else {\r
-      return;\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
-  // Select the other device on this channel to ensure this device to release the interrupt pin\r
-  //\r
-  if (IdeDev->Device == 0) {\r
-    RegisterValue = (1 << 4) | 0xe0;\r
-  } else {\r
-    RegisterValue = (0 << 4) | 0xe0;\r
-  }\r
-  IDEWritePortB (\r
-    IdeDev->PciIo,\r
-    IdeDev->IoPort->Head,\r
-    RegisterValue\r
-    );\r
-\r
-}\r