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;
551 CommandList
->AhciCmdC
= (DataLength
== 0) ? 1 : 0;
553 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
555 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
558 RemainedData
= (UINTN
) DataLength
;
559 MemAddr
= (UINTN
) DataPhysicalAddr
;
560 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
562 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
563 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
564 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
566 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
569 Data64
.Uint64
= (UINT64
)MemAddr
;
570 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
571 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
572 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
573 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
577 // Set the last PRDT to Interrupt On Complete
579 if (PrdtNumber
> 0) {
580 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
584 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
586 sizeof (EFI_AHCI_COMMAND_LIST
)
589 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
590 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
591 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
592 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
599 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
600 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
605 AhciBuildCommandFis (
606 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
607 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
610 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
612 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
614 // Indicator it's a command
616 CmdFis
->AhciCFisCmdInd
= 0x1;
617 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
619 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
620 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
622 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
623 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
625 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
626 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
628 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
629 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
631 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
632 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
634 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
638 Start a PIO data transfer on specific port.
640 @param[in] PciIo The PCI IO protocol instance.
641 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
642 @param[in] Port The number of port.
643 @param[in] PortMultiplier The timeout value of stop.
644 @param[in] AtapiCommand The atapi command will be used for the
646 @param[in] AtapiCommandLength The length of the atapi command.
647 @param[in] Read The transfer direction.
648 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
649 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
650 @param[in, out] MemoryAddr The pointer to the data buffer.
651 @param[in] DataCount The data count to be transferred.
652 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
653 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
654 used by non-blocking mode.
656 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
657 @retval EFI_TIMEOUT The operation is time out.
658 @retval EFI_UNSUPPORTED The device is not ready for transfer.
659 @retval EFI_SUCCESS The PIO data transfer executes successfully.
665 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
666 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
668 IN UINT8 PortMultiplier
,
669 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
670 IN UINT8 AtapiCommandLength
,
672 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
673 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
674 IN OUT VOID
*MemoryAddr
,
677 IN ATA_NONBLOCK_TASK
*Task
683 EFI_PHYSICAL_ADDRESS PhyAddr
;
686 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
688 EFI_AHCI_COMMAND_FIS CFis
;
689 EFI_AHCI_COMMAND_LIST CmdList
;
694 Flag
= EfiPciIoOperationBusMasterWrite
;
696 Flag
= EfiPciIoOperationBusMasterRead
;
700 // construct command list and command table with pci bus address
702 MapLength
= DataCount
;
703 Status
= PciIo
->Map (
712 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
713 return EFI_BAD_BUFFER_SIZE
;
717 // Package read needed
719 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
721 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
723 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
724 CmdList
.AhciCmdW
= Read
? 0 : 1;
736 (VOID
*)(UINTN
)PhyAddr
,
740 Status
= AhciStartCommand (
746 if (EFI_ERROR (Status
)) {
751 // Check the status and wait the driver sending data
753 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
755 if (Read
&& (AtapiCommand
== 0)) {
757 // Wait device sends the PIO setup fis before data transfer
759 Status
= EFI_TIMEOUT
;
760 Delay
= (UINT32
) (DivU64x32 (Timeout
, 1000) + 1);
762 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
764 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, 0);
765 if (!EFI_ERROR (Status
)) {
766 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
767 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
769 // PxTFD will be updated if there is a D2H or SetupFIS received.
770 // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
772 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
773 Status
= EFI_DEVICE_ERROR
;
777 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
778 if (PrdCount
== DataCount
) {
783 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
784 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, 0);
785 if (!EFI_ERROR (Status
)) {
786 Status
= EFI_DEVICE_ERROR
;
791 // Stall for 100 microseconds.
793 MicroSecondDelay(100);
799 // Wait for D2H Fis is received
801 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
802 Status
= AhciWaitMemSet (
804 EFI_AHCI_FIS_TYPE_MASK
,
805 EFI_AHCI_FIS_REGISTER_D2H
,
809 if (EFI_ERROR (Status
)) {
813 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
814 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
815 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
816 Status
= EFI_DEVICE_ERROR
;
827 AhciDisableFisReceive (
838 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
844 Start a DMA data transfer on specific port
846 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
847 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
848 @param[in] Port The number of port.
849 @param[in] PortMultiplier The timeout value of stop.
850 @param[in] AtapiCommand The atapi command will be used for the
852 @param[in] AtapiCommandLength The length of the atapi command.
853 @param[in] Read The transfer direction.
854 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
855 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
856 @param[in, out] MemoryAddr The pointer to the data buffer.
857 @param[in] DataCount The data count to be transferred.
858 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
859 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
860 used by non-blocking mode.
862 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
863 @retval EFI_TIMEOUT The operation is time out.
864 @retval EFI_UNSUPPORTED The device is not ready for transfer.
865 @retval EFI_SUCCESS The DMA data transfer executes successfully.
871 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
872 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
874 IN UINT8 PortMultiplier
,
875 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
876 IN UINT8 AtapiCommandLength
,
878 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
879 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
880 IN OUT VOID
*MemoryAddr
,
883 IN ATA_NONBLOCK_TASK
*Task
888 EFI_PHYSICAL_ADDRESS PhyAddr
;
891 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
892 EFI_AHCI_COMMAND_FIS CFis
;
893 EFI_AHCI_COMMAND_LIST CmdList
;
897 EFI_PCI_IO_PROTOCOL
*PciIo
;
901 PciIo
= Instance
->PciIo
;
904 return EFI_INVALID_PARAMETER
;
908 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
910 // Delay 100us to simulate the blocking time out checking.
912 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
913 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
914 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
918 MicroSecondDelay (100);
920 gBS
->RestoreTPL (OldTpl
);
922 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
924 // Mark the Task to indicate that it has been started.
927 Task
->IsStart
= TRUE
;
928 Task
->RetryTimes
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
931 Flag
= EfiPciIoOperationBusMasterWrite
;
933 Flag
= EfiPciIoOperationBusMasterRead
;
937 // Construct command list and command table with pci bus address.
939 MapLength
= DataCount
;
940 Status
= PciIo
->Map (
949 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
950 return EFI_BAD_BUFFER_SIZE
;
957 // Package read needed
959 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
961 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
963 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
964 CmdList
.AhciCmdW
= Read
? 0 : 1;
976 (VOID
*)(UINTN
)PhyAddr
,
980 Status
= AhciStartCommand (
986 if (EFI_ERROR (Status
)) {
992 // Wait for command compelte
994 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
995 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1000 Status
= AhciCheckMemSet (
1002 EFI_AHCI_FIS_TYPE_MASK
,
1003 EFI_AHCI_FIS_REGISTER_D2H
,
1004 (UINTN
*) (&Task
->RetryTimes
)
1007 Status
= AhciWaitMemSet (
1009 EFI_AHCI_FIS_TYPE_MASK
,
1010 EFI_AHCI_FIS_REGISTER_D2H
,
1015 if (EFI_ERROR (Status
)) {
1019 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1020 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1021 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1022 Status
= EFI_DEVICE_ERROR
;
1027 // For Blocking mode, the command should be stopped, the Fis should be disabled
1028 // and the PciIo should be unmapped.
1029 // For non-blocking mode, only when a error is happened (if the return status is
1030 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1031 // context cleanup, then set the packet's Asb status.
1034 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1042 AhciDisableFisReceive (
1050 (Task
!= NULL
) ? Task
->Map
: Map
1054 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1058 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1063 Start a non data transfer on specific port.
1065 @param[in] PciIo The PCI IO protocol instance.
1066 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1067 @param[in] Port The number of port.
1068 @param[in] PortMultiplier The timeout value of stop.
1069 @param[in] AtapiCommand The atapi command will be used for the
1071 @param[in] AtapiCommandLength The length of the atapi command.
1072 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1073 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1074 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1075 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1076 used by non-blocking mode.
1078 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1079 @retval EFI_TIMEOUT The operation is time out.
1080 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1081 @retval EFI_SUCCESS The non data transfer executes successfully.
1086 AhciNonDataTransfer (
1087 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1088 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1090 IN UINT8 PortMultiplier
,
1091 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1092 IN UINT8 AtapiCommandLength
,
1093 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1094 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1096 IN ATA_NONBLOCK_TASK
*Task
1103 EFI_AHCI_COMMAND_FIS CFis
;
1104 EFI_AHCI_COMMAND_LIST CmdList
;
1107 // Package read needed
1109 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1111 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1113 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1129 Status
= AhciStartCommand (
1135 if (EFI_ERROR (Status
)) {
1140 // Wait device sends the Response Fis
1142 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1143 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1144 Status
= AhciWaitMemSet (
1146 EFI_AHCI_FIS_TYPE_MASK
,
1147 EFI_AHCI_FIS_REGISTER_D2H
,
1151 if (EFI_ERROR (Status
)) {
1155 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1156 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1157 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1158 Status
= EFI_DEVICE_ERROR
;
1168 AhciDisableFisReceive (
1174 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1180 Stop command running for giving port
1182 @param PciIo The PCI IO protocol instance.
1183 @param Port The number of port.
1184 @param Timeout The timeout value of stop, uses 100ns as a unit.
1186 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1187 @retval EFI_TIMEOUT The operation is time out.
1188 @retval EFI_SUCCESS The command stop successfully.
1194 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1202 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1203 Data
= AhciReadReg (PciIo
, Offset
);
1205 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1209 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1210 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1213 return AhciWaitMmioSet (
1216 EFI_AHCI_PORT_CMD_CR
,
1223 Start command for give slot on specific port.
1225 @param PciIo The PCI IO protocol instance.
1226 @param Port The number of port.
1227 @param CommandSlot The number of Command Slot.
1228 @param Timeout The timeout value of start, uses 100ns as a unit.
1230 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1231 @retval EFI_TIMEOUT The operation is time out.
1232 @retval EFI_SUCCESS The command start successfully.
1238 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1240 IN UINT8 CommandSlot
,
1253 // Collect AHCI controller information
1255 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1257 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1259 AhciClearPortStatus (
1264 Status
= AhciEnableFisReceive (
1270 if (EFI_ERROR (Status
)) {
1274 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1275 PortStatus
= AhciReadReg (PciIo
, Offset
);
1278 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1279 StartCmd
= AhciReadReg (PciIo
, Offset
);
1280 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1281 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1284 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1285 PortTfd
= AhciReadReg (PciIo
, Offset
);
1287 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1288 if ((Capability
& BIT24
) != 0) {
1289 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1290 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1295 EFI_AHCI_PORT_CMD_CLO
,
1302 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1303 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1306 // Setting the command
1308 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1309 AhciAndReg (PciIo
, Offset
, 0);
1310 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1312 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1313 AhciAndReg (PciIo
, Offset
, 0);
1314 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1322 @param PciIo The PCI IO protocol instance.
1323 @param Port The number of port.
1324 @param Timeout The timeout value of reset, uses 100ns as a unit.
1326 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1327 @retval EFI_TIMEOUT The reset operation is time out.
1328 @retval EFI_SUCCESS The port reset successfully.
1334 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1342 AhciClearPortStatus (PciIo
, Port
);
1344 AhciStopCommand (PciIo
, Port
, Timeout
);
1346 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1348 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1350 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1352 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1355 // wait 5 millisecond before de-assert DET
1357 MicroSecondDelay (5000);
1359 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1362 // wait 5 millisecond before de-assert DET
1364 MicroSecondDelay (5000);
1367 // Wait for communication to be re-established
1369 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1370 Status
= AhciWaitMmioSet (
1373 EFI_AHCI_PORT_SSTS_DET_MASK
,
1374 EFI_AHCI_PORT_SSTS_DET_PCE
,
1378 if (EFI_ERROR (Status
)) {
1382 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1383 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1391 @param PciIo The PCI IO protocol instance.
1392 @param Timeout The timeout value of reset, uses 100ns as a unit.
1394 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1395 @retval EFI_TIMEOUT The reset operation is time out.
1396 @retval EFI_SUCCESS AHCI controller is reset successfully.
1402 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1409 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1411 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1413 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1416 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1418 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1423 // Stall for 100 microseconds.
1425 MicroSecondDelay(100);
1428 } while (Delay
> 0);
1438 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1440 @param PciIo The PCI IO protocol instance.
1441 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1442 @param Port The number of port.
1443 @param PortMultiplier The timeout value of stop.
1444 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1446 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1447 @retval Others Fail to get return status data.
1452 AhciAtaSmartReturnStatusCheck (
1453 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1454 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1456 IN UINT8 PortMultiplier
,
1457 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1461 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1467 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1469 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1470 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1471 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1472 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1475 // Send S.M.A.R.T Read Return Status command to device
1477 Status
= AhciNonDataTransfer (
1481 (UINT8
)PortMultiplier
,
1490 if (EFI_ERROR (Status
)) {
1491 return EFI_DEVICE_ERROR
;
1494 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1496 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1498 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1499 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1500 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1502 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1504 // The threshold exceeded condition is not detected by the device
1506 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1508 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1510 // The threshold exceeded condition is detected by the device
1512 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1520 Enable SMART command of the disk if supported.
1522 @param PciIo The PCI IO protocol instance.
1523 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1524 @param Port The number of port.
1525 @param PortMultiplier The timeout value of stop.
1526 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1527 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1532 AhciAtaSmartSupport (
1533 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1534 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1536 IN UINT8 PortMultiplier
,
1537 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1538 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1542 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1545 // Detect if the device supports S.M.A.R.T.
1547 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1549 // S.M.A.R.T is not supported by the device
1551 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1552 Port
, PortMultiplier
));
1555 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1557 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1558 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1560 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1561 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1562 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1563 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1566 // Send S.M.A.R.T Enable command to device
1568 Status
= AhciNonDataTransfer (
1572 (UINT8
)PortMultiplier
,
1582 if (!EFI_ERROR (Status
)) {
1584 // Send S.M.A.R.T AutoSave command to device
1586 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1588 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1589 AtaCommandBlock
.AtaFeatures
= 0xD2;
1590 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1591 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1592 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1594 Status
= AhciNonDataTransfer (
1598 (UINT8
)PortMultiplier
,
1607 if (!EFI_ERROR (Status
)) {
1608 Status
= AhciAtaSmartReturnStatusCheck (
1612 (UINT8
)PortMultiplier
,
1618 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1619 Port
, PortMultiplier
));
1626 Send Buffer cmd to specific device.
1628 @param PciIo The PCI IO protocol instance.
1629 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1630 @param Port The number of port.
1631 @param PortMultiplier The timeout value of stop.
1632 @param Buffer The data buffer to store IDENTIFY PACKET data.
1634 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1635 @retval EFI_TIMEOUT The operation is time out.
1636 @retval EFI_UNSUPPORTED The device is not ready for executing.
1637 @retval EFI_SUCCESS The cmd executes successfully.
1643 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1644 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1646 IN UINT8 PortMultiplier
,
1647 IN OUT EFI_IDENTIFY_DATA
*Buffer
1651 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1652 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1654 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1655 return EFI_INVALID_PARAMETER
;
1658 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1659 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1661 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1662 AtaCommandBlock
.AtaSectorCount
= 1;
1664 Status
= AhciPioTransfer (
1675 sizeof (EFI_IDENTIFY_DATA
),
1684 Send Buffer cmd to specific device.
1686 @param PciIo The PCI IO protocol instance.
1687 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1688 @param Port The number of port.
1689 @param PortMultiplier The timeout value of stop.
1690 @param Buffer The data buffer to store IDENTIFY PACKET data.
1692 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1693 @retval EFI_TIMEOUT The operation is time out.
1694 @retval EFI_UNSUPPORTED The device is not ready for executing.
1695 @retval EFI_SUCCESS The cmd executes successfully.
1700 AhciIdentifyPacket (
1701 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1702 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1704 IN UINT8 PortMultiplier
,
1705 IN OUT EFI_IDENTIFY_DATA
*Buffer
1709 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1710 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1712 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1713 return EFI_INVALID_PARAMETER
;
1716 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1717 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1719 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1720 AtaCommandBlock
.AtaSectorCount
= 1;
1722 Status
= AhciPioTransfer (
1733 sizeof (EFI_IDENTIFY_DATA
),
1742 Send SET FEATURE cmd on specific device.
1744 @param PciIo The PCI IO protocol instance.
1745 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1746 @param Port The number of port.
1747 @param PortMultiplier The timeout value of stop.
1748 @param Feature The data to send Feature register.
1749 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1751 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1752 @retval EFI_TIMEOUT The operation is time out.
1753 @retval EFI_UNSUPPORTED The device is not ready for executing.
1754 @retval EFI_SUCCESS The cmd executes successfully.
1759 AhciDeviceSetFeature (
1760 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1761 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1763 IN UINT8 PortMultiplier
,
1765 IN UINT32 FeatureSpecificData
1769 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1770 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1772 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1773 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1775 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1776 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1777 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1778 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1779 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1780 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1781 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1783 Status
= AhciNonDataTransfer (
1787 (UINT8
)PortMultiplier
,
1800 This function is used to send out ATAPI commands conforms to the Packet Command
1803 @param PciIo The PCI IO protocol instance.
1804 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1805 @param Port The number of port.
1806 @param PortMultiplier The number of port multiplier.
1807 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1809 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1810 and device sends data successfully.
1811 @retval EFI_DEVICE_ERROR the device failed to send data.
1816 AhciPacketCommandExecute (
1817 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1818 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1820 IN UINT8 PortMultiplier
,
1821 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1827 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1828 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1831 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1832 return EFI_INVALID_PARAMETER
;
1835 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1836 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1837 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1841 AtaCommandBlock
.AtaFeatures
= 0x00;
1843 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1844 // determine how many data should be transferred.
1846 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1847 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1849 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1850 Buffer
= Packet
->InDataBuffer
;
1851 Length
= Packet
->InTransferLength
;
1854 Buffer
= Packet
->OutDataBuffer
;
1855 Length
= Packet
->OutTransferLength
;
1860 Status
= AhciNonDataTransfer (
1873 Status
= AhciPioTransfer (
1893 Allocate transfer-related data struct which is used at AHCI mode.
1895 @param PciIo The PCI IO protocol instance.
1896 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1901 AhciCreateTransferDescriptor (
1902 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1903 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1911 UINT32 PortImplementBitMap
;
1912 UINT8 MaxPortNumber
;
1913 UINT8 MaxCommandSlotNumber
;
1914 BOOLEAN Support64Bit
;
1915 UINT64 MaxReceiveFisSize
;
1916 UINT64 MaxCommandListSize
;
1917 UINT64 MaxCommandTableSize
;
1918 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1919 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1920 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1924 // Collect AHCI controller information
1926 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1928 // Get the number of command slots per port supported by this HBA.
1930 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1931 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1933 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
1935 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
1937 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
1938 if (MaxPortNumber
== 0) {
1939 return EFI_DEVICE_ERROR
;
1942 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1943 Status
= PciIo
->AllocateBuffer (
1946 EfiBootServicesData
,
1947 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1952 if (EFI_ERROR (Status
)) {
1953 return EFI_OUT_OF_RESOURCES
;
1956 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1958 AhciRegisters
->AhciRFis
= Buffer
;
1959 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1960 Bytes
= (UINTN
)MaxReceiveFisSize
;
1962 Status
= PciIo
->Map (
1964 EfiPciIoOperationBusMasterCommonBuffer
,
1968 &AhciRegisters
->MapRFis
1971 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1973 // Map error or unable to map the whole RFis buffer into a contiguous region.
1975 Status
= EFI_OUT_OF_RESOURCES
;
1979 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1981 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1983 Status
= EFI_DEVICE_ERROR
;
1986 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1989 // Allocate memory for command list
1990 // Note that the implemenation is a single task model which only use a command list for all ports.
1993 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1994 Status
= PciIo
->AllocateBuffer (
1997 EfiBootServicesData
,
1998 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2003 if (EFI_ERROR (Status
)) {
2005 // Free mapped resource.
2007 Status
= EFI_OUT_OF_RESOURCES
;
2011 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2013 AhciRegisters
->AhciCmdList
= Buffer
;
2014 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2015 Bytes
= (UINTN
)MaxCommandListSize
;
2017 Status
= PciIo
->Map (
2019 EfiPciIoOperationBusMasterCommonBuffer
,
2022 &AhciCmdListPciAddr
,
2023 &AhciRegisters
->MapCmdList
2026 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2028 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2030 Status
= EFI_OUT_OF_RESOURCES
;
2034 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2036 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2038 Status
= EFI_DEVICE_ERROR
;
2041 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2044 // Allocate memory for command table
2045 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2048 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2050 Status
= PciIo
->AllocateBuffer (
2053 EfiBootServicesData
,
2054 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2059 if (EFI_ERROR (Status
)) {
2061 // Free mapped resource.
2063 Status
= EFI_OUT_OF_RESOURCES
;
2067 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2069 AhciRegisters
->AhciCommandTable
= Buffer
;
2070 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2071 Bytes
= (UINTN
)MaxCommandTableSize
;
2073 Status
= PciIo
->Map (
2075 EfiPciIoOperationBusMasterCommonBuffer
,
2078 &AhciCommandTablePciAddr
,
2079 &AhciRegisters
->MapCommandTable
2082 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2084 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2086 Status
= EFI_OUT_OF_RESOURCES
;
2090 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2092 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2094 Status
= EFI_DEVICE_ERROR
;
2097 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2101 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2106 AhciRegisters
->MapCommandTable
2111 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2112 AhciRegisters
->AhciCommandTable
2117 AhciRegisters
->MapCmdList
2122 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2123 AhciRegisters
->AhciCmdList
2128 AhciRegisters
->MapRFis
2133 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2134 AhciRegisters
->AhciRFis
2141 Initialize ATA host controller at AHCI mode.
2143 The function is designed to initialize ATA host controller.
2145 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2150 AhciModeInitialization (
2151 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2155 EFI_PCI_IO_PROTOCOL
*PciIo
;
2156 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2158 UINT8 MaxPortNumber
;
2159 UINT32 PortImplementBitMap
;
2161 EFI_AHCI_REGISTERS
*AhciRegisters
;
2167 EFI_IDENTIFY_DATA Buffer
;
2168 EFI_ATA_DEVICE_TYPE DeviceType
;
2169 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2170 EFI_ATA_TRANSFER_MODE TransferMode
;
2171 UINT32 PhyDetectDelay
;
2173 if (Instance
== NULL
) {
2174 return EFI_INVALID_PARAMETER
;
2177 PciIo
= Instance
->PciIo
;
2178 IdeInit
= Instance
->IdeControllerInit
;
2180 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2182 if (EFI_ERROR (Status
)) {
2183 return EFI_DEVICE_ERROR
;
2187 // Enable AE before accessing any AHCI registers
2189 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2192 // Collect AHCI controller information
2194 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2197 // Get the number of command slots per port supported by this HBA.
2199 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2202 // Get the bit map of those ports exposed by this HBA.
2203 // It indicates which ports that the HBA supports are available for software to use.
2205 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2207 AhciRegisters
= &Instance
->AhciRegisters
;
2208 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2210 if (EFI_ERROR (Status
)) {
2211 return EFI_OUT_OF_RESOURCES
;
2214 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2215 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2217 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2219 if ((MaxPortNumber
--) == 0) {
2221 // Should never be here.
2227 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2230 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2232 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2233 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2234 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2235 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2236 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2238 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2239 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2240 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2241 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2242 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2244 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2245 Data
= AhciReadReg (PciIo
, Offset
);
2246 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2247 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2250 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2251 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2255 // Disable aggressive power management.
2257 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2258 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2260 // Disable the reporting of the corresponding interrupt to system software.
2262 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2263 AhciAndReg (PciIo
, Offset
, 0);
2266 // Now inform the IDE Controller Init Module.
2268 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2271 // Enable FIS Receive DMA engine for the first D2H FIS.
2273 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2274 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2275 Status
= AhciWaitMmioSet (
2278 EFI_AHCI_PORT_CMD_FR
,
2279 EFI_AHCI_PORT_CMD_FR
,
2280 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2282 if (EFI_ERROR (Status
)) {
2287 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2288 // It's the requirment from SATA1.0a spec section 5.2.
2290 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2291 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2293 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2294 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2298 MicroSecondDelay (1000);
2300 } while (PhyDetectDelay
> 0);
2302 if (PhyDetectDelay
== 0) {
2304 // No device detected at this port.
2305 // Clear PxCMD.SUD for those ports at which there are no device present.
2307 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2308 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2313 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2314 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2316 PhyDetectDelay
= 16 * 1000;
2318 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2319 if (AhciReadReg(PciIo
, Offset
) != 0) {
2320 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2322 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2324 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2329 MicroSecondDelay (1000);
2331 } while (PhyDetectDelay
> 0);
2333 if (PhyDetectDelay
== 0) {
2338 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2340 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2341 Status
= AhciWaitMmioSet (
2346 EFI_TIMER_PERIOD_SECONDS(16)
2348 if (EFI_ERROR (Status
)) {
2352 Data
= AhciReadReg (PciIo
, Offset
);
2353 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2354 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2356 if (EFI_ERROR (Status
)) {
2360 DeviceType
= EfiIdeCdrom
;
2361 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2362 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2364 if (EFI_ERROR (Status
)) {
2365 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2369 DeviceType
= EfiIdeHarddisk
;
2373 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2374 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2377 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2379 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2380 AhciAtaSmartSupport (
2391 // Submit identify data to IDE controller init driver
2393 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2396 // Now start to config ide device parameter and transfer mode.
2398 Status
= IdeInit
->CalculateMode (
2404 if (EFI_ERROR (Status
)) {
2405 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2410 // Set best supported PIO mode on this IDE device
2412 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2413 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2415 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2418 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2421 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2422 // be set together. Only one DMA mode can be set to a device. If setting
2423 // DMA mode operation fails, we can continue moving on because we only use
2424 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2426 if (SupportedModes
->UdmaMode
.Valid
) {
2427 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2428 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2429 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2430 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2431 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2434 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2435 if (EFI_ERROR (Status
)) {
2436 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2441 // Found a ATA or ATAPI device, add it into the device list.
2443 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2444 if (DeviceType
== EfiIdeHarddisk
) {
2445 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));