2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2012, 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 "AtaAtapiPassThru.h"
18 Read AHCI Operation register.
20 @param PciIo The PCI IO protocol instance.
21 @param Offset The operation register offset.
23 @return The register content read.
29 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
35 ASSERT (PciIo
!= NULL
);
52 Write AHCI Operation register.
54 @param PciIo The PCI IO protocol instance.
55 @param Offset The operation register offset.
56 @param Data The data used to write down.
62 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
67 ASSERT (PciIo
!= NULL
);
82 Do AND operation with the value of AHCI Operation register.
84 @param PciIo The PCI IO protocol instance.
85 @param Offset The operation register offset.
86 @param AndData The data used to do AND operation.
92 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
99 ASSERT (PciIo
!= NULL
);
101 Data
= AhciReadReg (PciIo
, Offset
);
105 AhciWriteReg (PciIo
, Offset
, Data
);
109 Do OR operation with the value of AHCI Operation register.
111 @param PciIo The PCI IO protocol instance.
112 @param Offset The operation register offset.
113 @param OrData The data used to do OR operation.
119 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
126 ASSERT (PciIo
!= NULL
);
128 Data
= AhciReadReg (PciIo
, Offset
);
132 AhciWriteReg (PciIo
, Offset
, Data
);
136 Wait for the value of the specified MMIO register set to the test value.
138 @param PciIo The PCI IO protocol instance.
139 @param Offset The MMIO address to test.
140 @param MaskValue The mask value of memory.
141 @param TestValue The test value of memory.
142 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
144 @retval EFI_TIMEOUT The MMIO setting is time out.
145 @retval EFI_SUCCESS The MMIO is correct set.
151 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
161 Delay
= (UINT32
) (DivU64x32 (Timeout
, 1000) + 1);
165 // Access PCI MMIO space to see if the value is the tested one.
167 Value
= AhciReadReg (PciIo
, (UINT32
) Offset
) & MaskValue
;
169 if (Value
== TestValue
) {
174 // Stall for 100 microseconds.
176 MicroSecondDelay (100);
186 Wait for the value of the specified system memory set to the test value.
188 @param Address The system memory address to test.
189 @param MaskValue The mask value of memory.
190 @param TestValue The test value of memory.
191 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
193 @retval EFI_TIMEOUT The system memory setting is time out.
194 @retval EFI_SUCCESS The system memory is correct set.
200 IN EFI_PHYSICAL_ADDRESS Address
,
209 Delay
= (UINT32
) (DivU64x32 (Timeout
, 1000) + 1);
213 // Access sytem memory to see if the value is the tested one.
215 // The system memory pointed by Address will be updated by the
216 // SATA Host Controller, "volatile" is introduced to prevent
217 // compiler from optimizing the access to the memory address
218 // to only read once.
220 Value
= *(volatile UINT32
*) (UINTN
) Address
;
223 if (Value
== TestValue
) {
228 // Stall for 100 microseconds.
230 MicroSecondDelay (100);
240 Check the memory status to the test value.
242 @param[in] Address The memory address to test.
243 @param[in] MaskValue The mask value of memory.
244 @param[in] TestValue The test value of memory.
245 @param[in, out] RetryTimes The retry times value for waitting memory set. If 0, then just try once.
247 @retval EFI_NOTREADY The memory is not set.
248 @retval EFI_TIMEOUT The memory setting retry times out.
249 @retval EFI_SUCCESS The memory is correct set.
258 IN OUT UINTN
*RetryTimes OPTIONAL
263 if (RetryTimes
!= NULL
) {
267 Value
= *(volatile UINT32
*) Address
;
270 if (Value
== TestValue
) {
274 if ((RetryTimes
!= NULL
) && (*RetryTimes
== 0)) {
277 return EFI_NOT_READY
;
282 Check if the device is still on port. It also checks if the AHCI controller
283 supports the address and data count will be transferred.
285 @param PciIo The PCI IO protocol instance.
286 @param Port The number of port.
288 @retval EFI_SUCCESS The device is attached to port and the transfer data is
289 supported by AHCI controller.
290 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
292 @retval EFI_NOT_READY The physical communication between AHCI controller and device
298 AhciCheckDeviceStatus (
299 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
306 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
308 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
310 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
314 return EFI_NOT_READY
;
319 Clear the port interrupt and error status. It will also clear
320 HBA interrupt status.
322 @param PciIo The PCI IO protocol instance.
323 @param Port The number of port.
328 AhciClearPortStatus (
329 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
336 // Clear any error status
338 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
339 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
342 // Clear any port interrupt status
344 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
345 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
348 // Clear any HBA interrupt status
350 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
354 This function is used to dump the Status Registers and if there is ERR bit set
355 in the Status Register, the Error Register's value is also be dumped.
357 @param PciIo The PCI IO protocol instance.
358 @param Port The number of port.
359 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
365 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
367 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
373 ASSERT (PciIo
!= NULL
);
375 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
376 Data
= AhciReadReg (PciIo
, Offset
);
378 if (AtaStatusBlock
!= NULL
) {
379 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
381 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
382 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
383 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
390 Enable the FIS running for giving port.
392 @param PciIo The PCI IO protocol instance.
393 @param Port The number of port.
394 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
396 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
397 @retval EFI_TIMEOUT The FIS enable setting is time out.
398 @retval EFI_SUCCESS The FIS enable successfully.
403 AhciEnableFisReceive (
404 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
411 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
412 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
414 return AhciWaitMmioSet (
417 EFI_AHCI_PORT_CMD_FR
,
418 EFI_AHCI_PORT_CMD_FR
,
424 Disable the FIS running for giving port.
426 @param PciIo The PCI IO protocol instance.
427 @param Port The number of port.
428 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
430 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
431 @retval EFI_TIMEOUT The FIS disable setting is time out.
432 @retval EFI_UNSUPPORTED The port is in running state.
433 @retval EFI_SUCCESS The FIS disable successfully.
438 AhciDisableFisReceive (
439 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
447 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
448 Data
= AhciReadReg (PciIo
, Offset
);
451 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
453 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
454 return EFI_UNSUPPORTED
;
458 // Check if the Fis receive DMA engine for the port is running.
460 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
464 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
466 return AhciWaitMmioSet (
469 EFI_AHCI_PORT_CMD_FR
,
478 Build the command list, command table and prepare the fis receiver.
480 @param PciIo The PCI IO protocol instance.
481 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
482 @param Port The number of port.
483 @param PortMultiplier The timeout value of stop.
484 @param CommandFis The control fis will be used for the transfer.
485 @param CommandList The command list will be used for the transfer.
486 @param AtapiCommand The atapi command will be used for the transfer.
487 @param AtapiCommandLength The length of the atapi command.
488 @param CommandSlotNumber The command slot will be used for the transfer.
489 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
490 @param DataLength The data count to be transferred.
496 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
497 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
499 IN UINT8 PortMultiplier
,
500 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
501 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
502 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
503 IN UINT8 AtapiCommandLength
,
504 IN UINT8 CommandSlotNumber
,
505 IN OUT VOID
*DataPhysicalAddr
,
520 PrdtNumber
= (DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1) / EFI_AHCI_MAX_DATA_PER_PRDT
;
523 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
524 // It also limits that the maximum amount of the PRDT entry in the command table
527 ASSERT (PrdtNumber
<= 65535);
529 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
531 BaseAddr
= Data64
.Uint64
;
533 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
535 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
537 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
539 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
541 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
542 if (AtapiCommand
!= NULL
) {
544 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
549 CommandList
->AhciCmdA
= 1;
550 CommandList
->AhciCmdP
= 1;
552 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
554 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
557 RemainedData
= (UINTN
) DataLength
;
558 MemAddr
= (UINTN
) DataPhysicalAddr
;
559 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
561 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
562 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
563 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
565 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
568 Data64
.Uint64
= (UINT64
)MemAddr
;
569 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
570 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
571 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
572 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
576 // Set the last PRDT to Interrupt On Complete
578 if (PrdtNumber
> 0) {
579 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
583 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
585 sizeof (EFI_AHCI_COMMAND_LIST
)
588 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
589 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
590 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
591 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
598 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
599 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
604 AhciBuildCommandFis (
605 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
606 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
609 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
611 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
613 // Indicator it's a command
615 CmdFis
->AhciCFisCmdInd
= 0x1;
616 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
618 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
619 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
621 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
622 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
624 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
625 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
627 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
628 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
630 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
631 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
633 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
637 Start a PIO data transfer on specific port.
639 @param[in] PciIo The PCI IO protocol instance.
640 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
641 @param[in] Port The number of port.
642 @param[in] PortMultiplier The timeout value of stop.
643 @param[in] AtapiCommand The atapi command will be used for the
645 @param[in] AtapiCommandLength The length of the atapi command.
646 @param[in] Read The transfer direction.
647 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
648 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
649 @param[in, out] MemoryAddr The pointer to the data buffer.
650 @param[in] DataCount The data count to be transferred.
651 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
652 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
653 used by non-blocking mode.
655 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
656 @retval EFI_TIMEOUT The operation is time out.
657 @retval EFI_UNSUPPORTED The device is not ready for transfer.
658 @retval EFI_SUCCESS The PIO data transfer executes successfully.
664 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
665 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
667 IN UINT8 PortMultiplier
,
668 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
669 IN UINT8 AtapiCommandLength
,
671 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
672 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
673 IN OUT VOID
*MemoryAddr
,
676 IN ATA_NONBLOCK_TASK
*Task
682 EFI_PHYSICAL_ADDRESS PhyAddr
;
685 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
687 EFI_AHCI_COMMAND_FIS CFis
;
688 EFI_AHCI_COMMAND_LIST CmdList
;
693 Flag
= EfiPciIoOperationBusMasterWrite
;
695 Flag
= EfiPciIoOperationBusMasterRead
;
699 // construct command list and command table with pci bus address
701 MapLength
= DataCount
;
702 Status
= PciIo
->Map (
711 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
712 return EFI_BAD_BUFFER_SIZE
;
716 // Package read needed
718 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
720 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
722 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
723 CmdList
.AhciCmdW
= Read
? 0 : 1;
735 (VOID
*)(UINTN
)PhyAddr
,
739 Status
= AhciStartCommand (
745 if (EFI_ERROR (Status
)) {
750 // Check the status and wait the driver sending data
752 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
754 if (Read
&& (AtapiCommand
== 0)) {
756 // Wait device sends the PIO setup fis before data transfer
758 Status
= EFI_TIMEOUT
;
759 Delay
= (UINT32
) (DivU64x32 (Timeout
, 1000) + 1);
761 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
763 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, 0);
764 if (!EFI_ERROR (Status
)) {
765 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
766 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
768 // PxTFD will be updated if there is a D2H or SetupFIS received.
769 // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
771 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
772 Status
= EFI_DEVICE_ERROR
;
776 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
777 if (PrdCount
== DataCount
) {
782 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
783 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, 0);
784 if (!EFI_ERROR (Status
)) {
785 Status
= EFI_DEVICE_ERROR
;
790 // Stall for 100 microseconds.
792 MicroSecondDelay(100);
798 // Wait for D2H Fis is received
800 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
801 Status
= AhciWaitMemSet (
803 EFI_AHCI_FIS_TYPE_MASK
,
804 EFI_AHCI_FIS_REGISTER_D2H
,
808 if (EFI_ERROR (Status
)) {
812 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
813 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
814 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
815 Status
= EFI_DEVICE_ERROR
;
826 AhciDisableFisReceive (
837 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
843 Start a DMA data transfer on specific port
845 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
846 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
847 @param[in] Port The number of port.
848 @param[in] PortMultiplier The timeout value of stop.
849 @param[in] AtapiCommand The atapi command will be used for the
851 @param[in] AtapiCommandLength The length of the atapi command.
852 @param[in] Read The transfer direction.
853 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
854 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
855 @param[in, out] MemoryAddr The pointer to the data buffer.
856 @param[in] DataCount The data count to be transferred.
857 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
858 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
859 used by non-blocking mode.
861 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
862 @retval EFI_TIMEOUT The operation is time out.
863 @retval EFI_UNSUPPORTED The device is not ready for transfer.
864 @retval EFI_SUCCESS The DMA data transfer executes successfully.
870 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
871 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
873 IN UINT8 PortMultiplier
,
874 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
875 IN UINT8 AtapiCommandLength
,
877 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
878 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
879 IN OUT VOID
*MemoryAddr
,
882 IN ATA_NONBLOCK_TASK
*Task
887 EFI_PHYSICAL_ADDRESS PhyAddr
;
890 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
891 EFI_AHCI_COMMAND_FIS CFis
;
892 EFI_AHCI_COMMAND_LIST CmdList
;
896 EFI_PCI_IO_PROTOCOL
*PciIo
;
900 PciIo
= Instance
->PciIo
;
903 return EFI_INVALID_PARAMETER
;
907 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
909 // Delay 100us to simulate the blocking time out checking.
911 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
912 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
913 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
917 MicroSecondDelay (100);
919 gBS
->RestoreTPL (OldTpl
);
921 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
923 // Mark the Task to indicate that it has been started.
926 Task
->IsStart
= TRUE
;
927 Task
->RetryTimes
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
930 Flag
= EfiPciIoOperationBusMasterWrite
;
932 Flag
= EfiPciIoOperationBusMasterRead
;
936 // Construct command list and command table with pci bus address.
938 MapLength
= DataCount
;
939 Status
= PciIo
->Map (
948 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
949 return EFI_BAD_BUFFER_SIZE
;
956 // Package read needed
958 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
960 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
962 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
963 CmdList
.AhciCmdW
= Read
? 0 : 1;
975 (VOID
*)(UINTN
)PhyAddr
,
979 Status
= AhciStartCommand (
985 if (EFI_ERROR (Status
)) {
991 // Wait for command compelte
993 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
994 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
999 Status
= AhciCheckMemSet (
1001 EFI_AHCI_FIS_TYPE_MASK
,
1002 EFI_AHCI_FIS_REGISTER_D2H
,
1003 (UINTN
*) (&Task
->RetryTimes
)
1006 Status
= AhciWaitMemSet (
1008 EFI_AHCI_FIS_TYPE_MASK
,
1009 EFI_AHCI_FIS_REGISTER_D2H
,
1014 if (EFI_ERROR (Status
)) {
1018 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1019 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1020 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1021 Status
= EFI_DEVICE_ERROR
;
1026 // For Blocking mode, the command should be stopped, the Fis should be disabled
1027 // and the PciIo should be unmapped.
1028 // For non-blocking mode, only when a error is happened (if the return status is
1029 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1030 // context cleanup, then set the packet's Asb status.
1033 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1041 AhciDisableFisReceive (
1049 (Task
!= NULL
) ? Task
->Map
: Map
1053 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1057 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1062 Start a non data transfer on specific port.
1064 @param[in] PciIo The PCI IO protocol instance.
1065 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1066 @param[in] Port The number of port.
1067 @param[in] PortMultiplier The timeout value of stop.
1068 @param[in] AtapiCommand The atapi command will be used for the
1070 @param[in] AtapiCommandLength The length of the atapi command.
1071 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1072 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1073 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1074 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1075 used by non-blocking mode.
1077 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1078 @retval EFI_TIMEOUT The operation is time out.
1079 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1080 @retval EFI_SUCCESS The non data transfer executes successfully.
1085 AhciNonDataTransfer (
1086 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1087 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1089 IN UINT8 PortMultiplier
,
1090 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1091 IN UINT8 AtapiCommandLength
,
1092 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1093 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1095 IN ATA_NONBLOCK_TASK
*Task
1102 EFI_AHCI_COMMAND_FIS CFis
;
1103 EFI_AHCI_COMMAND_LIST CmdList
;
1106 // Package read needed
1108 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1110 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1112 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1128 Status
= AhciStartCommand (
1134 if (EFI_ERROR (Status
)) {
1139 // Wait device sends the Response Fis
1141 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1142 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1143 Status
= AhciWaitMemSet (
1145 EFI_AHCI_FIS_TYPE_MASK
,
1146 EFI_AHCI_FIS_REGISTER_D2H
,
1150 if (EFI_ERROR (Status
)) {
1154 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1155 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1156 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1157 Status
= EFI_DEVICE_ERROR
;
1167 AhciDisableFisReceive (
1173 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1179 Stop command running for giving port
1181 @param PciIo The PCI IO protocol instance.
1182 @param Port The number of port.
1183 @param Timeout The timeout value of stop, uses 100ns as a unit.
1185 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1186 @retval EFI_TIMEOUT The operation is time out.
1187 @retval EFI_SUCCESS The command stop successfully.
1193 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1201 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1202 Data
= AhciReadReg (PciIo
, Offset
);
1204 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1208 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1209 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1212 return AhciWaitMmioSet (
1215 EFI_AHCI_PORT_CMD_CR
,
1222 Start command for give slot on specific port.
1224 @param PciIo The PCI IO protocol instance.
1225 @param Port The number of port.
1226 @param CommandSlot The number of Command Slot.
1227 @param Timeout The timeout value of start, uses 100ns as a unit.
1229 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1230 @retval EFI_TIMEOUT The operation is time out.
1231 @retval EFI_SUCCESS The command start successfully.
1237 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1239 IN UINT8 CommandSlot
,
1252 // Collect AHCI controller information
1254 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1256 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1258 AhciClearPortStatus (
1263 Status
= AhciEnableFisReceive (
1269 if (EFI_ERROR (Status
)) {
1273 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1274 PortStatus
= AhciReadReg (PciIo
, Offset
);
1277 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1278 StartCmd
= AhciReadReg (PciIo
, Offset
);
1279 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1280 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1283 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1284 PortTfd
= AhciReadReg (PciIo
, Offset
);
1286 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1287 if ((Capability
& BIT24
) != 0) {
1288 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1289 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1294 EFI_AHCI_PORT_CMD_CLO
,
1301 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1302 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1305 // Setting the command
1307 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1308 AhciAndReg (PciIo
, Offset
, 0);
1309 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1311 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1312 AhciAndReg (PciIo
, Offset
, 0);
1313 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1321 @param PciIo The PCI IO protocol instance.
1322 @param Port The number of port.
1323 @param Timeout The timeout value of reset, uses 100ns as a unit.
1325 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1326 @retval EFI_TIMEOUT The reset operation is time out.
1327 @retval EFI_SUCCESS The port reset successfully.
1333 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1341 AhciClearPortStatus (PciIo
, Port
);
1343 AhciStopCommand (PciIo
, Port
, Timeout
);
1345 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1347 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1349 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1351 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1354 // wait 5 millisecond before de-assert DET
1356 MicroSecondDelay (5000);
1358 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1361 // wait 5 millisecond before de-assert DET
1363 MicroSecondDelay (5000);
1366 // Wait for communication to be re-established
1368 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1369 Status
= AhciWaitMmioSet (
1372 EFI_AHCI_PORT_SSTS_DET_MASK
,
1373 EFI_AHCI_PORT_SSTS_DET_PCE
,
1377 if (EFI_ERROR (Status
)) {
1381 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1382 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1390 @param PciIo The PCI IO protocol instance.
1391 @param Timeout The timeout value of reset, uses 100ns as a unit.
1393 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1394 @retval EFI_TIMEOUT The reset operation is time out.
1395 @retval EFI_SUCCESS AHCI controller is reset successfully.
1401 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1408 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1410 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1412 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1415 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1417 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1422 // Stall for 100 microseconds.
1424 MicroSecondDelay(100);
1427 } while (Delay
> 0);
1437 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1439 @param PciIo The PCI IO protocol instance.
1440 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1441 @param Port The number of port.
1442 @param PortMultiplier The timeout value of stop.
1443 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1445 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1446 @retval Others Fail to get return status data.
1451 AhciAtaSmartReturnStatusCheck (
1452 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1453 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1455 IN UINT8 PortMultiplier
,
1456 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1460 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1466 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1468 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1469 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1470 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1471 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1474 // Send S.M.A.R.T Read Return Status command to device
1476 Status
= AhciNonDataTransfer (
1480 (UINT8
)PortMultiplier
,
1489 if (EFI_ERROR (Status
)) {
1490 return EFI_DEVICE_ERROR
;
1493 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1495 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1497 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1498 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1499 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1501 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1503 // The threshold exceeded condition is not detected by the device
1505 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1507 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1509 // The threshold exceeded condition is detected by the device
1511 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1519 Enable SMART command of the disk if supported.
1521 @param PciIo The PCI IO protocol instance.
1522 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1523 @param Port The number of port.
1524 @param PortMultiplier The timeout value of stop.
1525 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1526 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1531 AhciAtaSmartSupport (
1532 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1533 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1535 IN UINT8 PortMultiplier
,
1536 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1537 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1541 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1544 // Detect if the device supports S.M.A.R.T.
1546 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1548 // S.M.A.R.T is not supported by the device
1550 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1551 Port
, PortMultiplier
));
1554 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1556 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1557 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1559 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1560 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1561 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1562 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1565 // Send S.M.A.R.T Enable command to device
1567 Status
= AhciNonDataTransfer (
1571 (UINT8
)PortMultiplier
,
1581 if (!EFI_ERROR (Status
)) {
1583 // Send S.M.A.R.T AutoSave command to device
1585 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1587 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1588 AtaCommandBlock
.AtaFeatures
= 0xD2;
1589 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1590 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1591 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1593 Status
= AhciNonDataTransfer (
1597 (UINT8
)PortMultiplier
,
1606 if (!EFI_ERROR (Status
)) {
1607 Status
= AhciAtaSmartReturnStatusCheck (
1611 (UINT8
)PortMultiplier
,
1617 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1618 Port
, PortMultiplier
));
1625 Send Buffer cmd to specific device.
1627 @param PciIo The PCI IO protocol instance.
1628 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1629 @param Port The number of port.
1630 @param PortMultiplier The timeout value of stop.
1631 @param Buffer The data buffer to store IDENTIFY PACKET data.
1633 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1634 @retval EFI_TIMEOUT The operation is time out.
1635 @retval EFI_UNSUPPORTED The device is not ready for executing.
1636 @retval EFI_SUCCESS The cmd executes successfully.
1642 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1643 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1645 IN UINT8 PortMultiplier
,
1646 IN OUT EFI_IDENTIFY_DATA
*Buffer
1650 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1651 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1653 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1654 return EFI_INVALID_PARAMETER
;
1657 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1658 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1660 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1661 AtaCommandBlock
.AtaSectorCount
= 1;
1663 Status
= AhciPioTransfer (
1674 sizeof (EFI_IDENTIFY_DATA
),
1683 Send Buffer cmd to specific device.
1685 @param PciIo The PCI IO protocol instance.
1686 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1687 @param Port The number of port.
1688 @param PortMultiplier The timeout value of stop.
1689 @param Buffer The data buffer to store IDENTIFY PACKET data.
1691 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1692 @retval EFI_TIMEOUT The operation is time out.
1693 @retval EFI_UNSUPPORTED The device is not ready for executing.
1694 @retval EFI_SUCCESS The cmd executes successfully.
1699 AhciIdentifyPacket (
1700 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1701 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1703 IN UINT8 PortMultiplier
,
1704 IN OUT EFI_IDENTIFY_DATA
*Buffer
1708 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1709 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1711 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1712 return EFI_INVALID_PARAMETER
;
1715 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1716 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1718 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1719 AtaCommandBlock
.AtaSectorCount
= 1;
1721 Status
= AhciPioTransfer (
1732 sizeof (EFI_IDENTIFY_DATA
),
1741 Send SET FEATURE cmd on specific device.
1743 @param PciIo The PCI IO protocol instance.
1744 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1745 @param Port The number of port.
1746 @param PortMultiplier The timeout value of stop.
1747 @param Feature The data to send Feature register.
1748 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1750 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1751 @retval EFI_TIMEOUT The operation is time out.
1752 @retval EFI_UNSUPPORTED The device is not ready for executing.
1753 @retval EFI_SUCCESS The cmd executes successfully.
1758 AhciDeviceSetFeature (
1759 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1760 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1762 IN UINT8 PortMultiplier
,
1764 IN UINT32 FeatureSpecificData
1768 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1769 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1771 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1772 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1774 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1775 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1776 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1777 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1778 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1779 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1780 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1782 Status
= AhciNonDataTransfer (
1786 (UINT8
)PortMultiplier
,
1799 This function is used to send out ATAPI commands conforms to the Packet Command
1802 @param PciIo The PCI IO protocol instance.
1803 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1804 @param Port The number of port.
1805 @param PortMultiplier The number of port multiplier.
1806 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1808 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1809 and device sends data successfully.
1810 @retval EFI_DEVICE_ERROR the device failed to send data.
1815 AhciPacketCommandExecute (
1816 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1817 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1819 IN UINT8 PortMultiplier
,
1820 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1826 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1827 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1830 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1831 return EFI_INVALID_PARAMETER
;
1834 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1835 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1836 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1840 AtaCommandBlock
.AtaFeatures
= 0x00;
1842 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1843 // determine how many data should be transferred.
1845 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1846 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1848 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1849 Buffer
= Packet
->InDataBuffer
;
1850 Length
= Packet
->InTransferLength
;
1853 Buffer
= Packet
->OutDataBuffer
;
1854 Length
= Packet
->OutTransferLength
;
1859 Status
= AhciNonDataTransfer (
1872 Status
= AhciPioTransfer (
1892 Allocate transfer-related data struct which is used at AHCI mode.
1894 @param PciIo The PCI IO protocol instance.
1895 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1900 AhciCreateTransferDescriptor (
1901 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1902 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1910 UINT32 PortImplementBitMap
;
1911 UINT8 MaxPortNumber
;
1912 UINT8 MaxCommandSlotNumber
;
1913 BOOLEAN Support64Bit
;
1914 UINT64 MaxReceiveFisSize
;
1915 UINT64 MaxCommandListSize
;
1916 UINT64 MaxCommandTableSize
;
1917 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1918 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1919 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1923 // Collect AHCI controller information
1925 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1927 // Get the number of command slots per port supported by this HBA.
1929 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1930 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1932 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
1934 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
1936 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
1937 if (MaxPortNumber
== 0) {
1938 return EFI_DEVICE_ERROR
;
1941 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1942 Status
= PciIo
->AllocateBuffer (
1945 EfiBootServicesData
,
1946 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1951 if (EFI_ERROR (Status
)) {
1952 return EFI_OUT_OF_RESOURCES
;
1955 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1957 AhciRegisters
->AhciRFis
= Buffer
;
1958 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1959 Bytes
= (UINTN
)MaxReceiveFisSize
;
1961 Status
= PciIo
->Map (
1963 EfiPciIoOperationBusMasterCommonBuffer
,
1967 &AhciRegisters
->MapRFis
1970 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1972 // Map error or unable to map the whole RFis buffer into a contiguous region.
1974 Status
= EFI_OUT_OF_RESOURCES
;
1978 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1980 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1982 Status
= EFI_DEVICE_ERROR
;
1985 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1988 // Allocate memory for command list
1989 // Note that the implemenation is a single task model which only use a command list for all ports.
1992 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1993 Status
= PciIo
->AllocateBuffer (
1996 EfiBootServicesData
,
1997 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2002 if (EFI_ERROR (Status
)) {
2004 // Free mapped resource.
2006 Status
= EFI_OUT_OF_RESOURCES
;
2010 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2012 AhciRegisters
->AhciCmdList
= Buffer
;
2013 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2014 Bytes
= (UINTN
)MaxCommandListSize
;
2016 Status
= PciIo
->Map (
2018 EfiPciIoOperationBusMasterCommonBuffer
,
2021 &AhciCmdListPciAddr
,
2022 &AhciRegisters
->MapCmdList
2025 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2027 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2029 Status
= EFI_OUT_OF_RESOURCES
;
2033 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2035 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2037 Status
= EFI_DEVICE_ERROR
;
2040 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2043 // Allocate memory for command table
2044 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2047 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2049 Status
= PciIo
->AllocateBuffer (
2052 EfiBootServicesData
,
2053 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2058 if (EFI_ERROR (Status
)) {
2060 // Free mapped resource.
2062 Status
= EFI_OUT_OF_RESOURCES
;
2066 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2068 AhciRegisters
->AhciCommandTable
= Buffer
;
2069 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2070 Bytes
= (UINTN
)MaxCommandTableSize
;
2072 Status
= PciIo
->Map (
2074 EfiPciIoOperationBusMasterCommonBuffer
,
2077 &AhciCommandTablePciAddr
,
2078 &AhciRegisters
->MapCommandTable
2081 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2083 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2085 Status
= EFI_OUT_OF_RESOURCES
;
2089 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2091 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2093 Status
= EFI_DEVICE_ERROR
;
2096 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2100 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2105 AhciRegisters
->MapCommandTable
2110 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2111 AhciRegisters
->AhciCommandTable
2116 AhciRegisters
->MapCmdList
2121 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2122 AhciRegisters
->AhciCmdList
2127 AhciRegisters
->MapRFis
2132 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2133 AhciRegisters
->AhciRFis
2140 Initialize ATA host controller at AHCI mode.
2142 The function is designed to initialize ATA host controller.
2144 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2149 AhciModeInitialization (
2150 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2154 EFI_PCI_IO_PROTOCOL
*PciIo
;
2155 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2157 UINT8 MaxPortNumber
;
2158 UINT32 PortImplementBitMap
;
2160 EFI_AHCI_REGISTERS
*AhciRegisters
;
2166 EFI_IDENTIFY_DATA Buffer
;
2167 EFI_ATA_DEVICE_TYPE DeviceType
;
2168 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2169 EFI_ATA_TRANSFER_MODE TransferMode
;
2170 UINT32 PhyDetectDelay
;
2172 if (Instance
== NULL
) {
2173 return EFI_INVALID_PARAMETER
;
2176 PciIo
= Instance
->PciIo
;
2177 IdeInit
= Instance
->IdeControllerInit
;
2179 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2181 if (EFI_ERROR (Status
)) {
2182 return EFI_DEVICE_ERROR
;
2186 // Enable AE before accessing any AHCI registers
2188 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2191 // Collect AHCI controller information
2193 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2196 // Get the number of command slots per port supported by this HBA.
2198 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2201 // Get the bit map of those ports exposed by this HBA.
2202 // It indicates which ports that the HBA supports are available for software to use.
2204 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2206 AhciRegisters
= &Instance
->AhciRegisters
;
2207 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2209 if (EFI_ERROR (Status
)) {
2210 return EFI_OUT_OF_RESOURCES
;
2213 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2214 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2216 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2218 if ((MaxPortNumber
--) == 0) {
2220 // Should never be here.
2226 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2229 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2231 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2232 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2233 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2234 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2235 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2237 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2238 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2239 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2240 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2241 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2243 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2244 Data
= AhciReadReg (PciIo
, Offset
);
2245 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2246 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2249 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2250 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2254 // Disable aggressive power management.
2256 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2257 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2259 // Disable the reporting of the corresponding interrupt to system software.
2261 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2262 AhciAndReg (PciIo
, Offset
, 0);
2265 // Now inform the IDE Controller Init Module.
2267 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2270 // Enable FIS Receive DMA engine for the first D2H FIS.
2272 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2273 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2274 Status
= AhciWaitMmioSet (
2277 EFI_AHCI_PORT_CMD_FR
,
2278 EFI_AHCI_PORT_CMD_FR
,
2279 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2281 if (EFI_ERROR (Status
)) {
2286 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2287 // It's the requirment from SATA1.0a spec section 5.2.
2289 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2290 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2292 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2293 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2297 MicroSecondDelay (1000);
2299 } while (PhyDetectDelay
> 0);
2301 if (PhyDetectDelay
== 0) {
2303 // No device detected at this port.
2304 // Clear PxCMD.SUD for those ports at which there are no device present.
2306 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2307 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2312 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2313 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2315 PhyDetectDelay
= 16 * 1000;
2317 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2318 if (AhciReadReg(PciIo
, Offset
) != 0) {
2319 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2321 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2323 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2328 MicroSecondDelay (1000);
2330 } while (PhyDetectDelay
> 0);
2332 if (PhyDetectDelay
== 0) {
2337 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2339 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2340 Status
= AhciWaitMmioSet (
2345 EFI_TIMER_PERIOD_SECONDS(16)
2347 if (EFI_ERROR (Status
)) {
2351 Data
= AhciReadReg (PciIo
, Offset
);
2352 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2353 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2355 if (EFI_ERROR (Status
)) {
2359 DeviceType
= EfiIdeCdrom
;
2360 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2361 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2363 if (EFI_ERROR (Status
)) {
2364 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2368 DeviceType
= EfiIdeHarddisk
;
2372 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2373 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2376 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2378 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2379 AhciAtaSmartSupport (
2390 // Submit identify data to IDE controller init driver
2392 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2395 // Now start to config ide device parameter and transfer mode.
2397 Status
= IdeInit
->CalculateMode (
2403 if (EFI_ERROR (Status
)) {
2404 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2409 // Set best supported PIO mode on this IDE device
2411 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2412 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2414 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2417 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2420 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2421 // be set together. Only one DMA mode can be set to a device. If setting
2422 // DMA mode operation fails, we can continue moving on because we only use
2423 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2425 if (SupportedModes
->UdmaMode
.Valid
) {
2426 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2427 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2428 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2429 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2430 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2433 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2434 if (EFI_ERROR (Status
)) {
2435 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2440 // Found a ATA or ATAPI device, add it into the device list.
2442 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2443 if (DeviceType
== EfiIdeHarddisk
) {
2444 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));