2 PEIM to produce gEfiPeiVirtualBlockIoPpiGuid & gEfiPeiVirtualBlockIo2PpiGuid PPI for
3 ATA controllers in the platform.
5 This PPI can be consumed by PEIM which produce gEfiPeiDeviceRecoveryModulePpiGuid
6 for Atapi CD ROM device.
8 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
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
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.
21 #include "AtapiPeim.h"
24 Initializes the Atapi Block Io PPI.
26 @param[in] FileHandle Handle of the file being invoked.
27 @param[in] PeiServices Describes the list of possible PEI Services.
29 @retval EFI_SUCCESS Operation performed successfully.
30 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate.
36 IN EFI_PEI_FILE_HANDLE FileHandle
,
37 IN CONST EFI_PEI_SERVICES
**PeiServices
40 PEI_ATA_CONTROLLER_PPI
*AtaControllerPpi
;
42 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
44 Status
= PeiServicesRegisterForShadow (FileHandle
);
45 if (!EFI_ERROR (Status
)) {
49 Status
= PeiServicesLocatePpi (
50 &gPeiAtaControllerPpiGuid
,
53 (VOID
**) &AtaControllerPpi
55 ASSERT_EFI_ERROR (Status
);
57 AtapiBlkIoDev
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*AtapiBlkIoDev
)));
58 if (AtapiBlkIoDev
== NULL
) {
59 return EFI_OUT_OF_RESOURCES
;
62 AtapiBlkIoDev
->Signature
= ATAPI_BLK_IO_DEV_SIGNATURE
;
63 AtapiBlkIoDev
->AtaControllerPpi
= AtaControllerPpi
;
66 // atapi device enumeration and build private data
68 AtapiEnumerateDevices (AtapiBlkIoDev
);
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
;
78 AtapiBlkIoDev
->PpiDescriptor
.Flags
= EFI_PEI_PPI_DESCRIPTOR_PPI
;
79 AtapiBlkIoDev
->PpiDescriptor
.Guid
= &gEfiPeiVirtualBlockIoPpiGuid
;
80 AtapiBlkIoDev
->PpiDescriptor
.Ppi
= &AtapiBlkIoDev
->AtapiBlkIo
;
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
;
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
;
98 Gets the count of block I/O devices that one specific block driver detects.
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.
107 @param[in] PeiServices General-purpose services that are available
109 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
111 @param[out] NumberBlockDevices The number of block I/O devices discovered.
113 @retval EFI_SUCCESS Operation performed successfully.
118 AtapiGetNumberOfBlockDevices (
119 IN EFI_PEI_SERVICES
**PeiServices
,
120 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
121 OUT UINTN
*NumberBlockDevices
124 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
126 AtapiBlkIoDev
= NULL
;
128 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
130 *NumberBlockDevices
= AtapiBlkIoDev
->DeviceCount
;
136 Gets a block device's media information.
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.
142 @param[in] PeiServices General-purpose services that are available to every
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
152 @param[out] MediaInfo The media information of the specified block media.
153 The caller is responsible for the ownership of this
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
160 @retval Others Other failure occurs.
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
173 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
177 AtapiBlkIoDev
= NULL
;
179 if (This
== NULL
|| MediaInfo
== NULL
) {
180 return EFI_INVALID_PARAMETER
;
183 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
185 DeviceCount
= AtapiBlkIoDev
->DeviceCount
;
188 // DeviceIndex is a value from 1 to NumberBlockDevices.
190 if ((DeviceIndex
< 1) || (DeviceIndex
> DeviceCount
) || (DeviceIndex
> MAX_IDE_DEVICES
)) {
191 return EFI_INVALID_PARAMETER
;
194 Index
= DeviceIndex
- 1;
197 // probe media and retrieve latest media information
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
));
205 Status
= DetectMedia (
207 AtapiBlkIoDev
->DeviceInfo
[Index
].DevicePosition
,
208 &AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
,
209 &AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo2
211 if (Status
!= EFI_SUCCESS
) {
212 return EFI_DEVICE_ERROR
;
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
));
222 // Get media info from AtapiBlkIoDev
224 CopyMem (MediaInfo
, &AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
, sizeof(EFI_PEI_BLOCK_IO_MEDIA
));
230 Reads the requested number of blocks from the specified block device.
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.
236 @param[in] PeiServices General-purpose services that are available to
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
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
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.
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
,
275 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
277 UINTN NumberOfBlocks
;
279 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
281 AtapiBlkIoDev
= NULL
;
284 return EFI_INVALID_PARAMETER
;
287 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
289 if (Buffer
== NULL
) {
290 return EFI_INVALID_PARAMETER
;
293 if (BufferSize
== 0) {
297 Status
= AtapiGetBlockDeviceMediaInfo (
303 if (Status
!= EFI_SUCCESS
) {
304 return EFI_DEVICE_ERROR
;
307 if (!MediaInfo
.MediaPresent
) {
311 BlockSize
= MediaInfo
.BlockSize
;
313 if (BufferSize
% BlockSize
!= 0) {
314 return EFI_BAD_BUFFER_SIZE
;
317 NumberOfBlocks
= BufferSize
/ BlockSize
;
319 if ((StartLBA
+ NumberOfBlocks
- 1) > AtapiBlkIoDev
->DeviceInfo
[DeviceIndex
- 1].MediaInfo2
.LastBlock
) {
320 return EFI_INVALID_PARAMETER
;
323 Status
= ReadSectors (
325 AtapiBlkIoDev
->DeviceInfo
[DeviceIndex
- 1].DevicePosition
,
331 if (EFI_ERROR (Status
)) {
332 return EFI_DEVICE_ERROR
;
339 Gets the count of block I/O devices that one specific block driver detects.
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.
348 @param[in] PeiServices General-purpose services that are available
350 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI
352 @param[out] NumberBlockDevices The number of block I/O devices discovered.
354 @retval EFI_SUCCESS Operation performed successfully.
359 AtapiGetNumberOfBlockDevices2 (
360 IN EFI_PEI_SERVICES
**PeiServices
,
361 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI
*This
,
362 OUT UINTN
*NumberBlockDevices
366 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
368 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This
);
370 Status
= AtapiGetNumberOfBlockDevices (
372 &AtapiBlkIoDev
->AtapiBlkIo
,
380 Gets a block device's media information.
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.
386 @param[in] PeiServices General-purpose services that are available to every
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
396 @param[out] MediaInfo The media information of the specified block media.
397 The caller is responsible for the ownership of this
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
404 @retval Others Other failure occurs.
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
416 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
418 EFI_PEI_BLOCK_IO_MEDIA Media
;
420 AtapiBlkIoDev
= NULL
;
422 if (This
== NULL
|| MediaInfo
== NULL
) {
423 return EFI_INVALID_PARAMETER
;
426 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This
);
428 Status
= AtapiGetBlockDeviceMediaInfo (
430 &AtapiBlkIoDev
->AtapiBlkIo
,
434 if (EFI_ERROR (Status
)) {
438 // Get media info from AtapiBlkIoDev
440 CopyMem (MediaInfo
, &AtapiBlkIoDev
->DeviceInfo
[DeviceIndex
- 1].MediaInfo2
, sizeof(EFI_PEI_BLOCK_IO2_MEDIA
));
446 Reads the requested number of blocks from the specified block device.
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.
452 @param[in] PeiServices General-purpose services that are available to
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
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
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.
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
,
491 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
493 AtapiBlkIoDev
= NULL
;
496 return EFI_INVALID_PARAMETER
;
499 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO2_THIS (This
);
501 Status
= AtapiReadBlocks (
503 &AtapiBlkIoDev
->AtapiBlkIo
,
515 Enumerate Atapi devices.
517 This function is used to enumerate Atatpi device in Ide channel.
519 @param[in] AtapiBlkIoDev A pointer to atapi block IO device
523 AtapiEnumerateDevices (
524 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
529 UINTN DevicePosition
;
530 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
531 EFI_PEI_BLOCK_IO2_MEDIA MediaInfo2
;
534 UINT16 CommandBlockBaseAddr
;
535 UINT16 ControlBlockBaseAddr
;
536 UINT32 IdeEnabledNumber
;
537 IDE_REGS_BASE_ADDR IdeRegsBaseAddr
[MAX_IDE_CHANNELS
];
543 // Scan IDE bus for ATAPI devices
547 // Enable Sata and IDE controller.
549 AtapiBlkIoDev
->AtaControllerPpi
->EnableAtaChannel (
550 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
551 AtapiBlkIoDev
->AtaControllerPpi
,
552 PEI_ICH_IDE_PRIMARY
| PEI_ICH_IDE_SECONDARY
556 // Allow SATA Devices to spin-up. This is needed if
557 // SEC and PEI phase is too short, for example Release Build.
559 DEBUG ((EFI_D_INFO
, "Delay for %d seconds for SATA devices to spin-up\n", PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath
)));
560 MicroSecondDelay (PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath
) * 1000 * 1000); //
563 // Get four channels (primary or secondary Pata, Sata Channel) Command and Control Regs Base address.
565 IdeEnabledNumber
= AtapiBlkIoDev
->AtaControllerPpi
->GetIdeRegsBaseAddr (
566 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
567 AtapiBlkIoDev
->AtaControllerPpi
,
572 // Using Command and Control Regs Base Address to fill other registers.
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);
585 ControlBlockBaseAddr
= IdeRegsBaseAddr
[Index1
].ControlBlockBaseAddr
;
586 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Alt
.DeviceControl
= ControlBlockBaseAddr
;
587 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x1);
590 // Scan IDE bus for ATAPI devices IDE or Sata device
592 for (Index2
= IdeMaster
; Index2
< IdeMaxDevice
; Index2
++) {
594 // Pata & Sata, Primary & Secondary channel, Master & Slave device
596 DevicePosition
= Index1
* 2 + Index2
;
598 if (DiscoverAtapiDevice (AtapiBlkIoDev
, DevicePosition
, &MediaInfo
, &MediaInfo2
)) {
600 // ATAPI Device at DevicePosition is found.
602 AtapiBlkIoDev
->DeviceInfo
[DeviceCount
].DevicePosition
= DevicePosition
;
604 // Retrieve Media Info
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
));
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
));
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;
626 AtapiBlkIoDev
->DeviceCount
= DeviceCount
;
630 Detect Atapi devices.
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.
637 @retval TRUE Atapi device exists in specified position.
638 @retval FALSE Atapi device does not exist in specified position.
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
651 if (!DetectIDEController (AtapiBlkIoDev
, DevicePosition
)) {
655 // test if it is an ATAPI device (only supported device)
657 if (ATAPIIdentify (AtapiBlkIoDev
, DevicePosition
) == EFI_SUCCESS
) {
659 Status
= Inquiry (AtapiBlkIoDev
, DevicePosition
, MediaInfo
, MediaInfo2
);
660 if (!EFI_ERROR (Status
)) {
669 Check power mode of Atapi devices.
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.
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.
683 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
684 IN UINTN DevicePosition
,
690 UINT16 StatusRegister
;
692 UINT16 CommandRegister
;
693 UINT16 ErrorRegister
;
694 UINT16 SectorCountRegister
;
698 UINT8 SectorCountValue
;
700 Channel
= (UINT8
) (DevicePosition
/ 2);
701 Device
= (UINT8
) (DevicePosition
% 2);
703 ASSERT (Channel
< MAX_IDE_CHANNELS
);
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
;
714 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
717 // refresh the SectorCount register
719 SectorCountValue
= 0x55;
720 IoWrite8 (SectorCountRegister
, SectorCountValue
);
725 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
727 Status
= DRDYReady (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 100);
732 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
734 // send 'check power' commandd via Command Register
736 IoWrite8 (CommandRegister
, AtaCommand
);
738 Status
= WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 3000);
739 if (EFI_ERROR (Status
)) {
743 StatusValue
= IoRead8 (StatusRegister
);
746 // command returned status is DRDY, indicating device supports the command,
747 // so device is present.
749 if ((StatusValue
& ATA_STSREG_DRDY
) == ATA_STSREG_DRDY
) {
753 SectorCountValue
= IoRead8 (SectorCountRegister
);
756 // command returned status is ERR & ABRT_ERR, indicating device does not support
757 // the command, so device is present.
759 if ((StatusValue
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
760 ErrorValue
= IoRead8 (ErrorRegister
);
761 if ((ErrorValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
765 // According to spec, no other error code is valid
767 return EFI_NOT_FOUND
;
771 if ((SectorCountValue
== 0x00) || (SectorCountValue
== 0x80) || (SectorCountValue
== 0xff)) {
773 // Write SectorCount 0x55 but return valid state value. Maybe no device
774 // exists or some slow kind of ATAPI device exists.
776 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
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.
783 SectorCountValue
= 0x55;
784 IoWrite8 (SectorCountRegister
, SectorCountValue
);
785 MicroSecondDelay (10000);
787 SectorCountValue
= IoRead8 (SectorCountRegister
);
788 if (SectorCountValue
!= 0x55) {
789 return EFI_NOT_FOUND
;
792 // Send a "ATAPI TEST UNIT READY" command ... slow but accurate
794 Status
= TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
798 return EFI_NOT_FOUND
;
802 Detect if an IDE controller exists in specified position.
804 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
805 @param[in] DevicePosition An integer to signify device position.
807 @retval TRUE The Atapi device exists.
808 @retval FALSE The Atapi device does not present.
812 DetectIDEController (
813 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
814 IN UINTN DevicePosition
821 Channel
= (UINT8
) (DevicePosition
/ 2);
823 ASSERT (Channel
< MAX_IDE_CHANNELS
);
825 // Wait 31 seconds for BSY clear
827 Status
= WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000);
828 if (EFI_ERROR (Status
)) {
832 // Send 'check power' command for IDE device
835 Status
= CheckPowerMode (AtapiBlkIoDev
, DevicePosition
, AtaCommand
);
836 if ((Status
== EFI_ABORTED
) || (Status
== EFI_SUCCESS
)) {
844 Wait specified time interval to poll for BSY bit clear in the Status Register.
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.
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.
856 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
857 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
858 IN UINTN TimeoutInMilliSeconds
862 UINT16 StatusRegister
;
867 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
869 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
871 StatusValue
= IoRead8 (StatusRegister
);
872 if ((StatusValue
& ATA_STSREG_BSY
) == 0x00) {
875 MicroSecondDelay (250);
879 } while (Delay
!= 0);
889 Wait specified time interval to poll for DRDY bit set in the Status register.
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.
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.
901 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
902 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
903 IN UINTN TimeoutInMilliSeconds
907 UINT16 StatusRegister
;
913 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
915 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
917 StatusValue
= IoRead8 (StatusRegister
);
919 // BSY == 0 , DRDY == 1
921 if ((StatusValue
& (ATA_STSREG_DRDY
| ATA_STSREG_BSY
)) == ATA_STSREG_DRDY
) {
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
) {
932 MicroSecondDelay (250);
936 } while (Delay
!= 0);
946 Wait specified time interval to poll for DRQ bit clear in the Status Register.
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.
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.
958 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
959 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
960 IN UINTN TimeoutInMilliSeconds
964 UINT16 StatusRegister
;
970 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
972 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
975 StatusValue
= IoRead8 (StatusRegister
);
978 // wait for BSY == 0 and DRQ == 0
980 if ((StatusValue
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
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
) {
991 MicroSecondDelay (250);
994 } while (Delay
!= 0);
1004 Wait specified time interval to poll for DRQ bit clear in the Alternate Status Register.
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.
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.
1016 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1017 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
1018 IN UINTN TimeoutInMilliSeconds
1022 UINT16 AltStatusRegister
;
1023 UINT8 AltStatusValue
;
1028 AltStatusRegister
= IdeIoRegisters
->Alt
.AltStatus
;
1030 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
1033 AltStatusValue
= IoRead8 (AltStatusRegister
);
1036 // wait for BSY == 0 and DRQ == 0
1038 if ((AltStatusValue
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
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
) {
1049 MicroSecondDelay (250);
1052 } while (Delay
!= 0);
1062 Wait specified time interval to poll for DRQ bit set in the Status Register.
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.
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.
1075 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1076 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
1077 IN UINTN TimeoutInMilliSeconds
1081 UINT16 StatusRegister
;
1088 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
1090 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
1093 // read Status Register will clear interrupt
1095 StatusValue
= IoRead8 (StatusRegister
);
1100 if ((StatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
1104 if ((StatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
1106 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
1107 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
1111 MicroSecondDelay (250);
1114 } while (Delay
!= 0);
1124 Wait specified time interval to poll for DRQ bit set in the Alternate Status Register.
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.
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.
1137 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1138 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
1139 IN UINTN TimeoutInMilliSeconds
1143 UINT16 AltStatusRegister
;
1144 UINT8 AltStatusValue
;
1149 AltStatusRegister
= IdeIoRegisters
->Alt
.AltStatus
;
1151 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
1154 AltStatusValue
= IoRead8 (AltStatusRegister
);
1159 if ((AltStatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
1163 if ((AltStatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
1165 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
1166 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
1170 MicroSecondDelay (250);
1173 } while (Delay
!= 0);
1183 Check if there is an error in Status Register.
1185 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1186 @param[in] StatusReg The address to IDE IO registers.
1188 @retval EFI_SUCCESS Operation success.
1189 @retval EFI_DEVICE_ERROR Device error.
1194 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1200 StatusValue
= IoRead8 (StatusReg
);
1202 if ((StatusValue
& (ATA_STSREG_ERR
| ATA_STSREG_DWF
| ATA_STSREG_CORR
)) == 0) {
1207 return EFI_DEVICE_ERROR
;
1212 Idendify Atapi devices.
1214 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1215 @param[in] DevicePosition An integer to signify device position.
1217 @retval EFI_SUCCESS Identify successfully.
1218 @retval EFI_DEVICE_ERROR Device cannot be identified successfully.
1223 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1224 IN UINTN DevicePosition
1227 ATAPI_IDENTIFY_DATA AtapiIdentifyData
;
1234 UINT16 SectorCountReg
;
1235 UINT16 SectorNumberReg
;
1236 UINT16 CylinderLsbReg
;
1237 UINT16 CylinderMsbReg
;
1247 ByteCount
= sizeof (AtapiIdentifyData
);
1248 Buffer16
= (UINT16
*) &AtapiIdentifyData
;
1250 Channel
= (UINT8
) (DevicePosition
/ 2);
1251 Device
= (UINT8
) (DevicePosition
% 2);
1253 ASSERT (Channel
< MAX_IDE_CHANNELS
);
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
;
1265 // Send ATAPI Identify Command to get IDENTIFY data.
1267 if (WaitForBSYClear (
1269 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1272 return EFI_DEVICE_ERROR
;
1275 // select device via Head/Device register.
1276 // Before write Head/Device register, BSY and DRQ must be 0.
1278 if (DRQClear2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), ATATIMEOUT
) != EFI_SUCCESS
) {
1279 return EFI_DEVICE_ERROR
;
1282 // e0:1110,0000-- bit7 and bit5 are reserved bits.
1283 // bit6 set means LBA mode
1285 IoWrite8 (HeadReg
, (UINT8
) ((Device
<< 4) | 0xe0));
1288 // set all the command parameters
1289 // Before write to all the following registers, BSY and DRQ must be 0.
1293 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1297 return EFI_DEVICE_ERROR
;
1300 IoWrite8 (SectorCountReg
, 0);
1301 IoWrite8 (SectorNumberReg
, 0);
1302 IoWrite8 (CylinderLsbReg
, 0);
1303 IoWrite8 (CylinderMsbReg
, 0);
1306 // send command via Command Register
1308 IoWrite8 (CommandReg
, ATA_CMD_IDENTIFY_DEVICE
);
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
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.
1328 // WordCount is used to record bytes of currently transfered data
1330 while (WordCount
< ByteCount
/ 2) {
1332 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
1334 Status
= DRQReady2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), ATATIMEOUT
);
1335 if (Status
!= EFI_SUCCESS
) {
1339 if (CheckErrorStatus (AtapiBlkIoDev
, StatusReg
) != EFI_SUCCESS
) {
1341 return EFI_DEVICE_ERROR
;
1344 // Get the byte count for one series of read
1346 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
1347 Increment
= ByteCount
/ 2 - WordCount
;
1350 // perform a series of read without check DRQ ready
1352 for (Index
= 0; Index
< Increment
; Index
++) {
1353 *Buffer16
++ = IoRead16 (DataReg
);
1356 WordCount
+= Increment
;
1364 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1367 return CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1375 Sends out ATAPI Test Unit Ready Packet Command to the specified device
1376 to find out whether device is accessible.
1378 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1379 @param[in] DevicePosition An integer to signify device position.
1381 @retval EFI_SUCCESS TestUnit command executed successfully.
1382 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
1387 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1388 IN UINTN DevicePosition
1391 ATAPI_PACKET_COMMAND Packet
;
1395 // fill command packet
1397 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1398 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
1401 // send command packet
1403 Status
= AtapiPacketCommandIn (AtapiBlkIoDev
, DevicePosition
, &Packet
, NULL
, 0, ATAPITIMEOUT
);
1408 Send out ATAPI commands conforms to the Packet Command with PIO Data In Protocol.
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.
1417 @retval EFI_SUCCESS Command executed successfully.
1418 @retval EFI_DEVICE_ERROR Device cannot be executed command successfully.
1422 AtapiPacketCommandIn (
1423 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1424 IN UINTN DevicePosition
,
1425 IN ATAPI_PACKET_COMMAND
*Packet
,
1427 IN UINT32 ByteCount
,
1428 IN UINTN TimeoutInMilliSeconds
1437 UINT16 CylinderLsbReg
;
1438 UINT16 CylinderMsbReg
;
1439 UINT16 DeviceControlReg
;
1443 UINT16
*CommandIndex
;
1450 // required transfer data in word unit.
1452 UINT32 RequiredWordCount
;
1455 // actual transfer data in word unit.
1457 UINT32 ActualWordCount
;
1459 Channel
= (UINT8
) (DevicePosition
/ 2);
1460 Device
= (UINT8
) (DevicePosition
% 2);
1462 ASSERT (Channel
< MAX_IDE_CHANNELS
);
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
;
1474 // Set all the command parameters by fill related registers.
1475 // Before write to all the following registers, BSY and DRQ must be 0.
1479 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1482 return EFI_DEVICE_ERROR
;
1485 // Select device via Device/Head Register.
1486 // DEFAULT_CMD: 0xa0 (1010,0000)
1488 IoWrite8 (HeadReg
, (UINT8
) ((Device
<< 4) | ATA_DEFAULT_CMD
));
1493 IoWrite8 (FeatureReg
, 0x00);
1496 // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
1497 // determine how many data should be transfered.
1499 IoWrite8 (CylinderLsbReg
, (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff));
1500 IoWrite8 (CylinderMsbReg
, (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8));
1503 // DEFAULT_CTL:0x0a (0000,1010)
1504 // Disable interrupt
1506 IoWrite8 (DeviceControlReg
, ATA_DEFAULT_CTL
);
1509 // Send Packet command to inform device
1510 // that the following data bytes are command packet.
1512 IoWrite8 (CommandReg
, ATA_CMD_PACKET
);
1514 Status
= DRQReady (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), TimeoutInMilliSeconds
);
1515 if (Status
!= EFI_SUCCESS
) {
1519 // Send out command packet
1521 CommandIndex
= Packet
->Data16
;
1522 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
1523 IoWrite16 (DataReg
, *CommandIndex
);
1524 MicroSecondDelay (10);
1527 StatusValue
= IoRead8 (StatusReg
);
1528 if ((StatusValue
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
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
1533 MicroSecondDelay (3000000);
1534 return EFI_DEVICE_ERROR
;
1537 if (Buffer
== NULL
|| ByteCount
== 0) {
1541 // call PioReadWriteData() function to get
1542 // requested transfer data form device.
1545 RequiredWordCount
= ByteCount
/ 2;
1547 // ActuralWordCount means the word count of data really transfered.
1549 ActualWordCount
= 0;
1551 Status
= EFI_SUCCESS
;
1552 while ((Status
== EFI_SUCCESS
) && (ActualWordCount
< RequiredWordCount
)) {
1554 // before each data transfer stream, the host should poll DRQ bit ready,
1555 // which informs device is ready to transfer data.
1559 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1560 TimeoutInMilliSeconds
1562 return CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1565 // read Status Register will clear interrupt
1567 StatusValue
= IoRead8 (StatusReg
);
1570 // get current data transfer size from Cylinder Registers.
1572 WordCount
= IoRead8 (CylinderMsbReg
) << 8;
1573 WordCount
= WordCount
| IoRead8 (CylinderLsbReg
);
1574 WordCount
= WordCount
& 0xffff;
1578 // perform a series data In/Out.
1580 for (Index
= 0; (Index
< WordCount
) && (ActualWordCount
< RequiredWordCount
); Index
++, ActualWordCount
++) {
1582 *PtrBuffer
= IoRead16 (DataReg
);
1588 if (((ATAPI_REQUEST_SENSE_CMD
*) Packet
)->opcode
== ATA_CMD_REQUEST_SENSE
&& ActualWordCount
>= 4) {
1589 RequiredWordCount
= MIN (
1591 (UINT32
) (4 + (((ATAPI_REQUEST_SENSE_DATA
*) Buffer
)->addnl_sense_length
/ 2))
1597 // After data transfer is completed, normally, DRQ bit should clear.
1599 Status
= DRQClear2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), TimeoutInMilliSeconds
);
1600 if (Status
!= EFI_SUCCESS
) {
1601 return EFI_DEVICE_ERROR
;
1604 // read status register to check whether error happens.
1606 Status
= CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1611 Sends out ATAPI Inquiry Packet Command to the specified device.
1612 This command will return INQUIRY data of the device.
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.
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.
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
1632 ATAPI_PACKET_COMMAND Packet
;
1634 ATAPI_INQUIRY_DATA Idata
;
1637 // prepare command packet for the ATAPI Inquiry Packet Command.
1639 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1640 ZeroMem (&Idata
, sizeof (ATAPI_INQUIRY_DATA
));
1642 Packet
.Inquiry
.opcode
= ATA_CMD_INQUIRY
;
1643 Packet
.Inquiry
.page_code
= 0;
1644 Packet
.Inquiry
.allocation_length
= (UINT8
) sizeof (ATAPI_INQUIRY_DATA
);
1647 // Send command packet and get requested Inquiry data.
1649 Status
= AtapiPacketCommandIn (
1653 (UINT16
*) (&Idata
),
1654 sizeof (ATAPI_INQUIRY_DATA
),
1659 if (Status
!= EFI_SUCCESS
) {
1660 return EFI_DEVICE_ERROR
;
1663 // Identify device type via INQUIRY data.
1665 switch (Idata
.peripheral_type
& 0x1f) {
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;
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;
1699 return EFI_UNSUPPORTED
;
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.
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.
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.
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
1732 ATAPI_REQUEST_SENSE_DATA
*SenseBuffers
;
1733 BOOLEAN NeedReadCapacity
;
1738 SenseBuffers
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*SenseBuffers
)));
1739 if (SenseBuffers
== NULL
) {
1740 return EFI_OUT_OF_RESOURCES
;
1744 // Test Unit Ready command is used to detect whether device is accessible,
1745 // the device will produce corresponding Sense data.
1747 for (Index
= 0; Index
< 2; Index
++) {
1749 Status
= TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
1750 if (Status
!= EFI_SUCCESS
) {
1751 Status
= ResetDevice (AtapiBlkIoDev
, DevicePosition
, FALSE
);
1753 if (Status
!= EFI_SUCCESS
) {
1754 ResetDevice (AtapiBlkIoDev
, DevicePosition
, TRUE
);
1762 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1763 Status
= EFI_SUCCESS
;
1764 NeedReadCapacity
= TRUE
;
1766 for (Index
= 0; Index
< 5; Index
++) {
1767 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1768 Status
= RequestSense (
1774 DEBUG ((EFI_D_INFO
, "Atapi Request Sense Count is %d\n", SenseCounts
));
1775 if (IsDeviceStateUnclear (SenseBuffers
, SenseCounts
) || IsNoMedia (SenseBuffers
, SenseCounts
)) {
1777 // We are not sure whether the media is present or not, try again
1779 TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
1785 if (Status
== EFI_SUCCESS
) {
1787 if (IsNoMedia (SenseBuffers
, SenseCounts
)) {
1789 NeedReadCapacity
= FALSE
;
1790 MediaInfo
->MediaPresent
= FALSE
;
1791 MediaInfo
->LastBlock
= 0;
1792 MediaInfo2
->MediaPresent
= FALSE
;
1793 MediaInfo2
->LastBlock
= 0;
1796 if (IsMediaError (SenseBuffers
, SenseCounts
)) {
1797 return EFI_DEVICE_ERROR
;
1801 if (NeedReadCapacity
) {
1803 // at most retry 5 times
1808 // initial retry once
1810 for (Index
= 0; (Index
< RetryNum
) && (Index
< MaxRetryNum
); Index
++) {
1812 Status
= ReadCapacity (AtapiBlkIoDev
, DevicePosition
, MediaInfo
, MediaInfo2
);
1813 MicroSecondDelay (200000);
1814 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1816 if (Status
!= EFI_SUCCESS
) {
1818 Status
= RequestSense (AtapiBlkIoDev
, DevicePosition
, SenseBuffers
, &SenseCounts
);
1820 // If Request Sense data failed, reset the device and retry.
1822 if (Status
!= EFI_SUCCESS
) {
1824 Status
= ResetDevice (AtapiBlkIoDev
, DevicePosition
, FALSE
);
1826 // if ATAPI soft reset fail,
1827 // use stronger reset mechanism -- ATA soft reset.
1829 if (Status
!= EFI_SUCCESS
) {
1830 ResetDevice (AtapiBlkIoDev
, DevicePosition
, TRUE
);
1842 if (IsNoMedia (SenseBuffers
, SenseCounts
)) {
1844 MediaInfo
->MediaPresent
= FALSE
;
1845 MediaInfo
->LastBlock
= 0;
1846 MediaInfo2
->MediaPresent
= FALSE
;
1847 MediaInfo2
->LastBlock
= 0;
1851 if (IsMediaError (SenseBuffers
, SenseCounts
)) {
1852 return EFI_DEVICE_ERROR
;
1855 if (!IsDriveReady (SenseBuffers
, SenseCounts
, &NeedRetry
)) {
1857 // Drive not ready: if NeedRetry, then retry once more;
1858 // else return error
1864 return EFI_DEVICE_ERROR
;
1868 // if read capacity fail not for above reasons, retry once more
1882 Reset specified Atapi device.
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.
1888 @retval EFI_SUCCESS Command executed successfully.
1889 @retval EFI_DEVICE_ERROR Some device errors happen.
1894 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1895 IN UINTN DevicePosition
,
1896 IN BOOLEAN Extensive
1902 UINT16 DeviceControlReg
;
1908 Channel
= (UINT8
) (DevicePosition
/ 2);
1909 Device
= (UINT8
) (DevicePosition
% 2);
1911 ASSERT (Channel
< MAX_IDE_CHANNELS
);
1913 DeviceControlReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Alt
.DeviceControl
;
1914 CommandReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Command
;
1915 HeadReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Head
;
1920 DevControl
|= ATA_CTLREG_SRST
;
1922 // set SRST bit to initiate soft reset
1926 // disable Interrupt
1928 IoWrite8 (DeviceControlReg
, DevControl
);
1933 MicroSecondDelay (10);
1942 IoWrite8 (DeviceControlReg
, DevControl
);
1945 // slave device needs at most 31s to clear BSY
1947 if (WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000) == EFI_TIMEOUT
) {
1948 return EFI_DEVICE_ERROR
;
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
1956 DeviceSelect
= (UINT8
) (((BIT7
| BIT5
) | (Device
<< 4)));
1957 IoWrite8 (HeadReg
, DeviceSelect
);
1959 Command
= ATA_CMD_SOFT_RESET
;
1960 IoWrite8 (CommandReg
, Command
);
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
1966 if (WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000) != EFI_SUCCESS
) {
1967 return EFI_DEVICE_ERROR
;
1970 // stall 5 seconds to make the device status stable
1972 MicroSecondDelay (STALL_1_SECONDS
* 5);
1980 Sends out ATAPI Request Sense Packet Command to the specified device.
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.
1987 @retval EFI_SUCCESS Command executed successfully.
1988 @retval EFI_DEVICE_ERROR Some device errors happen.
1993 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1994 IN UINTN DevicePosition
,
1995 IN ATAPI_REQUEST_SENSE_DATA
*SenseBuffers
,
1996 IN OUT UINT8
*SenseCounts
2000 ATAPI_REQUEST_SENSE_DATA
*Sense
;
2003 ATAPI_PACKET_COMMAND Packet
;
2005 ZeroMem (SenseBuffers
, sizeof (ATAPI_REQUEST_SENSE_DATA
) * (*SenseCounts
));
2007 // fill command packet for Request Sense Packet Command
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
);
2013 Ptr
= (UINT16
*) SenseBuffers
;
2015 // initialize pointer
2019 // request sense data from device continiously until no sense data exists in the device.
2021 for (SenseReq
= TRUE
; SenseReq
;) {
2023 Sense
= (ATAPI_REQUEST_SENSE_DATA
*) Ptr
;
2026 // send out Request Sense Packet Command and get one Sense data form device
2028 Status
= AtapiPacketCommandIn (
2033 sizeof (ATAPI_REQUEST_SENSE_DATA
),
2037 // failed to get Sense data
2039 if (Status
!= EFI_SUCCESS
) {
2040 if (*SenseCounts
== 0) {
2041 return EFI_DEVICE_ERROR
;
2049 if (*SenseCounts
> MAX_SENSE_KEY_COUNT
) {
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.
2058 if ((Sense
->sense_key
!= ATA_SK_NO_SENSE
) && ((*SenseCounts
) < 20)) {
2060 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
) / 2;
2062 // Ptr is word based pointer
2066 // when no sense key, skip out the loop
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.
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.
2085 @retval EFI_SUCCESS Command executed successfully.
2086 @retval EFI_DEVICE_ERROR Some device errors happen.
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
2098 ATAPI_PACKET_COMMAND Packet
;
2101 // used for capacity data returned from ATAPI device
2103 ATAPI_READ_CAPACITY_DATA Data
;
2104 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
2106 ZeroMem (&Data
, sizeof (Data
));
2107 ZeroMem (&FormatData
, sizeof (FormatData
));
2109 if (MediaInfo
->DeviceType
== IdeCDROM
) {
2111 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
2112 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
2113 Status
= AtapiPacketCommandIn (
2118 sizeof (ATAPI_READ_CAPACITY_DATA
),
2124 // DeviceType == IdeLS120
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 (
2133 (UINT16
*) (&FormatData
),
2134 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
2139 if (Status
== EFI_SUCCESS
) {
2141 if (MediaInfo
->DeviceType
== IdeCDROM
) {
2143 MediaInfo
->LastBlock
= ((UINT32
) Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
2144 MediaInfo
->MediaPresent
= TRUE
;
2146 // Because the user data portion in the sector of the Data CD supported
2149 MediaInfo
->BlockSize
= 0x800;
2151 MediaInfo2
->LastBlock
= MediaInfo
->LastBlock
;
2152 MediaInfo2
->MediaPresent
= MediaInfo
->MediaPresent
;
2153 MediaInfo2
->BlockSize
= (UINT32
)MediaInfo
->BlockSize
;
2156 if (MediaInfo
->DeviceType
== IdeLS120
) {
2158 if (FormatData
.DesCode
== 3) {
2159 MediaInfo
->MediaPresent
= FALSE
;
2160 MediaInfo
->LastBlock
= 0;
2161 MediaInfo2
->MediaPresent
= FALSE
;
2162 MediaInfo2
->LastBlock
= 0;
2164 MediaInfo
->LastBlock
= ((UINT32
) FormatData
.LastLba3
<< 24) |
2165 (FormatData
.LastLba2
<< 16) |
2166 (FormatData
.LastLba1
<< 8) |
2167 FormatData
.LastLba0
;
2168 MediaInfo
->LastBlock
--;
2170 MediaInfo
->MediaPresent
= TRUE
;
2172 MediaInfo
->BlockSize
= 0x200;
2174 MediaInfo2
->LastBlock
= MediaInfo
->LastBlock
;
2175 MediaInfo2
->MediaPresent
= MediaInfo
->MediaPresent
;
2176 MediaInfo2
->BlockSize
= (UINT32
)MediaInfo
->BlockSize
;
2184 return EFI_DEVICE_ERROR
;
2189 Perform read from disk in block unit.
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.
2198 @retval EFI_SUCCESS Command executed successfully.
2199 @retval EFI_DEVICE_ERROR Some device errors happen.
2204 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
2205 IN UINTN DevicePosition
,
2207 IN EFI_PEI_LBA StartLba
,
2208 IN UINTN NumberOfBlocks
,
2213 ATAPI_PACKET_COMMAND Packet
;
2214 ATAPI_READ10_CMD
*Read10Packet
;
2216 UINTN BlocksRemaining
;
2224 // fill command packet for Read(10) command
2226 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
2227 Read10Packet
= &Packet
.Read10
;
2228 Lba32
= (UINT32
) StartLba
;
2232 // limit the data bytes that can be transfered by one Read(10) Command
2234 MaxBlock
= (UINT16
) (0x10000 / BlockSize
);
2238 BlocksRemaining
= NumberOfBlocks
;
2240 Status
= EFI_SUCCESS
;
2241 while (BlocksRemaining
> 0) {
2243 if (BlocksRemaining
<= MaxBlock
) {
2244 SectorCount
= (UINT16
) BlocksRemaining
;
2246 SectorCount
= MaxBlock
;
2249 // fill the Packet data sturcture
2251 Read10Packet
->opcode
= ATA_CMD_READ_10
;
2254 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
2255 // Lba0 is MSB, Lba3 is LSB
2257 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
2258 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
2259 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
2260 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
2263 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
2264 // TranLen0 is MSB, TranLen is LSB
2266 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
2267 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
2269 ByteCount
= (UINT32
) (SectorCount
* BlockSize
);
2271 Status
= AtapiPacketCommandIn (
2275 (UINT16
*) PtrBuffer
,
2279 if (Status
!= EFI_SUCCESS
) {
2283 Lba32
+= SectorCount
;
2284 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
2285 BlocksRemaining
-= SectorCount
;
2292 Check if there is media according to sense data.
2294 @param[in] SenseData Pointer to sense data.
2295 @param[in] SenseCounts Count of sense data.
2297 @retval TRUE No media
2298 @retval FALSE Media exists
2303 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2304 IN UINTN SenseCounts
2307 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2313 SensePtr
= SenseData
;
2315 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2317 if ((SensePtr
->sense_key
== ATA_SK_NOT_READY
) && (SensePtr
->addnl_sense_code
== ATA_ASC_NO_MEDIA
)) {
2328 Check if device state is unclear according to sense data.
2330 @param[in] SenseData Pointer to sense data.
2331 @param[in] SenseCounts Count of sense data.
2333 @retval TRUE Device state is unclear
2334 @retval FALSE Device state is clear
2338 IsDeviceStateUnclear (
2339 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2340 IN UINTN SenseCounts
2343 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2349 SensePtr
= SenseData
;
2351 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2353 if (SensePtr
->sense_key
== 0x06) {
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.
2369 Check if there is media error according to sense data.
2371 @param[in] SenseData Pointer to sense data.
2372 @param[in] SenseCounts Count of sense data.
2374 @retval TRUE Media error
2375 @retval FALSE No media error
2380 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2381 IN UINTN SenseCounts
2384 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2390 SensePtr
= SenseData
;
2392 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2394 switch (SensePtr
->sense_key
) {
2396 case ATA_SK_MEDIUM_ERROR
:
2397 switch (SensePtr
->addnl_sense_code
) {
2398 case ATA_ASC_MEDIA_ERR1
:
2402 case ATA_ASC_MEDIA_ERR2
:
2406 case ATA_ASC_MEDIA_ERR3
:
2410 case ATA_ASC_MEDIA_ERR4
:
2420 case ATA_SK_NOT_READY
:
2421 switch (SensePtr
->addnl_sense_code
) {
2422 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
2442 Check if drive is ready according to sense data.
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.
2448 @retval TRUE Drive ready
2449 @retval FALSE Drive not ready
2454 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2455 IN UINTN SenseCounts
,
2456 OUT BOOLEAN
*NeedRetry
2459 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2466 SensePtr
= SenseData
;
2468 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2470 switch (SensePtr
->sense_key
) {
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
: