2 This driver is used for Opal Password Feature support at IDE mode.
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "OpalPasswordSmm.h"
18 Write multiple words of Data to the IDE Data port.
19 Call the IO abstraction once to do the complete read,
20 not one word at a time
22 @param Port IO port to read
23 @param Count No. of UINT16's to read
24 @param Buffer Pointer to the Data Buffer for read
29 IdeWritePortWMultiple (
37 for (Index
= 0; Index
< Count
; Index
++) {
38 IoWrite16 (Port
, Buffer
[Index
]);
43 Reads multiple words of Data from the IDE Data port.
44 Call the IO abstraction once to do the complete read,
45 not one word at a time
47 @param Port IO port to read
48 @param Count Number of UINT16's to read
49 @param Buffer Pointer to the Data Buffer for read
54 IdeReadPortWMultiple (
62 for (Index
= 0; Index
< Count
; Index
++) {
63 Buffer
[Count
] = IoRead16 (Port
);
68 This function is used to analyze the Status Register and print out
69 some debug information and if there is ERR bit set in the Status
70 Register, the Error Register's Value is also be parsed and print out.
72 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
78 IN EFI_IDE_REGISTERS
*IdeRegisters
81 ASSERT (IdeRegisters
!= NULL
);
84 if ((IoRead8 (IdeRegisters
->CmdOrStatus
) & ATA_STSREG_DWF
) != 0) {
85 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Write Fault\n", IoRead8 (IdeRegisters
->CmdOrStatus
)));
88 if ((IoRead8 (IdeRegisters
->CmdOrStatus
) & ATA_STSREG_CORR
) != 0) {
89 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Corrected Data\n", IoRead8 (IdeRegisters
->CmdOrStatus
)));
92 if ((IoRead8 (IdeRegisters
->CmdOrStatus
) & ATA_STSREG_ERR
) != 0) {
93 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_BBK
) != 0) {
94 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Bad Block Detected\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
97 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_UNC
) != 0) {
98 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Uncorrectable Data\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
101 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_MC
) != 0) {
102 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Media Change\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
105 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_ABRT
) != 0) {
106 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Abort\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
109 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_TK0NF
) != 0) {
110 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Track 0 Not Found\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
113 if ((IoRead8 (IdeRegisters
->ErrOrFeature
) & ATA_ERRREG_AMNF
) != 0) {
114 DEBUG ((EFI_D_ERROR
, "CheckRegisterStatus()-- %02x : Error : Address Mark Not Found\n", IoRead8 (IdeRegisters
->ErrOrFeature
)));
121 This function is used to analyze the Status Register and print out
122 some debug information and if there is ERR bit set in the Status
123 Register, the Error Register's Value is also be parsed and print out.
125 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
127 @retval EFI_SUCCESS No err information in the Status Register.
128 @retval EFI_DEVICE_ERROR Any err information in the Status Register.
133 CheckStatusRegister (
134 IN EFI_IDE_REGISTERS
*IdeRegisters
138 UINT8 StatusRegister
;
140 ASSERT (IdeRegisters
!= NULL
);
142 StatusRegister
= IoRead8 (IdeRegisters
->CmdOrStatus
);
144 if ((StatusRegister
& (ATA_STSREG_ERR
| ATA_STSREG_DWF
| ATA_STSREG_CORR
)) == 0) {
145 Status
= EFI_SUCCESS
;
147 Status
= EFI_DEVICE_ERROR
;
154 This function is used to poll for the DRQ bit clear in the Status
155 Register. DRQ is cleared when the device is finished transferring Data.
156 So this function is called after Data transfer is finished.
158 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
159 @param Timeout The time to complete the command.
161 @retval EFI_SUCCESS DRQ bit clear within the time out.
162 @retval EFI_TIMEOUT DRQ bit not clear within the time out.
165 Read Status Register will clear interrupt status.
171 IN EFI_IDE_REGISTERS
*IdeRegisters
,
176 UINT8 StatusRegister
;
178 ASSERT (IdeRegisters
!= NULL
);
180 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
182 StatusRegister
= IoRead8 (IdeRegisters
->CmdOrStatus
);
185 // wait for BSY == 0 and DRQ == 0
187 if ((StatusRegister
& ATA_STSREG_BSY
) == 0) {
189 if ((StatusRegister
& ATA_STSREG_DRQ
) == ATA_STSREG_DRQ
) {
190 return EFI_DEVICE_ERROR
;
197 // Stall for 100 microseconds.
199 MicroSecondDelay (100);
208 This function is used to poll for the DRQ bit clear in the Alternate
209 Status Register. DRQ is cleared when the device is finished
210 transferring Data. So this function is called after Data transfer
213 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
214 @param Timeout The time to complete the command.
216 @retval EFI_SUCCESS DRQ bit clear within the time out.
218 @retval EFI_TIMEOUT DRQ bit not clear within the time out.
219 @note Read Alternate Status Register will not clear interrupt status.
225 IN EFI_IDE_REGISTERS
*IdeRegisters
,
232 ASSERT (IdeRegisters
!= NULL
);
234 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
236 AltRegister
= IoRead8 (IdeRegisters
->AltOrDev
);
239 // wait for BSY == 0 and DRQ == 0
241 if ((AltRegister
& ATA_STSREG_BSY
) == 0) {
242 if ((AltRegister
& ATA_STSREG_DRQ
) == ATA_STSREG_DRQ
) {
243 return EFI_DEVICE_ERROR
;
250 // Stall for 100 microseconds.
252 MicroSecondDelay (100);
263 This function is used to poll for the DRQ bit set in the Alternate Status Register.
264 DRQ is set when the device is ready to transfer Data. So this function is called after
265 the command is sent to the device and before required Data is transferred.
267 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
268 @param Timeout The time to complete the command.
270 @retval EFI_SUCCESS DRQ bit set within the time out.
271 @retval EFI_TIMEOUT DRQ bit not set within the time out.
272 @retval EFI_ABORTED DRQ bit not set caused by the command abort.
273 @note Read Alternate Status Register will not clear interrupt status.
279 IN EFI_IDE_REGISTERS
*IdeRegisters
,
287 ASSERT (IdeRegisters
!= NULL
);
289 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
293 // Read Alternate Status Register will not clear interrupt status
295 AltRegister
= IoRead8 (IdeRegisters
->AltOrDev
);
297 // BSY == 0 , DRQ == 1
299 if ((AltRegister
& ATA_STSREG_BSY
) == 0) {
300 if ((AltRegister
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
301 ErrorRegister
= IoRead8 (IdeRegisters
->ErrOrFeature
);
303 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
306 return EFI_DEVICE_ERROR
;
309 if ((AltRegister
& ATA_STSREG_DRQ
) == ATA_STSREG_DRQ
) {
312 return EFI_NOT_READY
;
317 // Stall for 100 microseconds.
319 MicroSecondDelay (100);
328 This function is used to poll for the BSY bit clear in the Status Register. BSY
329 is clear when the device is not busy. Every command must be sent after device is not busy.
331 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
332 @param Timeout The time to complete the command.
334 @retval EFI_SUCCESS BSY bit clear within the time out.
335 @retval EFI_TIMEOUT BSY bit not clear within the time out.
337 @note Read Status Register will clear interrupt status.
342 IN EFI_IDE_REGISTERS
*IdeRegisters
,
347 UINT8 StatusRegister
;
349 ASSERT (IdeRegisters
!= NULL
);
351 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
353 StatusRegister
= IoRead8 (IdeRegisters
->CmdOrStatus
);
355 if ((StatusRegister
& ATA_STSREG_BSY
) == 0x00) {
360 // Stall for 100 microseconds.
362 MicroSecondDelay (100);
372 Get IDE i/o port registers' base addresses by mode.
374 In 'Compatibility' mode, use fixed addresses.
375 In Native-PCI mode, get base addresses from BARs in the PCI IDE controller's
378 The steps to get IDE i/o port registers' base addresses for each channel
381 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
382 controller's Configuration Space to determine the operating mode.
384 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
385 ___________________________________________
386 | | Command Block | Control Block |
387 | Channel | Registers | Registers |
388 |___________|_______________|_______________|
389 | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
390 |___________|_______________|_______________|
391 | Secondary | 170h - 177h | 376h - 377h |
392 |___________|_______________|_______________|
394 Table 1. Compatibility resource mappings
396 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
397 in IDE controller's PCI Configuration Space, shown in the Table 2 below.
398 ___________________________________________________
399 | | Command Block | Control Block |
400 | Channel | Registers | Registers |
401 |___________|___________________|___________________|
402 | Primary | BAR at offset 0x10| BAR at offset 0x14|
403 |___________|___________________|___________________|
404 | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
405 |___________|___________________|___________________|
407 Table 2. BARs for Register Mapping
409 @param[in] Bus The bus number of ata host controller.
410 @param[in] Device The device number of ata host controller.
411 @param[in] Function The function number of ata host controller.
412 @param[in, out] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to
413 store the IDE i/o port registers' base addresses
415 @retval EFI_UNSUPPORTED Return this Value when the BARs is not IO type
416 @retval EFI_SUCCESS Get the Base address successfully
417 @retval Other Read the pci configureation Data error
422 GetIdeRegisterIoAddr (
426 IN OUT EFI_IDE_REGISTERS
*IdeRegisters
429 UINT16 CommandBlockBaseAddr
;
430 UINT16 ControlBlockBaseAddr
;
432 UINT32 BaseAddress
[4];
434 if (IdeRegisters
== NULL
) {
435 return EFI_INVALID_PARAMETER
;
438 ClassCode
= PciRead8 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x9));
439 BaseAddress
[0] = PciRead32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x10));
440 BaseAddress
[1] = PciRead32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x14));
441 BaseAddress
[2] = PciRead32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x18));
442 BaseAddress
[3] = PciRead32 (PCI_LIB_ADDRESS (Bus
, Device
, Function
, 0x1C));
444 if ((ClassCode
& IDE_PRIMARY_OPERATING_MODE
) == 0) {
445 CommandBlockBaseAddr
= 0x1f0;
446 ControlBlockBaseAddr
= 0x3f6;
449 // The BARs should be of IO type
451 if ((BaseAddress
[0] & BIT0
) == 0 ||
452 (BaseAddress
[1] & BIT0
) == 0) {
453 return EFI_UNSUPPORTED
;
456 CommandBlockBaseAddr
= (UINT16
) (BaseAddress
[0] & 0x0000fff8);
457 ControlBlockBaseAddr
= (UINT16
) ((BaseAddress
[1] & 0x0000fffc) + 2);
461 // Calculate IDE primary channel I/O register base address.
463 IdeRegisters
[EfiIdePrimary
].Data
= CommandBlockBaseAddr
;
464 IdeRegisters
[EfiIdePrimary
].ErrOrFeature
= (UINT16
) (CommandBlockBaseAddr
+ 0x01);
465 IdeRegisters
[EfiIdePrimary
].SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
466 IdeRegisters
[EfiIdePrimary
].SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
467 IdeRegisters
[EfiIdePrimary
].CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
468 IdeRegisters
[EfiIdePrimary
].CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
469 IdeRegisters
[EfiIdePrimary
].Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
470 IdeRegisters
[EfiIdePrimary
].CmdOrStatus
= (UINT16
) (CommandBlockBaseAddr
+ 0x07);
471 IdeRegisters
[EfiIdePrimary
].AltOrDev
= ControlBlockBaseAddr
;
473 if ((ClassCode
& IDE_SECONDARY_OPERATING_MODE
) == 0) {
474 CommandBlockBaseAddr
= 0x170;
475 ControlBlockBaseAddr
= 0x376;
478 // The BARs should be of IO type
480 if ((BaseAddress
[2] & BIT0
) == 0 ||
481 (BaseAddress
[3] & BIT0
) == 0) {
482 return EFI_UNSUPPORTED
;
485 CommandBlockBaseAddr
= (UINT16
) (BaseAddress
[2] & 0x0000fff8);
486 ControlBlockBaseAddr
= (UINT16
) ((BaseAddress
[3] & 0x0000fffc) + 2);
490 // Calculate IDE secondary channel I/O register base address.
492 IdeRegisters
[EfiIdeSecondary
].Data
= CommandBlockBaseAddr
;
493 IdeRegisters
[EfiIdeSecondary
].ErrOrFeature
= (UINT16
) (CommandBlockBaseAddr
+ 0x01);
494 IdeRegisters
[EfiIdeSecondary
].SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
495 IdeRegisters
[EfiIdeSecondary
].SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
496 IdeRegisters
[EfiIdeSecondary
].CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
497 IdeRegisters
[EfiIdeSecondary
].CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
498 IdeRegisters
[EfiIdeSecondary
].Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
499 IdeRegisters
[EfiIdeSecondary
].CmdOrStatus
= (UINT16
) (CommandBlockBaseAddr
+ 0x07);
500 IdeRegisters
[EfiIdeSecondary
].AltOrDev
= ControlBlockBaseAddr
;
506 Send ATA Ext command into device with NON_DATA protocol.
508 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
509 @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK Data structure.
510 @param Timeout The time to complete the command.
512 @retval EFI_SUCCESS Reading succeed
513 @retval EFI_DEVICE_ERROR Error executing commands on this device.
519 IN EFI_IDE_REGISTERS
*IdeRegisters
,
520 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
528 ASSERT (IdeRegisters
!= NULL
);
529 ASSERT (AtaCommandBlock
!= NULL
);
531 DeviceHead
= AtaCommandBlock
->AtaDeviceHead
;
532 AtaCommand
= AtaCommandBlock
->AtaCommand
;
534 Status
= WaitForBSYClear (IdeRegisters
, Timeout
);
535 if (EFI_ERROR (Status
)) {
536 return EFI_DEVICE_ERROR
;
540 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
542 IoWrite8 (IdeRegisters
->Head
, (UINT8
) (0xe0 | DeviceHead
));
545 // set all the command parameters
546 // Before write to all the following registers, BSY and DRQ must be 0.
548 Status
= DRQClear2 (IdeRegisters
, Timeout
);
549 if (EFI_ERROR (Status
)) {
550 return EFI_DEVICE_ERROR
;
554 // Fill the feature register, which is a two-byte FIFO. Need write twice.
556 IoWrite8 (IdeRegisters
->ErrOrFeature
, AtaCommandBlock
->AtaFeaturesExp
);
557 IoWrite8 (IdeRegisters
->ErrOrFeature
, AtaCommandBlock
->AtaFeatures
);
560 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
562 IoWrite8 (IdeRegisters
->SectorCount
, AtaCommandBlock
->AtaSectorCountExp
);
563 IoWrite8 (IdeRegisters
->SectorCount
, AtaCommandBlock
->AtaSectorCount
);
566 // Fill the start LBA registers, which are also two-byte FIFO
568 IoWrite8 (IdeRegisters
->SectorNumber
, AtaCommandBlock
->AtaSectorNumberExp
);
569 IoWrite8 (IdeRegisters
->SectorNumber
, AtaCommandBlock
->AtaSectorNumber
);
571 IoWrite8 (IdeRegisters
->CylinderLsb
, AtaCommandBlock
->AtaCylinderLowExp
);
572 IoWrite8 (IdeRegisters
->CylinderLsb
, AtaCommandBlock
->AtaCylinderLow
);
574 IoWrite8 (IdeRegisters
->CylinderMsb
, AtaCommandBlock
->AtaCylinderHighExp
);
575 IoWrite8 (IdeRegisters
->CylinderMsb
, AtaCommandBlock
->AtaCylinderHigh
);
578 // Send command via Command Register
580 IoWrite8 (IdeRegisters
->CmdOrStatus
, AtaCommand
);
583 // Stall at least 400 microseconds.
585 MicroSecondDelay (400);
591 This function is used to send out ATA commands conforms to the PIO Data In Protocol.
593 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
594 @param Buffer A pointer to the source Buffer for the Data.
595 @param ByteCount The Length of the Data.
596 @param Read Flag used to determine the Data transfer direction.
597 Read equals 1, means Data transferred from device to host;
598 Read equals 0, means Data transferred from host to device.
599 @param AtaCommandBlock A pointer to EFI_ATA_COMMAND_BLOCK Data structure.
600 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK Data structure.
601 @param Timeout The time to complete the command.
603 @retval EFI_SUCCESS send out the ATA command and device send required Data successfully.
604 @retval EFI_DEVICE_ERROR command sent failed.
610 IN EFI_IDE_REGISTERS
*IdeRegisters
,
614 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
615 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
624 if ((IdeRegisters
== NULL
) || (Buffer
== NULL
) || (AtaCommandBlock
== NULL
)) {
625 return EFI_INVALID_PARAMETER
;
631 Status
= AtaIssueCommand (IdeRegisters
, AtaCommandBlock
, Timeout
);
632 if (EFI_ERROR (Status
)) {
633 Status
= EFI_DEVICE_ERROR
;
637 Buffer16
= (UINT16
*) Buffer
;
640 // According to PIO Data in protocol, host can perform a series of reads to
641 // the Data register after each time device set DRQ ready;
642 // The Data Size of "a series of read" is command specific.
643 // For most ATA command, Data Size received from device will not exceed
644 // 1 sector, hence the Data Size for "a series of read" can be the whole Data
645 // Size of one command request.
646 // For ATA command such as Read Sector command, the Data Size of one ATA
647 // command request is often larger than 1 sector, according to the
648 // Read Sector command, the Data Size of "a series of read" is exactly 1
650 // Here for simplification reason, we specify the Data Size for
651 // "a series of read" to 1 sector (256 words) if Data Size of one ATA command
652 // request is larger than 256 words.
657 // used to record bytes of currently transfered Data
661 while (WordCount
< RShiftU64(ByteCount
, 1)) {
663 // Poll DRQ bit set, Data transfer can be performed only when DRQ is ready
665 Status
= DRQReady2 (IdeRegisters
, Timeout
);
666 if (EFI_ERROR (Status
)) {
667 Status
= EFI_DEVICE_ERROR
;
672 // Get the byte count for one series of read
674 if ((WordCount
+ Increment
) > RShiftU64(ByteCount
, 1)) {
675 Increment
= (UINTN
)(RShiftU64(ByteCount
, 1) - WordCount
);
679 IdeReadPortWMultiple (
685 IdeWritePortWMultiple (
692 Status
= CheckStatusRegister (IdeRegisters
);
693 if (EFI_ERROR (Status
)) {
694 Status
= EFI_DEVICE_ERROR
;
698 WordCount
+= Increment
;
699 Buffer16
+= Increment
;
702 Status
= DRQClear (IdeRegisters
, Timeout
);
703 if (EFI_ERROR (Status
)) {
704 Status
= EFI_DEVICE_ERROR
;
710 // Dump All Ide registers to ATA_STATUS_BLOCK
712 DumpAllIdeRegisters (IdeRegisters
);
718 Sends out an ATA Identify Command to the specified device.
720 This function sends out the ATA Identify Command to the
721 specified device. Only ATA device responses to this command. If
722 the command succeeds, it returns the Identify Data structure which
723 contains information about the device. This function extracts the
724 information it needs to fill the IDE_BLK_IO_DEV Data structure,
725 including device type, media block Size, media capacity, and etc.
727 @param IdeRegisters A pointer to EFI_IDE_REGISTERS Data structure.
728 @param Channel The channel number of device.
729 @param Device The device number of device.
730 @param Buffer A pointer to Data Buffer which is used to contain IDENTIFY Data.
732 @retval EFI_SUCCESS Identify ATA device successfully.
733 @retval EFI_DEVICE_ERROR ATA Identify Device Command failed or device is not ATA device.
734 @retval EFI_OUT_OF_RESOURCES Allocate memory failed.
739 IN EFI_IDE_REGISTERS
*IdeRegisters
,
742 IN OUT ATA_IDENTIFY_DATA
*Buffer
746 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
748 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
750 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
751 AtaCommandBlock
.AtaDeviceHead
= (UINT8
)(Device
<< 0x4);
753 Status
= AtaPioDataInOut (
756 sizeof (ATA_IDENTIFY_DATA
),