2 Copyright (c) 2006 - 2008, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 BOOLEAN ChannelDeviceDetected
= FALSE
;
16 BOOLEAN SlaveDeviceExist
= FALSE
;
17 UINT8 SlaveDeviceType
= INVALID_DEVICE_TYPE
;
18 BOOLEAN MasterDeviceExist
= FALSE
;
19 UINT8 MasterDeviceType
= INVALID_DEVICE_TYPE
;
22 TODO: Add function description
24 @param PciIo TODO: add argument description
25 @param Port TODO: add argument description
27 TODO: add return values.
32 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
40 // perform 1-byte data read from register
45 EFI_PCI_IO_PASS_THROUGH_BAR
,
54 Reads multiple words of data from the IDE data port.
55 Call the IO abstraction once to do the complete read,
56 not one word at a time
58 @param PciIo Pointer to the EFI_PCI_IO instance
59 @param Port IO port to read
60 @param Count No. of UINT16's to read
61 @param Buffer Pointer to the data buffer for read
65 IDEReadPortWMultiple (
66 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
72 UINT16
*AlignedBuffer
;
73 UINT16
*WorkingBuffer
;
77 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
78 // not perform actual I/O operations if buffer pointer passed in is not at
79 // natural boundary. The "Buffer" argument is passed in by user and may not
80 // at 16-bit natural boundary.
82 Size
= sizeof (UINT16
) * Count
;
87 (VOID
**)&WorkingBuffer
90 AlignedBuffer
= (UINT16
*) ((UINTN
)(((UINTN
) WorkingBuffer
+ 0x1) & (~0x1)));
93 // Perform UINT16 data read from FIFO
97 EfiPciIoWidthFifoUint16
,
98 EFI_PCI_IO_PASS_THROUGH_BAR
,
101 (UINT16
*)AlignedBuffer
105 // Copy data to user buffer
107 CopyMem (Buffer
, (UINT16
*)AlignedBuffer
, Size
);
108 gBS
->FreePool (WorkingBuffer
);
112 TODO: Add function description
114 @param PciIo TODO: add argument description
115 @param Port TODO: add argument description
116 @param Data TODO: add argument description
118 TODO: add return values.
123 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
129 // perform 1-byte data write to register
134 EFI_PCI_IO_PASS_THROUGH_BAR
,
143 TODO: Add function description
145 @param PciIo TODO: add argument description
146 @param Port TODO: add argument description
147 @param Data TODO: add argument description
149 TODO: add return values.
154 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
160 // perform 1-word data write to register
165 EFI_PCI_IO_PASS_THROUGH_BAR
,
173 Write multiple words of data to the IDE data port.
174 Call the IO abstraction once to do the complete read,
175 not one word at a time
177 @param PciIo Pointer to the EFI_PCI_IO instance
178 @param Port IO port to read
179 @param Count No. of UINT16's to read
180 @param Buffer Pointer to the data buffer for read
184 IDEWritePortWMultiple (
185 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
191 UINT16
*AlignedBuffer
;
192 UINT32
*WorkingBuffer
;
196 // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
197 // not perform actual I/O operations if buffer pointer passed in is not at
198 // natural boundary. The "Buffer" argument is passed in by user and may not
199 // at 16-bit natural boundary.
201 Size
= sizeof (UINT16
) * Count
;
206 (VOID
**) &WorkingBuffer
209 AlignedBuffer
= (UINT16
*) ((UINTN
)(((UINTN
) WorkingBuffer
+ 0x1) & (~0x1)));
212 // Copy data from user buffer to working buffer
214 CopyMem ((UINT16
*) AlignedBuffer
, Buffer
, Size
);
217 // perform UINT16 data write to the FIFO
221 EfiPciIoWidthFifoUint16
,
222 EFI_PCI_IO_PASS_THROUGH_BAR
,
225 (UINT16
*) AlignedBuffer
228 gBS
->FreePool (WorkingBuffer
);
232 // GetIdeRegistersBaseAddr
235 Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
236 use fixed addresses. In Native-PCI mode, get base addresses from BARs in
237 the PCI IDE controller's Configuration Space.
239 The steps to get IDE IO port registers' base addresses for each channel
242 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
243 controller's Configuration Space to determine the operating mode.
245 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
247 ___________________________________________
248 | | Command Block | Control Block |
249 | Channel | Registers | Registers |
250 |___________|_______________|_______________|
251 | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
252 |___________|_______________|_______________|
253 | Secondary | 170h - 177h | 376h - 377h |
254 |___________|_______________|_______________|
256 Table 1. Compatibility resource mappings
259 b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
260 in IDE controller's PCI Configuration Space, shown in the Table 2 below.
262 ___________________________________________________
263 | | Command Block | Control Block |
264 | Channel | Registers | Registers |
265 |___________|___________________|___________________|
266 | Primary | BAR at offset 0x10| BAR at offset 0x14|
267 |___________|___________________|___________________|
268 | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
269 |___________|___________________|___________________|
271 Table 2. BARs for Register Mapping
273 @note Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
274 primary, 0374h for secondary. So 2 bytes extra offset should be
275 added to the base addresses read from BARs.
277 For more details, please refer to PCI IDE Controller Specification and Intel
280 @param PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
281 @param IdeRegsBaseAddr Pointer to IDE_REGISTERS_BASE_ADDR to
282 receive IDE IO port registers' base addresses
286 GetIdeRegistersBaseAddr (
287 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
288 OUT IDE_REGISTERS_BASE_ADDR
*IdeRegsBaseAddr
290 // TODO: EFI_UNSUPPORTED - add return value to function comment
291 // TODO: EFI_UNSUPPORTED - add return value to function comment
292 // TODO: EFI_SUCCESS - add return value to function comment
297 Status
= PciIo
->Pci
.Read (
305 if (EFI_ERROR (Status
)) {
309 if ((PciData
.Hdr
.ClassCode
[0] & IDE_PRIMARY_OPERATING_MODE
) == 0) {
310 IdeRegsBaseAddr
[IdePrimary
].CommandBlockBaseAddr
= 0x1f0;
311 IdeRegsBaseAddr
[IdePrimary
].ControlBlockBaseAddr
= 0x3f6;
312 IdeRegsBaseAddr
[IdePrimary
].BusMasterBaseAddr
=
313 (UINT16
)((PciData
.Device
.Bar
[4] & 0x0000fff0));
316 // The BARs should be of IO type
318 if ((PciData
.Device
.Bar
[0] & BIT0
) == 0 ||
319 (PciData
.Device
.Bar
[1] & BIT0
) == 0) {
320 return EFI_UNSUPPORTED
;
323 IdeRegsBaseAddr
[IdePrimary
].CommandBlockBaseAddr
=
324 (UINT16
) (PciData
.Device
.Bar
[0] & 0x0000fff8);
325 IdeRegsBaseAddr
[IdePrimary
].ControlBlockBaseAddr
=
326 (UINT16
) ((PciData
.Device
.Bar
[1] & 0x0000fffc) + 2);
327 IdeRegsBaseAddr
[IdePrimary
].BusMasterBaseAddr
=
328 (UINT16
) ((PciData
.Device
.Bar
[4] & 0x0000fff0));
331 if ((PciData
.Hdr
.ClassCode
[0] & IDE_SECONDARY_OPERATING_MODE
) == 0) {
332 IdeRegsBaseAddr
[IdeSecondary
].CommandBlockBaseAddr
= 0x170;
333 IdeRegsBaseAddr
[IdeSecondary
].ControlBlockBaseAddr
= 0x376;
334 IdeRegsBaseAddr
[IdeSecondary
].BusMasterBaseAddr
=
335 (UINT16
) ((PciData
.Device
.Bar
[4] & 0x0000fff0));
338 // The BARs should be of IO type
340 if ((PciData
.Device
.Bar
[2] & BIT0
) == 0 ||
341 (PciData
.Device
.Bar
[3] & BIT0
) == 0) {
342 return EFI_UNSUPPORTED
;
345 IdeRegsBaseAddr
[IdeSecondary
].CommandBlockBaseAddr
=
346 (UINT16
) (PciData
.Device
.Bar
[2] & 0x0000fff8);
347 IdeRegsBaseAddr
[IdeSecondary
].ControlBlockBaseAddr
=
348 (UINT16
) ((PciData
.Device
.Bar
[3] & 0x0000fffc) + 2);
349 IdeRegsBaseAddr
[IdeSecondary
].BusMasterBaseAddr
=
350 (UINT16
) ((PciData
.Device
.Bar
[4] & 0x0000fff0));
357 This function is used to requery IDE resources. The IDE controller will
358 probably switch between native and legacy modes during the EFI->CSM->OS
359 transfer. We do this everytime before an BlkIo operation to ensure its
362 @param IdeDev The BLK_IO private data which specifies the IDE device
366 ReassignIdeResources (
367 IN IDE_BLK_IO_DEV
*IdeDev
369 // TODO: EFI_SUCCESS - add return value to function comment
372 IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr
[IdeMaxChannel
];
373 UINT16 CommandBlockBaseAddr
;
374 UINT16 ControlBlockBaseAddr
;
377 // Requery IDE IO port registers' base addresses in case of the switch of
378 // native and legacy modes
380 Status
= GetIdeRegistersBaseAddr (IdeDev
->PciIo
, IdeRegsBaseAddr
);
381 if (EFI_ERROR (Status
)) {
385 ZeroMem (IdeDev
->IoPort
, sizeof (IDE_BASE_REGISTERS
));
386 CommandBlockBaseAddr
= IdeRegsBaseAddr
[IdeDev
->Channel
].CommandBlockBaseAddr
;
387 ControlBlockBaseAddr
= IdeRegsBaseAddr
[IdeDev
->Channel
].ControlBlockBaseAddr
;
389 IdeDev
->IoPort
->Data
= CommandBlockBaseAddr
;
390 (*(UINT16
*) &IdeDev
->IoPort
->Reg1
) = (UINT16
) (CommandBlockBaseAddr
+ 0x01);
391 IdeDev
->IoPort
->SectorCount
= (UINT16
) (CommandBlockBaseAddr
+ 0x02);
392 IdeDev
->IoPort
->SectorNumber
= (UINT16
) (CommandBlockBaseAddr
+ 0x03);
393 IdeDev
->IoPort
->CylinderLsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x04);
394 IdeDev
->IoPort
->CylinderMsb
= (UINT16
) (CommandBlockBaseAddr
+ 0x05);
395 IdeDev
->IoPort
->Head
= (UINT16
) (CommandBlockBaseAddr
+ 0x06);
397 (*(UINT16
*) &IdeDev
->IoPort
->Reg
) = (UINT16
) (CommandBlockBaseAddr
+ 0x07);
398 (*(UINT16
*) &IdeDev
->IoPort
->Alt
) = ControlBlockBaseAddr
;
399 IdeDev
->IoPort
->DriveAddress
= (UINT16
) (ControlBlockBaseAddr
+ 0x01);
400 IdeDev
->IoPort
->MasterSlave
= (UINT16
) ((IdeDev
->Device
== IdeMaster
) ? 1 : 0);
402 IdeDev
->IoPort
->BusMasterBaseAddr
= IdeRegsBaseAddr
[IdeDev
->Channel
].BusMasterBaseAddr
;
410 Detect if there is disk connected to this port
412 @param IdeDev The BLK_IO private data which specifies the IDE device.
417 IN IDE_BLK_IO_DEV
*IdeDev
419 // TODO: EFI_NOT_FOUND - add return value to function comment
420 // TODO: EFI_NOT_FOUND - add return value to function comment
421 // TODO: EFI_SUCCESS - add return value to function comment
424 EFI_STATUS LongPhyStatus
;
427 // If a channel has not been checked, check it now. Then set it to "checked" state
428 // After this step, all devices in this channel have been checked.
430 if (!ChannelDeviceDetected
) {
431 Status
= DetectIDEController (IdeDev
);
432 if (EFI_ERROR (Status
)) {
433 return EFI_NOT_FOUND
;
437 Status
= EFI_NOT_FOUND
;
440 // Device exists. test if it is an ATA device.
441 // Prefer the result from DetectIDEController,
442 // if failed, try another device type to handle
443 // devices that not follow the spec.
445 if ((IdeDev
->Device
== IdeMaster
) && (MasterDeviceExist
)) {
446 if (MasterDeviceType
== ATA_DEVICE_TYPE
) {
447 Status
= ATAIdentify (IdeDev
);
448 if (EFI_ERROR (Status
)) {
449 Status
= ATAPIIdentify (IdeDev
);
450 if (!EFI_ERROR (Status
)) {
451 MasterDeviceType
= ATAPI_DEVICE_TYPE
;
455 Status
= ATAPIIdentify (IdeDev
);
456 if (EFI_ERROR (Status
)) {
457 Status
= ATAIdentify (IdeDev
);
458 if (!EFI_ERROR (Status
)) {
459 MasterDeviceType
= ATA_DEVICE_TYPE
;
464 if ((IdeDev
->Device
== IdeSlave
) && (SlaveDeviceExist
)) {
465 if (SlaveDeviceType
== ATA_DEVICE_TYPE
) {
466 Status
= ATAIdentify (IdeDev
);
467 if (EFI_ERROR (Status
)) {
468 Status
= ATAPIIdentify (IdeDev
);
469 if (!EFI_ERROR (Status
)) {
470 SlaveDeviceType
= ATAPI_DEVICE_TYPE
;
474 Status
= ATAPIIdentify (IdeDev
);
475 if (EFI_ERROR (Status
)) {
476 Status
= ATAIdentify (IdeDev
);
477 if (!EFI_ERROR (Status
)) {
478 SlaveDeviceType
= ATA_DEVICE_TYPE
;
483 if (EFI_ERROR (Status
)) {
484 return EFI_NOT_FOUND
;
487 // Init Block I/O interface
489 LongPhyStatus
= AtaEnableLongPhysicalSector (IdeDev
);
490 if (!EFI_ERROR (LongPhyStatus
)) {
491 IdeDev
->BlkIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION2
;
493 IdeDev
->BlkIo
.Revision
= EFI_BLOCK_IO_PROTOCOL_REVISION
;
495 IdeDev
->BlkIo
.Reset
= IDEBlkIoReset
;
496 IdeDev
->BlkIo
.ReadBlocks
= IDEBlkIoReadBlocks
;
497 IdeDev
->BlkIo
.WriteBlocks
= IDEBlkIoWriteBlocks
;
498 IdeDev
->BlkIo
.FlushBlocks
= IDEBlkIoFlushBlocks
;
500 IdeDev
->BlkMedia
.LogicalPartition
= FALSE
;
501 IdeDev
->BlkMedia
.WriteCaching
= FALSE
;
504 // Init Disk Info interface
506 gBS
->CopyMem (&IdeDev
->DiskInfo
.Interface
, &gEfiDiskInfoIdeInterfaceGuid
, sizeof (EFI_GUID
));
507 IdeDev
->DiskInfo
.Inquiry
= IDEDiskInfoInquiry
;
508 IdeDev
->DiskInfo
.Identify
= IDEDiskInfoIdentify
;
509 IdeDev
->DiskInfo
.SenseData
= IDEDiskInfoSenseData
;
510 IdeDev
->DiskInfo
.WhichIde
= IDEDiskInfoWhichIde
;
516 This interface is used to initialize all state data related to the detection of one
519 @retval EFI_SUCCESS Completed Successfully.
523 InitializeIDEChannelData (
527 ChannelDeviceDetected
= FALSE
;
528 MasterDeviceExist
= FALSE
;
529 MasterDeviceType
= 0xff;
530 SlaveDeviceExist
= FALSE
;
531 SlaveDeviceType
= 0xff;
536 This function is called by DiscoverIdeDevice(). It is used for detect
537 whether the IDE device exists in the specified Channel as the specified
540 There is two IDE channels: one is Primary Channel, the other is
541 Secondary Channel.(Channel is the logical name for the physical "Cable".)
542 Different channel has different register group.
544 On each IDE channel, at most two IDE devices attach,
545 one is called Device 0 (Master device), the other is called Device 1
546 (Slave device). The devices on the same channel co-use the same register
547 group, so before sending out a command for a specified device via command
548 register, it is a must to select the current device to accept the command
549 by set the device number in the Head/Device Register.
552 pointer pointing to IDE_BLK_IO_DEV data structure, used
553 to record all the information of the IDE device.
556 successfully detects device.
559 any failure during detection process will return this
563 TODO: EFI_SUCCESS - add return value to function comment
564 TODO: EFI_NOT_FOUND - add return value to function comment
568 DetectIDEController (
569 IN IDE_BLK_IO_DEV
*IdeDev
573 UINT8 SectorCountReg
;
581 // Select slave device
585 IdeDev
->IoPort
->Head
,
586 (UINT8
) ((1 << 4) | 0xe0)
591 // Save the init slave status register
593 InitStatusReg
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
596 // Select Master back
600 IdeDev
->IoPort
->Head
,
601 (UINT8
) ((0 << 4) | 0xe0)
606 // Send ATA Device Execut Diagnostic command.
607 // This command should work no matter DRDY is ready or not
609 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, 0x90);
611 Status
= WaitForBSYClear (IdeDev
, 3500);
612 if (EFI_ERROR (Status
)) {
613 DEBUG((EFI_D_ERROR
, "New detecting method: Send Execute Diagnostic Command: WaitForBSYClear: Status: %d\n", Status
));
617 // Read device signature
624 IdeDev
->IoPort
->Head
,
625 (UINT8
) ((0 << 4) | 0xe0)
628 SectorCountReg
= IDEReadPortB (
630 IdeDev
->IoPort
->SectorCount
632 LBALowReg
= IDEReadPortB (
634 IdeDev
->IoPort
->SectorNumber
636 LBAMidReg
= IDEReadPortB (
638 IdeDev
->IoPort
->CylinderLsb
640 LBAHighReg
= IDEReadPortB (
642 IdeDev
->IoPort
->CylinderMsb
644 if ((SectorCountReg
== 0x1) &&
645 (LBALowReg
== 0x1) &&
646 (LBAMidReg
== 0x0) &&
647 (LBAHighReg
== 0x0)) {
648 MasterDeviceExist
= TRUE
;
649 MasterDeviceType
= ATA_DEVICE_TYPE
;
651 if ((LBAMidReg
== 0x14) &&
652 (LBAHighReg
== 0xeb)) {
653 MasterDeviceExist
= TRUE
;
654 MasterDeviceType
= ATAPI_DEVICE_TYPE
;
659 // For some Hard Drive, it takes some time to get
660 // the right signature when operating in single slave mode.
661 // We stall 20ms to work around this.
663 if (!MasterDeviceExist
) {
672 IdeDev
->IoPort
->Head
,
673 (UINT8
) ((1 << 4) | 0xe0)
676 SectorCountReg
= IDEReadPortB (
678 IdeDev
->IoPort
->SectorCount
680 LBALowReg
= IDEReadPortB (
682 IdeDev
->IoPort
->SectorNumber
684 LBAMidReg
= IDEReadPortB (
686 IdeDev
->IoPort
->CylinderLsb
688 LBAHighReg
= IDEReadPortB (
690 IdeDev
->IoPort
->CylinderMsb
692 StatusReg
= IDEReadPortB (
694 IdeDev
->IoPort
->Reg
.Status
696 if ((SectorCountReg
== 0x1) &&
697 (LBALowReg
== 0x1) &&
698 (LBAMidReg
== 0x0) &&
699 (LBAHighReg
== 0x0)) {
700 SlaveDeviceExist
= TRUE
;
701 SlaveDeviceType
= ATA_DEVICE_TYPE
;
703 if ((LBAMidReg
== 0x14) &&
704 (LBAHighReg
== 0xeb)) {
705 SlaveDeviceExist
= TRUE
;
706 SlaveDeviceType
= ATAPI_DEVICE_TYPE
;
711 // When single master is plugged, slave device
712 // will be wrongly detected. Here's the workaround
713 // for ATA devices by detecting DRY bit in status
715 // NOTE: This workaround doesn't apply to ATAPI.
717 if (MasterDeviceExist
&& SlaveDeviceExist
&&
718 (StatusReg
& ATA_STSREG_DRDY
) == 0 &&
719 (InitStatusReg
& ATA_STSREG_DRDY
) == 0 &&
720 MasterDeviceType
== SlaveDeviceType
&&
721 SlaveDeviceType
!= ATAPI_DEVICE_TYPE
) {
722 SlaveDeviceExist
= FALSE
;
726 // Indicate this channel has been detected
728 ChannelDeviceDetected
= TRUE
;
733 This function is used to poll for the DRQ bit clear in the Status
734 Register. DRQ is cleared when the device is finished transferring data.
735 So this function is called after data transfer is finished.
738 pointer pointing to IDE_BLK_IO_DEV data structure, used
739 to record all the information of the IDE device.
741 @param[in] TimeoutInMilliSeconds
742 used to designate the timeout for the DRQ clear.
745 DRQ bit clear within the time out.
748 DRQ bit not clear within the time out.
751 Read Status Register will clear interrupt status.
756 IN IDE_BLK_IO_DEV
*IdeDev
,
757 IN UINTN TimeoutInMilliSeconds
759 // TODO: function comment is missing 'Routine Description:'
760 // TODO: function comment is missing 'Arguments:'
761 // TODO: IdeDev - add argument and description to function comment
762 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
763 // TODO: EFI_ABORTED - add return value to function comment
766 UINT8 StatusRegister
;
769 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
772 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
775 // wait for BSY == 0 and DRQ == 0
777 if ((StatusRegister
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
781 if ((StatusRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
783 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
784 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
806 This function is used to poll for the DRQ bit clear in the Alternate
807 Status Register. DRQ is cleared when the device is finished
808 transferring data. So this function is called after data transfer
812 pointer pointing to IDE_BLK_IO_DEV data structure, used
813 to record all the information of the IDE device.
815 @param[in] TimeoutInMilliSeconds
816 used to designate the timeout for the DRQ clear.
819 DRQ bit clear within the time out.
822 DRQ bit not clear within the time out.
825 Read Alternate Status Register will not clear interrupt status.
830 IN IDE_BLK_IO_DEV
*IdeDev
,
831 IN UINTN TimeoutInMilliSeconds
833 // TODO: function comment is missing 'Routine Description:'
834 // TODO: function comment is missing 'Arguments:'
835 // TODO: IdeDev - add argument and description to function comment
836 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
837 // TODO: EFI_ABORTED - add return value to function comment
843 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
846 AltRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.AltStatus
);
849 // wait for BSY == 0 and DRQ == 0
851 if ((AltRegister
& (ATA_STSREG_DRQ
| ATA_STSREG_BSY
)) == 0) {
855 if ((AltRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
857 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
858 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
880 This function is used to poll for the DRQ bit set in the
882 DRQ is set when the device is ready to transfer data. So this function
883 is called after the command is sent to the device and before required
886 @param[in] IDE_BLK_IO_DEV IN *IdeDev
887 pointer pointing to IDE_BLK_IO_DEV data structure,used
888 to record all the information of the IDE device.
890 @param[in] UINTN IN TimeoutInMilliSeconds
891 used to designate the timeout for the DRQ ready.
894 DRQ bit set within the time out.
897 DRQ bit not set within the time out.
900 DRQ bit not set caused by the command abort.
903 Read Status Register will clear interrupt status.
908 IN IDE_BLK_IO_DEV
*IdeDev
,
909 IN UINTN TimeoutInMilliSeconds
911 // TODO: function comment is missing 'Routine Description:'
912 // TODO: function comment is missing 'Arguments:'
913 // TODO: IdeDev - add argument and description to function comment
914 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
917 UINT8 StatusRegister
;
920 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
923 // read Status Register will clear interrupt
925 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
930 if ((StatusRegister
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
934 if ((StatusRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
936 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
937 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
958 This function is used to poll for the DRQ bit set in the
959 Alternate Status Register. DRQ is set when the device is ready to
960 transfer data. So this function is called after the command
961 is sent to the device and before required data is transferred.
963 @param[in] IDE_BLK_IO_DEV IN *IdeDev
964 pointer pointing to IDE_BLK_IO_DEV data structure, used
965 to record all the information of the IDE device.
967 @param[in] UINTN IN TimeoutInMilliSeconds
968 used to designate the timeout for the DRQ ready.
971 DRQ bit set within the time out.
974 DRQ bit not set within the time out.
977 DRQ bit not set caused by the command abort.
980 Read Alternate Status Register will not clear interrupt status.
985 IN IDE_BLK_IO_DEV
*IdeDev
,
986 IN UINTN TimeoutInMilliSeconds
988 // TODO: function comment is missing 'Routine Description:'
989 // TODO: function comment is missing 'Arguments:'
990 // TODO: IdeDev - add argument and description to function comment
991 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
997 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
1001 // Read Alternate Status Register will not clear interrupt status
1003 AltRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.AltStatus
);
1005 // BSY == 0 , DRQ == 1
1007 if ((AltRegister
& (ATA_STSREG_BSY
| ATA_STSREG_DRQ
)) == ATA_STSREG_DRQ
) {
1011 if ((AltRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
1013 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
1014 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
1025 } while (Delay
> 0);
1035 This function is used to poll for the BSY bit clear in the
1036 Status Register. BSY is clear when the device is not busy.
1037 Every command must be sent after device is not busy.
1039 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1040 pointer pointing to IDE_BLK_IO_DEV data structure, used
1041 to record all the information of the IDE device.
1043 @param[in] UINTN IN TimeoutInMilliSeconds
1044 used to designate the timeout for the DRQ ready.
1047 BSY bit clear within the time out.
1050 BSY bit not clear within the time out.
1053 Read Status Register will clear interrupt status.
1058 IN IDE_BLK_IO_DEV
*IdeDev
,
1059 IN UINTN TimeoutInMilliSeconds
1061 // TODO: function comment is missing 'Routine Description:'
1062 // TODO: function comment is missing 'Arguments:'
1063 // TODO: IdeDev - add argument and description to function comment
1064 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
1067 UINT8 StatusRegister
;
1069 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
1072 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
1073 if ((StatusRegister
& ATA_STSREG_BSY
) == 0x00) {
1084 } while (Delay
> 0);
1096 This function is used to poll for the BSY bit clear in the
1097 Alternate Status Register. BSY is clear when the device is not busy.
1098 Every command must be sent after device is not busy.
1100 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1101 pointer pointing to IDE_BLK_IO_DEV data structure, used
1102 to record all the information of the IDE device.
1104 @param[in] UINTN IN TimeoutInMilliSeconds
1105 used to designate the timeout for the DRQ ready.
1108 BSY bit clear within the time out.
1111 BSY bit not clear within the time out.
1114 Read Alternate Status Register will not clear interrupt status.
1119 IN IDE_BLK_IO_DEV
*IdeDev
,
1120 IN UINTN TimeoutInMilliSeconds
1122 // TODO: function comment is missing 'Routine Description:'
1123 // TODO: function comment is missing 'Arguments:'
1124 // TODO: IdeDev - add argument and description to function comment
1125 // TODO: TimeoutInMilliSeconds - add argument and description to function comment
1130 Delay
= (UINT32
) (((TimeoutInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
1132 AltRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.AltStatus
);
1133 if ((AltRegister
& ATA_STSREG_BSY
) == 0x00) {
1141 } while (Delay
> 0);
1154 This function is used to poll for the DRDY bit set in the
1155 Status Register. DRDY bit is set when the device is ready
1156 to accept command. Most ATA commands must be sent after
1157 DRDY set except the ATAPI Packet Command.
1159 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1160 pointer pointing to IDE_BLK_IO_DEV data structure, used
1161 to record all the information of the IDE device.
1163 @param[in] UINTN IN DelayInMilliSeconds
1164 used to designate the timeout for the DRQ ready.
1167 DRDY bit set within the time out.
1170 DRDY bit not set within the time out.
1173 Read Status Register will clear interrupt status.
1178 IN IDE_BLK_IO_DEV
*IdeDev
,
1179 IN UINTN DelayInMilliSeconds
1181 // TODO: function comment is missing 'Routine Description:'
1182 // TODO: function comment is missing 'Arguments:'
1183 // TODO: IdeDev - add argument and description to function comment
1184 // TODO: DelayInMilliSeconds - add argument and description to function comment
1185 // TODO: EFI_ABORTED - add return value to function comment
1188 UINT8 StatusRegister
;
1189 UINT8 ErrorRegister
;
1191 Delay
= (UINT32
) (((DelayInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
1193 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
1195 // BSY == 0 , DRDY == 1
1197 if ((StatusRegister
& (ATA_STSREG_DRDY
| ATA_STSREG_BSY
)) == ATA_STSREG_DRDY
) {
1201 if ((StatusRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
1203 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
1204 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
1212 } while (Delay
> 0);
1225 This function is used to poll for the DRDY bit set in the
1226 Alternate Status Register. DRDY bit is set when the device is ready
1227 to accept command. Most ATA commands must be sent after
1228 DRDY set except the ATAPI Packet Command.
1230 @param[in] IDE_BLK_IO_DEV IN *IdeDev
1231 pointer pointing to IDE_BLK_IO_DEV data structure, used
1232 to record all the information of the IDE device.
1234 @param[in] UINTN IN DelayInMilliSeconds
1235 used to designate the timeout for the DRQ ready.
1238 DRDY bit set within the time out.
1241 DRDY bit not set within the time out.
1244 Read Alternate Status Register will clear interrupt status.
1249 IN IDE_BLK_IO_DEV
*IdeDev
,
1250 IN UINTN DelayInMilliSeconds
1252 // TODO: function comment is missing 'Routine Description:'
1253 // TODO: function comment is missing 'Arguments:'
1254 // TODO: IdeDev - add argument and description to function comment
1255 // TODO: DelayInMilliSeconds - add argument and description to function comment
1256 // TODO: EFI_ABORTED - add return value to function comment
1260 UINT8 ErrorRegister
;
1262 Delay
= (UINT32
) (((DelayInMilliSeconds
* STALL_1_MILLI_SECOND
) / 30) + 1);
1264 AltRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.AltStatus
);
1266 // BSY == 0 , DRDY == 1
1268 if ((AltRegister
& (ATA_STSREG_DRDY
| ATA_STSREG_BSY
)) == ATA_STSREG_DRDY
) {
1272 if ((AltRegister
& (ATA_STSREG_BSY
| ATA_STSREG_ERR
)) == ATA_STSREG_ERR
) {
1274 ErrorRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Error
);
1275 if ((ErrorRegister
& ATA_ERRREG_ABRT
) == ATA_ERRREG_ABRT
) {
1283 } while (Delay
> 0);
1296 This function is a helper function used to change the char order in a
1297 string. It is designed specially for the PrintAtaModuleName() function.
1298 After the IDE device is detected, the IDE driver gets the device module
1299 name by sending ATA command called ATA Identify Command or ATAPI
1300 Identify Command to the specified IDE device. The module name returned
1301 is a string of ASCII characters: the first character is bit8--bit15
1302 of the first word, the second character is BIT0--bit7 of the first word
1303 and so on. Thus the string can not be print directly before it is
1304 preprocessed by this func to change the order of characters in
1305 each word in the string.
1307 @param[in] CHAR8 IN *Destination
1308 Indicates the destination string.
1310 @param[in] CHAR8 IN *Source
1311 Indicates the source string.
1313 @param[in] UINT8 IN Size
1314 the length of the string
1319 IN CHAR8
*Destination
,
1327 for (Index
= 0; Index
< Size
; Index
+= 2) {
1329 Temp
= Source
[Index
+ 1];
1330 Destination
[Index
+ 1] = Source
[Index
];
1331 Destination
[Index
] = Temp
;
1336 // ReleaseIdeResources
1339 Release resources of an IDE device before stopping it.
1341 @param[in] *IdeBlkIoDevice Standard IDE device private data structure
1345 ReleaseIdeResources (
1346 IN IDE_BLK_IO_DEV
*IdeBlkIoDevice
1349 if (IdeBlkIoDevice
== NULL
) {
1354 // Release all the resourses occupied by the IDE_BLK_IO_DEV
1357 if (IdeBlkIoDevice
->SenseData
!= NULL
) {
1358 gBS
->FreePool (IdeBlkIoDevice
->SenseData
);
1359 IdeBlkIoDevice
->SenseData
= NULL
;
1362 if (IdeBlkIoDevice
->Cache
!= NULL
) {
1363 gBS
->FreePool (IdeBlkIoDevice
->Cache
);
1364 IdeBlkIoDevice
->Cache
= NULL
;
1367 if (IdeBlkIoDevice
->pIdData
!= NULL
) {
1368 gBS
->FreePool (IdeBlkIoDevice
->pIdData
);
1369 IdeBlkIoDevice
->pIdData
= NULL
;
1372 if (IdeBlkIoDevice
->pInquiryData
!= NULL
) {
1373 gBS
->FreePool (IdeBlkIoDevice
->pInquiryData
);
1374 IdeBlkIoDevice
->pInquiryData
= NULL
;
1377 if (IdeBlkIoDevice
->ControllerNameTable
!= NULL
) {
1378 FreeUnicodeStringTable (IdeBlkIoDevice
->ControllerNameTable
);
1379 IdeBlkIoDevice
->ControllerNameTable
= NULL
;
1382 if (IdeBlkIoDevice
->IoPort
!= NULL
) {
1383 gBS
->FreePool (IdeBlkIoDevice
->IoPort
);
1386 if (IdeBlkIoDevice
->DevicePath
!= NULL
) {
1387 gBS
->FreePool (IdeBlkIoDevice
->DevicePath
);
1390 if (IdeBlkIoDevice
->ExitBootServiceEvent
!= NULL
) {
1391 gBS
->CloseEvent (IdeBlkIoDevice
->ExitBootServiceEvent
);
1392 IdeBlkIoDevice
->ExitBootServiceEvent
= NULL
;
1395 gBS
->FreePool (IdeBlkIoDevice
);
1396 IdeBlkIoDevice
= NULL
;
1402 // SetDeviceTransferMode
1405 Set the calculated Best transfer mode to a detected device
1407 @param[in] *IdeDev Standard IDE device private data structure
1408 @param[in] *TransferMode The device transfer mode to be set
1410 @return Set transfer mode Command execute status.
1414 SetDeviceTransferMode (
1415 IN IDE_BLK_IO_DEV
*IdeDev
,
1416 IN ATA_TRANSFER_MODE
*TransferMode
1418 // TODO: function comment is missing 'Routine Description:'
1425 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
1426 SectorCount
= *((UINT8
*) TransferMode
);
1429 // Send SET FEATURE command (sub command 0x03) to set pio mode.
1431 Status
= AtaNonDataCommandIn (
1433 ATA_CMD_SET_FEATURES
,
1446 Send ATA command into device with NON_DATA protocol
1448 @param IdeDev Standard IDE device private data structure
1449 @param AtaCommand The ATA command to be sent
1450 @param Device The value in Device register
1451 @param Feature The value in Feature register
1452 @param SectorCount The value in SectorCount register
1453 @param LbaLow The value in LBA_LOW register
1454 @param LbaMiddle The value in LBA_MIDDLE register
1455 @param LbaHigh The value in LBA_HIGH register
1457 @retval EFI_SUCCESS Reading succeed
1458 @retval EFI_ABORTED Command failed
1459 @retval EFI_DEVICE_ERROR Device status error.
1463 AtaNonDataCommandIn (
1464 IN IDE_BLK_IO_DEV
*IdeDev
,
1465 IN UINT8 AtaCommand
,
1468 IN UINT8 SectorCount
,
1475 UINT8 StatusRegister
;
1477 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1478 if (EFI_ERROR (Status
)) {
1479 return EFI_DEVICE_ERROR
;
1483 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
1487 IdeDev
->IoPort
->Head
,
1488 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0)
1492 // ATA commands for ATA device must be issued when DRDY is set
1494 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
1495 if (EFI_ERROR (Status
)) {
1496 return EFI_DEVICE_ERROR
;
1500 // Pass parameter into device register block
1502 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
1503 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature
);
1504 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount
);
1505 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1506 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMiddle
);
1507 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1510 // Send command via Command Register
1512 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
1515 // Wait for command completion
1516 // For ATAPI_SMART_CMD, we may need more timeout to let device
1517 // adjust internal states.
1519 if (AtaCommand
== ATA_CMD_SMART
) {
1520 Status
= WaitForBSYClear (IdeDev
, ATASMARTTIMEOUT
);
1522 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1524 if (EFI_ERROR (Status
)) {
1525 return EFI_DEVICE_ERROR
;
1528 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
1529 if ((StatusRegister
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
1531 // Failed to execute command, abort operation
1540 Send ATA Ext command into device with NON_DATA protocol
1542 @param IdeDev Standard IDE device private data structure
1543 @param AtaCommand The ATA command to be sent
1544 @param Device The value in Device register
1545 @param Feature The value in Feature register
1546 @param SectorCount The value in SectorCount register
1547 @param LbaAddress The LBA address in 48-bit mode
1549 @retval EFI_SUCCESS Reading succeed
1550 @retval EFI_ABORTED Command failed
1551 @retval EFI_DEVICE_ERROR Device status error.
1555 AtaNonDataCommandInExt (
1556 IN IDE_BLK_IO_DEV
*IdeDev
,
1557 IN UINT8 AtaCommand
,
1560 IN UINT16 SectorCount
,
1561 IN EFI_LBA LbaAddress
1565 UINT8 StatusRegister
;
1572 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1573 if (EFI_ERROR (Status
)) {
1574 return EFI_DEVICE_ERROR
;
1578 // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
1582 IdeDev
->IoPort
->Head
,
1583 (UINT8
) ((IdeDev
->Device
<< 4) | 0xe0)
1587 // ATA commands for ATA device must be issued when DRDY is set
1589 Status
= DRDYReady (IdeDev
, ATATIMEOUT
);
1590 if (EFI_ERROR (Status
)) {
1591 return EFI_DEVICE_ERROR
;
1595 // Pass parameter into device register block
1597 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Head
, Device
);
1600 // Fill the feature register, which is a two-byte FIFO. Need write twice.
1602 Feature8
= (UINT8
) (Feature
>> 8);
1603 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature8
);
1605 Feature8
= (UINT8
) Feature
;
1606 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg1
.Feature
, Feature8
);
1609 // Fill the sector count register, which is a two-byte FIFO. Need write twice.
1611 SectorCount8
= (UINT8
) (SectorCount
>> 8);
1612 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1614 SectorCount8
= (UINT8
) SectorCount
;
1615 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorCount
, SectorCount8
);
1618 // Fill the start LBA registers, which are also two-byte FIFO
1620 LbaLow
= (UINT8
) RShiftU64 (LbaAddress
, 24);
1621 LbaMid
= (UINT8
) RShiftU64 (LbaAddress
, 32);
1622 LbaHigh
= (UINT8
) RShiftU64 (LbaAddress
, 40);
1623 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1624 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1625 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1627 LbaLow
= (UINT8
) LbaAddress
;
1628 LbaMid
= (UINT8
) RShiftU64 (LbaAddress
, 8);
1629 LbaHigh
= (UINT8
) RShiftU64 (LbaAddress
, 16);
1630 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->SectorNumber
, LbaLow
);
1631 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderLsb
, LbaMid
);
1632 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->CylinderMsb
, LbaHigh
);
1635 // Send command via Command Register
1637 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Command
, AtaCommand
);
1640 // Wait for command completion
1642 Status
= WaitForBSYClear (IdeDev
, ATATIMEOUT
);
1643 if (EFI_ERROR (Status
)) {
1644 return EFI_DEVICE_ERROR
;
1647 StatusRegister
= IDEReadPortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Reg
.Status
);
1648 if ((StatusRegister
& ATA_STSREG_ERR
) == ATA_STSREG_ERR
) {
1650 // Failed to execute command, abort operation
1659 // SetDriveParameters
1662 Set drive parameters for devices not support PACKETS command
1664 @param[in] IdeDev Standard IDE device private data structure
1665 @param[in] DriveParameters The device parameters to be set into the disk
1667 @return SetParameters Command execute status.
1671 SetDriveParameters (
1672 IN IDE_BLK_IO_DEV
*IdeDev
,
1673 IN ATA_DRIVE_PARMS
*DriveParameters
1680 DeviceSelect
= (UINT8
) ((IdeDev
->Device
) << 4);
1683 // Send Init drive parameters
1685 Status
= AtaNonDataCommandIn (
1687 ATA_CMD_INIT_DRIVE_PARAM
,
1688 (UINT8
) (DeviceSelect
+ DriveParameters
->Heads
),
1690 DriveParameters
->Sector
,
1697 // Send Set Multiple parameters
1699 Status
= AtaNonDataCommandIn (
1701 ATA_CMD_SET_MULTIPLE_MODE
,
1704 DriveParameters
->MultipleSector
,
1713 TODO: Add function description
1715 @param IdeDev TODO: add argument description
1717 @retval EFI_SUCCESS TODO: Add description for return value.
1722 IN IDE_BLK_IO_DEV
*IdeDev
1725 UINT8 DeviceControl
;
1728 // Enable interrupt for DMA operation
1731 IDEWritePortB (IdeDev
->PciIo
, IdeDev
->IoPort
->Alt
.DeviceControl
, DeviceControl
);
1737 Clear pending IDE interrupt before OS loader/kernel take control of the IDE device.
1739 @param[in] Event Pointer to this event
1740 @param[in] Context Event hanlder private data
1751 UINT64 IoPortForBmis
;
1752 UINT8 RegisterValue
;
1753 IDE_BLK_IO_DEV
*IdeDev
;
1758 IdeDev
= (IDE_BLK_IO_DEV
*) Context
;
1761 // Obtain IDE IO port registers' base addresses
1763 Status
= ReassignIdeResources (IdeDev
);
1764 if (EFI_ERROR (Status
)) {
1769 // Check whether interrupt is pending
1773 // Reset IDE device to force it de-assert interrupt pin
1774 // Note: this will reset all devices on this IDE channel
1776 AtaSoftReset (IdeDev
);
1777 if (EFI_ERROR (Status
)) {
1782 // Get base address of IDE Bus Master Status Regsiter
1784 if (IdePrimary
== IdeDev
->Channel
) {
1785 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISP_OFFSET
;
1787 if (IdeSecondary
== IdeDev
->Channel
) {
1788 IoPortForBmis
= IdeDev
->IoPort
->BusMasterBaseAddr
+ BMISS_OFFSET
;
1794 // Read BMIS register and clear ERROR and INTR bit
1796 IdeDev
->PciIo
->Io
.Read (
1799 EFI_PCI_IO_PASS_THROUGH_BAR
,
1805 RegisterValue
|= (BMIS_INTERRUPT
| BMIS_ERROR
);
1807 IdeDev
->PciIo
->Io
.Write (
1810 EFI_PCI_IO_PASS_THROUGH_BAR
,
1817 // Select the other device on this channel to ensure this device to release the interrupt pin
1819 if (IdeDev
->Device
== 0) {
1820 RegisterValue
= (1 << 4) | 0xe0;
1822 RegisterValue
= (0 << 4) | 0xe0;
1826 IdeDev
->IoPort
->Head
,