Home | History | Annotate | Download | only in IdeBusDxe
      1 /** @file
      2   This file implement UEFI driver for IDE Bus which includes device identification,
      3   Child device(Disk, CDROM, etc) enumeration and child handler installation, and
      4   driver stop.
      5 
      6   Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15   @par Revision Reference:
     16   This module is modified from DXE\IDE module for Ide Contriller Init support
     17 
     18 **/
     19 
     20 #include "IdeBus.h"
     21 
     22 #define PCI_CLASS_MASS_STORAGE  0x01
     23 #define PCI_SUB_CLASS_IDE       0x01
     24 
     25 
     26 //
     27 // IDE Bus Driver Binding Protocol Instance
     28 //
     29 EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
     30   IDEBusDriverBindingSupported,
     31   IDEBusDriverBindingStart,
     32   IDEBusDriverBindingStop,
     33   0xa,
     34   NULL,
     35   NULL
     36 };
     37 /**
     38   Deregister an IDE device and free resources
     39 
     40   @param  This Protocol instance pointer.
     41   @param  Controller Ide device handle
     42   @param  Handle Handle of device to deregister driver on
     43 
     44   @retval EFI_SUCCESS  Deregiter a specific IDE device successfully
     45 
     46 
     47 **/
     48 EFI_STATUS
     49 DeRegisterIdeDevice (
     50   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
     51   IN  EFI_HANDLE                     Controller,
     52   IN  EFI_HANDLE                     Handle
     53   )
     54 {
     55   EFI_STATUS            Status;
     56   EFI_BLOCK_IO_PROTOCOL *BlkIo;
     57   IDE_BLK_IO_DEV        *IdeBlkIoDevice;
     58   EFI_PCI_IO_PROTOCOL   *PciIo;
     59   UINTN                 Index;
     60 
     61   Status = gBS->OpenProtocol (
     62                   Handle,
     63                   &gEfiBlockIoProtocolGuid,
     64                   (VOID **) &BlkIo,
     65                   This->DriverBindingHandle,
     66                   Controller,
     67                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
     68                   );
     69   if (EFI_ERROR (Status)) {
     70     return Status;
     71   }
     72 
     73   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
     74 
     75   //
     76   // Report Status code: Device disabled
     77   //
     78   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
     79     EFI_PROGRESS_CODE,
     80     (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
     81     IdeBlkIoDevice->DevicePath
     82     );
     83 
     84   //
     85   // Close the child handle
     86   //
     87   Status = gBS->CloseProtocol (
     88                   Controller,
     89                   &gEfiPciIoProtocolGuid,
     90                   This->DriverBindingHandle,
     91                   Handle
     92                   );
     93 
     94   Status = gBS->UninstallMultipleProtocolInterfaces (
     95                   Handle,
     96                   &gEfiDevicePathProtocolGuid,
     97                   IdeBlkIoDevice->DevicePath,
     98                   &gEfiBlockIoProtocolGuid,
     99                   &IdeBlkIoDevice->BlkIo,
    100                   &gEfiDiskInfoProtocolGuid,
    101                   &IdeBlkIoDevice->DiskInfo,
    102                   NULL
    103                   );
    104 
    105   if (EFI_ERROR (Status)) {
    106     gBS->OpenProtocol (
    107           Controller,
    108           &gEfiPciIoProtocolGuid,
    109           (VOID **) &PciIo,
    110           This->DriverBindingHandle,
    111           Handle,
    112           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    113           );
    114     return Status;
    115   }
    116 
    117   //
    118   // Release allocated resources
    119   //
    120   Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
    121   if (Index < MAX_IDE_DEVICE) {
    122     IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
    123   }
    124   ReleaseIdeResources (IdeBlkIoDevice);
    125 
    126   return EFI_SUCCESS;
    127 }
    128 /**
    129   Supported function of Driver Binding protocol for this driver.
    130 
    131   @param This                A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    132   @param ControllerHandle    The handle of the controller to test.
    133   @param RemainingDevicePath A pointer to the remaining portion of a device path.
    134 
    135   @retval  EFI_SUCCESS Driver loaded.
    136   @retval  other       Driver not loaded.
    137 
    138 **/
    139 EFI_STATUS
    140 EFIAPI
    141 IDEBusDriverBindingSupported (
    142   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    143   IN EFI_HANDLE                   Controller,
    144   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    145   )
    146 {
    147   EFI_STATUS                        Status;
    148   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
    149   EFI_DEV_PATH                      *Node;
    150   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
    151   EFI_PCI_IO_PROTOCOL               *PciIo;
    152   PCI_TYPE00                        PciData;
    153 
    154   if (RemainingDevicePath != NULL) {
    155     Node = (EFI_DEV_PATH *) RemainingDevicePath;
    156     //
    157     // Check if RemainingDevicePath is the End of Device Path Node,
    158     // if yes, go on checking other conditions
    159     //
    160     if (!IsDevicePathEnd (Node)) {
    161       //
    162       // If RemainingDevicePath isn't the End of Device Path Node,
    163       // check its validation
    164       //
    165       if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
    166           Node->DevPath.SubType != MSG_ATAPI_DP ||
    167           DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
    168         return EFI_UNSUPPORTED;
    169       }
    170     }
    171   }
    172 
    173   //
    174   // Verify the Ide Controller Init Protocol, which installed by the
    175   // IdeController module.
    176   //
    177   Status = gBS->OpenProtocol (
    178                   Controller,
    179                   &gEfiIdeControllerInitProtocolGuid,
    180                   (VOID **) &IdeInit,
    181                   This->DriverBindingHandle,
    182                   Controller,
    183                   EFI_OPEN_PROTOCOL_BY_DRIVER
    184                   );
    185 
    186   if (Status == EFI_ALREADY_STARTED) {
    187     return EFI_SUCCESS;
    188   }
    189 
    190   if (EFI_ERROR (Status)) {
    191     return Status;
    192   }
    193 
    194   //
    195   // Close the I/O Abstraction(s) used to perform the supported test
    196   //
    197   gBS->CloseProtocol (
    198         Controller,
    199         &gEfiIdeControllerInitProtocolGuid,
    200         This->DriverBindingHandle,
    201         Controller
    202         );
    203 
    204   //
    205   // Open the EFI Device Path protocol needed to perform the supported test
    206   //
    207   Status = gBS->OpenProtocol (
    208                   Controller,
    209                   &gEfiDevicePathProtocolGuid,
    210                   (VOID **) &ParentDevicePath,
    211                   This->DriverBindingHandle,
    212                   Controller,
    213                   EFI_OPEN_PROTOCOL_BY_DRIVER
    214                   );
    215   if (Status == EFI_ALREADY_STARTED) {
    216     return EFI_SUCCESS;
    217   }
    218 
    219   //
    220   // Close protocol, don't use device path protocol in the Support() function
    221   //
    222   gBS->CloseProtocol (
    223         Controller,
    224         &gEfiDevicePathProtocolGuid,
    225         This->DriverBindingHandle,
    226         Controller
    227         );
    228 
    229   //
    230   // Get the EfiPciIoProtocol
    231   //
    232   Status = gBS->OpenProtocol (
    233                   Controller,
    234                   &gEfiPciIoProtocolGuid,
    235                   (VOID **) &PciIo,
    236                   This->DriverBindingHandle,
    237                   Controller,
    238                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    239                   );
    240 
    241   if (EFI_ERROR (Status)) {
    242     return Status;
    243   }
    244 
    245   //
    246   // Now further check the PCI header: Base class (offset 0x0B) and
    247   // Sub Class (offset 0x0A). This controller should be an IDE controller
    248   //
    249   Status = PciIo->Pci.Read (
    250                         PciIo,
    251                         EfiPciIoWidthUint8,
    252                         0,
    253                         sizeof (PciData),
    254                         &PciData
    255                         );
    256 
    257   if (!EFI_ERROR (Status)) {
    258     //
    259     // Examine if it is IDE mode by class code
    260     //
    261     if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) || (PciData.Hdr.ClassCode[1] != PCI_SUB_CLASS_IDE)) {
    262       Status = EFI_UNSUPPORTED;
    263     } else {
    264       Status = EFI_SUCCESS;
    265     }
    266   }
    267 
    268   return Status;
    269 }
    270 
    271 
    272 /**
    273   Start function of Driver binding protocol which start this driver on Controller
    274   by detecting all disks and installing BlockIo protocol on them.
    275 
    276   @param  This                Protocol instance pointer.
    277   @param  Controller          Handle of device to bind driver to.
    278   @param  RemainingDevicePath produce all possible children.
    279 
    280   @retval  EFI_SUCCESS         This driver is added to ControllerHandle.
    281   @retval  EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
    282   @retval  other               This driver does not support this device.
    283 
    284 **/
    285 EFI_STATUS
    286 EFIAPI
    287 IDEBusDriverBindingStart (
    288   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    289   IN EFI_HANDLE                   Controller,
    290   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    291   )
    292 {
    293   EFI_STATUS                        Status;
    294   EFI_STATUS                        SavedStatus;
    295   EFI_PCI_IO_PROTOCOL               *PciIo;
    296   EFI_DEVICE_PATH_PROTOCOL          *ParentDevicePath;
    297   EFI_DEV_PATH                      *Node;
    298   UINT8                             IdeChannel;
    299   UINT8                             BeginningIdeChannel;
    300   UINT8                             EndIdeChannel;
    301   UINT8                             IdeDevice;
    302   UINT8                             BeginningIdeDevice;
    303   UINT8                             EndIdeDevice;
    304   IDE_BLK_IO_DEV                    *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
    305   IDE_BLK_IO_DEV                    *IdeBlkIoDevicePtr;
    306   IDE_REGISTERS_BASE_ADDR           IdeRegsBaseAddr[IdeMaxChannel];
    307   ATA_TRANSFER_MODE                 TransferMode;
    308   ATA_DRIVE_PARMS                   DriveParameters;
    309   EFI_DEV_PATH                      NewNode;
    310   UINT8                             ConfigurationOptions;
    311   UINT16                            CommandBlockBaseAddr;
    312   UINT16                            ControlBlockBaseAddr;
    313   UINTN                             DataSize;
    314   IDE_BUS_DRIVER_PRIVATE_DATA       *IdeBusDriverPrivateData;
    315   UINT64                            Supports;
    316 
    317   //
    318   // Local variables declaration for IdeControllerInit support
    319   //
    320   EFI_IDE_CONTROLLER_INIT_PROTOCOL  *IdeInit;
    321   BOOLEAN                           EnumAll;
    322   BOOLEAN                           ChannelEnabled;
    323   UINT8                             MaxDevices;
    324   EFI_IDENTIFY_DATA                 IdentifyData;
    325   EFI_ATA_COLLECTIVE_MODE           *SupportedModes;
    326 
    327   IdeBusDriverPrivateData = NULL;
    328   SupportedModes          = NULL;
    329 
    330   //
    331   // Perform IdeBus initialization
    332   //
    333   Status = gBS->OpenProtocol (
    334                   Controller,
    335                   &gEfiDevicePathProtocolGuid,
    336                   (VOID **) &ParentDevicePath,
    337                   This->DriverBindingHandle,
    338                   Controller,
    339                   EFI_OPEN_PROTOCOL_BY_DRIVER
    340                   );
    341   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    342     return Status;
    343   }
    344 
    345   //
    346   // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
    347   //
    348   Status = gBS->OpenProtocol (
    349                   Controller,
    350                   &gEfiIdeControllerInitProtocolGuid,
    351                   (VOID **) &IdeInit,
    352                   This->DriverBindingHandle,
    353                   Controller,
    354                   EFI_OPEN_PROTOCOL_BY_DRIVER
    355                   );
    356 
    357   //
    358   // The following OpenProtocol function with _GET_PROTOCOL attribute and
    359   // will not return EFI_ALREADY_STARTED, so save it for now
    360   //
    361   SavedStatus = Status;
    362 
    363   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    364     DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
    365     //
    366     // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
    367     //
    368     goto ErrorExit;
    369   }
    370 
    371   //
    372   // Save Enumall. Step7.2
    373   //
    374   EnumAll       = IdeInit->EnumAll;
    375 
    376   //
    377   // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
    378   // attribute will not return EFI_ALREADY_STARTED
    379   //
    380   Status = gBS->OpenProtocol (
    381                   Controller,
    382                   &gEfiPciIoProtocolGuid,
    383                   (VOID **) &PciIo,
    384                   This->DriverBindingHandle,
    385                   Controller,
    386                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    387                   );
    388   if (EFI_ERROR (Status)) {
    389     DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
    390     goto ErrorExit;
    391   }
    392 
    393   //
    394   // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
    395   //
    396   if (SavedStatus != EFI_ALREADY_STARTED) {
    397     IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
    398     if (IdeBusDriverPrivateData == NULL) {
    399       Status = EFI_OUT_OF_RESOURCES;
    400       goto ErrorExit;
    401     }
    402 
    403     ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
    404     Status = gBS->InstallMultipleProtocolInterfaces (
    405                     &Controller,
    406                     &gEfiCallerIdGuid,
    407                     IdeBusDriverPrivateData,
    408                     NULL
    409                     );
    410     if (EFI_ERROR (Status)) {
    411       goto ErrorExit;
    412     }
    413 
    414   } else {
    415     Status = gBS->OpenProtocol (
    416                     Controller,
    417                     &gEfiCallerIdGuid,
    418                     (VOID **) &IdeBusDriverPrivateData,
    419                     This->DriverBindingHandle,
    420                     Controller,
    421                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    422                     );
    423     if (EFI_ERROR (Status)) {
    424       IdeBusDriverPrivateData = NULL;
    425       goto ErrorExit;
    426     }
    427   }
    428 
    429   Status = PciIo->Attributes (
    430                     PciIo,
    431                     EfiPciIoAttributeOperationSupported,
    432                     0,
    433                     &Supports
    434                     );
    435   if (!EFI_ERROR (Status)) {
    436     Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
    437     Status = PciIo->Attributes (
    438                       PciIo,
    439                       EfiPciIoAttributeOperationEnable,
    440                       Supports,
    441                       NULL
    442                       );
    443   }
    444 
    445   if (EFI_ERROR (Status)) {
    446     goto ErrorExit;
    447   }
    448 
    449   //
    450   // Read the environment variable that contains the IDEBus Driver's
    451   // Config options that were set by the Driver Configuration Protocol
    452   //
    453   DataSize = sizeof (ConfigurationOptions);
    454   Status = gRT->GetVariable (
    455                   (CHAR16 *) L"Configuration",
    456                   &gEfiCallerIdGuid,
    457                   NULL,
    458                   &DataSize,
    459                   &ConfigurationOptions
    460                   );
    461   if (EFI_ERROR (Status)) {
    462     ConfigurationOptions = 0x0f;
    463   }
    464 
    465    if (EnumAll || RemainingDevicePath == NULL) {
    466     //
    467     // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL,
    468     // must enumerate all IDE devices anyway
    469     //
    470     BeginningIdeChannel = IdePrimary;
    471     EndIdeChannel       = IdeSecondary;
    472     BeginningIdeDevice  = IdeMaster;
    473     EndIdeDevice        = IdeSlave;
    474 
    475   } else if (!IsDevicePathEnd (RemainingDevicePath)) {
    476     //
    477     // If RemainingDevicePath isn't the End of Device Path Node,
    478     // only scan the specified device by RemainingDevicePath
    479     //
    480     Node                = (EFI_DEV_PATH *) RemainingDevicePath;
    481     BeginningIdeChannel = Node->Atapi.PrimarySecondary;
    482     EndIdeChannel       = BeginningIdeChannel;
    483     BeginningIdeDevice  = Node->Atapi.SlaveMaster;
    484     EndIdeDevice        = BeginningIdeDevice;
    485     if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) {
    486       Status = EFI_INVALID_PARAMETER;
    487       goto ErrorExit;
    488     }
    489     if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) {
    490       Status = EFI_INVALID_PARAMETER;
    491       goto ErrorExit;
    492     }
    493 
    494   } else {
    495     //
    496     // If RemainingDevicePath is the End of Device Path Node,
    497     // skip enumerate any device and return EFI_SUCESSS
    498     //
    499     BeginningIdeChannel = IdeMaxChannel;
    500     EndIdeChannel       = IdeMaxChannel - 1;
    501     BeginningIdeDevice  = IdeMaxDevice;
    502     EndIdeDevice        = IdeMaxDevice - 1;
    503   }
    504 
    505   //
    506   // Obtain IDE IO port registers' base addresses
    507   //
    508   Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
    509   if (EFI_ERROR (Status)) {
    510     goto ErrorExit;
    511   }
    512 
    513   //
    514   // Report status code: begin IdeBus initialization
    515   //
    516   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    517     EFI_PROGRESS_CODE,
    518     (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
    519     ParentDevicePath
    520     );
    521 
    522   //
    523   // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
    524   //
    525   for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
    526 
    527     IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
    528 
    529     //
    530     // now obtain channel information fron IdeControllerInit protocol. Step9
    531     //
    532     Status = IdeInit->GetChannelInfo (
    533                         IdeInit,
    534                         IdeChannel,
    535                         &ChannelEnabled,
    536                         &MaxDevices
    537                         );
    538     if (EFI_ERROR (Status)) {
    539       DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
    540       continue;
    541     }
    542 
    543     if (!ChannelEnabled) {
    544       continue;
    545     }
    546 
    547     EndIdeDevice = (UINT8) MIN ((MaxDevices - 1), EndIdeDevice);
    548     ASSERT (EndIdeDevice < IdeMaxDevice);
    549     //
    550     // Now inform the IDE Controller Init Module. Sept10
    551     //
    552     IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
    553 
    554     //
    555     // No reset channel function implemented. Sept11
    556     //
    557     IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
    558 
    559     //
    560     // Step13
    561     //
    562     IdeInit->NotifyPhase (
    563               IdeInit,
    564               EfiIdeBusBeforeDevicePresenceDetection,
    565               IdeChannel
    566               );
    567 
    568     //
    569     // Prepare to detect IDE device of this channel
    570     //
    571     InitializeIDEChannelData ();
    572 
    573     //
    574     // -- 1st inner loop --- Master/Slave ------------  Step14
    575     //
    576     for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
    577       //
    578       // Check whether the configuration options allow this device
    579       //
    580       if ((ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice))) == 0) {
    581         continue;
    582       }
    583 
    584       //
    585       // The device has been scanned in another Start(), No need to scan it again
    586       // for perf optimization.
    587       //
    588       if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
    589         continue;
    590       }
    591 
    592       //
    593       // create child handle for the detected device.
    594       //
    595       IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
    596       if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
    597         continue;
    598       }
    599 
    600       IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
    601 
    602       ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
    603 
    604       IdeBlkIoDevicePtr->Signature  = IDE_BLK_IO_DEV_SIGNATURE;
    605       IdeBlkIoDevicePtr->Channel    = (EFI_IDE_CHANNEL) IdeChannel;
    606       IdeBlkIoDevicePtr->Device     = (EFI_IDE_DEVICE) IdeDevice;
    607 
    608       //
    609       // initialize Block IO interface's Media pointer
    610       //
    611       IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
    612 
    613       //
    614       // Initialize IDE IO port addresses, including Command Block registers
    615       // and Control Block registers
    616       //
    617       IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
    618       if (IdeBlkIoDevicePtr->IoPort == NULL) {
    619         continue;
    620       }
    621 
    622       ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
    623       CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
    624       ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
    625 
    626       IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
    627       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
    628       IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
    629       IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
    630       IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
    631       IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
    632       IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
    633       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
    634 
    635       (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
    636       IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
    637 
    638       IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
    639 
    640       IdeBlkIoDevicePtr->PciIo = PciIo;
    641       IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
    642       IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
    643 
    644       //
    645       // Report Status code: is about to detect IDE drive
    646       //
    647       REPORT_STATUS_CODE_EX (
    648         EFI_PROGRESS_CODE,
    649         (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
    650         0,
    651         &gEfiCallerIdGuid,
    652         NULL,
    653         NULL,
    654         0
    655       );
    656 
    657       //
    658       // Discover device, now!
    659       //
    660       PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0);
    661       Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
    662       PERF_END (NULL, "DiscoverIdeDevice", "IDE", 0);
    663 
    664       IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]  = TRUE;
    665       IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]    = FALSE;
    666 
    667       if (!EFI_ERROR (Status)) {
    668         //
    669         // Set Device Path
    670         //
    671         ZeroMem (&NewNode, sizeof (NewNode));
    672         NewNode.DevPath.Type    = MESSAGING_DEVICE_PATH;
    673         NewNode.DevPath.SubType = MSG_ATAPI_DP;
    674         SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
    675 
    676         NewNode.Atapi.PrimarySecondary  = (UINT8) IdeBlkIoDevicePtr->Channel;
    677         NewNode.Atapi.SlaveMaster       = (UINT8) IdeBlkIoDevicePtr->Device;
    678         NewNode.Atapi.Lun               = IdeBlkIoDevicePtr->Lun;
    679         IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
    680                                           ParentDevicePath,
    681                                           &NewNode.DevPath
    682                                           );
    683         if (IdeBlkIoDevicePtr->DevicePath == NULL) {
    684           ReleaseIdeResources (IdeBlkIoDevicePtr);
    685           continue;
    686         }
    687 
    688         //
    689         // Submit identify data to IDE controller init driver
    690         //
    691         CopyMem (&IdentifyData, IdeBlkIoDevicePtr->IdData, sizeof (IdentifyData));
    692         IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
    693         IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
    694       } else {
    695         //
    696         // Device detection failed
    697         //
    698         IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
    699         IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
    700         ReleaseIdeResources (IdeBlkIoDevicePtr);
    701         IdeBlkIoDevicePtr = NULL;
    702       }
    703       //
    704       // end of 1st inner loop ---
    705       //
    706     }
    707     //
    708     // end of 1st outer loop =========
    709     //
    710   }
    711 
    712   //
    713   // = 2nd outer loop == Primary/Secondary =================
    714   //
    715   for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
    716 
    717     //
    718     // -- 2nd inner loop --- Master/Slave --------
    719     //
    720     for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
    721 
    722       ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE);
    723       if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
    724         continue;
    725       }
    726 
    727       if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
    728         continue;
    729       }
    730 
    731       Status = IdeInit->CalculateMode (
    732                           IdeInit,
    733                           IdeChannel,
    734                           IdeDevice,
    735                           &SupportedModes
    736                           );
    737       if (EFI_ERROR (Status)) {
    738         DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
    739         continue;
    740       }
    741 
    742       ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice);
    743       IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
    744 
    745       //
    746       // Set best supported PIO mode on this IDE device
    747       //
    748       if (SupportedModes->PioMode.Mode <= AtaPioMode2) {
    749         TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
    750       } else {
    751         TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
    752       }
    753 
    754       TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
    755 
    756       if (SupportedModes->ExtModeCount == 0){
    757         Status                  = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
    758 
    759         if (EFI_ERROR (Status)) {
    760           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
    761           ReleaseIdeResources (IdeBlkIoDevicePtr);
    762           IdeBlkIoDevicePtr = NULL;
    763           continue;
    764         }
    765       }
    766 
    767       //
    768       // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
    769       // be set together. Only one DMA mode can be set to a device. If setting
    770       // DMA mode operation fails, we can continue moving on because we only use
    771       // PIO mode at boot time. DMA modes are used by certain kind of OS booting
    772       //
    773       if (SupportedModes->UdmaMode.Valid) {
    774 
    775         TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
    776         TransferMode.ModeNumber   = (UINT8) (SupportedModes->UdmaMode.Mode);
    777         Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
    778 
    779         if (EFI_ERROR (Status)) {
    780           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
    781           ReleaseIdeResources (IdeBlkIoDevicePtr);
    782           IdeBlkIoDevicePtr = NULL;
    783           continue;
    784         }
    785         //
    786         // Record Udma Mode
    787         //
    788         IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE;
    789         IdeBlkIoDevicePtr->UdmaMode.Mode  = SupportedModes->UdmaMode.Mode;
    790         EnableInterrupt (IdeBlkIoDevicePtr);
    791       } else if (SupportedModes->MultiWordDmaMode.Valid) {
    792 
    793         TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
    794         TransferMode.ModeNumber   = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
    795         Status                    = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
    796 
    797         if (EFI_ERROR (Status)) {
    798           IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
    799           ReleaseIdeResources (IdeBlkIoDevicePtr);
    800           IdeBlkIoDevicePtr = NULL;
    801           continue;
    802         }
    803 
    804         EnableInterrupt (IdeBlkIoDevicePtr);
    805       }
    806       //
    807       // Init driver parameters
    808       //
    809       DriveParameters.Sector          = (UINT8) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track;
    810       DriveParameters.Heads           = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1);
    811       DriveParameters.MultipleSector  = (UINT8) IdeBlkIoDevicePtr->IdData->AtaData.multi_sector_cmd_max_sct_cnt;
    812       //
    813       // Set Parameters for the device:
    814       // 1) Init
    815       // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
    816       //
    817       if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
    818         Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
    819       }
    820 
    821       //
    822       // Record PIO mode used in private data
    823       //
    824       IdeBlkIoDevicePtr->PioMode = (ATA_PIO_MODE) SupportedModes->PioMode.Mode;
    825 
    826       //
    827       // Set IDE controller Timing Blocks in the PCI Configuration Space
    828       //
    829       IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
    830 
    831       //
    832       // Add Component Name for the IDE/ATAPI device that was discovered.
    833       //
    834       IdeBlkIoDevicePtr->ControllerNameTable = NULL;
    835       ADD_IDE_ATAPI_NAME (IdeBlkIoDevicePtr);
    836 
    837       Status = gBS->InstallMultipleProtocolInterfaces (
    838                       &IdeBlkIoDevicePtr->Handle,
    839                       &gEfiDevicePathProtocolGuid,
    840                       IdeBlkIoDevicePtr->DevicePath,
    841                       &gEfiBlockIoProtocolGuid,
    842                       &IdeBlkIoDevicePtr->BlkIo,
    843                       &gEfiDiskInfoProtocolGuid,
    844                       &IdeBlkIoDevicePtr->DiskInfo,
    845                       NULL
    846                       );
    847 
    848       if (EFI_ERROR (Status)) {
    849         ReleaseIdeResources (IdeBlkIoDevicePtr);
    850       }
    851 
    852       gBS->OpenProtocol (
    853             Controller,
    854             &gEfiPciIoProtocolGuid,
    855             (VOID **) &PciIo,
    856             This->DriverBindingHandle,
    857             IdeBlkIoDevicePtr->Handle,
    858             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    859             );
    860 
    861       IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
    862 
    863       //
    864       // Report status code: device eanbled!
    865       //
    866       REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    867         EFI_PROGRESS_CODE,
    868         (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
    869         IdeBlkIoDevicePtr->DevicePath
    870         );
    871 
    872       //
    873       // Create event to clear pending IDE interrupt
    874       //
    875       Status = gBS->CreateEventEx (
    876                       EVT_NOTIFY_SIGNAL,
    877                       TPL_NOTIFY,
    878                       ClearInterrupt,
    879                       IdeBlkIoDevicePtr,
    880                       &gEfiEventExitBootServicesGuid,
    881                       &IdeBlkIoDevicePtr->ExitBootServiceEvent
    882                       );
    883 
    884       //
    885       // end of 2nd inner loop ----
    886       //
    887     }
    888     //
    889     // end of 2nd outer loop ==========
    890     //
    891   }
    892 
    893   //
    894   // All configurations done! Notify IdeController to do post initialization
    895   // work such as saving IDE controller PCI settings for S3 resume
    896   //
    897   IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
    898 
    899   if (SupportedModes != NULL) {
    900     FreePool (SupportedModes);
    901   }
    902 
    903   PERF_START (NULL, "Finish IDE detection", "IDE", 1);
    904   PERF_END (NULL, "Finish IDE detection", "IDE", 0);
    905 
    906   return EFI_SUCCESS;
    907 
    908 ErrorExit:
    909 
    910   //
    911   // Report error code: controller error
    912   //
    913   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    914     EFI_ERROR_CODE | EFI_ERROR_MINOR,
    915     (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
    916     ParentDevicePath
    917     );
    918 
    919   gBS->CloseProtocol (
    920         Controller,
    921         &gEfiIdeControllerInitProtocolGuid,
    922         This->DriverBindingHandle,
    923         Controller
    924         );
    925 
    926   gBS->UninstallMultipleProtocolInterfaces (
    927         Controller,
    928         &gEfiCallerIdGuid,
    929         IdeBusDriverPrivateData,
    930         NULL
    931         );
    932 
    933   if (IdeBusDriverPrivateData != NULL) {
    934     gBS->FreePool (IdeBusDriverPrivateData);
    935   }
    936 
    937   if (SupportedModes != NULL) {
    938     gBS->FreePool (SupportedModes);
    939   }
    940 
    941   gBS->CloseProtocol (
    942         Controller,
    943         &gEfiPciIoProtocolGuid,
    944         This->DriverBindingHandle,
    945         Controller
    946         );
    947 
    948   gBS->CloseProtocol (
    949         Controller,
    950         &gEfiDevicePathProtocolGuid,
    951         This->DriverBindingHandle,
    952         Controller
    953         );
    954 
    955   return Status;
    956 
    957 }
    958 /**
    959   Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all
    960   child handle attached to the controller handle if there are.
    961 
    962   @param  This Protocol instance pointer.
    963   @param  Controller Handle of device to stop driver on
    964   @param  NumberOfChildren Not used
    965   @param  ChildHandleBuffer Not used
    966 
    967   @retval  EFI_SUCCESS This driver is removed DeviceHandle
    968   @retval  other This driver was not removed from this device
    969 
    970 **/
    971 EFI_STATUS
    972 EFIAPI
    973 IDEBusDriverBindingStop (
    974   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    975   IN  EFI_HANDLE                      Controller,
    976   IN  UINTN                           NumberOfChildren,
    977   IN  EFI_HANDLE                      *ChildHandleBuffer
    978   )
    979 {
    980   EFI_STATUS                  Status;
    981   EFI_PCI_IO_PROTOCOL         *PciIo;
    982   BOOLEAN                     AllChildrenStopped;
    983   UINTN                       Index;
    984   IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
    985   UINT64                      Supports;
    986 
    987   IdeBusDriverPrivateData = NULL;
    988 
    989   if (NumberOfChildren == 0) {
    990 
    991     Status = gBS->OpenProtocol (
    992                     Controller,
    993                     &gEfiPciIoProtocolGuid,
    994                     (VOID **) &PciIo,
    995                     This->DriverBindingHandle,
    996                     Controller,
    997                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    998                     );
    999     if (!EFI_ERROR (Status)) {
   1000       Status = PciIo->Attributes (
   1001                         PciIo,
   1002                         EfiPciIoAttributeOperationSupported,
   1003                         0,
   1004                         &Supports
   1005                         );
   1006       if (!EFI_ERROR (Status)) {
   1007         Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE);
   1008         PciIo->Attributes (
   1009                 PciIo,
   1010                 EfiPciIoAttributeOperationDisable,
   1011                 Supports,
   1012                 NULL
   1013                 );
   1014       }
   1015     }
   1016 
   1017     gBS->OpenProtocol (
   1018           Controller,
   1019           &gEfiCallerIdGuid,
   1020           (VOID **) &IdeBusDriverPrivateData,
   1021           This->DriverBindingHandle,
   1022           Controller,
   1023           EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1024           );
   1025 
   1026     gBS->UninstallMultipleProtocolInterfaces (
   1027           Controller,
   1028           &gEfiCallerIdGuid,
   1029           IdeBusDriverPrivateData,
   1030           NULL
   1031           );
   1032 
   1033     if (IdeBusDriverPrivateData != NULL) {
   1034       gBS->FreePool (IdeBusDriverPrivateData);
   1035     }
   1036     //
   1037     // Close the bus driver
   1038     //
   1039     gBS->CloseProtocol (
   1040           Controller,
   1041           &gEfiIdeControllerInitProtocolGuid,
   1042           This->DriverBindingHandle,
   1043           Controller
   1044           );
   1045     gBS->CloseProtocol (
   1046           Controller,
   1047           &gEfiPciIoProtocolGuid,
   1048           This->DriverBindingHandle,
   1049           Controller
   1050           );
   1051     gBS->CloseProtocol (
   1052           Controller,
   1053           &gEfiDevicePathProtocolGuid,
   1054           This->DriverBindingHandle,
   1055           Controller
   1056           );
   1057 
   1058     return EFI_SUCCESS;
   1059   }
   1060 
   1061   AllChildrenStopped = TRUE;
   1062 
   1063   for (Index = 0; Index < NumberOfChildren; Index++) {
   1064 
   1065     Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
   1066 
   1067     if (EFI_ERROR (Status)) {
   1068       AllChildrenStopped = FALSE;
   1069     }
   1070   }
   1071 
   1072   if (!AllChildrenStopped) {
   1073     return EFI_DEVICE_ERROR;
   1074   }
   1075 
   1076   return EFI_SUCCESS;
   1077 }
   1078 
   1079 /**
   1080   issue ATA or ATAPI command to reset a block IO device.
   1081   @param  This                  Block IO protocol instance pointer.
   1082   @param  ExtendedVerification  If FALSE,for ATAPI device, driver will only invoke ATAPI reset method
   1083                                 If TRUE, for ATAPI device, driver need invoke ATA reset method after
   1084                                 invoke ATAPI reset method
   1085 
   1086   @retval EFI_DEVICE_ERROR      When the device is neighther ATA device or ATAPI device.
   1087   @retval EFI_SUCCESS           The device reset successfully
   1088 
   1089 **/
   1090 EFI_STATUS
   1091 EFIAPI
   1092 IDEBlkIoReset (
   1093   IN  EFI_BLOCK_IO_PROTOCOL   *This,
   1094   IN  BOOLEAN                 ExtendedVerification
   1095   )
   1096 {
   1097   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1098   EFI_STATUS      Status;
   1099   EFI_TPL         OldTpl;
   1100 
   1101   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1102 
   1103   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
   1104   //
   1105   // Requery IDE IO resources in case of the switch of native and legacy modes
   1106   //
   1107   ReassignIdeResources (IdeBlkIoDevice);
   1108 
   1109   //
   1110   // for ATA device, using ATA reset method
   1111   //
   1112   if (IdeBlkIoDevice->Type == IdeHardDisk ||
   1113       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
   1114     Status = AtaSoftReset (IdeBlkIoDevice);
   1115     goto Done;
   1116   }
   1117 
   1118   if (IdeBlkIoDevice->Type == IdeUnknown) {
   1119     Status = EFI_DEVICE_ERROR;
   1120     goto Done;
   1121   }
   1122 
   1123   //
   1124   // for ATAPI device, using ATAPI reset method
   1125   //
   1126   Status = AtapiSoftReset (IdeBlkIoDevice);
   1127   if (ExtendedVerification) {
   1128     Status = AtaSoftReset (IdeBlkIoDevice);
   1129   }
   1130 
   1131 Done:
   1132   gBS->RestoreTPL (OldTpl);
   1133   return Status;
   1134 }
   1135 
   1136 /**
   1137   Read data from a block IO device
   1138 
   1139   @param  This       Block IO protocol instance pointer.
   1140   @param  MediaId    The media ID of the device
   1141   @param  Lba        Starting LBA address to read data
   1142   @param  BufferSize The size of data to be read
   1143   @param  Buffer     Caller supplied buffer to save data
   1144 
   1145   @retval EFI_DEVICE_ERROR  unknown device type
   1146   @retval other             read data status.
   1147 
   1148 **/
   1149 EFI_STATUS
   1150 EFIAPI
   1151 IDEBlkIoReadBlocks (
   1152   IN  EFI_BLOCK_IO_PROTOCOL   *This,
   1153   IN  UINT32                  MediaId,
   1154   IN  EFI_LBA                 Lba,
   1155   IN  UINTN                   BufferSize,
   1156   OUT VOID                    *Buffer
   1157   )
   1158 {
   1159   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1160   EFI_STATUS      Status;
   1161   EFI_TPL         OldTpl;
   1162 
   1163   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1164 
   1165   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
   1166 
   1167   //
   1168   // Requery IDE IO resources in case of the switch of native and legacy modes
   1169   //
   1170   ReassignIdeResources (IdeBlkIoDevice);
   1171 
   1172   //
   1173   // For ATA compatible device, use ATA read block's mechanism
   1174   //
   1175   if (IdeBlkIoDevice->Type == IdeHardDisk ||
   1176       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
   1177     Status = AtaBlkIoReadBlocks (
   1178             IdeBlkIoDevice,
   1179             MediaId,
   1180             Lba,
   1181             BufferSize,
   1182             Buffer
   1183             );
   1184     goto Done;
   1185   }
   1186 
   1187   if (IdeBlkIoDevice->Type == IdeUnknown) {
   1188     Status = EFI_DEVICE_ERROR;
   1189     goto Done;
   1190   }
   1191 
   1192   //
   1193   // for ATAPI device, using ATAPI read block's mechanism
   1194   //
   1195   Status = AtapiBlkIoReadBlocks (
   1196           IdeBlkIoDevice,
   1197           MediaId,
   1198           Lba,
   1199           BufferSize,
   1200           Buffer
   1201           );
   1202 
   1203 Done:
   1204   gBS->RestoreTPL (OldTpl);
   1205 
   1206   return Status;
   1207 }
   1208 
   1209 /**
   1210   Write data to block io device.
   1211 
   1212   @param  This       Protocol instance pointer.
   1213   @param  MediaId    The media ID of the device
   1214   @param  Lba        Starting LBA address to write data
   1215   @param  BufferSize The size of data to be written
   1216   @param  Buffer     Caller supplied buffer to save data
   1217 
   1218   @retval EFI_DEVICE_ERROR  unknown device type
   1219   @retval other             write data status
   1220 
   1221 **/
   1222 EFI_STATUS
   1223 EFIAPI
   1224 IDEBlkIoWriteBlocks (
   1225   IN  EFI_BLOCK_IO_PROTOCOL   *This,
   1226   IN  UINT32                  MediaId,
   1227   IN  EFI_LBA                 Lba,
   1228   IN  UINTN                   BufferSize,
   1229   IN  VOID                    *Buffer
   1230   )
   1231 {
   1232   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1233   EFI_STATUS      Status;
   1234   EFI_TPL         OldTpl;
   1235 
   1236   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1237 
   1238   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
   1239   //
   1240   // Requery IDE IO resources in case of the switch of native and legacy modes
   1241   //
   1242   ReassignIdeResources (IdeBlkIoDevice);
   1243 
   1244   //
   1245   // for ATA device, using ATA write block's mechanism
   1246   //
   1247   if (IdeBlkIoDevice->Type == IdeHardDisk ||
   1248       IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
   1249 
   1250     Status = AtaBlkIoWriteBlocks (
   1251             IdeBlkIoDevice,
   1252             MediaId,
   1253             Lba,
   1254             BufferSize,
   1255             Buffer
   1256             );
   1257     goto Done;
   1258   }
   1259 
   1260   if (IdeBlkIoDevice->Type == IdeUnknown) {
   1261     Status = EFI_DEVICE_ERROR;
   1262     goto Done;
   1263   }
   1264 
   1265   //
   1266   // for ATAPI device, using ATAPI write block's mechanism
   1267   //
   1268   Status = AtapiBlkIoWriteBlocks (
   1269           IdeBlkIoDevice,
   1270           MediaId,
   1271           Lba,
   1272           BufferSize,
   1273           Buffer
   1274           );
   1275 
   1276 Done:
   1277   gBS->RestoreTPL (OldTpl);
   1278   return Status;
   1279 }
   1280 /**
   1281   Flushes all modified data to a physical block devices
   1282 
   1283   @param  This  Indicates a pointer to the calling context which to sepcify a
   1284                 sepcific block device
   1285 
   1286   @retval EFI_SUCCESS   Always return success.
   1287 **/
   1288 EFI_STATUS
   1289 EFIAPI
   1290 IDEBlkIoFlushBlocks (
   1291   IN  EFI_BLOCK_IO_PROTOCOL   *This
   1292   )
   1293 {
   1294   //
   1295   // return directly
   1296   //
   1297   return EFI_SUCCESS;
   1298 }
   1299 
   1300 /**
   1301   This function is used by the IDE bus driver to get inquiry data.
   1302   Data format of Identify data is defined by the Interface GUID.
   1303 
   1304   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
   1305   @param  InquiryData           Pointer to a buffer for the inquiry data.
   1306   @param  InquiryDataSize       Pointer to the value for the inquiry data size.
   1307 
   1308   @retval EFI_SUCCESS           The command was accepted without any errors.
   1309   @retval EFI_NOT_FOUND         Device does not support this data class
   1310   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device
   1311   @retval EFI_BUFFER_TOO_SMALL  IntquiryDataSize not big enough
   1312 
   1313 **/
   1314 EFI_STATUS
   1315 EFIAPI
   1316 IDEDiskInfoInquiry (
   1317   IN     EFI_DISK_INFO_PROTOCOL   *This,
   1318   IN OUT VOID                     *InquiryData,
   1319   IN OUT UINT32                   *InquiryDataSize
   1320   )
   1321 {
   1322   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1323 
   1324   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
   1325 
   1326   if (*InquiryDataSize < sizeof (ATAPI_INQUIRY_DATA)) {
   1327     *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
   1328     return EFI_BUFFER_TOO_SMALL;
   1329   }
   1330 
   1331   if (IdeBlkIoDevice->InquiryData == NULL) {
   1332     return EFI_NOT_FOUND;
   1333   }
   1334 
   1335   gBS->CopyMem (InquiryData, IdeBlkIoDevice->InquiryData, sizeof (ATAPI_INQUIRY_DATA));
   1336   *InquiryDataSize = sizeof (ATAPI_INQUIRY_DATA);
   1337 
   1338   return EFI_SUCCESS;
   1339 }
   1340 
   1341 /**
   1342   This function is used by the IDE bus driver to get identify data.
   1343   Data format of Identify data is defined by the Interface GUID.
   1344 
   1345   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
   1346   @param  IdentifyData          Pointer to a buffer for the identify data.
   1347   @param  IdentifyDataSize      Pointer to the value for the identify data size.
   1348 
   1349   @retval EFI_SUCCESS           The command was accepted without any errors.
   1350   @retval EFI_NOT_FOUND         Device does not support this data class
   1351   @retval EFI_DEVICE_ERROR      Error reading IdentifyData from device
   1352   @retval EFI_BUFFER_TOO_SMALL  IdentifyDataSize not big enough
   1353 
   1354 **/
   1355 EFI_STATUS
   1356 EFIAPI
   1357 IDEDiskInfoIdentify (
   1358   IN     EFI_DISK_INFO_PROTOCOL   *This,
   1359   IN OUT VOID                     *IdentifyData,
   1360   IN OUT UINT32                   *IdentifyDataSize
   1361   )
   1362 {
   1363   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1364 
   1365   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
   1366 
   1367   if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
   1368     *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
   1369     return EFI_BUFFER_TOO_SMALL;
   1370   }
   1371 
   1372   if (IdeBlkIoDevice->IdData == NULL) {
   1373     return EFI_NOT_FOUND;
   1374   }
   1375 
   1376   gBS->CopyMem (IdentifyData, IdeBlkIoDevice->IdData, sizeof (EFI_IDENTIFY_DATA));
   1377   *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
   1378 
   1379   return EFI_SUCCESS;
   1380 }
   1381 
   1382 /**
   1383   This function is used by the IDE bus driver to get sense data.
   1384   Data format of Sense data is defined by the Interface GUID.
   1385 
   1386   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
   1387   @param  SenseData             Pointer to the SenseData.
   1388   @param  SenseDataSize         Size of SenseData in bytes.
   1389   @param  SenseDataNumber       Pointer to the value for the identify data size.
   1390 
   1391   @retval EFI_SUCCESS           The command was accepted without any errors.
   1392   @retval EFI_NOT_FOUND         Device does not support this data class
   1393   @retval EFI_DEVICE_ERROR      Error reading InquiryData from device
   1394   @retval EFI_BUFFER_TOO_SMALL  SenseDataSize not big enough
   1395 
   1396 **/
   1397 EFI_STATUS
   1398 EFIAPI
   1399 IDEDiskInfoSenseData (
   1400   IN     EFI_DISK_INFO_PROTOCOL   *This,
   1401   IN OUT VOID                     *SenseData,
   1402   IN OUT UINT32                   *SenseDataSize,
   1403   OUT    UINT8                    *SenseDataNumber
   1404   )
   1405 {
   1406   return EFI_NOT_FOUND;
   1407 }
   1408 
   1409 /**
   1410   This function is used by the IDE bus driver to get controller information.
   1411 
   1412   @param  This                  Pointer to the EFI_DISK_INFO_PROTOCOL instance.
   1413   @param  IdeChannel            Pointer to the Ide Channel number. Primary or secondary.
   1414   @param  IdeDevice             Pointer to the Ide Device number. Master or slave.
   1415 
   1416   @retval EFI_SUCCESS           IdeChannel and IdeDevice are valid
   1417   @retval EFI_UNSUPPORTED       This is not an IDE device
   1418 
   1419 **/
   1420 EFI_STATUS
   1421 EFIAPI
   1422 IDEDiskInfoWhichIde (
   1423   IN  EFI_DISK_INFO_PROTOCOL   *This,
   1424   OUT UINT32                   *IdeChannel,
   1425   OUT UINT32                   *IdeDevice
   1426   )
   1427 {
   1428   IDE_BLK_IO_DEV  *IdeBlkIoDevice;
   1429 
   1430   IdeBlkIoDevice  = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
   1431   *IdeChannel     = IdeBlkIoDevice->Channel;
   1432   *IdeDevice      = IdeBlkIoDevice->Device;
   1433 
   1434   return EFI_SUCCESS;
   1435 }
   1436 
   1437 /**
   1438   The is an event(generally the event is exitBootService event) call back function.
   1439   Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
   1440 
   1441   @param  Event   Pointer to this event
   1442   @param  Context Event handler private data
   1443 
   1444 **/
   1445 VOID
   1446 EFIAPI
   1447 ClearInterrupt (
   1448   IN EFI_EVENT  Event,
   1449   IN VOID       *Context
   1450   )
   1451 {
   1452   EFI_STATUS      Status;
   1453   UINT64          IoPortForBmis;
   1454   UINT8           RegisterValue;
   1455   IDE_BLK_IO_DEV  *IdeDev;
   1456 
   1457   //
   1458   // Get our context
   1459   //
   1460   IdeDev = (IDE_BLK_IO_DEV *) Context;
   1461 
   1462   //
   1463   // Obtain IDE IO port registers' base addresses
   1464   //
   1465   Status = ReassignIdeResources (IdeDev);
   1466   if (EFI_ERROR (Status)) {
   1467     return;
   1468   }
   1469 
   1470   //
   1471   // Check whether interrupt is pending
   1472   //
   1473 
   1474   //
   1475   // Reset IDE device to force it de-assert interrupt pin
   1476   // Note: this will reset all devices on this IDE channel
   1477   //
   1478   Status = AtaSoftReset (IdeDev);
   1479   if (EFI_ERROR (Status)) {
   1480     return;
   1481   }
   1482 
   1483   //
   1484   // Get base address of IDE Bus Master Status Regsiter
   1485   //
   1486   if (IdePrimary == IdeDev->Channel) {
   1487     IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
   1488   } else {
   1489     if (IdeSecondary == IdeDev->Channel) {
   1490       IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
   1491     } else {
   1492       return;
   1493     }
   1494   }
   1495   //
   1496   // Read BMIS register and clear ERROR and INTR bit
   1497   //
   1498   IdeDev->PciIo->Io.Read (
   1499                       IdeDev->PciIo,
   1500                       EfiPciIoWidthUint8,
   1501                       EFI_PCI_IO_PASS_THROUGH_BAR,
   1502                       IoPortForBmis,
   1503                       1,
   1504                       &RegisterValue
   1505                       );
   1506 
   1507   RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
   1508 
   1509   IdeDev->PciIo->Io.Write (
   1510                       IdeDev->PciIo,
   1511                       EfiPciIoWidthUint8,
   1512                       EFI_PCI_IO_PASS_THROUGH_BAR,
   1513                       IoPortForBmis,
   1514                       1,
   1515                       &RegisterValue
   1516                       );
   1517 
   1518   //
   1519   // Select the other device on this channel to ensure this device to release the interrupt pin
   1520   //
   1521   if (IdeDev->Device == 0) {
   1522     RegisterValue = (1 << 4) | 0xe0;
   1523   } else {
   1524     RegisterValue = (0 << 4) | 0xe0;
   1525   }
   1526   IDEWritePortB (
   1527     IdeDev->PciIo,
   1528     IdeDev->IoPort->Head,
   1529     RegisterValue
   1530     );
   1531 
   1532 }
   1533 
   1534 /**
   1535   The user Entry Point for module IdeBus. The user code starts with this function.
   1536 
   1537   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1538   @param[in] SystemTable    A pointer to the EFI System Table.
   1539 
   1540   @retval EFI_SUCCESS       The entry point is executed successfully.
   1541   @retval other             Some error occurs when executing this entry point.
   1542 
   1543 **/
   1544 EFI_STATUS
   1545 EFIAPI
   1546 InitializeIdeBus(
   1547   IN EFI_HANDLE           ImageHandle,
   1548   IN EFI_SYSTEM_TABLE     *SystemTable
   1549   )
   1550 {
   1551   EFI_STATUS              Status;
   1552 
   1553   //
   1554   // Install driver model protocol(s).
   1555   //
   1556   Status = EfiLibInstallAllDriverProtocols2 (
   1557              ImageHandle,
   1558              SystemTable,
   1559              &gIDEBusDriverBinding,
   1560              ImageHandle,
   1561              &gIDEBusComponentName,
   1562              &gIDEBusComponentName2,
   1563              NULL,
   1564              NULL,
   1565              &gIDEBusDriverDiagnostics,
   1566              &gIDEBusDriverDiagnostics2
   1567              );
   1568   ASSERT_EFI_ERROR (Status);
   1569 
   1570   return Status;
   1571 }
   1572