Home | History | Annotate | Download | only in IdeBusDxe
      1 /** @file
      2   The file ontaining the helper functions implement of the Ide Bus driver
      3 
      4   Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "IdeBus.h"
     16 
     17 BOOLEAN ChannelDeviceDetected = FALSE;
     18 BOOLEAN SlaveDeviceExist      = FALSE;
     19 UINT8   SlaveDeviceType       = INVALID_DEVICE_TYPE;
     20 BOOLEAN MasterDeviceExist     = FALSE;
     21 UINT8   MasterDeviceType      = INVALID_DEVICE_TYPE;
     22 
     23 /**
     24   read a one-byte data from a IDE port.
     25 
     26   @param  PciIo  The PCI IO protocol instance
     27   @param  Port   the IDE Port number
     28 
     29   @return  the one-byte data read from IDE port
     30 **/
     31 UINT8
     32 IDEReadPortB (
     33   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
     34   IN  UINT16                Port
     35   )
     36 {
     37   UINT8 Data;
     38 
     39   Data = 0;
     40   //
     41   // perform 1-byte data read from register
     42   //
     43   PciIo->Io.Read (
     44               PciIo,
     45               EfiPciIoWidthUint8,
     46               EFI_PCI_IO_PASS_THROUGH_BAR,
     47               (UINT64) Port,
     48               1,
     49               &Data
     50               );
     51   return Data;
     52 }
     53 /**
     54   Reads multiple words of data from the IDE data port.
     55   Call the IO abstraction once to do the complete read,
     56   not one word at a time
     57 
     58   @param  PciIo Pointer to the EFI_PCI_IO instance
     59   @param  Port IO port to read
     60   @param  Count No. of UINT16's to read
     61   @param  Buffer Pointer to the data buffer for read
     62 
     63 **/
     64 VOID
     65 IDEReadPortWMultiple (
     66   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
     67   IN  UINT16                Port,
     68   IN  UINTN                 Count,
     69   OUT VOID                  *Buffer
     70   )
     71 {
     72   UINT16  *AlignedBuffer;
     73   UINT16  *WorkingBuffer;
     74   UINTN   Size;
     75 
     76   //
     77   // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
     78   // not perform actual I/O operations if buffer pointer passed in is not at
     79   // natural boundary. The "Buffer" argument is passed in by user and may not
     80   // at 16-bit natural boundary.
     81   //
     82   Size = sizeof (UINT16) * Count;
     83 
     84   gBS->AllocatePool (
     85         EfiBootServicesData,
     86         Size + 1,
     87         (VOID**)&WorkingBuffer
     88         );
     89 
     90   AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
     91 
     92   //
     93   // Perform UINT16 data read from FIFO
     94   //
     95   PciIo->Io.Read (
     96               PciIo,
     97               EfiPciIoWidthFifoUint16,
     98               EFI_PCI_IO_PASS_THROUGH_BAR,
     99               (UINT64) Port,
    100               Count,
    101               (UINT16*)AlignedBuffer
    102               );
    103 
    104   //
    105   // Copy data to user buffer
    106   //
    107   CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
    108   gBS->FreePool (WorkingBuffer);
    109 }
    110 
    111 /**
    112   write a 1-byte data to a specific IDE port.
    113 
    114   @param  PciIo  PCI IO protocol instance
    115   @param  Port   The IDE port to be writen
    116   @param  Data   The data to write to the port
    117 **/
    118 VOID
    119 IDEWritePortB (
    120   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
    121   IN  UINT16                Port,
    122   IN  UINT8                 Data
    123   )
    124 {
    125   //
    126   // perform 1-byte data write to register
    127   //
    128   PciIo->Io.Write (
    129               PciIo,
    130               EfiPciIoWidthUint8,
    131               EFI_PCI_IO_PASS_THROUGH_BAR,
    132               (UINT64) Port,
    133               1,
    134               &Data
    135               );
    136 
    137 }
    138 
    139 /**
    140   write a 1-word data to a specific IDE port.
    141 
    142   @param  PciIo  PCI IO protocol instance
    143   @param  Port   The IDE port to be writen
    144   @param  Data   The data to write to the port
    145 **/
    146 VOID
    147 IDEWritePortW (
    148   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
    149   IN  UINT16                Port,
    150   IN  UINT16                Data
    151   )
    152 {
    153   //
    154   // perform 1-word data write to register
    155   //
    156   PciIo->Io.Write (
    157               PciIo,
    158               EfiPciIoWidthUint16,
    159               EFI_PCI_IO_PASS_THROUGH_BAR,
    160               (UINT64) Port,
    161               1,
    162               &Data
    163               );
    164 }
    165 
    166 /**
    167   Write multiple words of data to the IDE data port.
    168   Call the IO abstraction once to do the complete read,
    169   not one word at a time
    170 
    171   @param  PciIo Pointer to the EFI_PCI_IO instance
    172   @param  Port IO port to read
    173   @param  Count No. of UINT16's to read
    174   @param  Buffer Pointer to the data buffer for read
    175 
    176 **/
    177 VOID
    178 IDEWritePortWMultiple (
    179   IN  EFI_PCI_IO_PROTOCOL   *PciIo,
    180   IN  UINT16                Port,
    181   IN  UINTN                 Count,
    182   IN  VOID                  *Buffer
    183   )
    184 {
    185   UINT16  *AlignedBuffer;
    186   UINT32  *WorkingBuffer;
    187   UINTN   Size;
    188 
    189   //
    190   // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
    191   // not perform actual I/O operations if buffer pointer passed in is not at
    192   // natural boundary. The "Buffer" argument is passed in by user and may not
    193   // at 16-bit natural boundary.
    194   //
    195   Size = sizeof (UINT16) * Count;
    196 
    197   gBS->AllocatePool (
    198         EfiBootServicesData,
    199         Size + 1,
    200         (VOID **) &WorkingBuffer
    201         );
    202 
    203   AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
    204 
    205   //
    206   // Copy data from user buffer to working buffer
    207   //
    208   CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
    209 
    210   //
    211   // perform UINT16 data write to the FIFO
    212   //
    213   PciIo->Io.Write (
    214               PciIo,
    215               EfiPciIoWidthFifoUint16,
    216               EFI_PCI_IO_PASS_THROUGH_BAR,
    217               (UINT64) Port,
    218               Count,
    219               (UINT16 *) AlignedBuffer
    220               );
    221 
    222   gBS->FreePool (WorkingBuffer);
    223 }
    224 /**
    225   Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
    226   use fixed addresses. In Native-PCI mode, get base addresses from BARs in
    227   the PCI IDE controller's Configuration Space.
    228 
    229   The steps to get IDE IO port registers' base addresses for each channel
    230   as follows:
    231 
    232   1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
    233   controller's Configuration Space to determine the operating mode.
    234 
    235   2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
    236   <pre>
    237   ___________________________________________
    238   |           | Command Block | Control Block |
    239   |  Channel  |   Registers   |   Registers   |
    240   |___________|_______________|_______________|
    241   |  Primary  |  1F0h - 1F7h  |  3F6h - 3F7h  |
    242   |___________|_______________|_______________|
    243   | Secondary |  170h - 177h  |  376h - 377h  |
    244   |___________|_______________|_______________|
    245 
    246   Table 1. Compatibility resource mappings
    247   </pre>
    248 
    249   b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
    250   in IDE controller's PCI Configuration Space, shown in the Table 2 below.
    251   <pre>
    252   ___________________________________________________
    253   |           |   Command Block   |   Control Block   |
    254   |  Channel  |     Registers     |     Registers     |
    255   |___________|___________________|___________________|
    256   |  Primary  | BAR at offset 0x10| BAR at offset 0x14|
    257   |___________|___________________|___________________|
    258   | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
    259   |___________|___________________|___________________|
    260 
    261   Table 2. BARs for Register Mapping
    262   </pre>
    263   @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
    264   primary, 0374h for secondary. So 2 bytes extra offset should be
    265   added to the base addresses read from BARs.
    266 
    267   For more details, please refer to PCI IDE Controller Specification and Intel
    268   ICH4 Datasheet.
    269 
    270   @param  PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
    271   @param  IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
    272            receive IDE IO port registers' base addresses
    273 
    274   @retval EFI_UNSUPPORTED return this value when the BARs is not IO type
    275   @retval EFI_SUCCESS     Get the Base address successfully
    276   @retval other           read the pci configureation data error
    277 
    278 **/
    279 EFI_STATUS
    280 GetIdeRegistersBaseAddr (
    281   IN  EFI_PCI_IO_PROTOCOL         *PciIo,
    282   OUT IDE_REGISTERS_BASE_ADDR     *IdeRegsBaseAddr
    283   )
    284 {
    285   EFI_STATUS  Status;
    286   PCI_TYPE00  PciData;
    287 
    288   Status = PciIo->Pci.Read (
    289                         PciIo,
    290                         EfiPciIoWidthUint8,
    291                         0,
    292                         sizeof (PciData),
    293                         &PciData
    294                         );
    295 
    296   if (EFI_ERROR (Status)) {
    297     return Status;
    298   }
    299 
    300   if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
    301     IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  = 0x1f0;
    302     IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  = 0x3f6;
    303     IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =
    304     (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
    305   } else {
    306     //
    307     // The BARs should be of IO type
    308     //
    309     if ((PciData.Device.Bar[0] & BIT0) == 0 ||
    310         (PciData.Device.Bar[1] & BIT0) == 0) {
    311       return EFI_UNSUPPORTED;
    312     }
    313 
    314     IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr  =
    315     (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
    316     IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr  =
    317     (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
    318     IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr     =
    319     (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
    320   }
    321 
    322   if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
    323     IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  = 0x170;
    324     IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  = 0x376;
    325     IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =
    326     (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
    327   } else {
    328     //
    329     // The BARs should be of IO type
    330     //
    331     if ((PciData.Device.Bar[2] & BIT0) == 0 ||
    332         (PciData.Device.Bar[3] & BIT0) == 0) {
    333       return EFI_UNSUPPORTED;
    334     }
    335 
    336     IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr  =
    337     (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
    338     IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr  =
    339     (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
    340     IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr     =
    341     (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
    342   }
    343 
    344   return EFI_SUCCESS;
    345 }
    346 
    347 /**
    348   This function is used to requery IDE resources. The IDE controller will
    349   probably switch between native and legacy modes during the EFI->CSM->OS
    350   transfer. We do this everytime before an BlkIo operation to ensure its
    351   succeess.
    352 
    353   @param  IdeDev The BLK_IO private data which specifies the IDE device
    354 
    355   @retval EFI_INVALID_PARAMETER return this value when the channel is invalid
    356   @retval EFI_SUCCESS           reassign the IDE IO resource successfully
    357   @retval other                 get the IDE current base address effor
    358 
    359 **/
    360 EFI_STATUS
    361 ReassignIdeResources (
    362   IN  IDE_BLK_IO_DEV  *IdeDev
    363   )
    364 {
    365   EFI_STATUS              Status;
    366   IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
    367   UINT16                  CommandBlockBaseAddr;
    368   UINT16                  ControlBlockBaseAddr;
    369 
    370   if (IdeDev->Channel >= IdeMaxChannel) {
    371     return EFI_INVALID_PARAMETER;
    372   }
    373 
    374   //
    375   // Requery IDE IO port registers' base addresses in case of the switch of
    376   // native and legacy modes
    377   //
    378   Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
    379   if (EFI_ERROR (Status)) {
    380     return Status;
    381   }
    382 
    383   ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
    384   CommandBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
    385   ControlBlockBaseAddr                = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
    386 
    387   IdeDev->IoPort->Data                = CommandBlockBaseAddr;
    388   (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
    389   IdeDev->IoPort->SectorCount         = (UINT16) (CommandBlockBaseAddr + 0x02);
    390   IdeDev->IoPort->SectorNumber        = (UINT16) (CommandBlockBaseAddr + 0x03);
    391   IdeDev->IoPort->CylinderLsb         = (UINT16) (CommandBlockBaseAddr + 0x04);
    392   IdeDev->IoPort->CylinderMsb         = (UINT16) (CommandBlockBaseAddr + 0x05);
    393   IdeDev->IoPort->Head                = (UINT16) (CommandBlockBaseAddr + 0x06);
    394 
    395   (*(UINT16 *) &IdeDev->IoPort->Reg)  = (UINT16) (CommandBlockBaseAddr + 0x07);
    396   (*(UINT16 *) &IdeDev->IoPort->Alt)  = ControlBlockBaseAddr;
    397   IdeDev->IoPort->DriveAddress        = (UINT16) (ControlBlockBaseAddr + 0x01);
    398   IdeDev->IoPort->MasterSlave         = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
    399 
    400   IdeDev->IoPort->BusMasterBaseAddr   = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
    401   return EFI_SUCCESS;
    402 }
    403 
    404 /**
    405   This function is called by DiscoverIdeDevice(). It is used for detect
    406   whether the IDE device exists in the specified Channel as the specified
    407   Device Number.
    408 
    409   There is two IDE channels: one is Primary Channel, the other is
    410   Secondary Channel.(Channel is the logical name for the physical "Cable".)
    411   Different channel has different register group.
    412 
    413   On each IDE channel, at most two IDE devices attach,
    414   one is called Device 0 (Master device), the other is called Device 1
    415   (Slave device). The devices on the same channel co-use the same register
    416   group, so before sending out a command for a specified device via command
    417   register, it is a must to select the current device to accept the command
    418   by set the device number in the Head/Device Register.
    419 
    420   @param IdeDev  pointer to IDE_BLK_IO_DEV data structure, used to record all the
    421                  information of the IDE device.
    422 
    423   @retval EFI_SUCCESS successfully detects device.
    424 
    425   @retval other       any failure during detection process will return this value.
    426 
    427 **/
    428 EFI_STATUS
    429 DetectIDEController (
    430   IN  IDE_BLK_IO_DEV  *IdeDev
    431   )
    432 {
    433   EFI_STATUS  Status;
    434   UINT8       SectorCountReg;
    435   UINT8       LBALowReg;
    436   UINT8       LBAMidReg;
    437   UINT8       LBAHighReg;
    438   UINT8       InitStatusReg;
    439   UINT8       StatusReg;
    440 
    441   //
    442   // Select slave device
    443   //
    444   IDEWritePortB (
    445     IdeDev->PciIo,
    446     IdeDev->IoPort->Head,
    447     (UINT8) ((1 << 4) | 0xe0)
    448     );
    449   gBS->Stall (100);
    450 
    451   //
    452   // Save the init slave status register
    453   //
    454   InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
    455 
    456   //
    457   // Select Master back
    458   //
    459   IDEWritePortB (
    460     IdeDev->PciIo,
    461     IdeDev->IoPort->Head,
    462     (UINT8) ((0 << 4) | 0xe0)
    463     );
    464   gBS->Stall (100);
    465 
    466   //
    467   // Send ATA Device Execut Diagnostic command.
    468   // This command should work no matter DRDY is ready or not
    469   //
    470   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
    471 
    472   Status    = WaitForBSYClear (IdeDev, 3500);
    473   if (EFI_ERROR (Status)) {
    474     DEBUG((EFI_D_ERROR, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status));
    475     return Status;
    476   }
    477   //
    478   // Read device signature
    479   //
    480   //
    481   // Select Master
    482   //
    483   IDEWritePortB (
    484     IdeDev->PciIo,
    485     IdeDev->IoPort->Head,
    486     (UINT8) ((0 << 4) | 0xe0)
    487     );
    488   gBS->Stall (100);
    489   SectorCountReg = IDEReadPortB (
    490                      IdeDev->PciIo,
    491                      IdeDev->IoPort->SectorCount
    492                      );
    493   LBALowReg      = IDEReadPortB (
    494                      IdeDev->PciIo,
    495                      IdeDev->IoPort->SectorNumber
    496                      );
    497   LBAMidReg      = IDEReadPortB (
    498                      IdeDev->PciIo,
    499                      IdeDev->IoPort->CylinderLsb
    500                      );
    501   LBAHighReg     = IDEReadPortB (
    502                      IdeDev->PciIo,
    503                      IdeDev->IoPort->CylinderMsb
    504                      );
    505   if ((SectorCountReg == 0x1) &&
    506       (LBALowReg      == 0x1) &&
    507       (LBAMidReg      == 0x0) &&
    508       (LBAHighReg     == 0x0)) {
    509     MasterDeviceExist = TRUE;
    510     MasterDeviceType  = ATA_DEVICE_TYPE;
    511   } else {
    512     if ((LBAMidReg      == 0x14) &&
    513         (LBAHighReg     == 0xeb)) {
    514       MasterDeviceExist = TRUE;
    515       MasterDeviceType  = ATAPI_DEVICE_TYPE;
    516     }
    517   }
    518 
    519   //
    520   // For some Hard Drive, it takes some time to get
    521   // the right signature when operating in single slave mode.
    522   // We stall 20ms to work around this.
    523   //
    524   if (!MasterDeviceExist) {
    525     gBS->Stall (20000);
    526   }
    527 
    528   //
    529   // Select Slave
    530   //
    531   IDEWritePortB (
    532     IdeDev->PciIo,
    533     IdeDev->IoPort->Head,
    534     (UINT8) ((1 << 4) | 0xe0)
    535     );
    536   gBS->Stall (100);
    537   SectorCountReg = IDEReadPortB (
    538                      IdeDev->PciIo,
    539                      IdeDev->IoPort->SectorCount
    540                      );
    541   LBALowReg  = IDEReadPortB (
    542                  IdeDev->PciIo,
    543                  IdeDev->IoPort->SectorNumber
    544                  );
    545   LBAMidReg  = IDEReadPortB (
    546                  IdeDev->PciIo,
    547                  IdeDev->IoPort->CylinderLsb
    548                  );
    549   LBAHighReg = IDEReadPortB (
    550                  IdeDev->PciIo,
    551                  IdeDev->IoPort->CylinderMsb
    552                  );
    553   StatusReg  = IDEReadPortB (
    554                  IdeDev->PciIo,
    555                  IdeDev->IoPort->Reg.Status
    556                  );
    557   if ((SectorCountReg == 0x1) &&
    558       (LBALowReg      == 0x1) &&
    559       (LBAMidReg      == 0x0) &&
    560       (LBAHighReg     == 0x0)) {
    561     SlaveDeviceExist = TRUE;
    562     SlaveDeviceType  = ATA_DEVICE_TYPE;
    563   } else {
    564     if ((LBAMidReg     == 0x14) &&
    565         (LBAHighReg    == 0xeb)) {
    566       SlaveDeviceExist = TRUE;
    567       SlaveDeviceType  = ATAPI_DEVICE_TYPE;
    568     }
    569   }
    570 
    571   //
    572   // When single master is plugged, slave device
    573   // will be wrongly detected. Here's the workaround
    574   // for ATA devices by detecting DRY bit in status
    575   // register.
    576   // NOTE: This workaround doesn't apply to ATAPI.
    577   //
    578   if (MasterDeviceExist && SlaveDeviceExist &&
    579       (StatusReg & ATA_STSREG_DRDY) == 0               &&
    580       (InitStatusReg & ATA_STSREG_DRDY) == 0           &&
    581       MasterDeviceType == SlaveDeviceType   &&
    582       SlaveDeviceType != ATAPI_DEVICE_TYPE) {
    583     SlaveDeviceExist = FALSE;
    584   }
    585 
    586   //
    587   // Indicate this channel has been detected
    588   //
    589   ChannelDeviceDetected = TRUE;
    590   return EFI_SUCCESS;
    591 }
    592 /**
    593   Detect if there is disk attached to this port
    594 
    595   @param  IdeDev The BLK_IO private data which specifies the IDE device.
    596 
    597   @retval EFI_NOT_FOUND   The device or channel is not found
    598   @retval EFI_SUCCESS     The device is found
    599 
    600 **/
    601 EFI_STATUS
    602 DiscoverIdeDevice (
    603   IN IDE_BLK_IO_DEV *IdeDev
    604   )
    605 {
    606   EFI_STATUS  Status;
    607   EFI_STATUS  LongPhyStatus;
    608 
    609   //
    610   // If a channel has not been checked, check it now. Then set it to "checked" state
    611   // After this step, all devices in this channel have been checked.
    612   //
    613   if (!ChannelDeviceDetected) {
    614     Status = DetectIDEController (IdeDev);
    615     if (EFI_ERROR (Status)) {
    616       return EFI_NOT_FOUND;
    617     }
    618   }
    619 
    620   Status = EFI_NOT_FOUND;
    621 
    622   //
    623   // Device exists. test if it is an ATA device.
    624   // Prefer the result from DetectIDEController,
    625   // if failed, try another device type to handle
    626   // devices that not follow the spec.
    627   //
    628   if ((IdeDev->Device == IdeMaster) && (MasterDeviceExist)) {
    629     if (MasterDeviceType == ATA_DEVICE_TYPE) {
    630       Status = ATAIdentify (IdeDev);
    631       if (EFI_ERROR (Status)) {
    632         Status = ATAPIIdentify (IdeDev);
    633         if (!EFI_ERROR (Status)) {
    634           MasterDeviceType = ATAPI_DEVICE_TYPE;
    635         }
    636       }
    637     } else {
    638       Status = ATAPIIdentify (IdeDev);
    639       if (EFI_ERROR (Status)) {
    640         Status = ATAIdentify (IdeDev);
    641         if (!EFI_ERROR (Status)) {
    642           MasterDeviceType = ATA_DEVICE_TYPE;
    643         }
    644       }
    645     }
    646   }
    647   if ((IdeDev->Device == IdeSlave) && (SlaveDeviceExist)) {
    648     if (SlaveDeviceType == ATA_DEVICE_TYPE) {
    649       Status = ATAIdentify (IdeDev);
    650       if (EFI_ERROR (Status)) {
    651         Status = ATAPIIdentify (IdeDev);
    652         if (!EFI_ERROR (Status)) {
    653           SlaveDeviceType = ATAPI_DEVICE_TYPE;
    654         }
    655       }
    656     } else {
    657       Status = ATAPIIdentify (IdeDev);
    658       if (EFI_ERROR (Status)) {
    659         Status = ATAIdentify (IdeDev);
    660         if (!EFI_ERROR (Status)) {
    661           SlaveDeviceType = ATA_DEVICE_TYPE;
    662         }
    663       }
    664     }
    665   }
    666   if (EFI_ERROR (Status)) {
    667     return EFI_NOT_FOUND;
    668   }
    669   //
    670   // Init Block I/O interface
    671   //
    672   LongPhyStatus = AtaEnableLongPhysicalSector (IdeDev);
    673   if (!EFI_ERROR (LongPhyStatus)) {
    674     IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
    675   } else {
    676     IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
    677   }
    678   IdeDev->BlkIo.Reset               = IDEBlkIoReset;
    679   IdeDev->BlkIo.ReadBlocks          = IDEBlkIoReadBlocks;
    680   IdeDev->BlkIo.WriteBlocks         = IDEBlkIoWriteBlocks;
    681   IdeDev->BlkIo.FlushBlocks         = IDEBlkIoFlushBlocks;
    682 
    683   IdeDev->BlkMedia.LogicalPartition = FALSE;
    684   IdeDev->BlkMedia.WriteCaching     = FALSE;
    685 
    686   //
    687   // Init Disk Info interface
    688   //
    689   gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
    690   IdeDev->DiskInfo.Inquiry    = IDEDiskInfoInquiry;
    691   IdeDev->DiskInfo.Identify   = IDEDiskInfoIdentify;
    692   IdeDev->DiskInfo.SenseData  = IDEDiskInfoSenseData;
    693   IdeDev->DiskInfo.WhichIde   = IDEDiskInfoWhichIde;
    694 
    695   return EFI_SUCCESS;
    696 }
    697 
    698 /**
    699   This interface is used to initialize all state data related to the detection of one
    700   channel.
    701 **/
    702 VOID
    703 InitializeIDEChannelData (
    704   VOID
    705   )
    706 {
    707   ChannelDeviceDetected = FALSE;
    708   MasterDeviceExist = FALSE;
    709   MasterDeviceType  = 0xff;
    710   SlaveDeviceExist  = FALSE;
    711   SlaveDeviceType   = 0xff;
    712 }
    713 /**
    714   This function is used to poll for the DRQ bit clear in the Status
    715   Register. DRQ is cleared when the device is finished transferring data.
    716   So this function is called after data transfer is finished.
    717 
    718   @param IdeDev                 pointer pointing to IDE_BLK_IO_DEV data structure, used
    719                                 to record all the information of the IDE device.
    720   @param TimeoutInMilliSeconds  used to designate the timeout for the DRQ clear.
    721 
    722   @retval EFI_SUCCESS           DRQ bit clear within the time out.
    723 
    724   @retval EFI_TIMEOUT           DRQ bit not clear within the time out.
    725 
    726   @note
    727   Read Status Register will clear interrupt status.
    728 
    729 **/
    730 EFI_STATUS
    731 DRQClear (
    732   IN  IDE_BLK_IO_DEV  *IdeDev,
    733   IN  UINTN           TimeoutInMilliSeconds
    734   )
    735 {
    736   UINT32  Delay;
    737   UINT8   StatusRegister;
    738   UINT8   ErrorRegister;
    739 
    740   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
    741   do {
    742 
    743     StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
    744 
    745     //
    746     // wait for BSY == 0 and DRQ == 0
    747     //
    748     if ((StatusRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
    749       break;
    750     }
    751 
    752     if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
    753 
    754       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
    755       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    756         return EFI_ABORTED;
    757       }
    758     }
    759 
    760     //
    761     //  Stall for 30 us
    762     //
    763     gBS->Stall (30);
    764 
    765     Delay--;
    766 
    767   } while (Delay > 0);
    768 
    769   if (Delay == 0) {
    770     return EFI_TIMEOUT;
    771   }
    772 
    773   return EFI_SUCCESS;
    774 }
    775 /**
    776   This function is used to poll for the DRQ bit clear in the Alternate
    777   Status Register. DRQ is cleared when the device is finished
    778   transferring data. So this function is called after data transfer
    779   is finished.
    780 
    781   @param IdeDev                pointer pointing to IDE_BLK_IO_DEV data structure, used
    782                                to record all the information of the IDE device.
    783 
    784   @param TimeoutInMilliSeconds used to designate the timeout for the DRQ clear.
    785 
    786   @retval EFI_SUCCESS          DRQ bit clear within the time out.
    787 
    788   @retval EFI_TIMEOUT          DRQ bit not clear within the time out.
    789   @note   Read Alternate Status Register will not clear interrupt status.
    790 
    791 **/
    792 EFI_STATUS
    793 DRQClear2 (
    794   IN  IDE_BLK_IO_DEV  *IdeDev,
    795   IN  UINTN           TimeoutInMilliSeconds
    796   )
    797 {
    798   UINT32  Delay;
    799   UINT8   AltRegister;
    800   UINT8   ErrorRegister;
    801 
    802   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
    803   do {
    804 
    805     AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
    806 
    807     //
    808     //  wait for BSY == 0 and DRQ == 0
    809     //
    810     if ((AltRegister & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
    811       break;
    812     }
    813 
    814     if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
    815 
    816       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
    817       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    818         return EFI_ABORTED;
    819       }
    820     }
    821 
    822     //
    823     // Stall for 30 us
    824     //
    825     gBS->Stall (30);
    826 
    827     Delay--;
    828 
    829   } while (Delay > 0);
    830 
    831   if (Delay == 0) {
    832     return EFI_TIMEOUT;
    833   }
    834 
    835   return EFI_SUCCESS;
    836 }
    837 
    838 /**
    839   This function is used to poll for the DRQ bit set in the
    840   Status Register.
    841   DRQ is set when the device is ready to transfer data. So this function
    842   is called after the command is sent to the device and before required
    843   data is transferred.
    844 
    845   @param IdeDev                pointer pointing to IDE_BLK_IO_DEV data structure,used to
    846                                record all the information of the IDE device.
    847   @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
    848 
    849   @retval EFI_SUCCESS          DRQ bit set within the time out.
    850   @retval EFI_TIMEOUT          DRQ bit not set within the time out.
    851   @retval EFI_ABORTED          DRQ bit not set caused by the command abort.
    852 
    853   @note  Read Status Register will clear interrupt status.
    854 
    855 **/
    856 EFI_STATUS
    857 DRQReady (
    858   IN  IDE_BLK_IO_DEV  *IdeDev,
    859   IN  UINTN           TimeoutInMilliSeconds
    860   )
    861 {
    862   UINT32  Delay;
    863   UINT8   StatusRegister;
    864   UINT8   ErrorRegister;
    865 
    866   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
    867   do {
    868     //
    869     //  read Status Register will clear interrupt
    870     //
    871     StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
    872 
    873     //
    874     //  BSY==0,DRQ==1
    875     //
    876     if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
    877       break;
    878     }
    879 
    880     if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
    881 
    882       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
    883       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    884         return EFI_ABORTED;
    885       }
    886     }
    887 
    888     //
    889     // Stall for 30 us
    890     //
    891     gBS->Stall (30);
    892 
    893     Delay--;
    894   } while (Delay > 0);
    895 
    896   if (Delay == 0) {
    897     return EFI_TIMEOUT;
    898   }
    899 
    900   return EFI_SUCCESS;
    901 }
    902 /**
    903   This function is used to poll for the DRQ bit set in the Alternate Status Register.
    904   DRQ is set when the device is ready to transfer data. So this function is called after
    905   the command is sent to the device and before required data is transferred.
    906 
    907   @param IdeDev                pointer pointing to IDE_BLK_IO_DEV data structure, used to
    908                                record all the information of the IDE device.
    909 
    910   @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
    911 
    912   @retval EFI_SUCCESS           DRQ bit set within the time out.
    913   @retval EFI_TIMEOUT           DRQ bit not set within the time out.
    914   @retval EFI_ABORTED           DRQ bit not set caused by the command abort.
    915   @note  Read Alternate Status Register will not clear interrupt status.
    916 
    917 **/
    918 EFI_STATUS
    919 DRQReady2 (
    920   IN  IDE_BLK_IO_DEV  *IdeDev,
    921   IN  UINTN           TimeoutInMilliSeconds
    922   )
    923 {
    924   UINT32  Delay;
    925   UINT8   AltRegister;
    926   UINT8   ErrorRegister;
    927 
    928   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
    929 
    930   do {
    931     //
    932     //  Read Alternate Status Register will not clear interrupt status
    933     //
    934     AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
    935     //
    936     // BSY == 0 , DRQ == 1
    937     //
    938     if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
    939       break;
    940     }
    941 
    942     if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
    943 
    944       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
    945       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    946         return EFI_ABORTED;
    947       }
    948     }
    949 
    950     //
    951     // Stall for 30 us
    952     //
    953     gBS->Stall (30);
    954 
    955     Delay--;
    956   } while (Delay > 0);
    957 
    958   if (Delay == 0) {
    959     return EFI_TIMEOUT;
    960   }
    961 
    962   return EFI_SUCCESS;
    963 }
    964 
    965 /**
    966   This function is used to poll for the BSY bit clear in the Status Register. BSY
    967   is clear when the device is not busy. Every command must be sent after device is not busy.
    968 
    969   @param IdeDev                pointer pointing to IDE_BLK_IO_DEV data structure, used
    970                                to record all the information of the IDE device.
    971   @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
    972 
    973   @retval EFI_SUCCESS          BSY bit clear within the time out.
    974   @retval EFI_TIMEOUT          BSY bit not clear within the time out.
    975 
    976   @note Read Status Register will clear interrupt status.
    977 **/
    978 EFI_STATUS
    979 WaitForBSYClear (
    980   IN  IDE_BLK_IO_DEV  *IdeDev,
    981   IN  UINTN           TimeoutInMilliSeconds
    982   )
    983 {
    984   UINT32  Delay;
    985   UINT8   StatusRegister;
    986 
    987   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
    988   do {
    989 
    990     StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
    991     if ((StatusRegister & ATA_STSREG_BSY) == 0x00) {
    992       break;
    993     }
    994 
    995     //
    996     // Stall for 30 us
    997     //
    998     gBS->Stall (30);
    999 
   1000     Delay--;
   1001 
   1002   } while (Delay > 0);
   1003 
   1004   if (Delay == 0) {
   1005     return EFI_TIMEOUT;
   1006   }
   1007 
   1008   return EFI_SUCCESS;
   1009 }
   1010 /**
   1011   This function is used to poll for the BSY bit clear in the Alternate Status Register.
   1012   BSY is clear when the device is not busy. Every command must be sent after device is
   1013   not busy.
   1014 
   1015   @param IdeDev               pointer pointing to IDE_BLK_IO_DEV data structure, used to record
   1016                               all the information of the IDE device.
   1017   @param TimeoutInMilliSeconds used to designate the timeout for the DRQ ready.
   1018 
   1019   @retval EFI_SUCCESS         BSY bit clear within the time out.
   1020   @retval EFI_TIMEOUT         BSY bit not clear within the time out.
   1021   @note   Read Alternate Status Register will not clear interrupt status.
   1022 
   1023 **/
   1024 EFI_STATUS
   1025 WaitForBSYClear2 (
   1026   IN  IDE_BLK_IO_DEV  *IdeDev,
   1027   IN  UINTN           TimeoutInMilliSeconds
   1028   )
   1029 {
   1030   UINT32  Delay;
   1031   UINT8   AltRegister;
   1032 
   1033   Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
   1034   do {
   1035     AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
   1036     if ((AltRegister & ATA_STSREG_BSY) == 0x00) {
   1037       break;
   1038     }
   1039 
   1040     gBS->Stall (30);
   1041 
   1042     Delay--;
   1043 
   1044   } while (Delay > 0);
   1045 
   1046   if (Delay == 0) {
   1047     return EFI_TIMEOUT;
   1048   }
   1049 
   1050   return EFI_SUCCESS;
   1051 }
   1052 /**
   1053   This function is used to poll for the DRDY bit set in the Status Register. DRDY
   1054   bit is set when the device is ready to accept command. Most ATA commands must be
   1055   sent after DRDY set except the ATAPI Packet Command.
   1056 
   1057   @param IdeDev               pointer pointing to IDE_BLK_IO_DEV data structure, used
   1058                               to record all the information of the IDE device.
   1059   @param DelayInMilliSeconds  used to designate the timeout for the DRQ ready.
   1060 
   1061   @retval EFI_SUCCESS         DRDY bit set within the time out.
   1062   @retval EFI_TIMEOUT         DRDY bit not set within the time out.
   1063 
   1064   @note  Read Status Register will clear interrupt status.
   1065 **/
   1066 EFI_STATUS
   1067 DRDYReady (
   1068   IN  IDE_BLK_IO_DEV  *IdeDev,
   1069   IN  UINTN           DelayInMilliSeconds
   1070   )
   1071 {
   1072   UINT32  Delay;
   1073   UINT8   StatusRegister;
   1074   UINT8   ErrorRegister;
   1075 
   1076   Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
   1077   do {
   1078     StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
   1079     //
   1080     //  BSY == 0 , DRDY == 1
   1081     //
   1082     if ((StatusRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
   1083       break;
   1084     }
   1085 
   1086     if ((StatusRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
   1087 
   1088       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
   1089       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
   1090         return EFI_ABORTED;
   1091       }
   1092     }
   1093 
   1094     gBS->Stall (30);
   1095 
   1096     Delay--;
   1097   } while (Delay > 0);
   1098 
   1099   if (Delay == 0) {
   1100     return EFI_TIMEOUT;
   1101   }
   1102 
   1103   return EFI_SUCCESS;
   1104 }
   1105 /**
   1106   This function is used to poll for the DRDY bit set in the Alternate Status Register.
   1107   DRDY bit is set when the device is ready to accept command. Most ATA commands must
   1108   be sent after DRDY set except the ATAPI Packet Command.
   1109 
   1110   @param IdeDev              pointer pointing to IDE_BLK_IO_DEV data structure, used
   1111                              to record all the information of the IDE device.
   1112   @param DelayInMilliSeconds used to designate the timeout for the DRQ ready.
   1113 
   1114   @retval EFI_SUCCESS      DRDY bit set within the time out.
   1115   @retval EFI_TIMEOUT      DRDY bit not set within the time out.
   1116 
   1117   @note  Read Alternate Status Register will clear interrupt status.
   1118 
   1119 **/
   1120 EFI_STATUS
   1121 DRDYReady2 (
   1122   IN  IDE_BLK_IO_DEV  *IdeDev,
   1123   IN  UINTN           DelayInMilliSeconds
   1124   )
   1125 {
   1126   UINT32  Delay;
   1127   UINT8   AltRegister;
   1128   UINT8   ErrorRegister;
   1129 
   1130   Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
   1131   do {
   1132     AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
   1133     //
   1134     //  BSY == 0 , DRDY == 1
   1135     //
   1136     if ((AltRegister & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
   1137       break;
   1138     }
   1139 
   1140     if ((AltRegister & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
   1141 
   1142       ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
   1143       if ((ErrorRegister & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
   1144         return EFI_ABORTED;
   1145       }
   1146     }
   1147 
   1148     gBS->Stall (30);
   1149 
   1150     Delay--;
   1151   } while (Delay > 0);
   1152 
   1153   if (Delay == 0) {
   1154     return EFI_TIMEOUT;
   1155   }
   1156 
   1157   return EFI_SUCCESS;
   1158 }
   1159 /**
   1160   Release resources of an IDE device before stopping it.
   1161 
   1162   @param IdeBlkIoDevice  Standard IDE device private data structure
   1163 
   1164 **/
   1165 VOID
   1166 ReleaseIdeResources (
   1167   IN  IDE_BLK_IO_DEV  *IdeBlkIoDevice
   1168   )
   1169 {
   1170   if (IdeBlkIoDevice == NULL) {
   1171     return ;
   1172   }
   1173 
   1174   //
   1175   // Release all the resourses occupied by the IDE_BLK_IO_DEV
   1176   //
   1177 
   1178   if (IdeBlkIoDevice->SenseData != NULL) {
   1179     gBS->FreePool (IdeBlkIoDevice->SenseData);
   1180     IdeBlkIoDevice->SenseData = NULL;
   1181   }
   1182 
   1183   if (IdeBlkIoDevice->Cache != NULL) {
   1184     gBS->FreePool (IdeBlkIoDevice->Cache);
   1185     IdeBlkIoDevice->Cache = NULL;
   1186   }
   1187 
   1188   if (IdeBlkIoDevice->IdData != NULL) {
   1189     gBS->FreePool (IdeBlkIoDevice->IdData);
   1190     IdeBlkIoDevice->IdData = NULL;
   1191   }
   1192 
   1193   if (IdeBlkIoDevice->InquiryData != NULL) {
   1194     gBS->FreePool (IdeBlkIoDevice->InquiryData);
   1195     IdeBlkIoDevice->InquiryData = NULL;
   1196   }
   1197 
   1198   if (IdeBlkIoDevice->ControllerNameTable != NULL) {
   1199     FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
   1200     IdeBlkIoDevice->ControllerNameTable = NULL;
   1201   }
   1202 
   1203   if (IdeBlkIoDevice->IoPort != NULL) {
   1204     gBS->FreePool (IdeBlkIoDevice->IoPort);
   1205   }
   1206 
   1207   if (IdeBlkIoDevice->DevicePath != NULL) {
   1208     gBS->FreePool (IdeBlkIoDevice->DevicePath);
   1209   }
   1210 
   1211   if (IdeBlkIoDevice->ExitBootServiceEvent != NULL) {
   1212     gBS->CloseEvent (IdeBlkIoDevice->ExitBootServiceEvent);
   1213     IdeBlkIoDevice->ExitBootServiceEvent = NULL;
   1214   }
   1215 
   1216   gBS->FreePool (IdeBlkIoDevice);
   1217   IdeBlkIoDevice = NULL;
   1218 
   1219   return ;
   1220 }
   1221 /**
   1222   Set the calculated Best transfer mode to a detected device.
   1223 
   1224   @param IdeDev       Standard IDE device private data structure
   1225   @param TransferMode The device transfer mode to be set
   1226   @return Set transfer mode Command execute status.
   1227 
   1228 **/
   1229 EFI_STATUS
   1230 SetDeviceTransferMode (
   1231   IN IDE_BLK_IO_DEV       *IdeDev,
   1232   IN ATA_TRANSFER_MODE    *TransferMode
   1233   )
   1234 {
   1235   EFI_STATUS  Status;
   1236   UINT8       DeviceSelect;
   1237   UINT8       SectorCount;
   1238 
   1239   DeviceSelect  = 0;
   1240   DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);
   1241   SectorCount   = *((UINT8 *) TransferMode);
   1242 
   1243   //
   1244   // Send SET FEATURE command (sub command 0x03) to set pio mode.
   1245   //
   1246   Status = AtaNonDataCommandIn (
   1247             IdeDev,
   1248             ATA_CMD_SET_FEATURES,
   1249             DeviceSelect,
   1250             0x03,
   1251             SectorCount,
   1252             0,
   1253             0,
   1254             0
   1255             );
   1256 
   1257   return Status;
   1258 }
   1259 /**
   1260   Set drive parameters for devices not support PACKETS command.
   1261 
   1262   @param IdeDev          Standard IDE device private data structure
   1263   @param DriveParameters The device parameters to be set into the disk
   1264   @return SetParameters Command execute status.
   1265 
   1266 **/
   1267 EFI_STATUS
   1268 SetDriveParameters (
   1269   IN IDE_BLK_IO_DEV       *IdeDev,
   1270   IN ATA_DRIVE_PARMS      *DriveParameters
   1271   )
   1272 {
   1273   EFI_STATUS  Status;
   1274   UINT8       DeviceSelect;
   1275 
   1276   DeviceSelect  = 0;
   1277   DeviceSelect  = (UINT8) ((IdeDev->Device) << 4);
   1278 
   1279   //
   1280   // Send Init drive parameters
   1281   //
   1282   Status = AtaNonDataCommandIn (
   1283             IdeDev,
   1284             ATA_CMD_INIT_DRIVE_PARAM,
   1285             (UINT8) (DeviceSelect + DriveParameters->Heads),
   1286             0,
   1287             DriveParameters->Sector,
   1288             0,
   1289             0,
   1290             0
   1291             );
   1292 
   1293   //
   1294   // Send Set Multiple parameters
   1295   //
   1296   Status = AtaNonDataCommandIn (
   1297             IdeDev,
   1298             ATA_CMD_SET_MULTIPLE_MODE,
   1299             DeviceSelect,
   1300             0,
   1301             DriveParameters->MultipleSector,
   1302             0,
   1303             0,
   1304             0
   1305             );
   1306   return Status;
   1307 }
   1308 
   1309 /**
   1310   Enable Interrupt on IDE controller.
   1311 
   1312   @param  IdeDev   Standard IDE device private data structure
   1313 
   1314   @retval  EFI_SUCCESS Enable Interrupt successfully
   1315 **/
   1316 EFI_STATUS
   1317 EnableInterrupt (
   1318   IN IDE_BLK_IO_DEV       *IdeDev
   1319   )
   1320 {
   1321   UINT8 DeviceControl;
   1322 
   1323   //
   1324   // Enable interrupt for DMA operation
   1325   //
   1326   DeviceControl = 0;
   1327   IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
   1328 
   1329   return EFI_SUCCESS;
   1330 }
   1331