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
AtapiPeimEntry(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)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
AtapiGetNumberOfBlockDevices(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO_PPI * This,OUT UINTN * NumberBlockDevices)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
AtapiGetBlockDeviceMediaInfo(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO_PPI * This,IN UINTN DeviceIndex,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo)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
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)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
AtapiGetNumberOfBlockDevices2(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI * This,OUT UINTN * NumberBlockDevices)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
AtapiGetBlockDeviceMediaInfo2(IN EFI_PEI_SERVICES ** PeiServices,IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI * This,IN UINTN DeviceIndex,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo)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
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)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
AtapiEnumerateDevices(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev)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
DiscoverAtapiDevice(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)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
CheckPowerMode(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN UINT8 AtaCommand)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
DetectIDEController(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)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
WaitForBSYClear(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
DRDYReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
DRQClear(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
DRQClear2(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
DRQReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
DRQReady2(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN IDE_BASE_REGISTERS * IdeIoRegisters,IN UINTN TimeoutInMilliSeconds)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
CheckErrorStatus(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINT16 StatusReg)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
ATAPIIdentify(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)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
TestUnitReady(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition)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
AtapiPacketCommandIn(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN ATAPI_PACKET_COMMAND * Packet,IN UINT16 * Buffer,IN UINT32 ByteCount,IN UINTN TimeoutInMilliSeconds)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
Inquiry(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,OUT EFI_PEI_BLOCK_IO_MEDIA * MediaInfo,OUT EFI_PEI_BLOCK_IO2_MEDIA * MediaInfo2)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
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)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
ResetDevice(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN BOOLEAN Extensive)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
RequestSense(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN ATAPI_REQUEST_SENSE_DATA * SenseBuffers,IN OUT UINT8 * SenseCounts)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
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)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
ReadSectors(IN ATAPI_BLK_IO_DEV * AtapiBlkIoDev,IN UINTN DevicePosition,IN VOID * Buffer,IN EFI_PEI_LBA StartLba,IN UINTN NumberOfBlocks,IN UINTN BlockSize)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
IsNoMedia(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)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
IsDeviceStateUnclear(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)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
IsMediaError(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts)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
IsDriveReady(IN ATAPI_REQUEST_SENSE_DATA * SenseData,IN UINTN SenseCounts,OUT BOOLEAN * NeedRetry)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