2 PEIM to produce gEfiPeiVirtualBlockIoPpiGuid PPI for ATA controllers in the platform.
3 This PPI canl be consumed by PEIM which produce gEfiPeiDeviceRecoveryModulePpiGuid
4 for Atapi CD ROM device.
6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions
10 of the BSD License which accompanies this distribution. The
11 full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "AtapiPeim.h"
22 Initializes the Atapi Block Io PPI.
24 @param[in] FileHandle Handle of the file being invoked.
25 @param[in] PeiServices Describes the list of possible PEI Services.
27 @retval EFI_SUCCESS Operation performed successfully.
28 @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate.
34 IN EFI_PEI_FILE_HANDLE FileHandle
,
35 IN CONST EFI_PEI_SERVICES
**PeiServices
38 PEI_ATA_CONTROLLER_PPI
*AtaControllerPpi
;
40 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
42 Status
= PeiServicesRegisterForShadow (FileHandle
);
43 if (!EFI_ERROR (Status
)) {
47 Status
= PeiServicesLocatePpi (
48 &gPeiAtaControllerPpiGuid
,
51 (VOID
**) &AtaControllerPpi
53 ASSERT_EFI_ERROR (Status
);
55 AtapiBlkIoDev
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*AtapiBlkIoDev
)));
56 if (AtapiBlkIoDev
== NULL
) {
57 return EFI_OUT_OF_RESOURCES
;
60 AtapiBlkIoDev
->Signature
= ATAPI_BLK_IO_DEV_SIGNATURE
;
61 AtapiBlkIoDev
->AtaControllerPpi
= AtaControllerPpi
;
64 // atapi device enumeration and build private data
66 AtapiEnumerateDevices (AtapiBlkIoDev
);
68 AtapiBlkIoDev
->AtapiBlkIo
.GetNumberOfBlockDevices
= AtapiGetNumberOfBlockDevices
;
69 AtapiBlkIoDev
->AtapiBlkIo
.GetBlockDeviceMediaInfo
= AtapiGetBlockDeviceMediaInfo
;
70 AtapiBlkIoDev
->AtapiBlkIo
.ReadBlocks
= AtapiReadBlocks
;
72 AtapiBlkIoDev
->PpiDescriptor
.Flags
= (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
);
73 AtapiBlkIoDev
->PpiDescriptor
.Guid
= &gEfiPeiVirtualBlockIoPpiGuid
;
74 AtapiBlkIoDev
->PpiDescriptor
.Ppi
= &AtapiBlkIoDev
->AtapiBlkIo
;
76 DEBUG ((EFI_D_INFO
, "Atatpi Device Count is %d\n", AtapiBlkIoDev
->DeviceCount
));
77 if (AtapiBlkIoDev
->DeviceCount
!= 0) {
78 Status
= PeiServicesInstallPpi (&AtapiBlkIoDev
->PpiDescriptor
);
79 if (EFI_ERROR (Status
)) {
80 return EFI_OUT_OF_RESOURCES
;
88 Gets the count of block I/O devices that one specific block driver detects.
90 This function is used for getting the count of block I/O devices that one
91 specific block driver detects. To the PEI ATAPI driver, it returns the number
92 of all the detected ATAPI devices it detects during the enumeration process.
93 To the PEI legacy floppy driver, it returns the number of all the legacy
94 devices it finds during its enumeration process. If no device is detected,
95 then the function will return zero.
97 @param[in] PeiServices General-purpose services that are available
99 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
101 @param[out] NumberBlockDevices The number of block I/O devices discovered.
103 @retval EFI_SUCCESS Operation performed successfully.
108 AtapiGetNumberOfBlockDevices (
109 IN EFI_PEI_SERVICES
**PeiServices
,
110 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
111 OUT UINTN
*NumberBlockDevices
114 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
116 AtapiBlkIoDev
= NULL
;
118 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
120 *NumberBlockDevices
= AtapiBlkIoDev
->DeviceCount
;
126 Gets a block device's media information.
128 This function will provide the caller with the specified block device's media
129 information. If the media changes, calling this function will update the media
130 information accordingly.
132 @param[in] PeiServices General-purpose services that are available to every
134 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
135 @param[in] DeviceIndex Specifies the block device to which the function wants
136 to talk. Because the driver that implements Block I/O
137 PPIs will manage multiple block devices, the PPIs that
138 want to talk to a single device must specify the
139 device index that was assigned during the enumeration
140 process. This index is a number from one to
142 @param[out] MediaInfo The media information of the specified block media.
143 The caller is responsible for the ownership of this
146 @retval EFI_SUCCESS Media information about the specified block device
147 was obtained successfully.
148 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
150 @retval Others Other failure occurs.
155 AtapiGetBlockDeviceMediaInfo (
156 IN EFI_PEI_SERVICES
**PeiServices
,
157 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
158 IN UINTN DeviceIndex
,
159 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
163 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
167 AtapiBlkIoDev
= NULL
;
169 if (This
== NULL
|| MediaInfo
== NULL
) {
170 return EFI_INVALID_PARAMETER
;
173 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
175 DeviceCount
= AtapiBlkIoDev
->DeviceCount
;
178 // DeviceIndex is a value from 1 to NumberBlockDevices.
180 if ((DeviceIndex
< 1) || (DeviceIndex
> DeviceCount
) || (DeviceIndex
> MAX_IDE_DEVICES
)) {
181 return EFI_INVALID_PARAMETER
;
184 Index
= DeviceIndex
- 1;
187 // probe media and retrieve latest media information
189 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].DevicePosition
));
190 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo DeviceType is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.DeviceType
));
191 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.MediaPresent
));
192 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo BlockSize is 0x%x\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.BlockSize
));
193 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo LastBlock is 0x%x\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.LastBlock
));
195 Status
= DetectMedia (
197 AtapiBlkIoDev
->DeviceInfo
[Index
].DevicePosition
,
198 &AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
200 if (Status
!= EFI_SUCCESS
) {
201 return EFI_DEVICE_ERROR
;
204 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo DevicePosition is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].DevicePosition
));
205 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo DeviceType is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.DeviceType
));
206 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo MediaPresent is %d\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.MediaPresent
));
207 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo BlockSize is 0x%x\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.BlockSize
));
208 DEBUG ((EFI_D_INFO
, "Atatpi GetInfo LastBlock is 0x%x\n", AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
.LastBlock
));
211 // Get media info from AtapiBlkIoDev
213 CopyMem (MediaInfo
, &AtapiBlkIoDev
->DeviceInfo
[Index
].MediaInfo
, sizeof(EFI_PEI_BLOCK_IO_MEDIA
));
219 Reads the requested number of blocks from the specified block device.
221 The function reads the requested number of blocks from the device. All the
222 blocks are read, or an error is returned. If there is no media in the device,
223 the function returns EFI_NO_MEDIA.
225 @param[in] PeiServices General-purpose services that are available to
227 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
228 @param[in] DeviceIndex Specifies the block device to which the function wants
229 to talk. Because the driver that implements Block I/O
230 PPIs will manage multiple block devices, the PPIs that
231 want to talk to a single device must specify the device
232 index that was assigned during the enumeration process.
233 This index is a number from one to NumberBlockDevices.
234 @param[in] StartLBA The starting logical block address (LBA) to read from
236 @param[in] BufferSize The size of the Buffer in bytes. This number must be
237 a multiple of the intrinsic block size of the device.
238 @param[out] Buffer A pointer to the destination buffer for the data.
239 The caller is responsible for the ownership of the
242 @retval EFI_SUCCESS The data was read correctly from the device.
243 @retval EFI_DEVICE_ERROR The device reported an error while attempting
244 to perform the read operation.
245 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
246 valid, or the buffer is not properly aligned.
247 @retval EFI_NO_MEDIA There is no media in the device.
248 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
249 the intrinsic block size of the device.
255 IN EFI_PEI_SERVICES
**PeiServices
,
256 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI
*This
,
257 IN UINTN DeviceIndex
,
258 IN EFI_PEI_LBA StartLBA
,
264 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
266 UINTN NumberOfBlocks
;
268 ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
;
270 AtapiBlkIoDev
= NULL
;
273 return EFI_INVALID_PARAMETER
;
276 AtapiBlkIoDev
= PEI_RECOVERY_ATAPI_FROM_BLKIO_THIS (This
);
278 if (Buffer
== NULL
) {
279 return EFI_INVALID_PARAMETER
;
282 if (BufferSize
== 0) {
286 Status
= AtapiGetBlockDeviceMediaInfo (
292 if (Status
!= EFI_SUCCESS
) {
293 return EFI_DEVICE_ERROR
;
296 if (!MediaInfo
.MediaPresent
) {
300 BlockSize
= MediaInfo
.BlockSize
;
302 if (BufferSize
% BlockSize
!= 0) {
303 return EFI_BAD_BUFFER_SIZE
;
306 NumberOfBlocks
= BufferSize
/ BlockSize
;
308 if ((StartLBA
+ NumberOfBlocks
- 1) > AtapiBlkIoDev
->DeviceInfo
[DeviceIndex
- 1].MediaInfo
.LastBlock
) {
309 return EFI_INVALID_PARAMETER
;
312 Status
= ReadSectors (
314 AtapiBlkIoDev
->DeviceInfo
[DeviceIndex
- 1].DevicePosition
,
320 if (EFI_ERROR (Status
)) {
321 return EFI_DEVICE_ERROR
;
328 Enumerate Atapi devices.
330 This function is used to enumerate Atatpi device in Ide channel.
332 @param[in] AtapiBlkIoDev A pointer to atapi block IO device
336 AtapiEnumerateDevices (
337 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
342 UINTN DevicePosition
;
343 EFI_PEI_BLOCK_IO_MEDIA MediaInfo
;
346 UINT16 CommandBlockBaseAddr
;
347 UINT16 ControlBlockBaseAddr
;
348 UINT32 IdeEnabledNumber
;
349 IDE_REGS_BASE_ADDR IdeRegsBaseAddr
[MAX_IDE_CHANNELS
];
355 // Scan IDE bus for ATAPI devices
359 // Enable Sata and IDE controller.
361 AtapiBlkIoDev
->AtaControllerPpi
->EnableAtaChannel (
362 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
363 AtapiBlkIoDev
->AtaControllerPpi
,
364 PEI_ICH_IDE_PRIMARY
| PEI_ICH_IDE_SECONDARY
368 // Allow SATA Devices to spin-up. This is needed if
369 // SEC and PEI phase is too short, for example Release Build.
371 DEBUG ((EFI_D_INFO
, "Delay for %d seconds for SATA devices to spin-up\n", PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath
)));
372 MicroSecondDelay (PcdGet16 (PcdSataSpinUpDelayInSecForRecoveryPath
) * 1000 * 1000); //
375 // Get four channels (primary or secondary Pata, Sata Channel) Command and Control Regs Base address.
377 IdeEnabledNumber
= AtapiBlkIoDev
->AtaControllerPpi
->GetIdeRegsBaseAddr (
378 (EFI_PEI_SERVICES
**) GetPeiServicesTablePointer(),
379 AtapiBlkIoDev
->AtaControllerPpi
,
384 // Using Command and Control Regs Base Address to fill other registers.
386 for (Index1
= 0; Index1
< IdeEnabledNumber
; Index1
++) {
387 CommandBlockBaseAddr
= IdeRegsBaseAddr
[Index1
].CommandBlockBaseAddr
;
388 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Data
= CommandBlockBaseAddr
;
389 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Reg1
.Feature
= (UINT16
) (CommandBlockBaseAddr
+ 0x1);
390 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x2);
391 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x3);
392 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x4);
393 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x5);
394 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x6);
395 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Reg
.Command
= (UINT16
) (CommandBlockBaseAddr
+ 0x7);
397 ControlBlockBaseAddr
= IdeRegsBaseAddr
[Index1
].ControlBlockBaseAddr
;
398 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].Alt
.DeviceControl
= ControlBlockBaseAddr
;
399 AtapiBlkIoDev
->IdeIoPortReg
[Index1
].DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x1);
402 // Scan IDE bus for ATAPI devices IDE or Sata device
404 for (Index2
= IdeMaster
; Index2
< IdeMaxDevice
; Index2
++) {
406 // Pata & Sata, Primary & Secondary channel, Master & Slave device
408 DevicePosition
= (UINTN
) (Index1
* 2 + Index2
);
410 if (DiscoverAtapiDevice (AtapiBlkIoDev
, DevicePosition
, &MediaInfo
)) {
412 // ATAPI Device at DevicePosition is found.
414 AtapiBlkIoDev
->DeviceInfo
[DeviceCount
].DevicePosition
= DevicePosition
;
416 // Retrieve Media Info
418 Status
= DetectMedia (AtapiBlkIoDev
, DevicePosition
, &MediaInfo
);
419 CopyMem (&(AtapiBlkIoDev
->DeviceInfo
[DeviceCount
].MediaInfo
), &MediaInfo
, sizeof (MediaInfo
));
421 DEBUG ((EFI_D_INFO
, "Atatpi Device Position is %d\n", DevicePosition
));
422 DEBUG ((EFI_D_INFO
, "Atatpi DeviceType is %d\n", MediaInfo
.DeviceType
));
423 DEBUG ((EFI_D_INFO
, "Atatpi MediaPresent is %d\n", MediaInfo
.MediaPresent
));
424 DEBUG ((EFI_D_INFO
, "Atatpi BlockSize is 0x%x\n", MediaInfo
.BlockSize
));
426 if (EFI_ERROR (Status
)) {
427 AtapiBlkIoDev
->DeviceInfo
[DeviceCount
].MediaInfo
.MediaPresent
= FALSE
;
428 AtapiBlkIoDev
->DeviceInfo
[DeviceCount
].MediaInfo
.LastBlock
= 0;
435 AtapiBlkIoDev
->DeviceCount
= DeviceCount
;
439 Detect Atapi devices.
441 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
442 @param[in] DevicePosition An integer to signify device position.
443 @param[out] MediaInfo The media information of the specified block media.
445 @retval TRUE Atapi device exists in specified position.
446 @retval FALSE Atapi device does not exist in specified position.
450 DiscoverAtapiDevice (
451 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
452 IN UINTN DevicePosition
,
453 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
458 if (!DetectIDEController (AtapiBlkIoDev
, DevicePosition
)) {
462 // test if it is an ATAPI device (only supported device)
464 if (ATAPIIdentify (AtapiBlkIoDev
, DevicePosition
) == EFI_SUCCESS
) {
466 Status
= Inquiry (AtapiBlkIoDev
, DevicePosition
, MediaInfo
);
467 if (!EFI_ERROR (Status
)) {
476 Check power mode of Atapi devices.
478 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
479 @param[in] DevicePosition An integer to signify device position.
480 @param[in] AtaCommand The Ata Command passed in.
482 @retval EFI_SUCCESS The Atapi device support power mode.
483 @retval EFI_NOT_FOUND The Atapi device not found.
484 @retval EFI_TIMEOUT Atapi command transaction is time out.
485 @retval EFI_ABORTED Atapi command abort.
490 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
491 IN UINTN DevicePosition
,
497 UINT16 StatusRegister
;
499 UINT16 CommandRegister
;
500 UINT16 ErrorRegister
;
501 UINT16 SectorCountRegister
;
505 UINT8 SectorCountValue
;
507 Channel
= (UINT8
) (DevicePosition
/ 2);
508 Device
= (UINT8
) (DevicePosition
% 2);
510 ASSERT (Channel
< MAX_IDE_CHANNELS
);
512 StatusRegister
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Status
;
513 HeadRegister
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Head
;
514 CommandRegister
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Command
;
515 ErrorRegister
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg1
.Error
;
516 SectorCountRegister
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].SectorCount
;
521 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
524 // refresh the SectorCount register
526 SectorCountValue
= 0x55;
527 IoWrite8 (SectorCountRegister
, SectorCountValue
);
532 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
534 Status
= DRDYReady (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 100);
539 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
541 // send 'check power' commandd via Command Register
543 IoWrite8 (CommandRegister
, AtaCommand
);
545 Status
= WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 3000);
546 if (EFI_ERROR (Status
)) {
550 StatusValue
= IoRead8 (StatusRegister
);
553 // command returned status is DRDY, indicating device supports the command,
554 // so device is present.
556 if ((StatusValue
& ATA_STSREG_DRDY
) == ATA_STSREG_DRDY
) {
560 SectorCountValue
= IoRead8 (SectorCountRegister
);
563 // command returned status is ERR & ABRT_ERR, indicating device does not support
564 // the command, so device is present.
566 if ((StatusValue
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
567 ErrorValue
= IoRead8 (ErrorRegister
);
568 if ((ErrorValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
572 // According to spec, no other error code is valid
574 return EFI_NOT_FOUND
;
578 if ((SectorCountValue
== 0x00) || (SectorCountValue
== 0x80) || (SectorCountValue
== 0xff)) {
580 // Write SectorCount 0x55 but return valid state value. Maybe no device
581 // exists or some slow kind of ATAPI device exists.
583 IoWrite8 (HeadRegister
, (UINT8
) ((Device
<< 4) | 0xe0));
586 // write 0x55 and 0xaa to SectorCounter register,
587 // if the data could be written into the register,
588 // indicating the device is present, otherwise the device is not present.
590 SectorCountValue
= 0x55;
591 IoWrite8 (SectorCountRegister
, SectorCountValue
);
592 MicroSecondDelay (10000);
594 SectorCountValue
= IoRead8 (SectorCountRegister
);
595 if (SectorCountValue
!= 0x55) {
596 return EFI_NOT_FOUND
;
599 // Send a "ATAPI TEST UNIT READY" command ... slow but accurate
601 Status
= TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
605 return EFI_NOT_FOUND
;
609 Detect if an IDE controller exists in specified position.
611 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
612 @param[in] DevicePosition An integer to signify device position.
614 @retval TRUE The Atapi device exists.
615 @retval FALSE The Atapi device does not present.
619 DetectIDEController (
620 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
621 IN UINTN DevicePosition
628 Channel
= (UINT8
) (DevicePosition
/ 2);
630 ASSERT (Channel
< MAX_IDE_CHANNELS
);
632 // Wait 31 seconds for BSY clear
634 Status
= WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000);
635 if (EFI_ERROR (Status
)) {
639 // Send 'check power' command for IDE device
642 Status
= CheckPowerMode (AtapiBlkIoDev
, DevicePosition
, AtaCommand
);
643 if ((Status
== EFI_ABORTED
) || (Status
== EFI_SUCCESS
)) {
651 Wait specified time interval to poll for BSY bit clear in the Status Register.
653 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
654 @param[in] IdeIoRegisters A pointer to IDE IO registers.
655 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
657 @retval EFI_SUCCESS BSY bit is cleared in the specified time interval.
658 @retval EFI_TIMEOUT BSY bit is not cleared in the specified time interval.
663 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
664 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
665 IN UINTN TimeoutInMilliSeconds
669 UINT16 StatusRegister
;
674 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
676 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
678 StatusValue
= IoRead8 (StatusRegister
);
679 if ((StatusValue
& ATA_STSREG_BSY
) == 0x00) {
682 MicroSecondDelay (250);
686 } while (Delay
!= 0);
696 Wait specified time interval to poll for DRDY bit set in the Status register.
698 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
699 @param[in] IdeIoRegisters A pointer to IDE IO registers.
700 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
702 @retval EFI_SUCCESS DRDY bit is set in the specified time interval.
703 @retval EFI_TIMEOUT DRDY bit is not set in the specified time interval.
708 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
709 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
710 IN UINTN TimeoutInMilliSeconds
714 UINT16 StatusRegister
;
720 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
722 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
724 StatusValue
= IoRead8 (StatusRegister
);
726 // BSY == 0 , DRDY == 1
728 if ((StatusValue
& (ATA_STSREG_DRDY
| ATA_STSREG_BSY
)) == ATA_STSREG_DRDY
) {
732 if ((StatusValue
& (ATA_STSREG_ERR
| ATA_STSREG_BSY
)) == ATA_STSREG_ERR
) {
733 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
734 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
739 MicroSecondDelay (250);
743 } while (Delay
!= 0);
753 Wait specified time interval to poll for DRQ bit clear in the Status Register.
755 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
756 @param[in] IdeIoRegisters A pointer to IDE IO registers.
757 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
759 @retval EFI_SUCCESS DRQ bit is cleared in the specified time interval.
760 @retval EFI_TIMEOUT DRQ bit is not cleared in the specified time interval.
765 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
766 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
767 IN UINTN TimeoutInMilliSeconds
771 UINT16 StatusRegister
;
777 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
779 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
782 StatusValue
= IoRead8 (StatusRegister
);
785 // wait for BSY == 0 and DRQ == 0
787 if ((StatusValue
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
791 if ((StatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
792 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
793 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
798 MicroSecondDelay (250);
801 } while (Delay
!= 0);
811 Wait specified time interval to poll for DRQ bit clear in the Alternate Status Register.
813 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
814 @param[in] IdeIoRegisters A pointer to IDE IO registers.
815 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
817 @retval EFI_SUCCESS DRQ bit is cleared in the specified time interval.
818 @retval EFI_TIMEOUT DRQ bit is not cleared in the specified time interval.
823 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
824 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
825 IN UINTN TimeoutInMilliSeconds
829 UINT16 AltStatusRegister
;
830 UINT8 AltStatusValue
;
835 AltStatusRegister
= IdeIoRegisters
->Alt
.AltStatus
;
837 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
840 AltStatusValue
= IoRead8 (AltStatusRegister
);
843 // wait for BSY == 0 and DRQ == 0
845 if ((AltStatusValue
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
849 if ((AltStatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
850 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
851 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
856 MicroSecondDelay (250);
859 } while (Delay
!= 0);
869 Wait specified time interval to poll for DRQ bit set in the Status Register.
871 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
872 @param[in] IdeIoRegisters A pointer to IDE IO registers.
873 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
875 @retval EFI_SUCCESS DRQ bit is set in the specified time interval.
876 @retval EFI_TIMEOUT DRQ bit is not set in the specified time interval.
877 @retval EFI_ABORTED Operation Aborted.
882 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
883 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
884 IN UINTN TimeoutInMilliSeconds
888 UINT16 StatusRegister
;
895 StatusRegister
= IdeIoRegisters
->Reg
.Status
;
897 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
900 // read Status Register will clear interrupt
902 StatusValue
= IoRead8 (StatusRegister
);
907 if ((StatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
911 if ((StatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
913 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
914 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
918 MicroSecondDelay (250);
921 } while (Delay
!= 0);
931 Wait specified time interval to poll for DRQ bit set in the Alternate Status Register.
933 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
934 @param[in] IdeIoRegisters A pointer to IDE IO registers.
935 @param[in] TimeoutInMilliSeconds Time specified in milliseconds.
937 @retval EFI_SUCCESS DRQ bit is set in the specified time interval.
938 @retval EFI_TIMEOUT DRQ bit is not set in the specified time interval.
939 @retval EFI_ABORTED Operation Aborted.
944 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
945 IN IDE_BASE_REGISTERS
*IdeIoRegisters
,
946 IN UINTN TimeoutInMilliSeconds
950 UINT16 AltStatusRegister
;
951 UINT8 AltStatusValue
;
956 AltStatusRegister
= IdeIoRegisters
->Alt
.AltStatus
;
958 Delay
= ((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 250) + 1;
961 AltStatusValue
= IoRead8 (AltStatusRegister
);
966 if ((AltStatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
970 if ((AltStatusValue
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
972 ErrValue
= IoRead8 (IdeIoRegisters
->Reg1
.Error
);
973 if ((ErrValue
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
977 MicroSecondDelay (250);
980 } while (Delay
!= 0);
990 Check if there is an error in Status Register.
992 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
993 @param[in] StatusReg The address to IDE IO registers.
995 @retval EFI_SUCCESS Operation success.
996 @retval EFI_DEVICE_ERROR Device error.
1001 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1007 StatusValue
= IoRead8 (StatusReg
);
1009 if ((StatusValue
& (ATA_STSREG_ERR
| ATA_STSREG_DWF
| ATA_STSREG_CORR
)) == 0) {
1014 return EFI_DEVICE_ERROR
;
1019 Idendify Atapi devices.
1021 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1022 @param[in] DevicePosition An integer to signify device position.
1024 @retval EFI_SUCCESS Identify successfully.
1025 @retval EFI_DEVICE_ERROR Device cannot be identified successfully.
1030 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1031 IN UINTN DevicePosition
1034 ATAPI_IDENTIFY_DATA AtapiIdentifyData
;
1041 UINT16 SectorCountReg
;
1042 UINT16 SectorNumberReg
;
1043 UINT16 CylinderLsbReg
;
1044 UINT16 CylinderMsbReg
;
1054 ByteCount
= sizeof (AtapiIdentifyData
);
1055 Buffer16
= (UINT16
*) &AtapiIdentifyData
;
1057 Channel
= (UINT8
) (DevicePosition
/ 2);
1058 Device
= (UINT8
) (DevicePosition
% 2);
1060 ASSERT (Channel
< MAX_IDE_CHANNELS
);
1062 StatusReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Status
;
1063 HeadReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Head
;
1064 CommandReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Command
;
1065 DataReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Data
;
1066 SectorCountReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].SectorCount
;
1067 SectorNumberReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].SectorNumber
;
1068 CylinderLsbReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].CylinderLsb
;
1069 CylinderMsbReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].CylinderMsb
;
1072 // Send ATAPI Identify Command to get IDENTIFY data.
1074 if (WaitForBSYClear (
1076 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1079 return EFI_DEVICE_ERROR
;
1082 // select device via Head/Device register.
1083 // Before write Head/Device register, BSY and DRQ must be 0.
1085 if (DRQClear2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), ATATIMEOUT
) != EFI_SUCCESS
) {
1086 return EFI_DEVICE_ERROR
;
1089 // e0:1110,0000-- bit7 and bit5 are reserved bits.
1090 // bit6 set means LBA mode
1092 IoWrite8 (HeadReg
, (UINT8
) ((Device
<< 4) | 0xe0));
1095 // set all the command parameters
1096 // Before write to all the following registers, BSY and DRQ must be 0.
1100 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1104 return EFI_DEVICE_ERROR
;
1107 IoWrite8 (SectorCountReg
, 0);
1108 IoWrite8 (SectorNumberReg
, 0);
1109 IoWrite8 (CylinderLsbReg
, 0);
1110 IoWrite8 (CylinderMsbReg
, 0);
1113 // send command via Command Register
1115 IoWrite8 (CommandReg
, ATA_CMD_IDENTIFY_DEVICE
);
1118 // According to PIO data in protocol, host can perform a series of reads to the
1119 // data register after each time device set DRQ ready;
1120 // The data size of "a series of read" is command specific.
1121 // For most ATA command, data size received from device will not exceed 1 sector,
1122 // hense the data size for "a series of read" can be the whole data size of one command request.
1123 // For ATA command such as Read Sector command, whole data size of one ATA command request is often larger
1124 // than 1 sector, according to the Read Sector command, the data size of "a series of read" is exactly
1126 // Here for simplification reason, we specify the data size for "a series of read" to
1127 // 1 sector (256 words) if whole data size of one ATA commmand request is larger than 256 words.
1135 // WordCount is used to record bytes of currently transfered data
1137 while (WordCount
< ByteCount
/ 2) {
1139 // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
1141 Status
= DRQReady2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), ATATIMEOUT
);
1142 if (Status
!= EFI_SUCCESS
) {
1146 if (CheckErrorStatus (AtapiBlkIoDev
, StatusReg
) != EFI_SUCCESS
) {
1148 return EFI_DEVICE_ERROR
;
1151 // Get the byte count for one series of read
1153 if ((WordCount
+ Increment
) > ByteCount
/ 2) {
1154 Increment
= ByteCount
/ 2 - WordCount
;
1157 // perform a series of read without check DRQ ready
1159 for (Index
= 0; Index
< Increment
; Index
++) {
1160 *Buffer16
++ = IoRead16 (DataReg
);
1163 WordCount
+= Increment
;
1171 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1174 return CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1182 Sends out ATAPI Test Unit Ready Packet Command to the specified device
1183 to find out whether device is accessible.
1185 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1186 @param[in] DevicePosition An integer to signify device position.
1188 @retval EFI_SUCCESS TestUnit command executed successfully.
1189 @retval EFI_DEVICE_ERROR Device cannot be executed TestUnit command successfully.
1194 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1195 IN UINTN DevicePosition
1198 ATAPI_PACKET_COMMAND Packet
;
1202 // fill command packet
1204 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1205 Packet
.TestUnitReady
.opcode
= ATA_CMD_TEST_UNIT_READY
;
1208 // send command packet
1210 Status
= AtapiPacketCommandIn (AtapiBlkIoDev
, DevicePosition
, &Packet
, NULL
, 0, ATAPITIMEOUT
);
1215 Send out ATAPI commands conforms to the Packet Command with PIO Data In Protocol.
1217 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1218 @param[in] DevicePosition An integer to signify device position.
1219 @param[in] Packet A pointer to ATAPI command packet.
1220 @param[in] Buffer Buffer to contain requested transfer data from device.
1221 @param[in] ByteCount Requested transfer data length.
1222 @param[in] TimeoutInMilliSeconds Time out value, in unit of milliseconds.
1224 @retval EFI_SUCCESS Command executed successfully.
1225 @retval EFI_DEVICE_ERROR Device cannot be executed command successfully.
1229 AtapiPacketCommandIn (
1230 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1231 IN UINTN DevicePosition
,
1232 IN ATAPI_PACKET_COMMAND
*Packet
,
1234 IN UINT32 ByteCount
,
1235 IN UINTN TimeoutInMilliSeconds
1244 UINT16 CylinderLsbReg
;
1245 UINT16 CylinderMsbReg
;
1246 UINT16 DeviceControlReg
;
1250 UINT16
*CommandIndex
;
1257 // required transfer data in word unit.
1259 UINT32 RequiredWordCount
;
1262 // actual transfer data in word unit.
1264 UINT32 ActualWordCount
;
1266 Channel
= (UINT8
) (DevicePosition
/ 2);
1267 Device
= (UINT8
) (DevicePosition
% 2);
1269 ASSERT (Channel
< MAX_IDE_CHANNELS
);
1271 StatusReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Status
;
1272 HeadReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Head
;
1273 CommandReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Command
;
1274 FeatureReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg1
.Feature
;
1275 CylinderLsbReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].CylinderLsb
;
1276 CylinderMsbReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].CylinderMsb
;
1277 DeviceControlReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Alt
.DeviceControl
;
1278 DataReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Data
;
1281 // Set all the command parameters by fill related registers.
1282 // Before write to all the following registers, BSY and DRQ must be 0.
1286 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1289 return EFI_DEVICE_ERROR
;
1292 // Select device via Device/Head Register.
1293 // DEFAULT_CMD: 0xa0 (1010,0000)
1295 IoWrite8 (HeadReg
, (UINT8
) ((Device
<< 4) | ATA_DEFAULT_CMD
));
1300 IoWrite8 (FeatureReg
, 0x00);
1303 // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
1304 // determine how many data should be transfered.
1306 IoWrite8 (CylinderLsbReg
, (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff));
1307 IoWrite8 (CylinderMsbReg
, (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8));
1310 // DEFAULT_CTL:0x0a (0000,1010)
1311 // Disable interrupt
1313 IoWrite8 (DeviceControlReg
, ATA_DEFAULT_CTL
);
1316 // Send Packet command to inform device
1317 // that the following data bytes are command packet.
1319 IoWrite8 (CommandReg
, ATA_CMD_PACKET
);
1321 Status
= DRQReady (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), TimeoutInMilliSeconds
);
1322 if (Status
!= EFI_SUCCESS
) {
1326 // Send out command packet
1328 CommandIndex
= Packet
->Data16
;
1329 for (Count
= 0; Count
< 6; Count
++, CommandIndex
++) {
1330 IoWrite16 (DataReg
, *CommandIndex
);
1331 MicroSecondDelay (10);
1334 StatusValue
= IoRead8 (StatusReg
);
1335 if ((StatusValue
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
1337 // Trouble! Something's wrong here... Wait some time and return. 3 second is
1338 // supposed to be long enough for a device reset latency or error recovery
1340 MicroSecondDelay (3000000);
1341 return EFI_DEVICE_ERROR
;
1344 if (Buffer
== NULL
|| ByteCount
== 0) {
1348 // call PioReadWriteData() function to get
1349 // requested transfer data form device.
1352 RequiredWordCount
= ByteCount
/ 2;
1354 // ActuralWordCount means the word count of data really transfered.
1356 ActualWordCount
= 0;
1358 Status
= EFI_SUCCESS
;
1359 while ((Status
== EFI_SUCCESS
) && (ActualWordCount
< RequiredWordCount
)) {
1361 // before each data transfer stream, the host should poll DRQ bit ready,
1362 // which informs device is ready to transfer data.
1366 &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]),
1367 TimeoutInMilliSeconds
1369 return CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1372 // read Status Register will clear interrupt
1374 StatusValue
= IoRead8 (StatusReg
);
1377 // get current data transfer size from Cylinder Registers.
1379 WordCount
= IoRead8 (CylinderMsbReg
) << 8;
1380 WordCount
= WordCount
| IoRead8 (CylinderLsbReg
);
1381 WordCount
= WordCount
& 0xffff;
1385 // perform a series data In/Out.
1387 for (Index
= 0; (Index
< WordCount
) && (ActualWordCount
< RequiredWordCount
); Index
++, ActualWordCount
++) {
1389 *PtrBuffer
= IoRead16 (DataReg
);
1395 if (((ATAPI_REQUEST_SENSE_CMD
*) Packet
)->opcode
== ATA_CMD_REQUEST_SENSE
&& ActualWordCount
>= 4) {
1396 RequiredWordCount
= MIN (
1398 (UINT32
) (4 + (((ATAPI_REQUEST_SENSE_DATA
*) Buffer
)->addnl_sense_length
/ 2))
1404 // After data transfer is completed, normally, DRQ bit should clear.
1406 Status
= DRQClear2 (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), TimeoutInMilliSeconds
);
1407 if (Status
!= EFI_SUCCESS
) {
1408 return EFI_DEVICE_ERROR
;
1411 // read status register to check whether error happens.
1413 Status
= CheckErrorStatus (AtapiBlkIoDev
, StatusReg
);
1418 Sends out ATAPI Inquiry Packet Command to the specified device.
1419 This command will return INQUIRY data of the device.
1421 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1422 @param[in] DevicePosition An integer to signify device position.
1423 @param[out] MediaInfo The media information of the specified block media.
1425 @retval EFI_SUCCESS Command executed successfully.
1426 @retval EFI_DEVICE_ERROR Device cannot be executed command successfully.
1427 @retval EFI_UNSUPPORTED Unsupported device type.
1432 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1433 IN UINTN DevicePosition
,
1434 OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
1437 ATAPI_PACKET_COMMAND Packet
;
1439 ATAPI_INQUIRY_DATA Idata
;
1442 // prepare command packet for the ATAPI Inquiry Packet Command.
1444 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1445 ZeroMem (&Idata
, sizeof (ATAPI_INQUIRY_DATA
));
1447 Packet
.Inquiry
.opcode
= ATA_CMD_INQUIRY
;
1448 Packet
.Inquiry
.page_code
= 0;
1449 Packet
.Inquiry
.allocation_length
= (UINT8
) sizeof (ATAPI_INQUIRY_DATA
);
1452 // Send command packet and get requested Inquiry data.
1454 Status
= AtapiPacketCommandIn (
1458 (UINT16
*) (&Idata
),
1459 sizeof (ATAPI_INQUIRY_DATA
),
1464 if (Status
!= EFI_SUCCESS
) {
1465 return EFI_DEVICE_ERROR
;
1468 // Identify device type via INQUIRY data.
1470 switch (Idata
.peripheral_type
& 0x1f) {
1475 MediaInfo
->DeviceType
= IdeLS120
;
1476 MediaInfo
->MediaPresent
= FALSE
;
1477 MediaInfo
->LastBlock
= 0;
1478 MediaInfo
->BlockSize
= 0x200;
1485 MediaInfo
->DeviceType
= IdeCDROM
;
1486 MediaInfo
->MediaPresent
= FALSE
;
1487 MediaInfo
->LastBlock
= 0;
1488 MediaInfo
->BlockSize
= 0x800;
1492 return EFI_UNSUPPORTED
;
1499 Used before read/write blocks from/to ATAPI device media.
1500 Since ATAPI device media is removable, it is necessary to detect
1501 whether media is present and get current present media's information.
1503 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1504 @param[in] DevicePosition An integer to signify device position.
1505 @param[in, out] MediaInfo The media information of the specified block media.
1507 @retval EFI_SUCCESS Command executed successfully.
1508 @retval EFI_DEVICE_ERROR Some device errors happen.
1509 @retval EFI_OUT_OF_RESOURCES Can not allocate required resources.
1514 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1515 IN UINTN DevicePosition
,
1516 IN OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
1523 ATAPI_REQUEST_SENSE_DATA
*SenseBuffers
;
1524 BOOLEAN NeedReadCapacity
;
1529 SenseBuffers
= AllocatePages (EFI_SIZE_TO_PAGES (sizeof (*SenseBuffers
)));
1530 if (SenseBuffers
== NULL
) {
1531 return EFI_OUT_OF_RESOURCES
;
1535 // Test Unit Ready command is used to detect whether device is accessible,
1536 // the device will produce corresponding Sense data.
1538 for (Index
= 0; Index
< 2; Index
++) {
1540 Status
= TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
1541 if (Status
!= EFI_SUCCESS
) {
1542 Status
= ResetDevice (AtapiBlkIoDev
, DevicePosition
, FALSE
);
1544 if (Status
!= EFI_SUCCESS
) {
1545 ResetDevice (AtapiBlkIoDev
, DevicePosition
, TRUE
);
1553 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1554 Status
= EFI_SUCCESS
;
1555 NeedReadCapacity
= TRUE
;
1557 for (Index
= 0; Index
< 5; Index
++) {
1558 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1559 Status
= RequestSense (
1565 DEBUG ((EFI_D_INFO
, "Atapi Request Sense Count is %d\n", SenseCounts
));
1566 if (IsDeviceStateUnclear (SenseBuffers
, SenseCounts
) || IsNoMedia (SenseBuffers
, SenseCounts
)) {
1568 // We are not sure whether the media is present or not, try again
1570 TestUnitReady (AtapiBlkIoDev
, DevicePosition
);
1576 if (Status
== EFI_SUCCESS
) {
1578 if (IsNoMedia (SenseBuffers
, SenseCounts
)) {
1580 NeedReadCapacity
= FALSE
;
1581 MediaInfo
->MediaPresent
= FALSE
;
1582 MediaInfo
->LastBlock
= 0;
1585 if (IsMediaError (SenseBuffers
, SenseCounts
)) {
1586 return EFI_DEVICE_ERROR
;
1590 if (NeedReadCapacity
) {
1592 // at most retry 5 times
1597 // initial retry once
1599 for (Index
= 0; (Index
< RetryNum
) && (Index
< MaxRetryNum
); Index
++) {
1601 Status
= ReadCapacity (AtapiBlkIoDev
, DevicePosition
, MediaInfo
);
1602 MicroSecondDelay (200000);
1603 SenseCounts
= MAX_SENSE_KEY_COUNT
;
1605 if (Status
!= EFI_SUCCESS
) {
1607 Status
= RequestSense (AtapiBlkIoDev
, DevicePosition
, SenseBuffers
, &SenseCounts
);
1609 // If Request Sense data failed, reset the device and retry.
1611 if (Status
!= EFI_SUCCESS
) {
1613 Status
= ResetDevice (AtapiBlkIoDev
, DevicePosition
, FALSE
);
1615 // if ATAPI soft reset fail,
1616 // use stronger reset mechanism -- ATA soft reset.
1618 if (Status
!= EFI_SUCCESS
) {
1619 ResetDevice (AtapiBlkIoDev
, DevicePosition
, TRUE
);
1631 if (IsNoMedia (SenseBuffers
, SenseCounts
)) {
1633 MediaInfo
->MediaPresent
= FALSE
;
1634 MediaInfo
->LastBlock
= 0;
1638 if (IsMediaError (SenseBuffers
, SenseCounts
)) {
1639 return EFI_DEVICE_ERROR
;
1642 if (!IsDriveReady (SenseBuffers
, SenseCounts
, &NeedRetry
)) {
1644 // Drive not ready: if NeedRetry, then retry once more;
1645 // else return error
1651 return EFI_DEVICE_ERROR
;
1655 // if read capacity fail not for above reasons, retry once more
1669 Reset specified Atapi device.
1671 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1672 @param[in] DevicePosition An integer to signify device position.
1673 @param[in] Extensive If TRUE, use ATA soft reset, otherwise use Atapi soft reset.
1675 @retval EFI_SUCCESS Command executed successfully.
1676 @retval EFI_DEVICE_ERROR Some device errors happen.
1681 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1682 IN UINTN DevicePosition
,
1683 IN BOOLEAN Extensive
1689 UINT16 DeviceControlReg
;
1695 Channel
= (UINT8
) (DevicePosition
/ 2);
1696 Device
= (UINT8
) (DevicePosition
% 2);
1698 ASSERT (Channel
< MAX_IDE_CHANNELS
);
1700 DeviceControlReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Alt
.DeviceControl
;
1701 CommandReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Reg
.Command
;
1702 HeadReg
= AtapiBlkIoDev
->IdeIoPortReg
[Channel
].Head
;
1707 DevControl
|= ATA_CTLREG_SRST
;
1709 // set SRST bit to initiate soft reset
1713 // disable Interrupt
1715 IoWrite8 (DeviceControlReg
, DevControl
);
1720 MicroSecondDelay (10);
1729 IoWrite8 (DeviceControlReg
, DevControl
);
1732 // slave device needs at most 31s to clear BSY
1734 if (WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000) == EFI_TIMEOUT
) {
1735 return EFI_DEVICE_ERROR
;
1740 // for ATAPI device, no need to wait DRDY ready after device selecting.
1741 // bit7 and bit5 are both set to 1 for backward compatibility
1743 DeviceSelect
= (UINT8
) (((BIT7
| BIT5
) | (Device
<< 4)));
1744 IoWrite8 (HeadReg
, DeviceSelect
);
1746 Command
= ATA_CMD_SOFT_RESET
;
1747 IoWrite8 (CommandReg
, Command
);
1750 // BSY cleared is the only status return to the host by the device when reset is completed
1751 // slave device needs at most 31s to clear BSY
1753 if (WaitForBSYClear (AtapiBlkIoDev
, &(AtapiBlkIoDev
->IdeIoPortReg
[Channel
]), 31000) != EFI_SUCCESS
) {
1754 return EFI_DEVICE_ERROR
;
1757 // stall 5 seconds to make the device status stable
1759 MicroSecondDelay (STALL_1_SECONDS
* 5);
1767 Sends out ATAPI Request Sense Packet Command to the specified device.
1769 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1770 @param[in] DevicePosition An integer to signify device position.
1771 @param[in] SenseBuffers Pointer to sense buffer.
1772 @param[in, out] SenseCounts Length of sense buffer.
1774 @retval EFI_SUCCESS Command executed successfully.
1775 @retval EFI_DEVICE_ERROR Some device errors happen.
1780 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1781 IN UINTN DevicePosition
,
1782 IN ATAPI_REQUEST_SENSE_DATA
*SenseBuffers
,
1783 IN OUT UINT8
*SenseCounts
1787 ATAPI_REQUEST_SENSE_DATA
*Sense
;
1790 ATAPI_PACKET_COMMAND Packet
;
1792 ZeroMem (SenseBuffers
, sizeof (ATAPI_REQUEST_SENSE_DATA
) * (*SenseCounts
));
1794 // fill command packet for Request Sense Packet Command
1796 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1797 Packet
.RequestSence
.opcode
= ATA_CMD_REQUEST_SENSE
;
1798 Packet
.RequestSence
.allocation_length
= (UINT8
) sizeof (ATAPI_REQUEST_SENSE_DATA
);
1800 Ptr
= (UINT16
*) SenseBuffers
;
1802 // initialize pointer
1806 // request sense data from device continiously until no sense data exists in the device.
1808 for (SenseReq
= TRUE
; SenseReq
;) {
1810 Sense
= (ATAPI_REQUEST_SENSE_DATA
*) Ptr
;
1813 // send out Request Sense Packet Command and get one Sense data form device
1815 Status
= AtapiPacketCommandIn (
1820 sizeof (ATAPI_REQUEST_SENSE_DATA
),
1824 // failed to get Sense data
1826 if (Status
!= EFI_SUCCESS
) {
1827 if (*SenseCounts
== 0) {
1828 return EFI_DEVICE_ERROR
;
1836 if (*SenseCounts
> MAX_SENSE_KEY_COUNT
) {
1840 // We limit MAX sense data count to 20 in order to avoid dead loop. Some
1841 // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
1842 // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
1843 // supposed to be large enough for any ATAPI device.
1845 if ((Sense
->sense_key
!= ATA_SK_NO_SENSE
) && ((*SenseCounts
) < 20)) {
1847 Ptr
+= sizeof (ATAPI_REQUEST_SENSE_DATA
) / 2;
1849 // Ptr is word based pointer
1853 // when no sense key, skip out the loop
1863 Sends out ATAPI Read Capacity Packet Command to the specified device.
1864 This command will return the information regarding the capacity of the
1865 media in the device.
1867 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1868 @param[in] DevicePosition An integer to signify device position.
1869 @param[in, out] MediaInfo The media information of the specified block media.
1871 @retval EFI_SUCCESS Command executed successfully.
1872 @retval EFI_DEVICE_ERROR Some device errors happen.
1877 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1878 IN UINTN DevicePosition
,
1879 IN OUT EFI_PEI_BLOCK_IO_MEDIA
*MediaInfo
1883 ATAPI_PACKET_COMMAND Packet
;
1886 // used for capacity data returned from ATAPI device
1888 ATAPI_READ_CAPACITY_DATA Data
;
1889 ATAPI_READ_FORMAT_CAPACITY_DATA FormatData
;
1891 ZeroMem (&Data
, sizeof (Data
));
1892 ZeroMem (&FormatData
, sizeof (FormatData
));
1894 if (MediaInfo
->DeviceType
== IdeCDROM
) {
1896 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1897 Packet
.Inquiry
.opcode
= ATA_CMD_READ_CAPACITY
;
1898 Status
= AtapiPacketCommandIn (
1903 sizeof (ATAPI_READ_CAPACITY_DATA
),
1909 // DeviceType == IdeLS120
1911 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
1912 Packet
.ReadFormatCapacity
.opcode
= ATA_CMD_READ_FORMAT_CAPACITY
;
1913 Packet
.ReadFormatCapacity
.allocation_length_lo
= 12;
1914 Status
= AtapiPacketCommandIn (
1918 (UINT16
*) (&FormatData
),
1919 sizeof (ATAPI_READ_FORMAT_CAPACITY_DATA
),
1924 if (Status
== EFI_SUCCESS
) {
1926 if (MediaInfo
->DeviceType
== IdeCDROM
) {
1928 MediaInfo
->LastBlock
= (Data
.LastLba3
<< 24) | (Data
.LastLba2
<< 16) | (Data
.LastLba1
<< 8) | Data
.LastLba0
;
1929 MediaInfo
->MediaPresent
= TRUE
;
1931 // Because the user data portion in the sector of the Data CD supported
1934 MediaInfo
->BlockSize
= 0x800;
1937 if (MediaInfo
->DeviceType
== IdeLS120
) {
1939 if (FormatData
.DesCode
== 3) {
1940 MediaInfo
->MediaPresent
= FALSE
;
1941 MediaInfo
->LastBlock
= 0;
1943 MediaInfo
->LastBlock
= (FormatData
.LastLba3
<< 24) |
1944 (FormatData
.LastLba2
<< 16) |
1945 (FormatData
.LastLba1
<< 8) |
1946 FormatData
.LastLba0
;
1947 MediaInfo
->LastBlock
--;
1949 MediaInfo
->MediaPresent
= TRUE
;
1951 MediaInfo
->BlockSize
= 0x200;
1959 return EFI_DEVICE_ERROR
;
1964 Perform read from disk in block unit.
1966 @param[in] AtapiBlkIoDev A pointer to atapi block IO device.
1967 @param[in] DevicePosition An integer to signify device position.
1968 @param[in] Buffer Buffer to contain read data.
1969 @param[in] StartLba Starting LBA address.
1970 @param[in] NumberOfBlocks Number of blocks to read.
1971 @param[in] BlockSize Size of each block.
1973 @retval EFI_SUCCESS Command executed successfully.
1974 @retval EFI_DEVICE_ERROR Some device errors happen.
1979 IN ATAPI_BLK_IO_DEV
*AtapiBlkIoDev
,
1980 IN UINTN DevicePosition
,
1982 IN EFI_PEI_LBA StartLba
,
1983 IN UINTN NumberOfBlocks
,
1988 ATAPI_PACKET_COMMAND Packet
;
1989 ATAPI_READ10_CMD
*Read10Packet
;
1991 UINTN BlocksRemaining
;
1999 // fill command packet for Read(10) command
2001 ZeroMem (&Packet
, sizeof (ATAPI_PACKET_COMMAND
));
2002 Read10Packet
= &Packet
.Read10
;
2003 Lba32
= (UINT32
) StartLba
;
2007 // limit the data bytes that can be transfered by one Read(10) Command
2009 MaxBlock
= (UINT16
) (0x10000 / BlockSize
);
2013 BlocksRemaining
= NumberOfBlocks
;
2015 Status
= EFI_SUCCESS
;
2016 while (BlocksRemaining
> 0) {
2018 if (BlocksRemaining
<= MaxBlock
) {
2019 SectorCount
= (UINT16
) BlocksRemaining
;
2021 SectorCount
= MaxBlock
;
2024 // fill the Packet data sturcture
2026 Read10Packet
->opcode
= ATA_CMD_READ_10
;
2029 // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
2030 // Lba0 is MSB, Lba3 is LSB
2032 Read10Packet
->Lba3
= (UINT8
) (Lba32
& 0xff);
2033 Read10Packet
->Lba2
= (UINT8
) (Lba32
>> 8);
2034 Read10Packet
->Lba1
= (UINT8
) (Lba32
>> 16);
2035 Read10Packet
->Lba0
= (UINT8
) (Lba32
>> 24);
2038 // TranLen0 ~ TranLen1 specify the transfer length in block unit.
2039 // TranLen0 is MSB, TranLen is LSB
2041 Read10Packet
->TranLen1
= (UINT8
) (SectorCount
& 0xff);
2042 Read10Packet
->TranLen0
= (UINT8
) (SectorCount
>> 8);
2044 ByteCount
= (UINT32
) (SectorCount
* BlockSize
);
2046 Status
= AtapiPacketCommandIn (
2050 (UINT16
*) PtrBuffer
,
2054 if (Status
!= EFI_SUCCESS
) {
2058 Lba32
+= SectorCount
;
2059 PtrBuffer
= (UINT8
*) PtrBuffer
+ SectorCount
* BlockSize
;
2060 BlocksRemaining
-= SectorCount
;
2067 Check if there is media according to sense data.
2069 @param[in] SenseData Pointer to sense data.
2070 @param[in] SenseCounts Count of sense data.
2072 @retval TRUE No media
2073 @retval FALSE Media exists
2078 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2079 IN UINTN SenseCounts
2082 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2088 SensePtr
= SenseData
;
2090 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2092 if ((SensePtr
->sense_key
== ATA_SK_NOT_READY
) && (SensePtr
->addnl_sense_code
== ATA_ASC_NO_MEDIA
)) {
2103 Check if device state is unclear according to sense data.
2105 @param[in] SenseData Pointer to sense data.
2106 @param[in] SenseCounts Count of sense data.
2108 @retval TRUE Device state is unclear
2109 @retval FALSE Device state is clear
2113 IsDeviceStateUnclear (
2114 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2115 IN UINTN SenseCounts
2118 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2124 SensePtr
= SenseData
;
2126 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2128 if (SensePtr
->sense_key
== 0x06) {
2130 // Sense key is 0x06 means the device is just be reset or media just
2131 // changed. The current state of the device is unclear.
2144 Check if there is media error according to sense data.
2146 @param[in] SenseData Pointer to sense data.
2147 @param[in] SenseCounts Count of sense data.
2149 @retval TRUE Media error
2150 @retval FALSE No media error
2155 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2156 IN UINTN SenseCounts
2159 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2165 SensePtr
= SenseData
;
2167 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2169 switch (SensePtr
->sense_key
) {
2171 case ATA_SK_MEDIUM_ERROR
:
2172 switch (SensePtr
->addnl_sense_code
) {
2173 case ATA_ASC_MEDIA_ERR1
:
2177 case ATA_ASC_MEDIA_ERR2
:
2181 case ATA_ASC_MEDIA_ERR3
:
2185 case ATA_ASC_MEDIA_ERR4
:
2195 case ATA_SK_NOT_READY
:
2196 switch (SensePtr
->addnl_sense_code
) {
2197 case ATA_ASC_MEDIA_UPSIDE_DOWN
:
2217 Check if drive is ready according to sense data.
2219 @param[in] SenseData Pointer to sense data.
2220 @param[in] SenseCounts Count of sense data.
2221 @param[out] NeedRetry Indicate if retry is needed.
2223 @retval TRUE Drive ready
2224 @retval FALSE Drive not ready
2229 IN ATAPI_REQUEST_SENSE_DATA
*SenseData
,
2230 IN UINTN SenseCounts
,
2231 OUT BOOLEAN
*NeedRetry
2234 ATAPI_REQUEST_SENSE_DATA
*SensePtr
;
2241 SensePtr
= SenseData
;
2243 for (Index
= 0; Index
< SenseCounts
; Index
++) {
2245 switch (SensePtr
->sense_key
) {
2247 case ATA_SK_NOT_READY
:
2248 switch (SensePtr
->addnl_sense_code
) {
2249 case ATA_ASC_NOT_READY
:
2250 switch (SensePtr
->addnl_sense_code_qualifier
) {
2251 case ATA_ASCQ_IN_PROGRESS
: