]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBus.c
Make end of line consistent.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / IdeBusDxe / IdeBus.c
index 629eadec52062ac61ca7a6c145629b3332c9420e..3c7159502de335ea403f9af36db9ce15c274dc87 100644 (file)
-/** @file
+/** @file\r
   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.
+  driver stop.\r
     \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
+  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 (NULL, "DiscoverIdeDevice", "IDE", 0);\r
+      Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);\r
+      PERF_END (NULL, "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 (NULL, "Finish IDE detection", "IDE", 1);\r
+  PERF_END (NULL, "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
   @param  Lba        Starting LBA address to read data\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,
+  @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
   IN  EFI_LBA                 Lba,\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,
+  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
             Lba,\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,
+            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
           Lba,\r
-          BufferSize,
-          Buffer
-          );
-
-Done:
-  gBS->RestoreTPL (OldTpl);
-
-  return Status;
-}
-
-/**
+          BufferSize,\r
+          Buffer\r
+          );\r
+\r
+Done:\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
   Write data to block io device.\r
-
-  @param  This       Protocol instance pointer.
-  @param  MediaId    The media ID of the device
+\r
+  @param  This       Protocol instance pointer.\r
+  @param  MediaId    The media ID of the device\r
   @param  Lba        Starting LBA address to write data\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,
+  @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
   IN  EFI_LBA                 Lba,\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,
+  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
             Lba,\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,
+            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
           Lba,\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;
-}
-
-/**
+          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
   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
-
-**/
-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;
-}
-
-/**
+\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
   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.
-
+  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  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
-
-**/
-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;
-}
-
-/**
+\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
   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.
-
+  Data format of Sense data is defined by the Interface GUID.\r
+\r
   @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
-
-**/
-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;
-}
-
-/**
+\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
   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
-
-**/
-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;
-}
+\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