Home | History | Annotate | Download | only in IdeBusPei
      1 /** @file
      2 PEIM to produce gEfiPeiVirtualBlockIoPpiGuid & gEfiPeiVirtualBlockIo2PpiGuid PPI for
      3 ATA controllers in the platform.
      4 
      5 This PPI can be consumed by PEIM which produce gEfiPeiDeviceRecoveryModulePpiGuid
      6 for Atapi CD ROM device.
      7 
      8 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
      9 
     10 This program and the accompanying materials
     11 are licensed and made available under the terms and conditions
     12 of the BSD License which accompanies this distribution.  The
     13 full text of the license may be found at
     14 http://opensource.org/licenses/bsd-license.php
     15 
     16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     18 
     19 **/
     20 
     21 #include "AtapiPeim.h"
     22 
     23 /**
     24   Initializes the Atapi Block Io PPI.
     25 
     26   @param[in]  FileHandle           Handle of the file being invoked.
     27   @param[in]  PeiServices          Describes the list of possible PEI Services.
     28 
     29   @retval     EFI_SUCCESS          Operation performed successfully.
     30   @retval     EFI_OUT_OF_RESOURCES Not enough memory to allocate.
     31 
     32 **/
     33 EFI_STATUS
     34 EFIAPI
     35 AtapiPeimEntry (
     36   IN EFI_PEI_FILE_HANDLE        FileHandle,
     37   IN CONST EFI_PEI_SERVICES     **PeiServices
     38   )
     39 {
     40   PEI_ATA_CONTROLLER_PPI  *AtaControllerPpi;
     41   EFI_STATUS              Status;
     42   ATAPI_BLK_IO_DEV        *AtapiBlkIoDev;
     43 
     44   Status = PeiServicesRegisterForShadow (FileHandle);
     45   if (!EFI_ERROR (Status)) {
     46     return Status;
     47   }
     48 
     49   Status = PeiServicesLocatePpi (
     50               &gPeiAtaControllerPpiGuid,
     51               0,
     52               NULL,
     53               (VOID **) &AtaControllerPpi
     54               );
     55   ASSERT_EFI_ERROR (Status);
     56 
     57   AtapiBlkIoDev = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*AtapiBlkIoDev)));
     58   if (AtapiBlkIoDev == NULL) {
     59     return EFI_OUT_OF_RESOURCES;
     60   }
     61 
     62   AtapiBlkIoDev->Signature        = ATAPI_BLK_IO_DEV_SIGNATURE;
     63   AtapiBlkIoDev->AtaControllerPpi = AtaControllerPpi;
     64 
     65   //
     66   // atapi device enumeration and build private data
     67   //
     68   AtapiEnumerateDevices (AtapiBlkIoDev);
     69 
     70   AtapiBlkIoDev->AtapiBlkIo.GetNumberOfBlockDevices = AtapiGetNumberOfBlockDevices;
     71   AtapiBlkIoDev->AtapiBlkIo.GetBlockDeviceMediaInfo = AtapiGetBlockDeviceMediaInfo;
     72   AtapiBlkIoDev->AtapiBlkIo.ReadBlocks              = AtapiReadBlocks;
     73   AtapiBlkIoDev->AtapiBlkIo2.Revision                = EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION;
     74   AtapiBlkIoDev->AtapiBlkIo2.GetNumberOfBlockDevices = AtapiGetNumberOfBlockDevices2;
     75   AtapiBlkIoDev->AtapiBlkIo2.GetBlockDeviceMediaInfo = AtapiGetBlockDeviceMediaInfo2;
     76   AtapiBlkIoDev->AtapiBlkIo2.ReadBlocks              = AtapiReadBlocks2;
     77 
     78   AtapiBlkIoDev->PpiDescriptor.Flags                = EFI_PEI_PPI_DESCRIPTOR_PPI;
     79   AtapiBlkIoDev->PpiDescriptor.Guid                 = &gEfiPeiVirtualBlockIoPpiGuid;
     80   AtapiBlkIoDev->PpiDescriptor.Ppi                  = &AtapiBlkIoDev->AtapiBlkIo;
     81 
     82   AtapiBlkIoDev->PpiDescriptor2.Flags                = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
     83   AtapiBlkIoDev->PpiDescriptor2.Guid                 = &gEfiPeiVirtualBlockIo2PpiGuid;
     84   AtapiBlkIoDev->PpiDescriptor2.Ppi                  = &AtapiBlkIoDev->AtapiBlkIo2;
     85 
     86   DEBUG ((EFI_D_INFO, "Atatpi Device Count is %d\n", AtapiBlkIoDev->DeviceCount));
     87   if (AtapiBlkIoDev->DeviceCount != 0) {
     88     Status = PeiServicesInstallPpi (&AtapiBlkIoDev->PpiDescriptor);
     89     if (EFI_ERROR (Status)) {
     90       return EFI_OUT_OF_RESOURCES;
     91     }
     92   }
     93 
     94   return EFI_SUCCESS;
     95 }
     96 
     97 /**
     98   Gets the count of block I/O devices that one specific block driver detects.
     99 
    100   This function is used for getting the count of block I/O devices that one
    101   specific block driver detects.  To the PEI ATAPI driver, it returns the number
    102   of all the detected ATAPI devices it detects during the enumeration process.
    103   To the PEI legacy floppy driver, it returns the number of all the legacy
    104   devices it finds during its enumeration process. If no device is detected,
    105   then the function will return zero.
    106 
    107   @param[in]  PeiServices          General-purpose services that are available
    108                                    to every PEIM.
    109   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
    110                                    instance.
    111   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
    112 
    113   @retval     EFI_SUCCESS          Operation performed successfully.
    114 
    115 **/
    116 EFI_STATUS
    117 EFIAPI
    118 AtapiGetNumberOfBlockDevices (
    119   IN   EFI_PEI_SERVICES                  **PeiServices,
    120   IN   EFI_PEI_RECOVERY_BLOCK_IO_PPI   *This,
    121   OUT  UINTN                             *NumberBlockDevices
    122   )
    123 {
    124   ATAPI_BLK_IO_DEV  *AtapiBlkIoDev;
    125 
    126   AtapiBlkIoDev = NULL;
    127 
    128   AtapiBlkIoDev       = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
    129 
    130   *NumberBlockDevices = AtapiBlkIoDev->DeviceCount;
    131 
    132   return EFI_SUCCESS;
    133 }
    134 
    135 /**
    136   Gets a block device's media information.
    137 
    138   This function will provide the caller with the specified block device's media
    139   information. If the media changes, calling this function will update the media
    140   information accordingly.
    141 
    142   @param[in]  PeiServices   General-purpose services that are available to every
    143                             PEIM
    144   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
    145   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    146                             to talk. Because the driver that implements Block I/O
    147                             PPIs will manage multiple block devices, the PPIs that
    148                             want to talk to a single device must specify the
    149                             device index that was assigned during the enumeration
    150                             process. This index is a number from one to
    151                             NumberBlockDevices.
    152   @param[out] MediaInfo     The media information of the specified block media.
    153                             The caller is responsible for the ownership of this
    154                             data structure.
    155 
    156   @retval EFI_SUCCESS           Media information about the specified block device
    157                                 was obtained successfully.
    158   @retval EFI_DEVICE_ERROR      Cannot get the media information due to a hardware
    159                                 error.
    160   @retval Others                Other failure occurs.
    161 
    162 **/
    163 EFI_STATUS
    164 EFIAPI
    165 AtapiGetBlockDeviceMediaInfo (
    166   IN   EFI_PEI_SERVICES                     **PeiServices,
    167   IN   EFI_PEI_RECOVERY_BLOCK_IO_PPI        *This,
    168   IN   UINTN                                DeviceIndex,
    169   OUT  EFI_PEI_BLOCK_IO_MEDIA               *MediaInfo
    170   )
    171 {
    172   UINTN             DeviceCount;
    173   ATAPI_BLK_IO_DEV  *AtapiBlkIoDev;
    174   EFI_STATUS        Status;
    175   UINTN             Index;
    176 
    177   AtapiBlkIoDev = NULL;
    178 
    179   if (This == NULL || MediaInfo == NULL) {
    180     return EFI_INVALID_PARAMETER;
    181   }
    182 
    183   AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
    184 
    185   DeviceCount   = AtapiBlkIoDev->DeviceCount;
    186 
    187   //
    188   // DeviceIndex is a value from 1 to NumberBlockDevices.
    189   //
    190   if ((DeviceIndex < 1) || (DeviceIndex > DeviceCount) || (DeviceIndex > MAX_IDE_DEVICES)) {
    191     return EFI_INVALID_PARAMETER;
    192   }
    193 
    194   Index = DeviceIndex - 1;
    195 
    196   //
    197   // probe media and retrieve latest media information
    198   //
    199   DEBUG ((EFI_D_INFO, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev->DeviceInfo[Index].DevicePosition));
    200   DEBUG ((EFI_D_INFO, "Atatpi GetInfo DeviceType is   %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.DeviceType));
    201   DEBUG ((EFI_D_INFO, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.MediaPresent));
    202   DEBUG ((EFI_D_INFO, "Atatpi GetInfo BlockSize is  0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.BlockSize));
    203   DEBUG ((EFI_D_INFO, "Atatpi GetInfo LastBlock is  0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.LastBlock));
    204 
    205   Status = DetectMedia (
    206              AtapiBlkIoDev,
    207              AtapiBlkIoDev->DeviceInfo[Index].DevicePosition,
    208              &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo,
    209              &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo2
    210              );
    211   if (Status != EFI_SUCCESS) {
    212     return EFI_DEVICE_ERROR;
    213   }
    214 
    215   DEBUG ((EFI_D_INFO, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev->DeviceInfo[Index].DevicePosition));
    216   DEBUG ((EFI_D_INFO, "Atatpi GetInfo DeviceType is   %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.DeviceType));
    217   DEBUG ((EFI_D_INFO, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.MediaPresent));
    218   DEBUG ((EFI_D_INFO, "Atatpi GetInfo BlockSize is  0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.BlockSize));
    219   DEBUG ((EFI_D_INFO, "Atatpi GetInfo LastBlock is  0x%x\n", AtapiBlkIoDev->DeviceInfo[Index].MediaInfo.LastBlock));
    220 
    221   //
    222   // Get media info from AtapiBlkIoDev
    223   //
    224   CopyMem (MediaInfo, &AtapiBlkIoDev->DeviceInfo[Index].MediaInfo, sizeof(EFI_PEI_BLOCK_IO_MEDIA));
    225 
    226   return EFI_SUCCESS;
    227 }
    228 
    229 /**
    230   Reads the requested number of blocks from the specified block device.
    231 
    232   The function reads the requested number of blocks from the device. All the
    233   blocks are read, or an error is returned. If there is no media in the device,
    234   the function returns EFI_NO_MEDIA.
    235 
    236   @param[in]  PeiServices   General-purpose services that are available to
    237                             every PEIM.
    238   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
    239   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    240                             to talk. Because the driver that implements Block I/O
    241                             PPIs will manage multiple block devices, the PPIs that
    242                             want to talk to a single device must specify the device
    243                             index that was assigned during the enumeration process.
    244                             This index is a number from one to NumberBlockDevices.
    245   @param[in]  StartLBA      The starting logical block address (LBA) to read from
    246                             on the device
    247   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
    248                             a multiple of the intrinsic block size of the device.
    249   @param[out] Buffer        A pointer to the destination buffer for the data.
    250                             The caller is responsible for the ownership of the
    251                             buffer.
    252 
    253   @retval EFI_SUCCESS             The data was read correctly from the device.
    254   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    255                                   to perform the read operation.
    256   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    257                                   valid, or the buffer is not properly aligned.
    258   @retval EFI_NO_MEDIA            There is no media in the device.
    259   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    260                                   the intrinsic block size of the device.
    261 
    262 **/
    263 EFI_STATUS
    264 EFIAPI
    265 AtapiReadBlocks (
    266   IN   EFI_PEI_SERVICES                  **PeiServices,
    267   IN   EFI_PEI_RECOVERY_BLOCK_IO_PPI     *This,
    268   IN   UINTN                             DeviceIndex,
    269   IN   EFI_PEI_LBA                       StartLBA,
    270   IN   UINTN                             BufferSize,
    271   OUT  VOID                              *Buffer
    272   )
    273 {
    274 
    275   EFI_PEI_BLOCK_IO_MEDIA  MediaInfo;
    276   EFI_STATUS              Status;
    277   UINTN                   NumberOfBlocks;
    278   UINTN                   BlockSize;
    279   ATAPI_BLK_IO_DEV        *AtapiBlkIoDev;
    280 
    281   AtapiBlkIoDev = NULL;
    282 
    283   if (This == NULL) {
    284     return EFI_INVALID_PARAMETER;
    285   }
    286 
    287   AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This);
    288 
    289   if (Buffer == NULL) {
    290     return EFI_INVALID_PARAMETER;
    291   }
    292 
    293   if (BufferSize == 0) {
    294     return EFI_SUCCESS;
    295   }
    296 
    297   Status = AtapiGetBlockDeviceMediaInfo (
    298             PeiServices,
    299             This,
    300             DeviceIndex,
    301             &MediaInfo
    302             );
    303   if (Status != EFI_SUCCESS) {
    304     return EFI_DEVICE_ERROR;
    305   }
    306 
    307   if (!MediaInfo.MediaPresent) {
    308     return EFI_NO_MEDIA;
    309   }
    310 
    311   BlockSize = MediaInfo.BlockSize;
    312 
    313   if (BufferSize % BlockSize != 0) {
    314     return EFI_BAD_BUFFER_SIZE;
    315   }
    316 
    317   NumberOfBlocks = BufferSize / BlockSize;
    318 
    319   if ((StartLBA + NumberOfBlocks - 1) > AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo2.LastBlock) {
    320     return EFI_INVALID_PARAMETER;
    321   }
    322 
    323   Status = ReadSectors (
    324             AtapiBlkIoDev,
    325             AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].DevicePosition,
    326             Buffer,
    327             StartLBA,
    328             NumberOfBlocks,
    329             BlockSize
    330             );
    331   if (EFI_ERROR (Status)) {
    332     return EFI_DEVICE_ERROR;
    333   }
    334 
    335   return EFI_SUCCESS;
    336 }
    337 
    338 /**
    339   Gets the count of block I/O devices that one specific block driver detects.
    340 
    341   This function is used for getting the count of block I/O devices that one
    342   specific block driver detects.  To the PEI ATAPI driver, it returns the number
    343   of all the detected ATAPI devices it detects during the enumeration process.
    344   To the PEI legacy floppy driver, it returns the number of all the legacy
    345   devices it finds during its enumeration process. If no device is detected,
    346   then the function will return zero.
    347 
    348   @param[in]  PeiServices          General-purpose services that are available
    349                                    to every PEIM.
    350   @param[in]  This                 Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
    351                                    instance.
    352   @param[out] NumberBlockDevices   The number of block I/O devices discovered.
    353 
    354   @retval     EFI_SUCCESS          Operation performed successfully.
    355 
    356 **/
    357 EFI_STATUS
    358 EFIAPI
    359 AtapiGetNumberOfBlockDevices2 (
    360   IN   EFI_PEI_SERVICES                  **PeiServices,
    361   IN   EFI_PEI_RECOVERY_BLOCK_IO2_PPI    *This,
    362   OUT  UINTN                             *NumberBlockDevices
    363   )
    364 {
    365   EFI_STATUS        Status;
    366   ATAPI_BLK_IO_DEV  *AtapiBlkIoDev;
    367 
    368   AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
    369 
    370   Status = AtapiGetNumberOfBlockDevices (
    371              PeiServices,
    372              &AtapiBlkIoDev->AtapiBlkIo,
    373              NumberBlockDevices
    374              );
    375 
    376   return Status;
    377 }
    378 
    379 /**
    380   Gets a block device's media information.
    381 
    382   This function will provide the caller with the specified block device's media
    383   information. If the media changes, calling this function will update the media
    384   information accordingly.
    385 
    386   @param[in]  PeiServices   General-purpose services that are available to every
    387                             PEIM
    388   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
    389   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    390                             to talk. Because the driver that implements Block I/O
    391                             PPIs will manage multiple block devices, the PPIs that
    392                             want to talk to a single device must specify the
    393                             device index that was assigned during the enumeration
    394                             process. This index is a number from one to
    395                             NumberBlockDevices.
    396   @param[out] MediaInfo     The media information of the specified block media.
    397                             The caller is responsible for the ownership of this
    398                             data structure.
    399 
    400   @retval EFI_SUCCESS           Media information about the specified block device
    401                                 was obtained successfully.
    402   @retval EFI_DEVICE_ERROR      Cannot get the media information due to a hardware
    403                                 error.
    404   @retval Others                Other failure occurs.
    405 
    406 **/
    407 EFI_STATUS
    408 EFIAPI
    409 AtapiGetBlockDeviceMediaInfo2 (
    410   IN   EFI_PEI_SERVICES                     **PeiServices,
    411   IN   EFI_PEI_RECOVERY_BLOCK_IO2_PPI       *This,
    412   IN   UINTN                                DeviceIndex,
    413   OUT  EFI_PEI_BLOCK_IO2_MEDIA              *MediaInfo
    414   )
    415 {
    416   ATAPI_BLK_IO_DEV           *AtapiBlkIoDev;
    417   EFI_STATUS                 Status;
    418   EFI_PEI_BLOCK_IO_MEDIA     Media;
    419 
    420   AtapiBlkIoDev = NULL;
    421 
    422   if (This == NULL || MediaInfo == NULL) {
    423     return EFI_INVALID_PARAMETER;
    424   }
    425 
    426   AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
    427 
    428   Status = AtapiGetBlockDeviceMediaInfo (
    429              PeiServices,
    430              &AtapiBlkIoDev->AtapiBlkIo,
    431              DeviceIndex,
    432              &Media
    433              );
    434   if (EFI_ERROR (Status)) {
    435     return Status;
    436   }
    437   //
    438   // Get media info from AtapiBlkIoDev
    439   //
    440   CopyMem (MediaInfo, &AtapiBlkIoDev->DeviceInfo[DeviceIndex - 1].MediaInfo2, sizeof(EFI_PEI_BLOCK_IO2_MEDIA));
    441 
    442   return EFI_SUCCESS;
    443 }
    444 
    445 /**
    446   Reads the requested number of blocks from the specified block device.
    447 
    448   The function reads the requested number of blocks from the device. All the
    449   blocks are read, or an error is returned. If there is no media in the device,
    450   the function returns EFI_NO_MEDIA.
    451 
    452   @param[in]  PeiServices   General-purpose services that are available to
    453                             every PEIM.
    454   @param[in]  This          Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.
    455   @param[in]  DeviceIndex   Specifies the block device to which the function wants
    456                             to talk. Because the driver that implements Block I/O
    457                             PPIs will manage multiple block devices, the PPIs that
    458                             want to talk to a single device must specify the device
    459                             index that was assigned during the enumeration process.
    460                             This index is a number from one to NumberBlockDevices.
    461   @param[in]  StartLBA      The starting logical block address (LBA) to read from
    462                             on the device
    463   @param[in]  BufferSize    The size of the Buffer in bytes. This number must be
    464                             a multiple of the intrinsic block size of the device.
    465   @param[out] Buffer        A pointer to the destination buffer for the data.
    466                             The caller is responsible for the ownership of the
    467                             buffer.
    468 
    469   @retval EFI_SUCCESS             The data was read correctly from the device.
    470   @retval EFI_DEVICE_ERROR        The device reported an error while attempting
    471                                   to perform the read operation.
    472   @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
    473                                   valid, or the buffer is not properly aligned.
    474   @retval EFI_NO_MEDIA            There is no media in the device.
    475   @retval EFI_BAD_BUFFER_SIZE     The BufferSize parameter is not a multiple of
    476                                   the intrinsic block size of the device.
    477 
    478 **/
    479 EFI_STATUS
    480 EFIAPI
    481 AtapiReadBlocks2 (
    482   IN   EFI_PEI_SERVICES                  **PeiServices,
    483   IN   EFI_PEI_RECOVERY_BLOCK_IO2_PPI    *This,
    484   IN   UINTN                             DeviceIndex,
    485   IN   EFI_PEI_LBA                       StartLBA,
    486   IN   UINTN                             BufferSize,
    487   OUT  VOID                              *Buffer
    488   )
    489 {
    490   EFI_STATUS          Status;
    491   ATAPI_BLK_IO_DEV    *AtapiBlkIoDev;
    492 
    493   AtapiBlkIoDev = NULL;
    494 
    495   if (This == NULL) {
    496     return EFI_INVALID_PARAMETER;
    497   }
    498 
    499   AtapiBlkIoDev = PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This);
    500 
    501   Status = AtapiReadBlocks (
    502              PeiServices,
    503              &AtapiBlkIoDev->AtapiBlkIo,
    504              DeviceIndex,
    505              StartLBA,
    506              BufferSize,
    507              Buffer
    508              );
    509 
    510   return Status;
    511 }
    512 
    513 
    514 /**
    515   Enumerate Atapi devices.
    516 
    517   This function is used to enumerate Atatpi device in Ide channel.
    518 
    519   @param[in]  AtapiBlkIoDev  A pointer to atapi block IO device
    520 
    521 **/
    522 VOID
    523 AtapiEnumerateDevices (
    524   IN  ATAPI_BLK_IO_DEV  *AtapiBlkIoDev
    525   )
    526 {
    527   UINT8                   Index1;
    528   UINT8                   Index2;
    529   UINTN                   DevicePosition;
    530   EFI_PEI_BLOCK_IO_MEDIA  MediaInfo;
    531   EFI_PEI_BLOCK_IO2_MEDIA MediaInfo2;
    532   EFI_STATUS              Status;
    533   UINTN                   DeviceCount;
    534   UINT16                  CommandBlockBaseAddr;
    535   UINT16                  ControlBlockBaseAddr;
    536   UINT32                  IdeEnabledNumber;
    537   IDE_REGS_BASE_ADDR      IdeRegsBaseAddr[MAX_IDE_CHANNELS];
    538 
    539   DeviceCount = 0;
    540   DevicePosition = 0;
    541 
    542   //
    543   // Scan IDE bus for ATAPI devices
    544   //
    545 
    546   //
    547   // Enable Sata and IDE controller.
    548   //
    549   AtapiBlkIoDev->AtaControllerPpi->EnableAtaChannel (
    550                                   (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
    551                                   AtapiBlkIoDev->AtaControllerPpi,
    552                                   PEI_ICH_IDE_PRIMARY | PEI_ICH_IDE_SECONDARY
    553                                   );
    554 
    555   //
    556   // Allow SATA Devices to spin-up. This is needed if
    557   // SEC and PEI phase is too short, for example Release Build.
    558   //
    559   DEBUG ((EFI_D_INFO, "Delay for %d seconds for SATA devices to spin-up\n", PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath)));
    560   MicroSecondDelay (PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath) * 1000 * 1000); //
    561 
    562   //
    563   // Get four channels (primary or secondary Pata, Sata Channel) Command and Control Regs Base address.
    564   //
    565   IdeEnabledNumber = AtapiBlkIoDev->AtaControllerPpi->GetIdeRegsBaseAddr (
    566                                                       (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
    567                                                       AtapiBlkIoDev->AtaControllerPpi,
    568                                                       IdeRegsBaseAddr
    569                                                       );
    570 
    571   //
    572   // Using Command and Control Regs Base Address to fill other registers.
    573   //
    574   for (Index1 = 0; Index1 < IdeEnabledNumber; Index1 ++) {
    575     CommandBlockBaseAddr               = IdeRegsBaseAddr[Index1].CommandBlockBaseAddr;
    576     AtapiBlkIoDev->IdeIoPortReg[Index1].Data         = CommandBlockBaseAddr;
    577     AtapiBlkIoDev->IdeIoPortReg[Index1].Reg1.Feature = (UINT16) (CommandBlockBaseAddr + 0x1);
    578     AtapiBlkIoDev->IdeIoPortReg[Index1].SectorCount  = (UINT16) (CommandBlockBaseAddr + 0x2);
    579     AtapiBlkIoDev->IdeIoPortReg[Index1].SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x3);
    580     AtapiBlkIoDev->IdeIoPortReg[Index1].CylinderLsb  = (UINT16) (CommandBlockBaseAddr + 0x4);
    581     AtapiBlkIoDev->IdeIoPortReg[Index1].CylinderMsb  = (UINT16) (CommandBlockBaseAddr + 0x5);
    582     AtapiBlkIoDev->IdeIoPortReg[Index1].Head         = (UINT16) (CommandBlockBaseAddr + 0x6);
    583     AtapiBlkIoDev->IdeIoPortReg[Index1].Reg.Command  = (UINT16) (CommandBlockBaseAddr + 0x7);
    584 
    585     ControlBlockBaseAddr                = IdeRegsBaseAddr[Index1].ControlBlockBaseAddr;
    586     AtapiBlkIoDev->IdeIoPortReg[Index1].Alt.DeviceControl = ControlBlockBaseAddr;
    587     AtapiBlkIoDev->IdeIoPortReg[Index1].DriveAddress      = (UINT16) (ControlBlockBaseAddr + 0x1);
    588 
    589     //
    590     // Scan IDE bus for ATAPI devices IDE or Sata device
    591     //
    592     for (Index2 = IdeMaster; Index2 < IdeMaxDevice; Index2++) {
    593       //
    594       // Pata & Sata, Primary & Secondary channel, Master & Slave device
    595       //
    596       DevicePosition = (UINTN) (Index1 * 2 + Index2);
    597 
    598       if (DiscoverAtapiDevice (AtapiBlkIoDev, DevicePosition, &MediaInfo, &MediaInfo2)) {
    599         //
    600         // ATAPI Device at DevicePosition is found.
    601         //
    602         AtapiBlkIoDev->DeviceInfo[DeviceCount].DevicePosition = DevicePosition;
    603         //
    604         // Retrieve Media Info
    605         //
    606         Status  = DetectMedia (AtapiBlkIoDev, DevicePosition, &MediaInfo, &MediaInfo2);
    607         CopyMem (&(AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo), &MediaInfo, sizeof (MediaInfo));
    608         CopyMem (&(AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2), &MediaInfo2, sizeof (MediaInfo2));
    609 
    610         DEBUG ((EFI_D_INFO, "Atatpi Device Position is %d\n", DevicePosition));
    611         DEBUG ((EFI_D_INFO, "Atatpi DeviceType is   %d\n", MediaInfo.DeviceType));
    612         DEBUG ((EFI_D_INFO, "Atatpi MediaPresent is %d\n", MediaInfo.MediaPresent));
    613         DEBUG ((EFI_D_INFO, "Atatpi BlockSize is  0x%x\n", MediaInfo.BlockSize));
    614 
    615         if (EFI_ERROR (Status)) {
    616           AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo.MediaPresent = FALSE;
    617           AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo.LastBlock    = 0;
    618           AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2.MediaPresent = FALSE;
    619           AtapiBlkIoDev->DeviceInfo[DeviceCount].MediaInfo2.LastBlock    = 0;
    620         }
    621         DeviceCount += 1;
    622       }
    623     }
    624   }
    625 
    626   AtapiBlkIoDev->DeviceCount = DeviceCount;
    627 }
    628 
    629 /**
    630   Detect Atapi devices.
    631 
    632   @param[in]  AtapiBlkIoDev   A pointer to atapi block IO device.
    633   @param[in]  DevicePosition  An integer to signify device position.
    634   @param[out] MediaInfo       The media information of the specified block media.
    635   @param[out] MediaInfo2      The media information 2 of the specified block media.
    636 
    637   @retval TRUE                Atapi device exists in specified position.
    638   @retval FALSE               Atapi device does not exist in specified position.
    639 
    640 **/
    641 BOOLEAN
    642 DiscoverAtapiDevice (
    643   IN  ATAPI_BLK_IO_DEV              *AtapiBlkIoDev,
    644   IN  UINTN                         DevicePosition,
    645   OUT EFI_PEI_BLOCK_IO_MEDIA        *MediaInfo,
    646   OUT EFI_PEI_BLOCK_IO2_MEDIA       *MediaInfo2
    647   )
    648 {
    649   EFI_STATUS  Status;
    650 
    651   if (!DetectIDEController (AtapiBlkIoDev, DevicePosition)) {
    652     return FALSE;
    653   }
    654   //
    655   // test if it is an ATAPI device (only supported device)
    656   //
    657   if (ATAPIIdentify (AtapiBlkIoDev, DevicePosition) == EFI_SUCCESS) {
    658 
    659     Status = Inquiry (AtapiBlkIoDev, DevicePosition, MediaInfo, MediaInfo2);
    660     if (!EFI_ERROR (Status)) {
    661       return TRUE;
    662     }
    663   }
    664 
    665   return FALSE;
    666 }
    667 
    668 /**
    669   Check power mode of Atapi devices.
    670 
    671   @param[in]  AtapiBlkIoDev   A pointer to atapi block IO device.
    672   @param[in]  DevicePosition  An integer to signify device position.
    673   @param[in]  AtaCommand      The Ata Command passed in.
    674 
    675   @retval EFI_SUCCESS         The Atapi device support power mode.
    676   @retval EFI_NOT_FOUND       The Atapi device not found.
    677   @retval EFI_TIMEOUT         Atapi command transaction is time out.
    678   @retval EFI_ABORTED         Atapi command abort.
    679 
    680 **/
    681 EFI_STATUS
    682 CheckPowerMode (
    683   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
    684   IN  UINTN               DevicePosition,
    685   IN  UINT8               AtaCommand
    686   )
    687 {
    688   UINT8       Channel;
    689   UINT8       Device;
    690   UINT16      StatusRegister;
    691   UINT16      HeadRegister;
    692   UINT16      CommandRegister;
    693   UINT16      ErrorRegister;
    694   UINT16      SectorCountRegister;
    695   EFI_STATUS  Status;
    696   UINT8       StatusValue;
    697   UINT8       ErrorValue;
    698   UINT8       SectorCountValue;
    699 
    700   Channel             = (UINT8) (DevicePosition / 2);
    701   Device              = (UINT8) (DevicePosition % 2);
    702 
    703   ASSERT (Channel < MAX_IDE_CHANNELS);
    704 
    705   StatusRegister      = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
    706   HeadRegister        = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
    707   CommandRegister     = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
    708   ErrorRegister       = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg1.Error;
    709   SectorCountRegister = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorCount;
    710 
    711   //
    712   // select device
    713   //
    714   IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
    715 
    716   //
    717   // refresh the SectorCount register
    718   //
    719   SectorCountValue = 0x55;
    720   IoWrite8 (SectorCountRegister, SectorCountValue);
    721 
    722   //
    723   // select device
    724   //
    725   IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
    726 
    727   Status = DRDYReady (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 100);
    728 
    729   //
    730   // select device
    731   //
    732   IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
    733   //
    734   // send 'check power' commandd via Command Register
    735   //
    736   IoWrite8 (CommandRegister, AtaCommand);
    737 
    738   Status = WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 3000);
    739   if (EFI_ERROR (Status)) {
    740     return EFI_TIMEOUT;
    741   }
    742 
    743   StatusValue = IoRead8 (StatusRegister);
    744 
    745   //
    746   // command returned status is DRDY, indicating device supports the command,
    747   // so device is present.
    748   //
    749   if ((StatusValue & ATA_STSREG_DRDY) == ATA_STSREG_DRDY) {
    750     return EFI_SUCCESS;
    751   }
    752 
    753   SectorCountValue = IoRead8 (SectorCountRegister);
    754 
    755   //
    756   // command returned status is ERR & ABRT_ERR, indicating device does not support
    757   // the command, so device is present.
    758   //
    759   if ((StatusValue & ATA_STSREG_ERR) == ATA_STSREG_ERR) {
    760     ErrorValue = IoRead8 (ErrorRegister);
    761     if ((ErrorValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    762       return EFI_ABORTED;
    763     } else {
    764       //
    765       // According to spec, no other error code is valid
    766       //
    767       return EFI_NOT_FOUND;
    768     }
    769   }
    770 
    771   if ((SectorCountValue == 0x00) || (SectorCountValue == 0x80) || (SectorCountValue == 0xff)) {
    772     //
    773     // Write SectorCount 0x55 but return valid state value. Maybe no device
    774     // exists or some slow kind of ATAPI device exists.
    775     //
    776     IoWrite8 (HeadRegister, (UINT8) ((Device << 4) | 0xe0));
    777 
    778     //
    779     // write 0x55 and 0xaa to SectorCounter register,
    780     // if the data could be written into the register,
    781     // indicating the device is present, otherwise the device is not present.
    782     //
    783     SectorCountValue = 0x55;
    784     IoWrite8 (SectorCountRegister, SectorCountValue);
    785     MicroSecondDelay (10000);
    786 
    787     SectorCountValue = IoRead8 (SectorCountRegister);
    788     if (SectorCountValue != 0x55) {
    789       return EFI_NOT_FOUND;
    790     }
    791     //
    792     // Send a "ATAPI TEST UNIT READY" command ... slow but accurate
    793     //
    794     Status = TestUnitReady (AtapiBlkIoDev, DevicePosition);
    795     return Status;
    796   }
    797 
    798   return EFI_NOT_FOUND;
    799 }
    800 
    801 /**
    802   Detect if an IDE controller exists in specified position.
    803 
    804   @param[in]  AtapiBlkIoDev   A pointer to atapi block IO device.
    805   @param[in]  DevicePosition  An integer to signify device position.
    806 
    807   @retval TRUE         The Atapi device exists.
    808   @retval FALSE        The Atapi device does not present.
    809 
    810 **/
    811 BOOLEAN
    812 DetectIDEController (
    813   IN  ATAPI_BLK_IO_DEV   *AtapiBlkIoDev,
    814   IN  UINTN              DevicePosition
    815   )
    816 {
    817   UINT8       Channel;
    818   EFI_STATUS  Status;
    819   UINT8       AtaCommand;
    820 
    821   Channel           = (UINT8) (DevicePosition / 2);
    822 
    823   ASSERT (Channel < MAX_IDE_CHANNELS);
    824   //
    825   //  Wait 31 seconds for BSY clear
    826   //
    827   Status = WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000);
    828   if (EFI_ERROR (Status)) {
    829     return FALSE;
    830   }
    831   //
    832   // Send 'check power' command for IDE device
    833   //
    834   AtaCommand  = 0xE5;
    835   Status      = CheckPowerMode (AtapiBlkIoDev, DevicePosition, AtaCommand);
    836   if ((Status == EFI_ABORTED) || (Status == EFI_SUCCESS)) {
    837     return TRUE;
    838   }
    839 
    840   return FALSE;
    841 }
    842 
    843 /**
    844   Wait specified time interval to poll for BSY bit clear in the Status Register.
    845 
    846   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
    847   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
    848   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
    849 
    850   @retval EFI_SUCCESS        BSY bit is cleared in the specified time interval.
    851   @retval EFI_TIMEOUT        BSY bit is not cleared in the specified time interval.
    852 
    853 **/
    854 EFI_STATUS
    855 WaitForBSYClear (
    856   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
    857   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
    858   IN  UINTN               TimeoutInMilliSeconds
    859   )
    860 {
    861   UINTN   Delay;
    862   UINT16  StatusRegister;
    863   UINT8   StatusValue;
    864 
    865   StatusValue     = 0;
    866 
    867   StatusRegister  = IdeIoRegisters->Reg.Status;
    868 
    869   Delay           = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
    870   do {
    871     StatusValue = IoRead8 (StatusRegister);
    872     if ((StatusValue & ATA_STSREG_BSY) == 0x00) {
    873       break;
    874     }
    875     MicroSecondDelay (250);
    876 
    877     Delay--;
    878 
    879   } while (Delay != 0);
    880 
    881   if (Delay == 0) {
    882     return EFI_TIMEOUT;
    883   }
    884 
    885   return EFI_SUCCESS;
    886 }
    887 
    888 /**
    889   Wait specified time interval to poll for DRDY bit set in the Status register.
    890 
    891   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
    892   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
    893   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
    894 
    895   @retval EFI_SUCCESS        DRDY bit is set in the specified time interval.
    896   @retval EFI_TIMEOUT        DRDY bit is not set in the specified time interval.
    897 
    898 **/
    899 EFI_STATUS
    900 DRDYReady (
    901   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
    902   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
    903   IN  UINTN               TimeoutInMilliSeconds
    904   )
    905 {
    906   UINTN   Delay;
    907   UINT16  StatusRegister;
    908   UINT8   StatusValue;
    909   UINT8   ErrValue;
    910 
    911   StatusValue     = 0;
    912 
    913   StatusRegister  = IdeIoRegisters->Reg.Status;
    914 
    915   Delay           = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
    916   do {
    917     StatusValue = IoRead8 (StatusRegister);
    918     //
    919     //  BSY == 0 , DRDY == 1
    920     //
    921     if ((StatusValue & (ATA_STSREG_DRDY | ATA_STSREG_BSY)) == ATA_STSREG_DRDY) {
    922       break;
    923     }
    924 
    925   if ((StatusValue & (ATA_STSREG_ERR | ATA_STSREG_BSY)) == ATA_STSREG_ERR) {
    926     ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
    927     if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    928     return EFI_ABORTED;
    929     }
    930   }
    931 
    932     MicroSecondDelay (250);
    933 
    934     Delay--;
    935 
    936   } while (Delay != 0);
    937 
    938   if (Delay == 0) {
    939     return EFI_TIMEOUT;
    940   }
    941 
    942   return EFI_SUCCESS;
    943 }
    944 
    945 /**
    946   Wait specified time interval to poll for DRQ bit clear in the Status Register.
    947 
    948   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
    949   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
    950   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
    951 
    952   @retval EFI_SUCCESS        DRQ bit is cleared in the specified time interval.
    953   @retval EFI_TIMEOUT        DRQ bit is not cleared in the specified time interval.
    954 
    955 **/
    956 EFI_STATUS
    957 DRQClear (
    958   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
    959   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
    960   IN  UINTN               TimeoutInMilliSeconds
    961   )
    962 {
    963   UINTN   Delay;
    964   UINT16  StatusRegister;
    965   UINT8   StatusValue;
    966   UINT8   ErrValue;
    967 
    968   StatusValue     = 0;
    969 
    970   StatusRegister  = IdeIoRegisters->Reg.Status;
    971 
    972   Delay           = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
    973   do {
    974 
    975     StatusValue = IoRead8 (StatusRegister);
    976 
    977     //
    978     // wait for BSY == 0 and DRQ == 0
    979     //
    980     if ((StatusValue & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
    981       break;
    982     }
    983 
    984   if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
    985     ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
    986     if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
    987     return EFI_ABORTED;
    988     }
    989   }
    990 
    991     MicroSecondDelay (250);
    992 
    993     Delay--;
    994   } while (Delay != 0);
    995 
    996   if (Delay == 0) {
    997     return EFI_TIMEOUT;
    998   }
    999 
   1000   return EFI_SUCCESS;
   1001 }
   1002 
   1003 /**
   1004   Wait specified time interval to poll for DRQ bit clear in the Alternate Status Register.
   1005 
   1006   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
   1007   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
   1008   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
   1009 
   1010   @retval EFI_SUCCESS        DRQ bit is cleared in the specified time interval.
   1011   @retval EFI_TIMEOUT        DRQ bit is not cleared in the specified time interval.
   1012 
   1013 **/
   1014 EFI_STATUS
   1015 DRQClear2 (
   1016   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   1017   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
   1018   IN  UINTN               TimeoutInMilliSeconds
   1019   )
   1020 {
   1021   UINTN   Delay;
   1022   UINT16  AltStatusRegister;
   1023   UINT8   AltStatusValue;
   1024   UINT8   ErrValue;
   1025 
   1026   AltStatusValue    = 0;
   1027 
   1028   AltStatusRegister = IdeIoRegisters->Alt.AltStatus;
   1029 
   1030   Delay             = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
   1031   do {
   1032 
   1033     AltStatusValue = IoRead8 (AltStatusRegister);
   1034 
   1035     //
   1036     // wait for BSY == 0 and DRQ == 0
   1037     //
   1038     if ((AltStatusValue & (ATA_STSREG_DRQ | ATA_STSREG_BSY)) == 0) {
   1039       break;
   1040     }
   1041 
   1042   if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
   1043     ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
   1044     if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
   1045     return EFI_ABORTED;
   1046     }
   1047   }
   1048 
   1049     MicroSecondDelay (250);
   1050 
   1051     Delay--;
   1052   } while (Delay != 0);
   1053 
   1054   if (Delay == 0) {
   1055     return EFI_TIMEOUT;
   1056   }
   1057 
   1058   return EFI_SUCCESS;
   1059 }
   1060 
   1061 /**
   1062   Wait specified time interval to poll for DRQ bit set in the Status Register.
   1063 
   1064   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
   1065   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
   1066   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
   1067 
   1068   @retval EFI_SUCCESS        DRQ bit is set in the specified time interval.
   1069   @retval EFI_TIMEOUT        DRQ bit is not set in the specified time interval.
   1070   @retval EFI_ABORTED        Operation Aborted.
   1071 
   1072 **/
   1073 EFI_STATUS
   1074 DRQReady (
   1075   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   1076   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
   1077   IN  UINTN               TimeoutInMilliSeconds
   1078   )
   1079 {
   1080   UINTN   Delay;
   1081   UINT16  StatusRegister;
   1082   UINT8   StatusValue;
   1083   UINT8   ErrValue;
   1084 
   1085   StatusValue     = 0;
   1086   ErrValue        = 0;
   1087 
   1088   StatusRegister  = IdeIoRegisters->Reg.Status;
   1089 
   1090   Delay           = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
   1091   do {
   1092     //
   1093     //  read Status Register will clear interrupt
   1094     //
   1095     StatusValue = IoRead8 (StatusRegister);
   1096 
   1097     //
   1098     //  BSY==0,DRQ==1
   1099     //
   1100     if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
   1101       break;
   1102     }
   1103 
   1104     if ((StatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
   1105 
   1106       ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
   1107       if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
   1108         return EFI_ABORTED;
   1109       }
   1110     }
   1111     MicroSecondDelay (250);
   1112 
   1113     Delay--;
   1114   } while (Delay != 0);
   1115 
   1116   if (Delay == 0) {
   1117     return EFI_TIMEOUT;
   1118   }
   1119 
   1120   return EFI_SUCCESS;
   1121 }
   1122 
   1123 /**
   1124   Wait specified time interval to poll for DRQ bit set in the Alternate Status Register.
   1125 
   1126   @param[in]  AtapiBlkIoDev          A pointer to atapi block IO device.
   1127   @param[in]  IdeIoRegisters         A pointer to IDE IO registers.
   1128   @param[in]  TimeoutInMilliSeconds  Time specified in milliseconds.
   1129 
   1130   @retval EFI_SUCCESS        DRQ bit is set in the specified time interval.
   1131   @retval EFI_TIMEOUT        DRQ bit is not set in the specified time interval.
   1132   @retval EFI_ABORTED        Operation Aborted.
   1133 
   1134 **/
   1135 EFI_STATUS
   1136 DRQReady2 (
   1137   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   1138   IN  IDE_BASE_REGISTERS  *IdeIoRegisters,
   1139   IN  UINTN               TimeoutInMilliSeconds
   1140   )
   1141 {
   1142   UINTN   Delay;
   1143   UINT16  AltStatusRegister;
   1144   UINT8   AltStatusValue;
   1145   UINT8   ErrValue;
   1146 
   1147   AltStatusValue    = 0;
   1148 
   1149   AltStatusRegister = IdeIoRegisters->Alt.AltStatus;
   1150 
   1151   Delay             = ((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 250) + 1;
   1152   do {
   1153 
   1154     AltStatusValue = IoRead8 (AltStatusRegister);
   1155 
   1156     //
   1157     //  BSY==0,DRQ==1
   1158     //
   1159     if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_DRQ)) == ATA_STSREG_DRQ) {
   1160       break;
   1161     }
   1162 
   1163     if ((AltStatusValue & (ATA_STSREG_BSY | ATA_STSREG_ERR)) == ATA_STSREG_ERR) {
   1164 
   1165       ErrValue = IoRead8 (IdeIoRegisters->Reg1.Error);
   1166       if ((ErrValue & ATA_ERRREG_ABRT) == ATA_ERRREG_ABRT) {
   1167         return EFI_ABORTED;
   1168       }
   1169     }
   1170     MicroSecondDelay (250);
   1171 
   1172     Delay--;
   1173   } while (Delay != 0);
   1174 
   1175   if (Delay == 0) {
   1176     return EFI_TIMEOUT;
   1177   }
   1178 
   1179   return EFI_SUCCESS;
   1180 }
   1181 
   1182 /**
   1183   Check if there is an error in Status Register.
   1184 
   1185   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   1186   @param[in]  StatusReg         The address to IDE IO registers.
   1187 
   1188   @retval EFI_SUCCESS        Operation success.
   1189   @retval EFI_DEVICE_ERROR   Device error.
   1190 
   1191 **/
   1192 EFI_STATUS
   1193 CheckErrorStatus (
   1194   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   1195   IN  UINT16              StatusReg
   1196   )
   1197 {
   1198   UINT8 StatusValue;
   1199 
   1200   StatusValue = IoRead8 (StatusReg);
   1201 
   1202   if ((StatusValue & (ATA_STSREG_ERR | ATA_STSREG_DWF | ATA_STSREG_CORR)) == 0) {
   1203 
   1204     return EFI_SUCCESS;
   1205   }
   1206 
   1207   return EFI_DEVICE_ERROR;
   1208 
   1209 }
   1210 
   1211 /**
   1212   Idendify Atapi devices.
   1213 
   1214   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   1215   @param[in]  DevicePosition    An integer to signify device position.
   1216 
   1217   @retval EFI_SUCCESS        Identify successfully.
   1218   @retval EFI_DEVICE_ERROR   Device cannot be identified successfully.
   1219 
   1220 **/
   1221 EFI_STATUS
   1222 ATAPIIdentify (
   1223   IN  ATAPI_BLK_IO_DEV        *AtapiBlkIoDev,
   1224   IN  UINTN                   DevicePosition
   1225   )
   1226 {
   1227   ATAPI_IDENTIFY_DATA  AtapiIdentifyData;
   1228   UINT8                Channel;
   1229   UINT8                Device;
   1230   UINT16               StatusReg;
   1231   UINT16               HeadReg;
   1232   UINT16               CommandReg;
   1233   UINT16               DataReg;
   1234   UINT16               SectorCountReg;
   1235   UINT16               SectorNumberReg;
   1236   UINT16               CylinderLsbReg;
   1237   UINT16               CylinderMsbReg;
   1238 
   1239   UINT32               WordCount;
   1240   UINT32               Increment;
   1241   UINT32               Index;
   1242   UINT32               ByteCount;
   1243   UINT16               *Buffer16;
   1244 
   1245   EFI_STATUS           Status;
   1246 
   1247   ByteCount       = sizeof (AtapiIdentifyData);
   1248   Buffer16        = (UINT16 *) &AtapiIdentifyData;
   1249 
   1250   Channel         = (UINT8) (DevicePosition / 2);
   1251   Device          = (UINT8) (DevicePosition % 2);
   1252 
   1253   ASSERT (Channel < MAX_IDE_CHANNELS);
   1254 
   1255   StatusReg       = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
   1256   HeadReg         = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
   1257   CommandReg      = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
   1258   DataReg         = AtapiBlkIoDev->IdeIoPortReg[Channel].Data;
   1259   SectorCountReg  = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorCount;
   1260   SectorNumberReg = AtapiBlkIoDev->IdeIoPortReg[Channel].SectorNumber;
   1261   CylinderLsbReg  = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderLsb;
   1262   CylinderMsbReg  = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderMsb;
   1263 
   1264   //
   1265   // Send ATAPI Identify Command to get IDENTIFY data.
   1266   //
   1267   if (WaitForBSYClear (
   1268         AtapiBlkIoDev,
   1269         &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
   1270         ATATIMEOUT
   1271         ) != EFI_SUCCESS) {
   1272     return EFI_DEVICE_ERROR;
   1273   }
   1274   //
   1275   // select device via Head/Device register.
   1276   // Before write Head/Device register, BSY and DRQ must be 0.
   1277   //
   1278   if (DRQClear2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), ATATIMEOUT) != EFI_SUCCESS) {
   1279     return EFI_DEVICE_ERROR;
   1280   }
   1281   //
   1282   //  e0:1110,0000-- bit7 and bit5 are reserved bits.
   1283   //           bit6 set means LBA mode
   1284   //
   1285   IoWrite8 (HeadReg, (UINT8) ((Device << 4) | 0xe0));
   1286 
   1287   //
   1288   // set all the command parameters
   1289   // Before write to all the following registers, BSY and DRQ must be 0.
   1290   //
   1291   if (DRQClear2 (
   1292         AtapiBlkIoDev,
   1293         &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
   1294         ATATIMEOUT
   1295         ) != EFI_SUCCESS) {
   1296 
   1297     return EFI_DEVICE_ERROR;
   1298   }
   1299 
   1300   IoWrite8 (SectorCountReg, 0);
   1301   IoWrite8 (SectorNumberReg, 0);
   1302   IoWrite8 (CylinderLsbReg, 0);
   1303   IoWrite8 (CylinderMsbReg, 0);
   1304 
   1305   //
   1306   // send command via Command Register
   1307   //
   1308   IoWrite8 (CommandReg, ATA_CMD_IDENTIFY_DEVICE);
   1309 
   1310   //
   1311   // According to PIO data in protocol, host can perform a series of reads to the
   1312   // data register after each time device set DRQ ready;
   1313   // The data size of "a series of read" is command specific.
   1314   // For most ATA command, data size received from device will not exceed 1 sector,
   1315   // hense the data size for "a series of read" can be the whole data size of one command request.
   1316   // For ATA command such as Read Sector command, whole data size of one ATA command request is often larger
   1317   // than 1 sector, according to the Read Sector command, the data size of "a series of read" is exactly
   1318   // 1 sector.
   1319   // Here for simplification reason, we specify the data size for "a series of read" to
   1320   // 1 sector (256 words) if whole data size of one ATA commmand request is larger than 256 words.
   1321   //
   1322   Increment = 256;
   1323   //
   1324   // 256 words
   1325   //
   1326   WordCount = 0;
   1327   //
   1328   // WordCount is used to record bytes of currently transfered data
   1329   //
   1330   while (WordCount < ByteCount / 2) {
   1331     //
   1332     // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
   1333     //
   1334     Status = DRQReady2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), ATATIMEOUT);
   1335     if (Status != EFI_SUCCESS) {
   1336       return Status;
   1337     }
   1338 
   1339     if (CheckErrorStatus (AtapiBlkIoDev, StatusReg) != EFI_SUCCESS) {
   1340 
   1341       return EFI_DEVICE_ERROR;
   1342     }
   1343     //
   1344     // Get the byte count for one series of read
   1345     //
   1346     if ((WordCount + Increment) > ByteCount / 2) {
   1347       Increment = ByteCount / 2 - WordCount;
   1348     }
   1349     //
   1350     // perform a series of read without check DRQ ready
   1351     //
   1352     for (Index = 0; Index < Increment; Index++) {
   1353       *Buffer16++ = IoRead16 (DataReg);
   1354     }
   1355 
   1356     WordCount += Increment;
   1357 
   1358   }
   1359   //
   1360   // while
   1361   //
   1362   if (DRQClear (
   1363         AtapiBlkIoDev,
   1364         &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
   1365         ATATIMEOUT
   1366         ) != EFI_SUCCESS) {
   1367     return CheckErrorStatus (AtapiBlkIoDev, StatusReg);
   1368   }
   1369 
   1370   return EFI_SUCCESS;
   1371 
   1372 }
   1373 
   1374 /**
   1375   Sends out ATAPI Test Unit Ready Packet Command to the specified device
   1376   to find out whether device is accessible.
   1377 
   1378   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   1379   @param[in]  DevicePosition    An integer to signify device position.
   1380 
   1381   @retval EFI_SUCCESS        TestUnit command executed successfully.
   1382   @retval EFI_DEVICE_ERROR   Device cannot be executed TestUnit command successfully.
   1383 
   1384 **/
   1385 EFI_STATUS
   1386 TestUnitReady (
   1387   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   1388   IN  UINTN               DevicePosition
   1389   )
   1390 {
   1391   ATAPI_PACKET_COMMAND  Packet;
   1392   EFI_STATUS            Status;
   1393 
   1394   //
   1395   // fill command packet
   1396   //
   1397   ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   1398   Packet.TestUnitReady.opcode = ATA_CMD_TEST_UNIT_READY;
   1399 
   1400   //
   1401   // send command packet
   1402   //
   1403   Status = AtapiPacketCommandIn (AtapiBlkIoDev, DevicePosition, &Packet, NULL, 0, ATAPITIMEOUT);
   1404   return Status;
   1405 }
   1406 
   1407 /**
   1408   Send out ATAPI commands conforms to the Packet Command with PIO Data In Protocol.
   1409 
   1410   @param[in]  AtapiBlkIoDev         A pointer to atapi block IO device.
   1411   @param[in]  DevicePosition        An integer to signify device position.
   1412   @param[in]  Packet                A pointer to ATAPI command packet.
   1413   @param[in]  Buffer                Buffer to contain requested transfer data from device.
   1414   @param[in]  ByteCount             Requested transfer data length.
   1415   @param[in]  TimeoutInMilliSeconds Time out value, in unit of milliseconds.
   1416 
   1417   @retval EFI_SUCCESS        Command executed successfully.
   1418   @retval EFI_DEVICE_ERROR   Device cannot be executed command successfully.
   1419 
   1420 **/
   1421 EFI_STATUS
   1422 AtapiPacketCommandIn (
   1423   IN  ATAPI_BLK_IO_DEV      *AtapiBlkIoDev,
   1424   IN  UINTN                 DevicePosition,
   1425   IN  ATAPI_PACKET_COMMAND  *Packet,
   1426   IN  UINT16                *Buffer,
   1427   IN  UINT32                ByteCount,
   1428   IN  UINTN                 TimeoutInMilliSeconds
   1429   )
   1430 {
   1431   UINT8       Channel;
   1432   UINT8       Device;
   1433   UINT16      StatusReg;
   1434   UINT16      HeadReg;
   1435   UINT16      CommandReg;
   1436   UINT16      FeatureReg;
   1437   UINT16      CylinderLsbReg;
   1438   UINT16      CylinderMsbReg;
   1439   UINT16      DeviceControlReg;
   1440   UINT16      DataReg;
   1441   EFI_STATUS  Status;
   1442   UINT32      Count;
   1443   UINT16      *CommandIndex;
   1444   UINT16      *PtrBuffer;
   1445   UINT32      Index;
   1446   UINT8       StatusValue;
   1447   UINT32      WordCount;
   1448 
   1449   //
   1450   // required transfer data in word unit.
   1451   //
   1452   UINT32      RequiredWordCount;
   1453 
   1454   //
   1455   // actual transfer data in word unit.
   1456   //
   1457   UINT32      ActualWordCount;
   1458 
   1459   Channel           = (UINT8) (DevicePosition / 2);
   1460   Device            = (UINT8) (DevicePosition % 2);
   1461 
   1462   ASSERT (Channel < MAX_IDE_CHANNELS);
   1463 
   1464   StatusReg         = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Status;
   1465   HeadReg           = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
   1466   CommandReg        = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
   1467   FeatureReg        = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg1.Feature;
   1468   CylinderLsbReg    = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderLsb;
   1469   CylinderMsbReg    = AtapiBlkIoDev->IdeIoPortReg[Channel].CylinderMsb;
   1470   DeviceControlReg  = AtapiBlkIoDev->IdeIoPortReg[Channel].Alt.DeviceControl;
   1471   DataReg           = AtapiBlkIoDev->IdeIoPortReg[Channel].Data;
   1472 
   1473   //
   1474   // Set all the command parameters by fill related registers.
   1475   // Before write to all the following registers, BSY and DRQ must be 0.
   1476   //
   1477   if (DRQClear2 (
   1478         AtapiBlkIoDev,
   1479         &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
   1480         ATATIMEOUT
   1481         ) != EFI_SUCCESS) {
   1482     return EFI_DEVICE_ERROR;
   1483   }
   1484   //
   1485   // Select device via Device/Head Register.
   1486   // DEFAULT_CMD: 0xa0 (1010,0000)
   1487   //
   1488   IoWrite8 (HeadReg, (UINT8) ((Device << 4) | ATA_DEFAULT_CMD));
   1489 
   1490   //
   1491   // No OVL; No DMA
   1492   //
   1493   IoWrite8 (FeatureReg, 0x00);
   1494 
   1495   //
   1496   // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
   1497   // determine how many data should be transfered.
   1498   //
   1499   IoWrite8 (CylinderLsbReg, (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff));
   1500   IoWrite8 (CylinderMsbReg, (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8));
   1501 
   1502   //
   1503   //  DEFAULT_CTL:0x0a (0000,1010)
   1504   //  Disable interrupt
   1505   //
   1506   IoWrite8 (DeviceControlReg, ATA_DEFAULT_CTL);
   1507 
   1508   //
   1509   // Send Packet command to inform device
   1510   // that the following data bytes are command packet.
   1511   //
   1512   IoWrite8 (CommandReg, ATA_CMD_PACKET);
   1513 
   1514   Status = DRQReady (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), TimeoutInMilliSeconds);
   1515   if (Status != EFI_SUCCESS) {
   1516     return Status;
   1517   }
   1518   //
   1519   // Send out command packet
   1520   //
   1521   CommandIndex = Packet->Data16;
   1522   for (Count = 0; Count < 6; Count++, CommandIndex++) {
   1523     IoWrite16 (DataReg, *CommandIndex);
   1524     MicroSecondDelay (10);
   1525   }
   1526 
   1527   StatusValue = IoRead8 (StatusReg);
   1528   if ((StatusValue & ATA_STSREG_ERR) == ATA_STSREG_ERR) {
   1529     //
   1530     // Trouble! Something's wrong here... Wait some time and return. 3 second is
   1531     // supposed to be long enough for a device reset latency or error recovery
   1532     //
   1533     MicroSecondDelay (3000000);
   1534     return EFI_DEVICE_ERROR;
   1535   }
   1536 
   1537   if (Buffer == NULL || ByteCount == 0) {
   1538     return EFI_SUCCESS;
   1539   }
   1540   //
   1541   // call PioReadWriteData() function to get
   1542   // requested transfer data form device.
   1543   //
   1544   PtrBuffer         = Buffer;
   1545   RequiredWordCount = ByteCount / 2;
   1546   //
   1547   // ActuralWordCount means the word count of data really transfered.
   1548   //
   1549   ActualWordCount = 0;
   1550 
   1551   Status          = EFI_SUCCESS;
   1552   while ((Status == EFI_SUCCESS) && (ActualWordCount < RequiredWordCount)) {
   1553     //
   1554     // before each data transfer stream, the host should poll DRQ bit ready,
   1555     // which informs device is ready to transfer data.
   1556     //
   1557     if (DRQReady2 (
   1558           AtapiBlkIoDev,
   1559           &(AtapiBlkIoDev->IdeIoPortReg[Channel]),
   1560           TimeoutInMilliSeconds
   1561           ) != EFI_SUCCESS) {
   1562       return CheckErrorStatus (AtapiBlkIoDev, StatusReg);
   1563     }
   1564     //
   1565     // read Status Register will clear interrupt
   1566     //
   1567     StatusValue = IoRead8 (StatusReg);
   1568 
   1569     //
   1570     // get current data transfer size from Cylinder Registers.
   1571     //
   1572     WordCount = IoRead8 (CylinderMsbReg) << 8;
   1573     WordCount = WordCount | IoRead8 (CylinderLsbReg);
   1574     WordCount = WordCount & 0xffff;
   1575     WordCount /= 2;
   1576 
   1577     //
   1578     // perform a series data In/Out.
   1579     //
   1580     for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) {
   1581 
   1582       *PtrBuffer = IoRead16 (DataReg);
   1583 
   1584       PtrBuffer++;
   1585 
   1586     }
   1587 
   1588     if (((ATAPI_REQUEST_SENSE_CMD *) Packet)->opcode == ATA_CMD_REQUEST_SENSE && ActualWordCount >= 4) {
   1589       RequiredWordCount = MIN (
   1590                             RequiredWordCount,
   1591                             (UINT32) (4 + (((ATAPI_REQUEST_SENSE_DATA *) Buffer)->addnl_sense_length / 2))
   1592                             );
   1593     }
   1594 
   1595   }
   1596   //
   1597   // After data transfer is completed, normally, DRQ bit should clear.
   1598   //
   1599   Status = DRQClear2 (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), TimeoutInMilliSeconds);
   1600   if (Status != EFI_SUCCESS) {
   1601     return EFI_DEVICE_ERROR;
   1602   }
   1603   //
   1604   // read status register to check whether error happens.
   1605   //
   1606   Status = CheckErrorStatus (AtapiBlkIoDev, StatusReg);
   1607   return Status;
   1608 }
   1609 
   1610 /**
   1611   Sends out ATAPI Inquiry Packet Command to the specified device.
   1612   This command will return INQUIRY data of the device.
   1613 
   1614   @param[in]  AtapiBlkIoDev   A pointer to atapi block IO device.
   1615   @param[in]  DevicePosition  An integer to signify device position.
   1616   @param[out] MediaInfo       The media information of the specified block media.
   1617   @param[out] MediaInfo2      The media information 2 of the specified block media.
   1618 
   1619   @retval EFI_SUCCESS        Command executed successfully.
   1620   @retval EFI_DEVICE_ERROR   Device cannot be executed command successfully.
   1621   @retval EFI_UNSUPPORTED    Unsupported device type.
   1622 
   1623 **/
   1624 EFI_STATUS
   1625 Inquiry (
   1626   IN  ATAPI_BLK_IO_DEV              *AtapiBlkIoDev,
   1627   IN  UINTN                         DevicePosition,
   1628   OUT EFI_PEI_BLOCK_IO_MEDIA        *MediaInfo,
   1629   OUT EFI_PEI_BLOCK_IO2_MEDIA       *MediaInfo2
   1630   )
   1631 {
   1632   ATAPI_PACKET_COMMAND        Packet;
   1633   EFI_STATUS                  Status;
   1634   ATAPI_INQUIRY_DATA          Idata;
   1635 
   1636   //
   1637   // prepare command packet for the ATAPI Inquiry Packet Command.
   1638   //
   1639   ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   1640   ZeroMem (&Idata, sizeof (ATAPI_INQUIRY_DATA));
   1641 
   1642   Packet.Inquiry.opcode             = ATA_CMD_INQUIRY;
   1643   Packet.Inquiry.page_code          = 0;
   1644   Packet.Inquiry.allocation_length  = (UINT8) sizeof (ATAPI_INQUIRY_DATA);
   1645 
   1646   //
   1647   // Send command packet and get requested Inquiry data.
   1648   //
   1649   Status = AtapiPacketCommandIn (
   1650             AtapiBlkIoDev,
   1651             DevicePosition,
   1652             &Packet,
   1653             (UINT16 *) (&Idata),
   1654             sizeof (ATAPI_INQUIRY_DATA),
   1655             ATAPITIMEOUT
   1656             //50
   1657             );
   1658 
   1659   if (Status != EFI_SUCCESS) {
   1660     return EFI_DEVICE_ERROR;
   1661   }
   1662   //
   1663   // Identify device type via INQUIRY data.
   1664   //
   1665   switch (Idata.peripheral_type & 0x1f) {
   1666   case 0x00:
   1667     //
   1668     // Magnetic Disk
   1669     //
   1670     MediaInfo->DeviceType   = IdeLS120;
   1671     MediaInfo->MediaPresent = FALSE;
   1672     MediaInfo->LastBlock    = 0;
   1673     MediaInfo->BlockSize    = 0x200;
   1674     MediaInfo2->InterfaceType  = MSG_ATAPI_DP;
   1675     MediaInfo2->RemovableMedia = TRUE;
   1676     MediaInfo2->MediaPresent   = FALSE;
   1677     MediaInfo2->ReadOnly       = FALSE;
   1678     MediaInfo2->BlockSize      = 0x200;
   1679     MediaInfo2->LastBlock      = 0;
   1680     break;
   1681 
   1682   case 0x05:
   1683     //
   1684     // CD-ROM
   1685     //
   1686     MediaInfo->DeviceType   = IdeCDROM;
   1687     MediaInfo->MediaPresent = FALSE;
   1688     MediaInfo->LastBlock    = 0;
   1689     MediaInfo->BlockSize    = 0x800;
   1690     MediaInfo2->InterfaceType  = MSG_ATAPI_DP;
   1691     MediaInfo2->RemovableMedia = TRUE;
   1692     MediaInfo2->MediaPresent   = FALSE;
   1693     MediaInfo2->ReadOnly       = TRUE;
   1694     MediaInfo2->BlockSize      = 0x200;
   1695     MediaInfo2->LastBlock      = 0;
   1696     break;
   1697 
   1698   default:
   1699     return EFI_UNSUPPORTED;
   1700   }
   1701 
   1702   return EFI_SUCCESS;
   1703 }
   1704 
   1705 /**
   1706   Used before read/write blocks from/to ATAPI device media.
   1707   Since ATAPI device media is removable, it is necessary to detect
   1708   whether media is present and get current present media's information.
   1709 
   1710   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   1711   @param[in]  DevicePosition    An integer to signify device position.
   1712   @param[in, out] MediaInfo     The media information of the specified block media.
   1713   @param[in, out] MediaInfo2    The media information 2 of the specified block media.
   1714 
   1715   @retval EFI_SUCCESS           Command executed successfully.
   1716   @retval EFI_DEVICE_ERROR      Some device errors happen.
   1717   @retval EFI_OUT_OF_RESOURCES  Can not allocate required resources.
   1718 
   1719 **/
   1720 EFI_STATUS
   1721 DetectMedia (
   1722   IN  ATAPI_BLK_IO_DEV              *AtapiBlkIoDev,
   1723   IN  UINTN                         DevicePosition,
   1724   IN OUT EFI_PEI_BLOCK_IO_MEDIA     *MediaInfo,
   1725   IN OUT EFI_PEI_BLOCK_IO2_MEDIA    *MediaInfo2
   1726   )
   1727 {
   1728 
   1729   UINTN                     Index;
   1730   UINTN                     RetryNum;
   1731   UINTN                     MaxRetryNum;
   1732   ATAPI_REQUEST_SENSE_DATA  *SenseBuffers;
   1733   BOOLEAN                   NeedReadCapacity;
   1734   BOOLEAN                   NeedRetry;
   1735   EFI_STATUS                Status;
   1736   UINT8                     SenseCounts;
   1737 
   1738   SenseBuffers = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*SenseBuffers)));
   1739   if (SenseBuffers == NULL) {
   1740     return EFI_OUT_OF_RESOURCES;
   1741   }
   1742 
   1743   //
   1744   // Test Unit Ready command is used to detect whether device is accessible,
   1745   // the device will produce corresponding Sense data.
   1746   //
   1747   for (Index = 0; Index < 2; Index++) {
   1748 
   1749     Status = TestUnitReady (AtapiBlkIoDev, DevicePosition);
   1750     if (Status != EFI_SUCCESS) {
   1751       Status = ResetDevice (AtapiBlkIoDev, DevicePosition, FALSE);
   1752 
   1753       if (Status != EFI_SUCCESS) {
   1754         ResetDevice (AtapiBlkIoDev, DevicePosition, TRUE);
   1755       }
   1756 
   1757     } else {
   1758       break;
   1759     }
   1760   }
   1761 
   1762   SenseCounts       = MAX_SENSE_KEY_COUNT;
   1763   Status            = EFI_SUCCESS;
   1764   NeedReadCapacity  = TRUE;
   1765 
   1766   for (Index = 0; Index < 5; Index++) {
   1767     SenseCounts = MAX_SENSE_KEY_COUNT;
   1768     Status = RequestSense (
   1769               AtapiBlkIoDev,
   1770               DevicePosition,
   1771               SenseBuffers,
   1772               &SenseCounts
   1773               );
   1774     DEBUG ((EFI_D_INFO, "Atapi Request Sense Count is %d\n", SenseCounts));
   1775     if (IsDeviceStateUnclear (SenseBuffers, SenseCounts) || IsNoMedia (SenseBuffers, SenseCounts)) {
   1776       //
   1777       // We are not sure whether the media is present or not, try again
   1778       //
   1779       TestUnitReady (AtapiBlkIoDev, DevicePosition);
   1780     } else {
   1781       break;
   1782     }
   1783   }
   1784 
   1785   if (Status == EFI_SUCCESS) {
   1786 
   1787     if (IsNoMedia (SenseBuffers, SenseCounts)) {
   1788 
   1789       NeedReadCapacity        = FALSE;
   1790       MediaInfo->MediaPresent = FALSE;
   1791       MediaInfo->LastBlock    = 0;
   1792       MediaInfo2->MediaPresent = FALSE;
   1793       MediaInfo2->LastBlock    = 0;
   1794     }
   1795 
   1796     if (IsMediaError (SenseBuffers, SenseCounts)) {
   1797       return EFI_DEVICE_ERROR;
   1798     }
   1799   }
   1800 
   1801   if (NeedReadCapacity) {
   1802     //
   1803     // at most retry 5 times
   1804     //
   1805     MaxRetryNum = 5;
   1806     RetryNum    = 1;
   1807     //
   1808     // initial retry once
   1809     //
   1810     for (Index = 0; (Index < RetryNum) && (Index < MaxRetryNum); Index++) {
   1811 
   1812       Status = ReadCapacity (AtapiBlkIoDev, DevicePosition, MediaInfo, MediaInfo2);
   1813       MicroSecondDelay (200000);
   1814       SenseCounts = MAX_SENSE_KEY_COUNT;
   1815 
   1816       if (Status != EFI_SUCCESS) {
   1817 
   1818         Status = RequestSense (AtapiBlkIoDev, DevicePosition, SenseBuffers, &SenseCounts);
   1819         //
   1820         // If Request Sense data failed, reset the device and retry.
   1821         //
   1822         if (Status != EFI_SUCCESS) {
   1823 
   1824           Status = ResetDevice (AtapiBlkIoDev, DevicePosition, FALSE);
   1825           //
   1826           // if ATAPI soft reset fail,
   1827           // use stronger reset mechanism -- ATA soft reset.
   1828           //
   1829           if (Status != EFI_SUCCESS) {
   1830             ResetDevice (AtapiBlkIoDev, DevicePosition, TRUE);
   1831           }
   1832 
   1833           RetryNum++;
   1834           //
   1835           // retry once more
   1836           //
   1837           continue;
   1838         }
   1839         //
   1840         // No Media
   1841         //
   1842         if (IsNoMedia (SenseBuffers, SenseCounts)) {
   1843 
   1844           MediaInfo->MediaPresent = FALSE;
   1845           MediaInfo->LastBlock    = 0;
   1846           MediaInfo2->MediaPresent = FALSE;
   1847           MediaInfo2->LastBlock    = 0;
   1848           break;
   1849         }
   1850 
   1851         if (IsMediaError (SenseBuffers, SenseCounts)) {
   1852           return EFI_DEVICE_ERROR;
   1853         }
   1854 
   1855         if (!IsDriveReady (SenseBuffers, SenseCounts, &NeedRetry)) {
   1856           //
   1857           // Drive not ready: if NeedRetry, then retry once more;
   1858           // else return error
   1859           //
   1860           if (NeedRetry) {
   1861             RetryNum++;
   1862             continue;
   1863           } else {
   1864             return EFI_DEVICE_ERROR;
   1865           }
   1866         }
   1867         //
   1868         // if read capacity fail not for above reasons, retry once more
   1869         //
   1870         RetryNum++;
   1871 
   1872       }
   1873 
   1874     }
   1875 
   1876   }
   1877 
   1878   return EFI_SUCCESS;
   1879 }
   1880 
   1881 /**
   1882   Reset specified Atapi device.
   1883 
   1884   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   1885   @param[in]  DevicePosition    An integer to signify device position.
   1886   @param[in]  Extensive         If TRUE, use ATA soft reset, otherwise use Atapi soft reset.
   1887 
   1888   @retval EFI_SUCCESS           Command executed successfully.
   1889   @retval EFI_DEVICE_ERROR      Some device errors happen.
   1890 
   1891 **/
   1892 EFI_STATUS
   1893 ResetDevice (
   1894   IN  ATAPI_BLK_IO_DEV  *AtapiBlkIoDev,
   1895   IN  UINTN             DevicePosition,
   1896   IN  BOOLEAN           Extensive
   1897   )
   1898 {
   1899   UINT8   DevControl;
   1900   UINT8   Command;
   1901   UINT8   DeviceSelect;
   1902   UINT16  DeviceControlReg;
   1903   UINT16  CommandReg;
   1904   UINT16  HeadReg;
   1905   UINT8   Channel;
   1906   UINT8   Device;
   1907 
   1908   Channel           = (UINT8) (DevicePosition / 2);
   1909   Device            = (UINT8) (DevicePosition % 2);
   1910 
   1911   ASSERT (Channel < MAX_IDE_CHANNELS);
   1912 
   1913   DeviceControlReg  = AtapiBlkIoDev->IdeIoPortReg[Channel].Alt.DeviceControl;
   1914   CommandReg        = AtapiBlkIoDev->IdeIoPortReg[Channel].Reg.Command;
   1915   HeadReg           = AtapiBlkIoDev->IdeIoPortReg[Channel].Head;
   1916 
   1917   if (Extensive) {
   1918 
   1919     DevControl = 0;
   1920     DevControl |= ATA_CTLREG_SRST;
   1921     //
   1922     // set SRST bit to initiate soft reset
   1923     //
   1924     DevControl |= BIT1;
   1925     //
   1926     // disable Interrupt
   1927     //
   1928     IoWrite8 (DeviceControlReg, DevControl);
   1929 
   1930     //
   1931     // Wait 10us
   1932     //
   1933     MicroSecondDelay (10);
   1934 
   1935     //
   1936     // Clear SRST bit
   1937     //
   1938     DevControl &= 0xfb;
   1939     //
   1940     // 0xfb:1111,1011
   1941     //
   1942     IoWrite8 (DeviceControlReg, DevControl);
   1943 
   1944     //
   1945     // slave device needs at most 31s to clear BSY
   1946     //
   1947     if (WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000) == EFI_TIMEOUT) {
   1948       return EFI_DEVICE_ERROR;
   1949     }
   1950 
   1951   } else {
   1952     //
   1953     // for ATAPI device, no need to wait DRDY ready after device selecting.
   1954     // bit7 and bit5 are both set to 1 for backward compatibility
   1955     //
   1956     DeviceSelect = (UINT8) (((BIT7 | BIT5) | (Device << 4)));
   1957     IoWrite8 (HeadReg, DeviceSelect);
   1958 
   1959     Command = ATA_CMD_SOFT_RESET;
   1960     IoWrite8 (CommandReg, Command);
   1961 
   1962     //
   1963     // BSY cleared is the only status return to the host by the device when reset is completed
   1964     // slave device needs at most 31s to clear BSY
   1965     //
   1966     if (WaitForBSYClear (AtapiBlkIoDev, &(AtapiBlkIoDev->IdeIoPortReg[Channel]), 31000) != EFI_SUCCESS) {
   1967       return EFI_DEVICE_ERROR;
   1968     }
   1969     //
   1970     // stall 5 seconds to make the device status stable
   1971     //
   1972     MicroSecondDelay (STALL_1_SECONDS * 5);
   1973   }
   1974 
   1975   return EFI_SUCCESS;
   1976 
   1977 }
   1978 
   1979 /**
   1980   Sends out ATAPI Request Sense Packet Command to the specified device.
   1981 
   1982   @param[in]      AtapiBlkIoDev   A pointer to atapi block IO device.
   1983   @param[in]      DevicePosition  An integer to signify device position.
   1984   @param[in]      SenseBuffers    Pointer to sense buffer.
   1985   @param[in, out] SenseCounts     Length of sense buffer.
   1986 
   1987   @retval EFI_SUCCESS           Command executed successfully.
   1988   @retval EFI_DEVICE_ERROR      Some device errors happen.
   1989 
   1990 **/
   1991 EFI_STATUS
   1992 RequestSense (
   1993   IN  ATAPI_BLK_IO_DEV           *AtapiBlkIoDev,
   1994   IN  UINTN                      DevicePosition,
   1995   IN  ATAPI_REQUEST_SENSE_DATA   *SenseBuffers,
   1996   IN  OUT  UINT8                 *SenseCounts
   1997   )
   1998 {
   1999   EFI_STATUS            Status;
   2000   ATAPI_REQUEST_SENSE_DATA    *Sense;
   2001   UINT16                *Ptr;
   2002   BOOLEAN               SenseReq;
   2003   ATAPI_PACKET_COMMAND  Packet;
   2004 
   2005   ZeroMem (SenseBuffers, sizeof (ATAPI_REQUEST_SENSE_DATA) * (*SenseCounts));
   2006   //
   2007   // fill command packet for Request Sense Packet Command
   2008   //
   2009   ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   2010   Packet.RequestSence.opcode            = ATA_CMD_REQUEST_SENSE;
   2011   Packet.RequestSence.allocation_length = (UINT8) sizeof (ATAPI_REQUEST_SENSE_DATA);
   2012 
   2013   Ptr = (UINT16 *) SenseBuffers;
   2014   //
   2015   // initialize pointer
   2016   //
   2017   *SenseCounts = 0;
   2018   //
   2019   //  request sense data from device continiously until no sense data exists in the device.
   2020   //
   2021   for (SenseReq = TRUE; SenseReq;) {
   2022 
   2023     Sense = (ATAPI_REQUEST_SENSE_DATA *) Ptr;
   2024 
   2025     //
   2026     // send out Request Sense Packet Command and get one Sense data form device
   2027     //
   2028     Status = AtapiPacketCommandIn (
   2029               AtapiBlkIoDev,
   2030               DevicePosition,
   2031               &Packet,
   2032               Ptr,
   2033               sizeof (ATAPI_REQUEST_SENSE_DATA),
   2034               ATAPITIMEOUT
   2035               );
   2036     //
   2037     // failed to get Sense data
   2038     //
   2039     if (Status != EFI_SUCCESS) {
   2040       if (*SenseCounts == 0) {
   2041         return EFI_DEVICE_ERROR;
   2042       } else {
   2043         return EFI_SUCCESS;
   2044       }
   2045     }
   2046 
   2047     (*SenseCounts)++;
   2048 
   2049     if (*SenseCounts > MAX_SENSE_KEY_COUNT) {
   2050       return EFI_SUCCESS;
   2051     }
   2052     //
   2053     // We limit MAX sense data count to 20 in order to avoid dead loop. Some
   2054     // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
   2055     // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
   2056     // supposed to be large enough for any ATAPI device.
   2057     //
   2058     if ((Sense->sense_key != ATA_SK_NO_SENSE) && ((*SenseCounts) < 20)) {
   2059 
   2060       Ptr += sizeof (ATAPI_REQUEST_SENSE_DATA) / 2;
   2061       //
   2062       // Ptr is word based pointer
   2063       //
   2064     } else {
   2065       //
   2066       // when no sense key, skip out the loop
   2067       //
   2068       SenseReq = FALSE;
   2069     }
   2070   }
   2071 
   2072   return EFI_SUCCESS;
   2073 }
   2074 
   2075 /**
   2076   Sends out ATAPI Read Capacity Packet Command to the specified device.
   2077   This command will return the information regarding the capacity of the
   2078   media in the device.
   2079 
   2080   @param[in]  AtapiBlkIoDev     A pointer to atapi block IO device.
   2081   @param[in]  DevicePosition    An integer to signify device position.
   2082   @param[in, out] MediaInfo     The media information of the specified block media.
   2083   @param[in, out] MediaInfo2    The media information 2 of the specified block media.
   2084 
   2085   @retval EFI_SUCCESS           Command executed successfully.
   2086   @retval EFI_DEVICE_ERROR      Some device errors happen.
   2087 
   2088 **/
   2089 EFI_STATUS
   2090 ReadCapacity (
   2091   IN  ATAPI_BLK_IO_DEV              *AtapiBlkIoDev,
   2092   IN  UINTN                         DevicePosition,
   2093   IN OUT EFI_PEI_BLOCK_IO_MEDIA     *MediaInfo,
   2094   IN OUT EFI_PEI_BLOCK_IO2_MEDIA    *MediaInfo2
   2095   )
   2096 {
   2097   EFI_STATUS                Status;
   2098   ATAPI_PACKET_COMMAND      Packet;
   2099 
   2100   //
   2101   // used for capacity data returned from ATAPI device
   2102   //
   2103   ATAPI_READ_CAPACITY_DATA        Data;
   2104   ATAPI_READ_FORMAT_CAPACITY_DATA FormatData;
   2105 
   2106   ZeroMem (&Data, sizeof (Data));
   2107   ZeroMem (&FormatData, sizeof (FormatData));
   2108 
   2109   if (MediaInfo->DeviceType == IdeCDROM) {
   2110 
   2111     ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   2112     Packet.Inquiry.opcode = ATA_CMD_READ_CAPACITY;
   2113     Status = AtapiPacketCommandIn (
   2114               AtapiBlkIoDev,
   2115               DevicePosition,
   2116               &Packet,
   2117               (UINT16 *) (&Data),
   2118               sizeof (ATAPI_READ_CAPACITY_DATA),
   2119               ATAPITIMEOUT
   2120               );
   2121 
   2122   } else {
   2123     //
   2124     // DeviceType == IdeLS120
   2125     //
   2126     ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   2127     Packet.ReadFormatCapacity.opcode                = ATA_CMD_READ_FORMAT_CAPACITY;
   2128     Packet.ReadFormatCapacity.allocation_length_lo  = 12;
   2129     Status = AtapiPacketCommandIn (
   2130               AtapiBlkIoDev,
   2131               DevicePosition,
   2132               &Packet,
   2133               (UINT16 *) (&FormatData),
   2134               sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA),
   2135               ATAPITIMEOUT*10
   2136               );
   2137   }
   2138 
   2139   if (Status == EFI_SUCCESS) {
   2140 
   2141     if (MediaInfo->DeviceType == IdeCDROM) {
   2142 
   2143       MediaInfo->LastBlock    = (Data.LastLba3 << 24) | (Data.LastLba2 << 16) | (Data.LastLba1 << 8) | Data.LastLba0;
   2144       MediaInfo->MediaPresent = TRUE;
   2145       //
   2146       // Because the user data portion in the sector of the Data CD supported
   2147       // is always 800h
   2148       //
   2149       MediaInfo->BlockSize     = 0x800;
   2150 
   2151       MediaInfo2->LastBlock    = MediaInfo->LastBlock;
   2152       MediaInfo2->MediaPresent = MediaInfo->MediaPresent;
   2153       MediaInfo2->BlockSize    = (UINT32)MediaInfo->BlockSize;
   2154     }
   2155 
   2156     if (MediaInfo->DeviceType == IdeLS120) {
   2157 
   2158       if (FormatData.DesCode == 3) {
   2159         MediaInfo->MediaPresent = FALSE;
   2160         MediaInfo->LastBlock    = 0;
   2161         MediaInfo2->MediaPresent = FALSE;
   2162         MediaInfo2->LastBlock    = 0;
   2163       } else {
   2164         MediaInfo->LastBlock = (FormatData.LastLba3 << 24) |
   2165           (FormatData.LastLba2 << 16) |
   2166           (FormatData.LastLba1 << 8) |
   2167           FormatData.LastLba0;
   2168         MediaInfo->LastBlock--;
   2169 
   2170         MediaInfo->MediaPresent = TRUE;
   2171 
   2172         MediaInfo->BlockSize    = 0x200;
   2173 
   2174         MediaInfo2->LastBlock    = MediaInfo->LastBlock;
   2175         MediaInfo2->MediaPresent = MediaInfo->MediaPresent;
   2176         MediaInfo2->BlockSize    = (UINT32)MediaInfo->BlockSize;
   2177 
   2178       }
   2179     }
   2180 
   2181     return EFI_SUCCESS;
   2182 
   2183   } else {
   2184     return EFI_DEVICE_ERROR;
   2185   }
   2186 }
   2187 
   2188 /**
   2189   Perform read from disk in block unit.
   2190 
   2191   @param[in]  AtapiBlkIoDev   A pointer to atapi block IO device.
   2192   @param[in]  DevicePosition  An integer to signify device position.
   2193   @param[in]  Buffer          Buffer to contain read data.
   2194   @param[in]  StartLba        Starting LBA address.
   2195   @param[in]  NumberOfBlocks  Number of blocks to read.
   2196   @param[in]  BlockSize       Size of each block.
   2197 
   2198   @retval EFI_SUCCESS           Command executed successfully.
   2199   @retval EFI_DEVICE_ERROR      Some device errors happen.
   2200 
   2201 **/
   2202 EFI_STATUS
   2203 ReadSectors (
   2204   IN  ATAPI_BLK_IO_DEV    *AtapiBlkIoDev,
   2205   IN  UINTN               DevicePosition,
   2206   IN  VOID                *Buffer,
   2207   IN  EFI_PEI_LBA         StartLba,
   2208   IN  UINTN               NumberOfBlocks,
   2209   IN  UINTN               BlockSize
   2210   )
   2211 {
   2212 
   2213   ATAPI_PACKET_COMMAND  Packet;
   2214   ATAPI_READ10_CMD      *Read10Packet;
   2215   EFI_STATUS            Status;
   2216   UINTN                 BlocksRemaining;
   2217   UINT32                Lba32;
   2218   UINT32                ByteCount;
   2219   UINT16                SectorCount;
   2220   VOID                  *PtrBuffer;
   2221   UINT16                MaxBlock;
   2222 
   2223   //
   2224   // fill command packet for Read(10) command
   2225   //
   2226   ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
   2227   Read10Packet  = &Packet.Read10;
   2228   Lba32         = (UINT32) StartLba;
   2229   PtrBuffer     = Buffer;
   2230 
   2231   //
   2232   // limit the data bytes that can be transfered by one Read(10) Command
   2233   //
   2234   MaxBlock = (UINT16) (0x10000 / BlockSize);
   2235   //
   2236   // (64k bytes)
   2237   //
   2238   BlocksRemaining = NumberOfBlocks;
   2239 
   2240   Status          = EFI_SUCCESS;
   2241   while (BlocksRemaining > 0) {
   2242 
   2243     if (BlocksRemaining <= MaxBlock) {
   2244       SectorCount = (UINT16) BlocksRemaining;
   2245     } else {
   2246       SectorCount = MaxBlock;
   2247     }
   2248     //
   2249     // fill the Packet data sturcture
   2250     //
   2251     Read10Packet->opcode = ATA_CMD_READ_10;
   2252 
   2253     //
   2254     // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
   2255     // Lba0 is MSB, Lba3 is LSB
   2256     //
   2257     Read10Packet->Lba3  = (UINT8) (Lba32 & 0xff);
   2258     Read10Packet->Lba2  = (UINT8) (Lba32 >> 8);
   2259     Read10Packet->Lba1  = (UINT8) (Lba32 >> 16);
   2260     Read10Packet->Lba0  = (UINT8) (Lba32 >> 24);
   2261 
   2262     //
   2263     // TranLen0 ~ TranLen1 specify the transfer length in block unit.
   2264     // TranLen0 is MSB, TranLen is LSB
   2265     //
   2266     Read10Packet->TranLen1  = (UINT8) (SectorCount & 0xff);
   2267     Read10Packet->TranLen0  = (UINT8) (SectorCount >> 8);
   2268 
   2269     ByteCount               = (UINT32) (SectorCount * BlockSize);
   2270 
   2271     Status = AtapiPacketCommandIn (
   2272               AtapiBlkIoDev,
   2273               DevicePosition,
   2274               &Packet,
   2275               (UINT16 *) PtrBuffer,
   2276               ByteCount,
   2277               ATAPILONGTIMEOUT
   2278               );
   2279     if (Status != EFI_SUCCESS) {
   2280       return Status;
   2281     }
   2282 
   2283     Lba32 += SectorCount;
   2284     PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
   2285     BlocksRemaining -= SectorCount;
   2286   }
   2287 
   2288   return Status;
   2289 }
   2290 
   2291 /**
   2292   Check if there is media according to sense data.
   2293 
   2294   @param[in]  SenseData   Pointer to sense data.
   2295   @param[in]  SenseCounts Count of sense data.
   2296 
   2297   @retval TRUE    No media
   2298   @retval FALSE   Media exists
   2299 
   2300 **/
   2301 BOOLEAN
   2302 IsNoMedia (
   2303   IN  ATAPI_REQUEST_SENSE_DATA  *SenseData,
   2304   IN  UINTN                     SenseCounts
   2305   )
   2306 {
   2307   ATAPI_REQUEST_SENSE_DATA  *SensePtr;
   2308   UINTN                     Index;
   2309   BOOLEAN                   IsNoMedia;
   2310 
   2311   IsNoMedia = FALSE;
   2312 
   2313   SensePtr  = SenseData;
   2314 
   2315   for (Index = 0; Index < SenseCounts; Index++) {
   2316 
   2317     if ((SensePtr->sense_key == ATA_SK_NOT_READY) && (SensePtr->addnl_sense_code == ATA_ASC_NO_MEDIA)) {
   2318       IsNoMedia = TRUE;
   2319     }
   2320 
   2321     SensePtr++;
   2322   }
   2323 
   2324   return IsNoMedia;
   2325 }
   2326 
   2327 /**
   2328   Check if device state is unclear according to sense data.
   2329 
   2330   @param[in]  SenseData   Pointer to sense data.
   2331   @param[in]  SenseCounts Count of sense data.
   2332 
   2333   @retval TRUE    Device state is unclear
   2334   @retval FALSE   Device state is clear
   2335 
   2336 **/
   2337 BOOLEAN
   2338 IsDeviceStateUnclear (
   2339   IN  ATAPI_REQUEST_SENSE_DATA    *SenseData,
   2340   IN  UINTN                       SenseCounts
   2341   )
   2342 {
   2343   ATAPI_REQUEST_SENSE_DATA  *SensePtr;
   2344   UINTN                     Index;
   2345   BOOLEAN                   Unclear;
   2346 
   2347   Unclear  = FALSE;
   2348 
   2349   SensePtr  = SenseData;
   2350 
   2351   for (Index = 0; Index < SenseCounts; Index++) {
   2352 
   2353     if (SensePtr->sense_key == 0x06) {
   2354       //
   2355       // Sense key is 0x06 means the device is just be reset or media just
   2356       // changed. The current state of the device is unclear.
   2357       //
   2358       Unclear = TRUE;
   2359       break;
   2360     }
   2361 
   2362     SensePtr++;
   2363   }
   2364 
   2365   return Unclear;
   2366 }
   2367 
   2368 /**
   2369   Check if there is media error according to sense data.
   2370 
   2371   @param[in]  SenseData   Pointer to sense data.
   2372   @param[in]  SenseCounts Count of sense data.
   2373 
   2374   @retval TRUE    Media error
   2375   @retval FALSE   No media error
   2376 
   2377 **/
   2378 BOOLEAN
   2379 IsMediaError (
   2380   IN  ATAPI_REQUEST_SENSE_DATA  *SenseData,
   2381   IN  UINTN                     SenseCounts
   2382   )
   2383 {
   2384   ATAPI_REQUEST_SENSE_DATA  *SensePtr;
   2385   UINTN                     Index;
   2386   BOOLEAN                   IsError;
   2387 
   2388   IsError   = FALSE;
   2389 
   2390   SensePtr  = SenseData;
   2391 
   2392   for (Index = 0; Index < SenseCounts; Index++) {
   2393 
   2394     switch (SensePtr->sense_key) {
   2395 
   2396     case ATA_SK_MEDIUM_ERROR:
   2397       switch (SensePtr->addnl_sense_code) {
   2398       case ATA_ASC_MEDIA_ERR1:
   2399         //
   2400         // fall through
   2401         //
   2402       case ATA_ASC_MEDIA_ERR2:
   2403         //
   2404         // fall through
   2405         //
   2406       case ATA_ASC_MEDIA_ERR3:
   2407         //
   2408         // fall through
   2409         //
   2410       case ATA_ASC_MEDIA_ERR4:
   2411         IsError = TRUE;
   2412         break;
   2413 
   2414       default:
   2415         break;
   2416       }
   2417 
   2418       break;
   2419 
   2420     case ATA_SK_NOT_READY:
   2421       switch (SensePtr->addnl_sense_code) {
   2422       case ATA_ASC_MEDIA_UPSIDE_DOWN:
   2423         IsError = TRUE;
   2424         break;
   2425 
   2426       default:
   2427         break;
   2428       }
   2429       break;
   2430 
   2431     default:
   2432       break;
   2433     }
   2434 
   2435     SensePtr++;
   2436   }
   2437 
   2438   return IsError;
   2439 }
   2440 
   2441 /**
   2442   Check if drive is ready according to sense data.
   2443 
   2444   @param[in]  SenseData   Pointer to sense data.
   2445   @param[in]  SenseCounts Count of sense data.
   2446   @param[out] NeedRetry   Indicate if retry is needed.
   2447 
   2448   @retval TRUE    Drive ready
   2449   @retval FALSE   Drive not ready
   2450 
   2451 **/
   2452 BOOLEAN
   2453 IsDriveReady (
   2454   IN  ATAPI_REQUEST_SENSE_DATA    *SenseData,
   2455   IN  UINTN                       SenseCounts,
   2456   OUT BOOLEAN                     *NeedRetry
   2457   )
   2458 {
   2459   ATAPI_REQUEST_SENSE_DATA  *SensePtr;
   2460   UINTN                     Index;
   2461   BOOLEAN                   IsReady;
   2462 
   2463   IsReady     = TRUE;
   2464   *NeedRetry  = FALSE;
   2465 
   2466   SensePtr    = SenseData;
   2467 
   2468   for (Index = 0; Index < SenseCounts; Index++) {
   2469 
   2470     switch (SensePtr->sense_key) {
   2471 
   2472     case ATA_SK_NOT_READY:
   2473       switch (SensePtr->addnl_sense_code) {
   2474       case ATA_ASC_NOT_READY:
   2475         switch (SensePtr->addnl_sense_code_qualifier) {
   2476         case ATA_ASCQ_IN_PROGRESS:
   2477           IsReady     = FALSE;
   2478           *NeedRetry  = TRUE;
   2479           break;
   2480 
   2481         default:
   2482           IsReady     = FALSE;
   2483           *NeedRetry  = FALSE;
   2484           break;
   2485         }
   2486         break;
   2487 
   2488       default:
   2489         break;
   2490       }
   2491       break;
   2492 
   2493     default:
   2494       break;
   2495     }
   2496 
   2497     SensePtr++;
   2498   }
   2499 
   2500   return IsReady;
   2501 }
   2502