]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c
Clean up PERF macro usage. The macros were being used with 0 as the first parameter...
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / IdeBus.c
index 224b2cac8dc0c7cd59d53782efe44887ad3860ad..629eadec52062ac61ca7a6c145629b3332c9420e 100644 (file)
-/** @file\r
+/** @file
   This file implement UEFI driver for IDE Bus which includes device identification, \r
   Child device(Disk, CDROM, etc) enumeration and child handler installation, and \r
-  driver stop.\r
+  driver stop.
     \r
-  Copyright (c) 2006 - 2008, 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
-  @par Revision Reference:\r
-  This module is modified from DXE\IDE module for Ide Contriller Init support\r
-\r
-**/\r
-\r
-#include "IdeBus.h"\r
-\r
-#define PCI_CLASS_MASS_STORAGE  0x01\r
-#define PCI_SUB_CLASS_IDE       0x01\r
-\r
-\r
-//\r
-// IDE Bus Driver Binding Protocol Instance\r
-//\r
-EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {\r
-  IDEBusDriverBindingSupported,\r
-  IDEBusDriverBindingStart,\r
-  IDEBusDriverBindingStop,\r
-  0xa,\r
-  NULL,\r
-  NULL\r
-};\r
-/**\r
-  Deregister an IDE device and free resources\r
-\r
-  @param  This Protocol instance pointer.\r
-  @param  Controller Ide device handle\r
-  @param  Handle Handle of device to deregister driver on\r
-\r
-  @retval EFI_SUCCESS  Deregiter a specific IDE device successfully\r
-  \r
-\r
-**/\r
-EFI_STATUS\r
-DeRegisterIdeDevice (\r
-  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,\r
-  IN  EFI_HANDLE                     Controller,\r
-  IN  EFI_HANDLE                     Handle\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
-  IDE_BLK_IO_DEV        *IdeBlkIoDevice;\r
-  EFI_PCI_IO_PROTOCOL   *PciIo;\r
-  UINTN                 Index;\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Handle,\r
-                  &gEfiBlockIoProtocolGuid,\r
-                  (VOID **) &BlkIo,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);\r
-\r
-  //\r
-  // Report Status code: Device disabled\r
-  //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-    EFI_PROGRESS_CODE,\r
-    (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),\r
-    IdeBlkIoDevice->DevicePath\r
-    );\r
-\r
-  //\r
-  // Close the child handle\r
-  //\r
-  Status = gBS->CloseProtocol (\r
-                  Controller,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  This->DriverBindingHandle,\r
-                  Handle\r
-                  );\r
-\r
-  Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                  Handle,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  IdeBlkIoDevice->DevicePath,\r
-                  &gEfiBlockIoProtocolGuid,\r
-                  &IdeBlkIoDevice->BlkIo,\r
-                  &gEfiDiskInfoProtocolGuid,\r
-                  &IdeBlkIoDevice->DiskInfo,\r
-                  NULL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->OpenProtocol (\r
-          Controller,\r
-          &gEfiPciIoProtocolGuid,\r
-          (VOID **) &PciIo,\r
-          This->DriverBindingHandle,\r
-          Handle,\r
-          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-          );\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Release allocated resources\r
-  //\r
-  Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;\r
-  if (Index < MAX_IDE_DEVICE) {\r
-    IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;\r
-  }\r
-  ReleaseIdeResources (IdeBlkIoDevice);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-/**\r
-  Supported function of Driver Binding protocol for this driver.\r
-\r
-  @param This                A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
-  @param ControllerHandle    The handle of the controller to test.\r
-  @param RemainingDevicePath A pointer to the remaining portion of a device path.\r
-\r
-  @retval  EFI_SUCCESS Driver loaded.\r
-  @retval  other       Driver not loaded.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBusDriverBindingSupported (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;\r
-  EFI_DEV_PATH                      *Node;\r
-  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;\r
-\r
-  if (RemainingDevicePath != NULL) {\r
-    Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
-    if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||\r
-        Node->DevPath.SubType != MSG_ATAPI_DP ||\r
-        DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {\r
-      return EFI_UNSUPPORTED;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Open the IO Abstraction(s) needed to perform the supported test\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Close protocol, don't use device path protocol in the .Support() function\r
-  //\r
-  gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiDevicePathProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-\r
-  //\r
-  // Verify the Ide Controller Init Protocol, which installed by the\r
-  // IdeController module.\r
-  // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't\r
-  //         open BY_DRIVER here) That's why we don't check pciio protocol\r
-  // Note 2: ide_init driver check ide controller's pci config space, so we dont\r
-  //         check here any more to save code size\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiIdeControllerInitProtocolGuid,\r
-                  (VOID **) &IdeInit,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  if (Status == EFI_ALREADY_STARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // If protocols were opened normally, closed it\r
-  //\r
-  gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiIdeControllerInitProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Start function of Driver binding protocol which start this driver on Controller\r
-  by detecting all disks and installing BlockIo protocol on them.\r
-\r
-  @param  This                Protocol instance pointer.\r
-  @param  Controller          Handle of device to bind driver to.\r
-  @param  RemainingDevicePath produce all possible children.\r
-\r
-  @retval  EFI_SUCCESS         This driver is added to ControllerHandle.\r
-  @retval  EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
-  @retval  other               This driver does not support this device.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBusDriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
-  IN EFI_HANDLE                   Controller,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
-  )\r
-{\r
-  EFI_STATUS                        Status;\r
-  EFI_STATUS                        SavedStatus;\r
-  EFI_PCI_IO_PROTOCOL               *PciIo;\r
-  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;\r
-  EFI_DEV_PATH                      *Node;\r
-  UINT8                             IdeChannel;\r
-  UINT8                             BeginningIdeChannel;\r
-  UINT8                             EndIdeChannel;\r
-  UINT8                             IdeDevice;\r
-  UINT8                             BeginningIdeDevice;\r
-  UINT8                             EndIdeDevice;\r
-  IDE_BLK_IO_DEV                    *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];\r
-  IDE_BLK_IO_DEV                    *IdeBlkIoDevicePtr;\r
-  IDE_REGISTERS_BASE_ADDR           IdeRegsBaseAddr[IdeMaxChannel];\r
-  ATA_TRANSFER_MODE                 TransferMode;\r
-  ATA_DRIVE_PARMS                   DriveParameters;\r
-  EFI_DEV_PATH                      NewNode;\r
-  UINT8                             ConfigurationOptions;\r
-  UINT16                            CommandBlockBaseAddr;\r
-  UINT16                            ControlBlockBaseAddr;\r
-  UINTN                             DataSize;\r
-  IDE_BUS_DRIVER_PRIVATE_DATA       *IdeBusDriverPrivateData;\r
-  UINT64                            Supports;\r
-\r
-  //\r
-  // Local variables declaration for IdeControllerInit support\r
-  //\r
-  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;\r
-  BOOLEAN                           EnumAll;\r
-  BOOLEAN                           ChannelEnabled;\r
-  UINT8                             MaxDevices;\r
-  EFI_IDENTIFY_DATA                 IdentifyData;\r
-  EFI_ATA_COLLECTIVE_MODE           *SupportedModes;\r
-\r
-  IdeBusDriverPrivateData = NULL;\r
-  SupportedModes          = NULL;\r
-\r
-  //\r
-  // Perform IdeBus initialization\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Now open the IDE_CONTROLLER_INIT protocol. Step7.1\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiIdeControllerInitProtocolGuid,\r
-                  (VOID **) &IdeInit,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-\r
-  //\r
-  // The following OpenProtocol function with _GET_PROTOCOL attribute and\r
-  // will not return EFI_ALREADY_STARTED, so save it for now\r
-  //\r
-  SavedStatus = Status;\r
-\r
-  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
-    DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));\r
-    //\r
-    // open protocol is not SUCCESS or not ALREADY_STARTED, error exit\r
-    //\r
-    goto ErrorExit;\r
-  }\r
-\r
-  //\r
-  // Save Enumall. Step7.2\r
-  //\r
-  EnumAll       = IdeInit->EnumAll;\r
-\r
-  //\r
-  // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL\r
-  // attribute will not return EFI_ALREADY_STARTED\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **) &PciIo,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));\r
-    goto ErrorExit;\r
-  }\r
-\r
-  //\r
-  // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable\r
-  //\r
-  if (SavedStatus != EFI_ALREADY_STARTED) {\r
-    IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));\r
-    if (IdeBusDriverPrivateData == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto ErrorExit;\r
-    }\r
-\r
-    ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    IdeBusDriverPrivateData,\r
-                    NULL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      goto ErrorExit;\r
-    }\r
-\r
-  } else {\r
-    Status = gBS->OpenProtocol (\r
-                    Controller,\r
-                    &gEfiCallerIdGuid,\r
-                    (VOID **) &IdeBusDriverPrivateData,\r
-                    This->DriverBindingHandle,\r
-                    Controller,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      IdeBusDriverPrivateData = NULL;\r
-      goto ErrorExit;\r
-    }\r
-  }\r
-\r
-  Status = PciIo->Attributes (\r
-                    PciIo,\r
-                    EfiPciIoAttributeOperationSupported,\r
-                    0,\r
-                    &Supports\r
-                    );\r
-  if (!EFI_ERROR (Status)) {\r
-    Supports &= EFI_PCI_DEVICE_ENABLE;\r
-    Status = PciIo->Attributes (\r
-                      PciIo,\r
-                      EfiPciIoAttributeOperationEnable,\r
-                      Supports,\r
-                      NULL\r
-                      );\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ErrorExit;\r
-  }\r
-\r
-  //\r
-  // Read the environment variable that contains the IDEBus Driver's\r
-  // Config options that were set by the Driver Configuration Protocol\r
-  //\r
-  DataSize = sizeof (ConfigurationOptions);\r
-  Status = gRT->GetVariable (\r
-                  (CHAR16 *) L"Configuration",\r
-                  &gEfiCallerIdGuid,\r
-                  NULL,\r
-                  &DataSize,\r
-                  &ConfigurationOptions\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    ConfigurationOptions = 0x0f;\r
-  }\r
-\r
-  if (EnumAll) {\r
-    //\r
-    // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway\r
-    //\r
-    BeginningIdeChannel = IdePrimary;\r
-    EndIdeChannel       = IdeSecondary;\r
-    BeginningIdeDevice  = IdeMaster;\r
-    EndIdeDevice        = IdeSlave;\r
-  } else if (RemainingDevicePath == NULL) {\r
-    //\r
-    // RemainingDevicePath is NULL, scan IDE bus for each device;\r
-    //\r
-    BeginningIdeChannel = IdePrimary;\r
-    EndIdeChannel       = IdeSecondary;\r
-    BeginningIdeDevice  = IdeMaster;\r
-    //\r
-    // default, may be redefined by IdeInit\r
-    //\r
-    EndIdeDevice = IdeSlave;\r
-  } else {\r
-    //\r
-    // RemainingDevicePath is not NULL, only scan the specified device.\r
-    //\r
-    Node                = (EFI_DEV_PATH *) RemainingDevicePath;\r
-    BeginningIdeChannel = Node->Atapi.PrimarySecondary;\r
-    EndIdeChannel       = BeginningIdeChannel;\r
-    BeginningIdeDevice  = Node->Atapi.SlaveMaster;\r
-    EndIdeDevice        = BeginningIdeDevice;\r
-    if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ErrorExit;\r
-    }\r
-    if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {\r
-      Status = EFI_INVALID_PARAMETER;\r
-      goto ErrorExit;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Obtain IDE IO port registers' base addresses\r
-  //\r
-  Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ErrorExit;\r
-  }\r
-\r
-  //\r
-  // Report status code: begin IdeBus initialization\r
-  //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-    EFI_PROGRESS_CODE,\r
-    (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
-    ParentDevicePath\r
-    );\r
-\r
-  //\r
-  // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol\r
-  //\r
-  for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {\r
-\r
-    IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);\r
-\r
-    //\r
-    // now obtain channel information fron IdeControllerInit protocol. Step9\r
-    //\r
-    Status = IdeInit->GetChannelInfo (\r
-                        IdeInit,\r
-                        IdeChannel,\r
-                        &ChannelEnabled,\r
-                        &MaxDevices\r
-                        );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));\r
-      continue;\r
-    }\r
-\r
-    if (!ChannelEnabled) {\r
-      continue;\r
-    }\r
-\r
-    EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);\r
-    ASSERT (EndIdeDevice < IdeMaxDevice);\r
-    //\r
-    // Now inform the IDE Controller Init Module. Sept10\r
-    //\r
-    IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);\r
-\r
-    //\r
-    // No reset channel function implemented. Sept11\r
-    //\r
-    IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);\r
-\r
-    //\r
-    // Step13\r
-    //\r
-    IdeInit->NotifyPhase (\r
-              IdeInit,\r
-              EfiIdeBusBeforeDevicePresenceDetection,\r
-              IdeChannel\r
-              );\r
-\r
-    //\r
-    // Prepare to detect IDE device of this channel\r
-    //\r
-    InitializeIDEChannelData ();\r
-\r
-    //\r
-    // -- 1st inner loop --- Master/Slave ------------  Step14\r
-    //\r
-    for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {\r
-      //\r
-      // Check whether the configuration options allow this device\r
-      //\r
-      if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // The device has been scanned in another Start(), No need to scan it again\r
-      // for perf optimization.\r
-      //\r
-      if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // create child handle for the detected device.\r
-      //\r
-      IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));\r
-      if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {\r
-        continue;\r
-      }\r
-\r
-      IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];\r
-\r
-      ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));\r
-\r
-      IdeBlkIoDevicePtr->Signature  = IDE_BLK_IO_DEV_SIGNATURE;\r
-      IdeBlkIoDevicePtr->Channel    = (EFI_IDE_CHANNEL) IdeChannel;\r
-      IdeBlkIoDevicePtr->Device     = (EFI_IDE_DEVICE) IdeDevice;\r
-\r
-      //\r
-      // initialize Block IO interface's Media pointer\r
-      //\r
-      IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;\r
-\r
-      //\r
-      // Initialize IDE IO port addresses, including Command Block registers\r
-      // and Control Block registers\r
-      //\r
-      IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));\r
-      if (IdeBlkIoDevicePtr->IoPort == NULL) {\r
-        continue;\r
-      }\r
-\r
-      ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));\r
-      CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;\r
-      ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;\r
-\r
-      IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;\r
-      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);\r
-      IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);\r
-      IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);\r
-      IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);\r
-      IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);\r
-      IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);\r
-      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);\r
-\r
-      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;\r
-      IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);\r
-\r
-      IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);\r
-\r
-      IdeBlkIoDevicePtr->PciIo = PciIo;\r
-      IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;\r
-      IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;\r
-\r
-      //\r
-      // Report Status code: is about to detect IDE drive\r
-      //\r
-      REPORT_STATUS_CODE_EX (\r
-        EFI_PROGRESS_CODE,\r
-        (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),\r
-        0,\r
-        &gEfiCallerIdGuid,\r
-        NULL,\r
-        NULL,\r
-        0\r
-      );\r
-\r
-      //\r
-      // Discover device, now!\r
-      //\r
-      PERF_START (0, "DiscoverIdeDevice", "IDE", 0);\r
-      Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);\r
-      PERF_END (0, "DiscoverIdeDevice", "IDE", 0);\r
-\r
-      IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]  = TRUE;\r
-      IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]    = FALSE;\r
-\r
-      if (!EFI_ERROR (Status)) {\r
-        //\r
-        // Set Device Path\r
-        //\r
-        ZeroMem (&NewNode, sizeof (NewNode));\r
-        NewNode.DevPath.Type    = MESSAGING_DEVICE_PATH;\r
-        NewNode.DevPath.SubType = MSG_ATAPI_DP;\r
-        SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));\r
-\r
-        NewNode.Atapi.PrimarySecondary  = (UINT8) IdeBlkIoDevicePtr->Channel;\r
-        NewNode.Atapi.SlaveMaster       = (UINT8) IdeBlkIoDevicePtr->Device;\r
-        NewNode.Atapi.Lun               = IdeBlkIoDevicePtr->Lun;\r
-        IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (\r
-                                          ParentDevicePath,\r
-                                          &NewNode.DevPath\r
-                                          );\r
-        if (IdeBlkIoDevicePtr->DevicePath == NULL) {\r
-          ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-          continue;\r
-        }\r
-\r
-        //\r
-        // Submit identify data to IDE controller init driver\r
-        //\r
-        CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));\r
-        IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;\r
-        IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);\r
-      } else {\r
-        //\r
-        // Device detection failed\r
-        //\r
-        IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
-        IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);\r
-        ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-        IdeBlkIoDevicePtr = NULL;\r
-      }\r
-      //\r
-      // end of 1st inner loop ---\r
-      //\r
-    }\r
-    //\r
-    // end of 1st outer loop =========\r
-    //\r
-  }\r
-\r
-  //\r
-  // = 2nd outer loop == Primary/Secondary =================\r
-  //\r
-  for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {\r
-\r
-    //\r
-    // -- 2nd inner loop --- Master/Slave --------\r
-    //\r
-    for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {\r
-\r
-      if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {\r
-        continue;\r
-      }\r
-\r
-      if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {\r
-        continue;\r
-      }\r
-\r
-      Status = IdeInit->CalculateMode (\r
-                          IdeInit,\r
-                          IdeChannel,\r
-                          IdeDevice,\r
-                          &SupportedModes\r
-                          );\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));\r
-        continue;\r
-      }\r
-\r
-      IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];\r
-\r
-      //\r
-      // Set best supported PIO mode on this IDE device\r
-      //\r
-      if (SupportedModes->PioMode.Mode <= AtaPioMode2) {\r
-        TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;\r
-      } else {\r
-        TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;\r
-      }\r
-\r
-      TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);\r
-\r
-      if (SupportedModes->ExtModeCount == 0){\r
-        Status                  = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
-          ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-          IdeBlkIoDevicePtr = NULL;\r
-          continue;\r
-        }\r
-      }\r
-\r
-      //\r
-      // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't\r
-      // be set together. Only one DMA mode can be set to a device. If setting\r
-      // DMA mode operation fails, we can continue moving on because we only use\r
-      // PIO mode at boot time. DMA modes are used by certain kind of OS booting\r
-      //\r
-      if (SupportedModes->UdmaMode.Valid) {\r
-\r
-        TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;\r
-        TransferMode.ModeNumber   = (UINT8) (SupportedModes->UdmaMode.Mode);\r
-        Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
-          ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-          IdeBlkIoDevicePtr = NULL;\r
-          continue;\r
-        }\r
-        //\r
-        // Record Udma Mode\r
-        //\r
-        IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;\r
-        IdeBlkIoDevicePtr->UdmaMode.Mode  = SupportedModes->UdmaMode.Mode;\r
-        EnableInterrupt (IdeBlkIoDevicePtr);\r
-      } else if (SupportedModes->MultiWordDmaMode.Valid) {\r
-\r
-        TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;\r
-        TransferMode.ModeNumber   = (UINT8) SupportedModes->MultiWordDmaMode.Mode;\r
-        Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;\r
-          ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-          IdeBlkIoDevicePtr = NULL;\r
-          continue;\r
-        }\r
-\r
-        EnableInterrupt (IdeBlkIoDevicePtr);\r
-      }\r
-      //\r
-      // Init driver parameters\r
-      //\r
-      DriveParameters.Sector          = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.sectors_per_track;\r
-      DriveParameters.Heads           = (UINT8) (IdeBlkIoDevicePtr->IdData->AtaData.heads - 1);\r
-      DriveParameters.MultipleSector  = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;\r
-      //\r
-      // Set Parameters for the device:\r
-      // 1) Init\r
-      // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command\r
-      //\r
-      if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {\r
-        Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);\r
-      }\r
-\r
-      //\r
-      // Record PIO mode used in private data\r
-      //\r
-      IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;\r
-\r
-      //\r
-      // Set IDE controller Timing Blocks in the PCI Configuration Space\r
-      //\r
-      IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);\r
-\r
-      //\r
-      // Add Component Name for the IDE/ATAPI device that was discovered.\r
-      //\r
-      IdeBlkIoDevicePtr->ControllerNameTable = NULL;\r
-      ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);\r
-\r
-      Status = gBS->InstallMultipleProtocolInterfaces (\r
-                      &IdeBlkIoDevicePtr->Handle,\r
-                      &gEfiDevicePathProtocolGuid,\r
-                      IdeBlkIoDevicePtr->DevicePath,\r
-                      &gEfiBlockIoProtocolGuid,\r
-                      &IdeBlkIoDevicePtr->BlkIo,\r
-                      &gEfiDiskInfoProtocolGuid,\r
-                      &IdeBlkIoDevicePtr->DiskInfo,\r
-                      NULL\r
-                      );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        ReleaseIdeResources (IdeBlkIoDevicePtr);\r
-      }\r
-\r
-      gBS->OpenProtocol (\r
-            Controller,\r
-            &gEfiPciIoProtocolGuid,\r
-            (VOID **) &PciIo,\r
-            This->DriverBindingHandle,\r
-            IdeBlkIoDevicePtr->Handle,\r
-            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-            );\r
-\r
-      IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;\r
-\r
-      //\r
-      // Report status code: device eanbled!\r
-      //\r
-      REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-        EFI_PROGRESS_CODE,\r
-        (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),\r
-        IdeBlkIoDevicePtr->DevicePath\r
-        );\r
-\r
-      //\r
-      // Create event to clear pending IDE interrupt\r
-      //\r
-      Status = gBS->CreateEventEx (\r
-                      EVT_NOTIFY_SIGNAL,\r
-                      TPL_NOTIFY,\r
-                      ClearInterrupt,\r
-                      IdeBlkIoDevicePtr,\r
-                      &gEfiEventExitBootServicesGuid,\r
-                      &IdeBlkIoDevicePtr->ExitBootServiceEvent\r
-                      );\r
-\r
-      //\r
-      // end of 2nd inner loop ----\r
-      //\r
-    }\r
-    //\r
-    // end of 2nd outer loop ==========\r
-    //\r
-  }\r
-\r
-  //\r
-  // All configurations done! Notify IdeController to do post initialization\r
-  // work such as saving IDE controller PCI settings for S3 resume\r
-  //\r
-  IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);\r
-\r
-  if (SupportedModes != NULL) {\r
-    gBS->FreePool (SupportedModes);\r
-  }\r
-\r
-  PERF_START (0, "Finish IDE detection", "IDE", 1);\r
-  PERF_END (0, "Finish IDE detection", "IDE", 0);\r
-\r
-  return EFI_SUCCESS;\r
-\r
-ErrorExit:\r
-\r
-  //\r
-  // Report error code: controller error\r
-  //\r
-  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
-    EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
-    (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),\r
-    ParentDevicePath\r
-    );\r
-\r
-  gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiIdeControllerInitProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-\r
-  gBS->UninstallMultipleProtocolInterfaces (\r
-        Controller,\r
-        &gEfiCallerIdGuid,\r
-        IdeBusDriverPrivateData,\r
-        NULL\r
-        );\r
-\r
-  if (IdeBusDriverPrivateData != NULL) {\r
-    gBS->FreePool (IdeBusDriverPrivateData);\r
-  }\r
-\r
-  if (SupportedModes != NULL) {\r
-    gBS->FreePool (SupportedModes);\r
-  }\r
-\r
-  gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiPciIoProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-\r
-  gBS->CloseProtocol (\r
-        Controller,\r
-        &gEfiDevicePathProtocolGuid,\r
-        This->DriverBindingHandle,\r
-        Controller\r
-        );\r
-\r
-  return Status;\r
-\r
-}\r
-/**\r
-  Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all\r
-  child handle attached to the controller handle if there are.\r
-\r
-  @param  This Protocol instance pointer.\r
-  @param  Controller Handle of device to stop driver on\r
-  @param  NumberOfChildren Not used\r
-  @param  ChildHandleBuffer Not used\r
-\r
-  @retval  EFI_SUCCESS This driver is removed DeviceHandle\r
-  @retval  other This driver was not removed from this device\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBusDriverBindingStop (\r
-  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,\r
-  IN  EFI_HANDLE                      Controller,\r
-  IN  UINTN                           NumberOfChildren,\r
-  IN  EFI_HANDLE                      *ChildHandleBuffer\r
-  )\r
-{\r
-  EFI_STATUS                  Status;\r
-  EFI_PCI_IO_PROTOCOL         *PciIo;\r
-  BOOLEAN                     AllChildrenStopped;\r
-  UINTN                       Index;\r
-  IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;\r
-  UINT64                      Supports;\r
-\r
-  IdeBusDriverPrivateData = NULL;\r
-\r
-  if (NumberOfChildren == 0) {\r
-\r
-    Status = gBS->OpenProtocol (\r
-                    Controller,\r
-                    &gEfiPciIoProtocolGuid,\r
-                    (VOID **) &PciIo,\r
-                    This->DriverBindingHandle,\r
-                    Controller,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (!EFI_ERROR (Status)) {\r
-      Status = PciIo->Attributes (\r
-                        PciIo,\r
-                        EfiPciIoAttributeOperationSupported,\r
-                        0,\r
-                        &Supports\r
-                        );\r
-      if (!EFI_ERROR (Status)) {\r
-        Supports &= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;\r
-        PciIo->Attributes (\r
-                PciIo,\r
-                EfiPciIoAttributeOperationDisable,\r
-                Supports,\r
-                NULL\r
-                );\r
-      }\r
-    }\r
-\r
-    gBS->OpenProtocol (\r
-          Controller,\r
-          &gEfiCallerIdGuid,\r
-          (VOID **) &IdeBusDriverPrivateData,\r
-          This->DriverBindingHandle,\r
-          Controller,\r
-          EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-          );\r
-\r
-    gBS->UninstallMultipleProtocolInterfaces (\r
-          Controller,\r
-          &gEfiCallerIdGuid,\r
-          IdeBusDriverPrivateData,\r
-          NULL\r
-          );\r
-\r
-    if (IdeBusDriverPrivateData != NULL) {\r
-      gBS->FreePool (IdeBusDriverPrivateData);\r
-    }\r
-    //\r
-    // Close the bus driver\r
-    //\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiIdeControllerInitProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiPciIoProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiDevicePathProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  AllChildrenStopped = TRUE;\r
-\r
-  for (Index = 0; Index < NumberOfChildren; Index++) {\r
-\r
-    Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      AllChildrenStopped = FALSE;\r
-    }\r
-  }\r
-\r
-  if (!AllChildrenStopped) {\r
-    return EFI_DEVICE_ERROR;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  issue ATA or ATAPI command to reset a block IO device.\r
-  @param  This                  Block IO protocol instance pointer.\r
-  @param  ExtendedVerification  If FALSE,for ATAPI device, driver will only invoke ATAPI reset method\r
-                                If TRUE, for ATAPI device, driver need invoke ATA reset method after\r
-                                invoke ATAPI reset method\r
-\r
-  @retval EFI_DEVICE_ERROR      When the device is neighther ATA device or ATAPI device.\r
-  @retval EFI_SUCCESS           The device reset successfully\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBlkIoReset (\r
-  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
-  IN  BOOLEAN                 ExtendedVerification\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-  EFI_STATUS      Status;\r
-  EFI_TPL         OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
-  //\r
-  // Requery IDE IO resources in case of the switch of native and legacy modes\r
-  //\r
-  ReassignIdeResources (IdeBlkIoDevice);\r
-\r
-  //\r
-  // for ATA device, using ATA reset method\r
-  //\r
-  if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
-      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
-    Status = AtaSoftReset (IdeBlkIoDevice);\r
-    goto Done;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->Type == IdeUnknown) {\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // for ATAPI device, using ATAPI reset method\r
-  //\r
-  Status = AtapiSoftReset (IdeBlkIoDevice);\r
-  if (ExtendedVerification) {\r
-    Status = AtaSoftReset (IdeBlkIoDevice);\r
-  }\r
-\r
-Done:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Read data from a block IO device\r
-\r
-  @param  This       Block IO protocol instance pointer.\r
-  @param  MediaId    The media ID of the device\r
+  Copyright (c) 2006 - 2008, Intel Corporation
+  All rights reserved. This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+  @par Revision Reference:
+  This module is modified from DXE\IDE module for Ide Contriller Init support
+
+**/
+
+#include "IdeBus.h"
+
+#define PCI_CLASS_MASS_STORAGE  0x01
+#define PCI_SUB_CLASS_IDE       0x01
+
+
+//
+// IDE Bus Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
+  IDEBusDriverBindingSupported,
+  IDEBusDriverBindingStart,
+  IDEBusDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+/**
+  Deregister an IDE device and free resources
+
+  @param  This Protocol instance pointer.
+  @param  Controller Ide device handle
+  @param  Handle Handle of device to deregister driver on
+
+  @retval EFI_SUCCESS  Deregiter a specific IDE device successfully
+
+
+**/
+EFI_STATUS
+DeRegisterIdeDevice (
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN  EFI_HANDLE                     Controller,
+  IN  EFI_HANDLE                     Handle
+  )
+{
+  EFI_STATUS            Status;
+  EFI_BLOCK_IO_PROTOCOL *BlkIo;
+  IDE_BLK_IO_DEV        *IdeBlkIoDevice;
+  EFI_PCI_IO_PROTOCOL   *PciIo;
+  UINTN                 Index;
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiBlockIoProtocolGuid,
+                  (VOID **) &BlkIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+  //
+  // Report Status code: Device disabled
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
+    IdeBlkIoDevice->DevicePath
+    );
+
+  //
+  // Close the child handle
+  //
+  Status = gBS->CloseProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  This->DriverBindingHandle,
+                  Handle
+                  );
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Handle,
+                  &gEfiDevicePathProtocolGuid,
+                  IdeBlkIoDevice->DevicePath,
+                  &gEfiBlockIoProtocolGuid,
+                  &IdeBlkIoDevice->BlkIo,
+                  &gEfiDiskInfoProtocolGuid,
+                  &IdeBlkIoDevice->DiskInfo,
+                  NULL
+                  );
+
+  if (EFI_ERROR (Status)) {
+    gBS->OpenProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          (VOID **) &PciIo,
+          This->DriverBindingHandle,
+          Handle,
+          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+          );
+    return Status;
+  }
+
+  //
+  // Release allocated resources
+  //
+  Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
+  if (Index < MAX_IDE_DEVICE) {
+    IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
+  }
+  ReleaseIdeResources (IdeBlkIoDevice);
+
+  return EFI_SUCCESS;
+}
+/**
+  Supported function of Driver Binding protocol for this driver.
+
+  @param This                A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param ControllerHandle    The handle of the controller to test.
+  @param RemainingDevicePath A pointer to the remaining portion of a device path.
+
+  @retval  EFI_SUCCESS Driver loaded.
+  @retval  other       Driver not loaded.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
+  EFI_DEV_PATH                      *Node;
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
+
+  if (RemainingDevicePath != NULL) {
+    Node = (EFI_DEV_PATH *) RemainingDevicePath;
+    if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
+        Node->DevPath.SubType != MSG_ATAPI_DP ||
+        DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
+      return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // Open the IO Abstraction(s) needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Close protocol, don't use device path protocol in the .Support() function
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiDevicePathProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  //
+  // Verify the Ide Controller Init Protocol, which installed by the
+  // IdeController module.
+  // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
+  //         open BY_DRIVER here) That's why we don't check pciio protocol
+  // Note 2: ide_init driver check ide controller's pci config space, so we dont
+  //         check here any more to save code size
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiIdeControllerInitProtocolGuid,
+                  (VOID **) &IdeInit,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (Status == EFI_ALREADY_STARTED) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // If protocols were opened normally, closed it
+  //
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiIdeControllerInitProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  return Status;
+}
+
+
+/**
+  Start function of Driver binding protocol which start this driver on Controller
+  by detecting all disks and installing BlockIo protocol on them.
+
+  @param  This                Protocol instance pointer.
+  @param  Controller          Handle of device to bind driver to.
+  @param  RemainingDevicePath produce all possible children.
+
+  @retval  EFI_SUCCESS         This driver is added to ControllerHandle.
+  @retval  EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
+  @retval  other               This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_STATUS                        SavedStatus;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
+  EFI_DEV_PATH                      *Node;
+  UINT8                             IdeChannel;
+  UINT8                             BeginningIdeChannel;
+  UINT8                             EndIdeChannel;
+  UINT8                             IdeDevice;
+  UINT8                             BeginningIdeDevice;
+  UINT8                             EndIdeDevice;
+  IDE_BLK_IO_DEV                    *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
+  IDE_BLK_IO_DEV                    *IdeBlkIoDevicePtr;
+  IDE_REGISTERS_BASE_ADDR           IdeRegsBaseAddr[IdeMaxChannel];
+  ATA_TRANSFER_MODE                 TransferMode;
+  ATA_DRIVE_PARMS                   DriveParameters;
+  EFI_DEV_PATH                      NewNode;
+  UINT8                             ConfigurationOptions;
+  UINT16                            CommandBlockBaseAddr;
+  UINT16                            ControlBlockBaseAddr;
+  UINTN                             DataSize;
+  IDE_BUS_DRIVER_PRIVATE_DATA       *IdeBusDriverPrivateData;
+  UINT64                            Supports;
+
+  //
+  // Local variables declaration for IdeControllerInit support
+  //
+  EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
+  BOOLEAN                           EnumAll;
+  BOOLEAN                           ChannelEnabled;
+  UINT8                             MaxDevices;
+  EFI_IDENTIFY_DATA                 IdentifyData;
+  EFI_ATA_COLLECTIVE_MODE           *SupportedModes;
+
+  IdeBusDriverPrivateData = NULL;
+  SupportedModes          = NULL;
+
+  //
+  // Perform IdeBus initialization
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &ParentDevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+    return Status;
+  }
+
+  //
+  // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiIdeControllerInitProtocolGuid,
+                  (VOID **) &IdeInit,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  //
+  // The following OpenProtocol function with _GET_PROTOCOL attribute and
+  // will not return EFI_ALREADY_STARTED, so save it for now
+  //
+  SavedStatus = Status;
+
+  if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+    DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
+    //
+    // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
+    //
+    goto ErrorExit;
+  }
+
+  //
+  // Save Enumall. Step7.2
+  //
+  EnumAll       = IdeInit->EnumAll;
+
+  //
+  // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
+  // attribute will not return EFI_ALREADY_STARTED
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
+    goto ErrorExit;
+  }
+
+  //
+  // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
+  //
+  if (SavedStatus != EFI_ALREADY_STARTED) {
+    IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+    if (IdeBusDriverPrivateData == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ErrorExit;
+    }
+
+    ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &Controller,
+                    &gEfiCallerIdGuid,
+                    IdeBusDriverPrivateData,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      goto ErrorExit;
+    }
+
+  } else {
+    Status = gBS->OpenProtocol (
+                    Controller,
+                    &gEfiCallerIdGuid,
+                    (VOID **) &IdeBusDriverPrivateData,
+                    This->DriverBindingHandle,
+                    Controller,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      IdeBusDriverPrivateData = NULL;
+      goto ErrorExit;
+    }
+  }
+
+  Status = PciIo->Attributes (
+                    PciIo,
+                    EfiPciIoAttributeOperationSupported,
+                    0,
+                    &Supports
+                    );
+  if (!EFI_ERROR (Status)) {
+    Supports &= EFI_PCI_DEVICE_ENABLE;
+    Status = PciIo->Attributes (
+                      PciIo,
+                      EfiPciIoAttributeOperationEnable,
+                      Supports,
+                      NULL
+                      );
+  }
+
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  //
+  // Read the environment variable that contains the IDEBus Driver's
+  // Config options that were set by the Driver Configuration Protocol
+  //
+  DataSize = sizeof (ConfigurationOptions);
+  Status = gRT->GetVariable (
+                  (CHAR16 *) L"Configuration",
+                  &gEfiCallerIdGuid,
+                  NULL,
+                  &DataSize,
+                  &ConfigurationOptions
+                  );
+  if (EFI_ERROR (Status)) {
+    ConfigurationOptions = 0x0f;
+  }
+
+  if (EnumAll) {
+    //
+    // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
+    //
+    BeginningIdeChannel = IdePrimary;
+    EndIdeChannel       = IdeSecondary;
+    BeginningIdeDevice  = IdeMaster;
+    EndIdeDevice        = IdeSlave;
+  } else if (RemainingDevicePath == NULL) {
+    //
+    // RemainingDevicePath is NULL, scan IDE bus for each device;
+    //
+    BeginningIdeChannel = IdePrimary;
+    EndIdeChannel       = IdeSecondary;
+    BeginningIdeDevice  = IdeMaster;
+    //
+    // default, may be redefined by IdeInit
+    //
+    EndIdeDevice = IdeSlave;
+  } else {
+    //
+    // RemainingDevicePath is not NULL, only scan the specified device.
+    //
+    Node                = (EFI_DEV_PATH *) RemainingDevicePath;
+    BeginningIdeChannel = Node->Atapi.PrimarySecondary;
+    EndIdeChannel       = BeginningIdeChannel;
+    BeginningIdeDevice  = Node->Atapi.SlaveMaster;
+    EndIdeDevice        = BeginningIdeDevice;
+    if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ErrorExit;
+    }
+    if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ErrorExit;
+    }
+  }
+
+  //
+  // Obtain IDE IO port registers' base addresses
+  //
+  Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  //
+  // Report status code: begin IdeBus initialization
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+    ParentDevicePath
+    );
+
+  //
+  // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
+  //
+  for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+    IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
+
+    //
+    // now obtain channel information fron IdeControllerInit protocol. Step9
+    //
+    Status = IdeInit->GetChannelInfo (
+                        IdeInit,
+                        IdeChannel,
+                        &ChannelEnabled,
+                        &MaxDevices
+                        );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
+      continue;
+    }
+
+    if (!ChannelEnabled) {
+      continue;
+    }
+
+    EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);
+    ASSERT (EndIdeDevice < IdeMaxDevice);
+    //
+    // Now inform the IDE Controller Init Module. Sept10
+    //
+    IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
+
+    //
+    // No reset channel function implemented. Sept11
+    //
+    IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
+
+    //
+    // Step13
+    //
+    IdeInit->NotifyPhase (
+              IdeInit,
+              EfiIdeBusBeforeDevicePresenceDetection,
+              IdeChannel
+              );
+
+    //
+    // Prepare to detect IDE device of this channel
+    //
+    InitializeIDEChannelData ();
+
+    //
+    // -- 1st inner loop --- Master/Slave ------------  Step14
+    //
+    for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+      //
+      // Check whether the configuration options allow this device
+      //
+      if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {
+        continue;
+      }
+
+      //
+      // The device has been scanned in another Start(), No need to scan it again
+      // for perf optimization.
+      //
+      if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
+        continue;
+      }
+
+      //
+      // create child handle for the detected device.
+      //
+      IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
+      if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
+        continue;
+      }
+
+      IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+      ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
+
+      IdeBlkIoDevicePtr->Signature  = IDE_BLK_IO_DEV_SIGNATURE;
+      IdeBlkIoDevicePtr->Channel    = (EFI_IDE_CHANNEL) IdeChannel;
+      IdeBlkIoDevicePtr->Device     = (EFI_IDE_DEVICE) IdeDevice;
+
+      //
+      // initialize Block IO interface's Media pointer
+      //
+      IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
+
+      //
+      // Initialize IDE IO port addresses, including Command Block registers
+      // and Control Block registers
+      //
+      IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
+      if (IdeBlkIoDevicePtr->IoPort == NULL) {
+        continue;
+      }
+
+      ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
+      CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
+      ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
+
+      IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
+      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+      IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+      IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+      IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+      IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+      IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+
+      (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
+      IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+
+      IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
+
+      IdeBlkIoDevicePtr->PciIo = PciIo;
+      IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
+      IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
+
+      //
+      // Report Status code: is about to detect IDE drive
+      //
+      REPORT_STATUS_CODE_EX (
+        EFI_PROGRESS_CODE,
+        (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
+        0,
+        &gEfiCallerIdGuid,
+        NULL,
+        NULL,
+        0
+      );
+
+      //
+      // Discover device, now!
+      //
+      PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);
+      Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
+      PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);
+
+      IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]  = TRUE;
+      IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]    = FALSE;
+
+      if (!EFI_ERROR (Status)) {
+        //
+        // Set Device Path
+        //
+        ZeroMem (&NewNode, sizeof (NewNode));
+        NewNode.DevPath.Type    = MESSAGING_DEVICE_PATH;
+        NewNode.DevPath.SubType = MSG_ATAPI_DP;
+        SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
+
+        NewNode.Atapi.PrimarySecondary  = (UINT8) IdeBlkIoDevicePtr->Channel;
+        NewNode.Atapi.SlaveMaster       = (UINT8) IdeBlkIoDevicePtr->Device;
+        NewNode.Atapi.Lun               = IdeBlkIoDevicePtr->Lun;
+        IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
+                                          ParentDevicePath,
+                                          &NewNode.DevPath
+                                          );
+        if (IdeBlkIoDevicePtr->DevicePath == NULL) {
+          ReleaseIdeResources (IdeBlkIoDevicePtr);
+          continue;
+        }
+
+        //
+        // Submit identify data to IDE controller init driver
+        //
+        CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));
+        IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
+        IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
+      } else {
+        //
+        // Device detection failed
+        //
+        IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+        IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
+        ReleaseIdeResources (IdeBlkIoDevicePtr);
+        IdeBlkIoDevicePtr = NULL;
+      }
+      //
+      // end of 1st inner loop ---
+      //
+    }
+    //
+    // end of 1st outer loop =========
+    //
+  }
+
+  //
+  // = 2nd outer loop == Primary/Secondary =================
+  //
+  for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+    //
+    // -- 2nd inner loop --- Master/Slave --------
+    //
+    for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+
+      if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
+        continue;
+      }
+
+      if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
+        continue;
+      }
+
+      Status = IdeInit->CalculateMode (
+                          IdeInit,
+                          IdeChannel,
+                          IdeDevice,
+                          &SupportedModes
+                          );
+      if (EFI_ERROR (Status)) {
+        DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
+        continue;
+      }
+
+      IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+      //
+      // Set best supported PIO mode on this IDE device
+      //
+      if (SupportedModes->PioMode.Mode <= AtaPioMode2) {
+        TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
+      } else {
+        TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
+      }
+
+      TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
+
+      if (SupportedModes->ExtModeCount == 0){
+        Status                  = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+        if (EFI_ERROR (Status)) {
+          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+          ReleaseIdeResources (IdeBlkIoDevicePtr);
+          IdeBlkIoDevicePtr = NULL;
+          continue;
+        }
+      }
+
+      //
+      // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
+      // be set together. Only one DMA mode can be set to a device. If setting
+      // DMA mode operation fails, we can continue moving on because we only use
+      // PIO mode at boot time. DMA modes are used by certain kind of OS booting
+      //
+      if (SupportedModes->UdmaMode.Valid) {
+
+        TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
+        TransferMode.ModeNumber   = (UINT8) (SupportedModes->UdmaMode.Mode);
+        Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+        if (EFI_ERROR (Status)) {
+          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+          ReleaseIdeResources (IdeBlkIoDevicePtr);
+          IdeBlkIoDevicePtr = NULL;
+          continue;
+        }
+        //
+        // Record Udma Mode
+        //
+        IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
+        IdeBlkIoDevicePtr->UdmaMode.Mode  = SupportedModes->UdmaMode.Mode;
+        EnableInterrupt (IdeBlkIoDevicePtr);
+      } else if (SupportedModes->MultiWordDmaMode.Valid) {
+
+        TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
+        TransferMode.ModeNumber   = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
+        Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+        if (EFI_ERROR (Status)) {
+          IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+          ReleaseIdeResources (IdeBlkIoDevicePtr);
+          IdeBlkIoDevicePtr = NULL;
+          continue;
+        }
+
+        EnableInterrupt (IdeBlkIoDevicePtr);
+      }
+      //
+      // Init driver parameters
+      //
+      DriveParameters.Sector          = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.sectors_per_track;
+      DriveParameters.Heads           = (UINT8) (IdeBlkIoDevicePtr->IdData->AtaData.heads - 1);
+      DriveParameters.MultipleSector  = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;
+      //
+      // Set Parameters for the device:
+      // 1) Init
+      // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
+      //
+      if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
+        Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
+      }
+
+      //
+      // Record PIO mode used in private data
+      //
+      IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
+
+      //
+      // Set IDE controller Timing Blocks in the PCI Configuration Space
+      //
+      IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
+
+      //
+      // Add Component Name for the IDE/ATAPI device that was discovered.
+      //
+      IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+      ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);
+
+      Status = gBS->InstallMultipleProtocolInterfaces (
+                      &IdeBlkIoDevicePtr->Handle,
+                      &gEfiDevicePathProtocolGuid,
+                      IdeBlkIoDevicePtr->DevicePath,
+                      &gEfiBlockIoProtocolGuid,
+                      &IdeBlkIoDevicePtr->BlkIo,
+                      &gEfiDiskInfoProtocolGuid,
+                      &IdeBlkIoDevicePtr->DiskInfo,
+                      NULL
+                      );
+
+      if (EFI_ERROR (Status)) {
+        ReleaseIdeResources (IdeBlkIoDevicePtr);
+      }
+
+      gBS->OpenProtocol (
+            Controller,
+            &gEfiPciIoProtocolGuid,
+            (VOID **) &PciIo,
+            This->DriverBindingHandle,
+            IdeBlkIoDevicePtr->Handle,
+            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+            );
+
+      IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
+
+      //
+      // Report status code: device eanbled!
+      //
+      REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+        EFI_PROGRESS_CODE,
+        (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
+        IdeBlkIoDevicePtr->DevicePath
+        );
+
+      //
+      // Create event to clear pending IDE interrupt
+      //
+      Status = gBS->CreateEventEx (
+                      EVT_NOTIFY_SIGNAL,
+                      TPL_NOTIFY,
+                      ClearInterrupt,
+                      IdeBlkIoDevicePtr,
+                      &gEfiEventExitBootServicesGuid,
+                      &IdeBlkIoDevicePtr->ExitBootServiceEvent
+                      );
+
+      //
+      // end of 2nd inner loop ----
+      //
+    }
+    //
+    // end of 2nd outer loop ==========
+    //
+  }
+
+  //
+  // All configurations done! Notify IdeController to do post initialization
+  // work such as saving IDE controller PCI settings for S3 resume
+  //
+  IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
+
+  if (SupportedModes != NULL) {
+    gBS->FreePool (SupportedModes);
+  }
+
+  PERF_START (NULL, "Finish IDE detection", "IDE", 1);
+  PERF_END (NULL, "Finish IDE detection", "IDE", 0);
+
+  return EFI_SUCCESS;
+
+ErrorExit:
+
+  //
+  // Report error code: controller error
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_ERROR_CODE | EFI_ERROR_MINOR,
+    (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
+    ParentDevicePath
+    );
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiIdeControllerInitProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  gBS->UninstallMultipleProtocolInterfaces (
+        Controller,
+        &gEfiCallerIdGuid,
+        IdeBusDriverPrivateData,
+        NULL
+        );
+
+  if (IdeBusDriverPrivateData != NULL) {
+    gBS->FreePool (IdeBusDriverPrivateData);
+  }
+
+  if (SupportedModes != NULL) {
+    gBS->FreePool (SupportedModes);
+  }
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiPciIoProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  gBS->CloseProtocol (
+        Controller,
+        &gEfiDevicePathProtocolGuid,
+        This->DriverBindingHandle,
+        Controller
+        );
+
+  return Status;
+
+}
+/**
+  Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
+  child handle attached to the controller handle if there are.
+
+  @param  This Protocol instance pointer.
+  @param  Controller Handle of device to stop driver on
+  @param  NumberOfChildren Not used
+  @param  ChildHandleBuffer Not used
+
+  @retval  EFI_SUCCESS This driver is removed DeviceHandle
+  @retval  other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
+  IN  EFI_HANDLE                      Controller,
+  IN  UINTN                           NumberOfChildren,
+  IN  EFI_HANDLE                      *ChildHandleBuffer
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PCI_IO_PROTOCOL         *PciIo;
+  BOOLEAN                     AllChildrenStopped;
+  UINTN                       Index;
+  IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+  UINT64                      Supports;
+
+  IdeBusDriverPrivateData = NULL;
+
+  if (NumberOfChildren == 0) {
+
+    Status = gBS->OpenProtocol (
+                    Controller,
+                    &gEfiPciIoProtocolGuid,
+                    (VOID **) &PciIo,
+                    This->DriverBindingHandle,
+                    Controller,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+    if (!EFI_ERROR (Status)) {
+      Status = PciIo->Attributes (
+                        PciIo,
+                        EfiPciIoAttributeOperationSupported,
+                        0,
+                        &Supports
+                        );
+      if (!EFI_ERROR (Status)) {
+        Supports &= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;
+        PciIo->Attributes (
+                PciIo,
+                EfiPciIoAttributeOperationDisable,
+                Supports,
+                NULL
+                );
+      }
+    }
+
+    gBS->OpenProtocol (
+          Controller,
+          &gEfiCallerIdGuid,
+          (VOID **) &IdeBusDriverPrivateData,
+          This->DriverBindingHandle,
+          Controller,
+          EFI_OPEN_PROTOCOL_GET_PROTOCOL
+          );
+
+    gBS->UninstallMultipleProtocolInterfaces (
+          Controller,
+          &gEfiCallerIdGuid,
+          IdeBusDriverPrivateData,
+          NULL
+          );
+
+    if (IdeBusDriverPrivateData != NULL) {
+      gBS->FreePool (IdeBusDriverPrivateData);
+    }
+    //
+    // Close the bus driver
+    //
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiIdeControllerInitProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+    gBS->CloseProtocol (
+          Controller,
+          &gEfiDevicePathProtocolGuid,
+          This->DriverBindingHandle,
+          Controller
+          );
+
+    return EFI_SUCCESS;
+  }
+
+  AllChildrenStopped = TRUE;
+
+  for (Index = 0; Index < NumberOfChildren; Index++) {
+
+    Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
+
+    if (EFI_ERROR (Status)) {
+      AllChildrenStopped = FALSE;
+    }
+  }
+
+  if (!AllChildrenStopped) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  issue ATA or ATAPI command to reset a block IO device.
+  @param  This                  Block IO protocol instance pointer.
+  @param  ExtendedVerification  If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
+                                If TRUE, for ATAPI device, driver need invoke ATA reset method after
+                                invoke ATAPI reset method
+
+  @retval EFI_DEVICE_ERROR      When the device is neighther ATA device or ATAPI device.
+  @retval EFI_SUCCESS           The device reset successfully
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,
+  IN  BOOLEAN                 ExtendedVerification
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+  EFI_STATUS      Status;
+  EFI_TPL         OldTpl;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+  //
+  // Requery IDE IO resources in case of the switch of native and legacy modes
+  //
+  ReassignIdeResources (IdeBlkIoDevice);
+
+  //
+  // for ATA device, using ATA reset method
+  //
+  if (IdeBlkIoDevice->Type == IdeHardDisk ||
+      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+    Status = AtaSoftReset (IdeBlkIoDevice);
+    goto Done;
+  }
+
+  if (IdeBlkIoDevice->Type == IdeUnknown) {
+    Status = EFI_DEVICE_ERROR;
+    goto Done;
+  }
+
+  //
+  // for ATAPI device, using ATAPI reset method
+  //
+  Status = AtapiSoftReset (IdeBlkIoDevice);
+  if (ExtendedVerification) {
+    Status = AtaSoftReset (IdeBlkIoDevice);
+  }
+
+Done:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Read data from a block IO device
+
+  @param  This       Block IO protocol instance pointer.
+  @param  MediaId    The media ID of the device
   @param  Lba        Starting LBA address to read data\r
-  @param  BufferSize The size of data to be read\r
-  @param  Buffer     Caller supplied buffer to save data\r
-\r
-  @retval EFI_DEVICE_ERROR  unknown device type\r
-  @retval other             read data status.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBlkIoReadBlocks (\r
-  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
-  IN  UINT32                  MediaId,\r
+  @param  BufferSize The size of data to be read
+  @param  Buffer     Caller supplied buffer to save data
+
+  @retval EFI_DEVICE_ERROR  unknown device type
+  @retval other             read data status.
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,
+  IN  UINT32                  MediaId,
   IN  EFI_LBA                 Lba,\r
-  IN  UINTN                   BufferSize,\r
-  OUT VOID                    *Buffer\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-  EFI_STATUS      Status;\r
-  EFI_TPL         OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
-\r
-  //\r
-  // Requery IDE IO resources in case of the switch of native and legacy modes\r
-  //\r
-  ReassignIdeResources (IdeBlkIoDevice);\r
-\r
-  //\r
-  // For ATA compatible device, use ATA read block's mechanism\r
-  //\r
-  if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
-      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
-    Status = AtaBlkIoReadBlocks (\r
-            IdeBlkIoDevice,\r
-            MediaId,\r
+  IN  UINTN                   BufferSize,
+  OUT VOID                    *Buffer
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+  EFI_STATUS      Status;
+  EFI_TPL         OldTpl;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+
+  //
+  // Requery IDE IO resources in case of the switch of native and legacy modes
+  //
+  ReassignIdeResources (IdeBlkIoDevice);
+
+  //
+  // For ATA compatible device, use ATA read block's mechanism
+  //
+  if (IdeBlkIoDevice->Type == IdeHardDisk ||
+      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+    Status = AtaBlkIoReadBlocks (
+            IdeBlkIoDevice,
+            MediaId,
             Lba,\r
-            BufferSize,\r
-            Buffer\r
-            );\r
-    goto Done;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->Type == IdeUnknown) {\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // for ATAPI device, using ATAPI read block's mechanism\r
-  //\r
-  Status = AtapiBlkIoReadBlocks (\r
-          IdeBlkIoDevice,\r
-          MediaId,\r
+            BufferSize,
+            Buffer
+            );
+    goto Done;
+  }
+
+  if (IdeBlkIoDevice->Type == IdeUnknown) {
+    Status = EFI_DEVICE_ERROR;
+    goto Done;
+  }
+
+  //
+  // for ATAPI device, using ATAPI read block's mechanism
+  //
+  Status = AtapiBlkIoReadBlocks (
+          IdeBlkIoDevice,
+          MediaId,
           Lba,\r
-          BufferSize,\r
-          Buffer\r
-          );\r
-\r
-Done:\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
+          BufferSize,
+          Buffer
+          );
+
+Done:
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+}
+
+/**
   Write data to block io device.\r
-\r
-  @param  This       Protocol instance pointer.\r
-  @param  MediaId    The media ID of the device\r
+
+  @param  This       Protocol instance pointer.
+  @param  MediaId    The media ID of the device
   @param  Lba        Starting LBA address to write data\r
-  @param  BufferSize The size of data to be written\r
-  @param  Buffer     Caller supplied buffer to save data\r
-\r
-  @retval EFI_DEVICE_ERROR  unknown device type\r
-  @retval other             write data status\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBlkIoWriteBlocks (\r
-  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
-  IN  UINT32                  MediaId,\r
+  @param  BufferSize The size of data to be written
+  @param  Buffer     Caller supplied buffer to save data
+
+  @retval EFI_DEVICE_ERROR  unknown device type
+  @retval other             write data status
+
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,
+  IN  UINT32                  MediaId,
   IN  EFI_LBA                 Lba,\r
-  IN  UINTN                   BufferSize,\r
-  IN  VOID                    *Buffer\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-  EFI_STATUS      Status;\r
-  EFI_TPL         OldTpl;\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);\r
-  //\r
-  // Requery IDE IO resources in case of the switch of native and legacy modes\r
-  //\r
-  ReassignIdeResources (IdeBlkIoDevice);\r
-\r
-  //\r
-  // for ATA device, using ATA write block's mechanism\r
-  //\r
-  if (IdeBlkIoDevice->Type == IdeHardDisk ||\r
-      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {\r
-\r
-    Status = AtaBlkIoWriteBlocks (\r
-            IdeBlkIoDevice,\r
-            MediaId,\r
+  IN  UINTN                   BufferSize,
+  IN  VOID                    *Buffer
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+  EFI_STATUS      Status;
+  EFI_TPL         OldTpl;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+  //
+  // Requery IDE IO resources in case of the switch of native and legacy modes
+  //
+  ReassignIdeResources (IdeBlkIoDevice);
+
+  //
+  // for ATA device, using ATA write block's mechanism
+  //
+  if (IdeBlkIoDevice->Type == IdeHardDisk ||
+      IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+
+    Status = AtaBlkIoWriteBlocks (
+            IdeBlkIoDevice,
+            MediaId,
             Lba,\r
-            BufferSize,\r
-            Buffer\r
-            );\r
-    goto Done;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->Type == IdeUnknown) {\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Done;\r
-  }\r
-\r
-  //\r
-  // for ATAPI device, using ATAPI write block's mechanism\r
-  //\r
-  Status = AtapiBlkIoWriteBlocks (\r
-          IdeBlkIoDevice,\r
-          MediaId,\r
+            BufferSize,
+            Buffer
+            );
+    goto Done;
+  }
+
+  if (IdeBlkIoDevice->Type == IdeUnknown) {
+    Status = EFI_DEVICE_ERROR;
+    goto Done;
+  }
+
+  //
+  // for ATAPI device, using ATAPI write block's mechanism
+  //
+  Status = AtapiBlkIoWriteBlocks (
+          IdeBlkIoDevice,
+          MediaId,
           Lba,\r
-          BufferSize,\r
-          Buffer\r
-          );\r
-\r
-Done:\r
-  gBS->RestoreTPL (OldTpl);\r
-  return Status;\r
-}\r
-/**\r
-  Flushes all modified data to a physical block devices\r
-\r
-  @param  This  Indicates a pointer to the calling context which to sepcify a \r
-                sepcific block device\r
-\r
-  @retval EFI_SUCCESS   Always return success.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEBlkIoFlushBlocks (\r
-  IN  EFI_BLOCK_IO_PROTOCOL   *This\r
-  )\r
-{\r
-  //\r
-  // return directly\r
-  //\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
+          BufferSize,
+          Buffer
+          );
+
+Done:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+/**
+  Flushes all modified data to a physical block devices
+
+  @param  This  Indicates a pointer to the calling context which to sepcify a
+                sepcific block device
+
+  @retval EFI_SUCCESS   Always return success.
+**/
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+  IN  EFI_BLOCK_IO_PROTOCOL   *This
+  )
+{
+  //
+  // return directly
+  //
+  return EFI_SUCCESS;
+}
+
+/**
   This function is used by the IDE bus driver to get inquiry data. \r
   Data format of Identify data is defined by the Interface GUID.\r
-\r
+
   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
   @param  InquiryData           Pointer to a buffer for the inquiry data.\r
   @param  InquiryDataSize       Pointer to the value for the inquiry data size.\r
-\r
+
   @retval EFI_SUCCESS           The command was accepted without any errors.\r
   @retval EFI_NOT_FOUND         Device does not support this data class \r
   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device \r
   @retval EFI_BUFFER_TOO_SMALL  IntquiryDataSize not big enough \r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEDiskInfoInquiry (\r
-  IN     EFI_DISK_INFO_PROTOCOL   *This,\r
-  IN OUT VOID                     *InquiryData,\r
-  IN OUT UINT32                   *InquiryDataSize\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
-\r
-  if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {\r
-    *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->InquiryData == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));\r
-  *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+  IN     EFI_DISK_INFO_PROTOCOL   *This,
+  IN OUT VOID                     *InquiryData,
+  IN OUT UINT32                   *InquiryDataSize
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+  if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {
+    *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (IdeBlkIoDevice->InquiryData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));
+  *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
+
+  return EFI_SUCCESS;
+}
+
+/**
   This function is used by the IDE bus driver to get identify data. \r
-  Data format of Identify data is defined by the Interface GUID.\r
-\r
+  Data format of Identify data is defined by the Interface GUID.
+
   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.\r
   @param  IdentifyData          Pointer to a buffer for the identify data.\r
   @param  IdentifyDataSize      Pointer to the value for the identify data size.\r
-\r
+
   @retval EFI_SUCCESS           The command was accepted without any errors.\r
   @retval EFI_NOT_FOUND         Device does not support this data class \r
   @retval EFI_DEVICE_ERROR      Error reading IdentifyData from device \r
   @retval EFI_BUFFER_TOO_SMALL  IdentifyDataSize not big enough \r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEDiskInfoIdentify (\r
-  IN     EFI_DISK_INFO_PROTOCOL   *This,\r
-  IN OUT VOID                     *IdentifyData,\r
-  IN OUT UINT32                   *IdentifyDataSize\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-\r
-  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
-\r
-  if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {\r
-    *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
-\r
-  if (IdeBlkIoDevice->IdData == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));\r
-  *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+  IN     EFI_DISK_INFO_PROTOCOL   *This,
+  IN OUT VOID                     *IdentifyData,
+  IN OUT UINT32                   *IdentifyDataSize
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+
+  IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+  if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
+    *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (IdeBlkIoDevice->IdData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));
+  *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+
+  return EFI_SUCCESS;
+}
+
+/**
   This function is used by the IDE bus driver to get sense data. \r
-  Data format of Sense data is defined by the Interface GUID.\r
-\r
+  Data format of Sense data is defined by the Interface GUID.
+
   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance. \r
   @param  SenseData             Pointer to the SenseData. \r
   @param  SenseDataSize         Size of SenseData in bytes. \r
   @param  SenseDataNumber       Pointer to the value for the identify data size.\r
-\r
+
   @retval EFI_SUCCESS           The command was accepted without any errors.\r
   @retval EFI_NOT_FOUND         Device does not support this data class \r
   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device \r
   @retval EFI_BUFFER_TOO_SMALL  SenseDataSize not big enough \r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEDiskInfoSenseData (\r
-  IN     EFI_DISK_INFO_PROTOCOL   *This,\r
-  IN OUT VOID                     *SenseData,\r
-  IN OUT UINT32                   *SenseDataSize,\r
-  OUT    UINT8                    *SenseDataNumber\r
-  )\r
-{\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+  IN     EFI_DISK_INFO_PROTOCOL   *This,
+  IN OUT VOID                     *SenseData,
+  IN OUT UINT32                   *SenseDataSize,
+  OUT    UINT8                    *SenseDataNumber
+  )
+{
+  return EFI_NOT_FOUND;
+}
+
+/**
   This function is used by the IDE bus driver to get controller information.\r
-\r
+
   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance. \r
   @param  IdeChannel            Pointer to the Ide Channel number. Primary or secondary.\r
   @param  IdeDevice             Pointer to the Ide Device number. Master or slave.\r
-\r
+
   @retval EFI_SUCCESS           IdeChannel and IdeDevice are valid \r
   @retval EFI_UNSUPPORTED       This is not an IDE device \r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IDEDiskInfoWhichIde (\r
-  IN  EFI_DISK_INFO_PROTOCOL   *This,\r
-  OUT UINT32                   *IdeChannel,\r
-  OUT UINT32                   *IdeDevice\r
-  )\r
-{\r
-  IDE_BLK_IO_DEV  *IdeBlkIoDevice;\r
-\r
-  IdeBlkIoDevice  = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);\r
-  *IdeChannel     = IdeBlkIoDevice->Channel;\r
-  *IdeDevice      = IdeBlkIoDevice->Device;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The is an event(generally the event is exitBootService event) call back function. \r
-  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.\r
-\r
-  @param  Event   Pointer to this event\r
-  @param  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
-\r
-/**\r
-  The user Entry Point for module IdeBus. The user code starts with this function.\r
-\r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
-  @retval EFI_SUCCESS       The entry point is executed successfully.\r
-  @retval other             Some error occurs when executing this entry point.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeIdeBus(\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-\r
-  //\r
-  // Install driver model protocol(s).\r
-  //\r
-  Status = EfiLibInstallAllDriverProtocols2 (\r
-             ImageHandle,\r
-             SystemTable,\r
-             &gIDEBusDriverBinding,\r
-             ImageHandle,\r
-             &gIDEBusComponentName,\r
-             &gIDEBusComponentName2,\r
-             NULL,\r
-             NULL,\r
-             &gIDEBusDriverDiagnostics,\r
-             &gIDEBusDriverDiagnostics2\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return Status;\r
-}\r
+
+**/
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+  IN  EFI_DISK_INFO_PROTOCOL   *This,
+  OUT UINT32                   *IdeChannel,
+  OUT UINT32                   *IdeDevice
+  )
+{
+  IDE_BLK_IO_DEV  *IdeBlkIoDevice;
+
+  IdeBlkIoDevice  = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+  *IdeChannel     = IdeBlkIoDevice->Channel;
+  *IdeDevice      = IdeBlkIoDevice->Device;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The is an event(generally the event is exitBootService event) call back function.
+  Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
+
+  @param  Event   Pointer to this event
+  @param  Context Event hanlder private data
+
+**/
+VOID
+EFIAPI
+ClearInterrupt (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS      Status;
+  UINT64          IoPortForBmis;
+  UINT8           RegisterValue;
+  IDE_BLK_IO_DEV  *IdeDev;
+
+  //
+  // Get our context
+  //
+  IdeDev = (IDE_BLK_IO_DEV *) Context;
+
+  //
+  // Obtain IDE IO port registers' base addresses
+  //
+  Status = ReassignIdeResources (IdeDev);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Check whether interrupt is pending
+  //
+
+  //
+  // Reset IDE device to force it de-assert interrupt pin
+  // Note: this will reset all devices on this IDE channel
+  //
+  AtaSoftReset (IdeDev);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  //
+  // Get base address of IDE Bus Master Status Regsiter
+  //
+  if (IdePrimary == IdeDev->Channel) {
+    IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+  } else {
+    if (IdeSecondary == IdeDev->Channel) {
+      IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+    } else {
+      return;
+    }
+  }
+  //
+  // Read BMIS register and clear ERROR and INTR bit
+  //
+  IdeDev->PciIo->Io.Read (
+                      IdeDev->PciIo,
+                      EfiPciIoWidthUint8,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      IoPortForBmis,
+                      1,
+                      &RegisterValue
+                      );
+
+  RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+  IdeDev->PciIo->Io.Write (
+                      IdeDev->PciIo,
+                      EfiPciIoWidthUint8,
+                      EFI_PCI_IO_PASS_THROUGH_BAR,
+                      IoPortForBmis,
+                      1,
+                      &RegisterValue
+                      );
+
+  //
+  // Select the other device on this channel to ensure this device to release the interrupt pin
+  //
+  if (IdeDev->Device == 0) {
+    RegisterValue = (1 << 4) | 0xe0;
+  } else {
+    RegisterValue = (0 << 4) | 0xe0;
+  }
+  IDEWritePortB (
+    IdeDev->PciIo,
+    IdeDev->IoPort->Head,
+    RegisterValue
+    );
+
+}
+
+/**
+  The user Entry Point for module IdeBus. The user code starts with this function.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIdeBus(
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+
+  //
+  // Install driver model protocol(s).
+  //
+  Status = EfiLibInstallAllDriverProtocols2 (
+             ImageHandle,
+             SystemTable,
+             &gIDEBusDriverBinding,
+             ImageHandle,
+             &gIDEBusComponentName,
+             &gIDEBusComponentName2,
+             NULL,
+             NULL,
+             &gIDEBusDriverDiagnostics,
+             &gIDEBusDriverDiagnostics2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}