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