2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2011, 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
= (UINT32
)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
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
763 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
765 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
766 Status
= EFI_DEVICE_ERROR
;
769 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
771 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, 0);
772 if (!EFI_ERROR (Status
)) {
773 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
774 if (PrdCount
== DataCount
) {
779 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
780 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, 0);
781 if (!EFI_ERROR (Status
)) {
782 Status
= EFI_DEVICE_ERROR
;
787 // Stall for 100 microseconds.
789 MicroSecondDelay(100);
795 // Wait for D2H Fis is received
797 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
798 Status
= AhciWaitMemSet (
800 EFI_AHCI_FIS_TYPE_MASK
,
801 EFI_AHCI_FIS_REGISTER_D2H
,
805 if (EFI_ERROR (Status
)) {
809 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
810 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
811 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
812 Status
= EFI_DEVICE_ERROR
;
823 AhciDisableFisReceive (
834 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
840 Start a DMA data transfer on specific port
842 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
843 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
844 @param[in] Port The number of port.
845 @param[in] PortMultiplier The timeout value of stop.
846 @param[in] AtapiCommand The atapi command will be used for the
848 @param[in] AtapiCommandLength The length of the atapi command.
849 @param[in] Read The transfer direction.
850 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
851 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
852 @param[in, out] MemoryAddr The pointer to the data buffer.
853 @param[in] DataCount The data count to be transferred.
854 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
855 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
856 used by non-blocking mode.
858 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
859 @retval EFI_TIMEOUT The operation is time out.
860 @retval EFI_UNSUPPORTED The device is not ready for transfer.
861 @retval EFI_SUCCESS The DMA data transfer executes successfully.
867 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
868 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
870 IN UINT8 PortMultiplier
,
871 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
872 IN UINT8 AtapiCommandLength
,
874 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
875 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
876 IN OUT VOID
*MemoryAddr
,
879 IN ATA_NONBLOCK_TASK
*Task
884 EFI_PHYSICAL_ADDRESS PhyAddr
;
887 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
888 EFI_AHCI_COMMAND_FIS CFis
;
889 EFI_AHCI_COMMAND_LIST CmdList
;
893 EFI_PCI_IO_PROTOCOL
*PciIo
;
897 PciIo
= Instance
->PciIo
;
900 return EFI_INVALID_PARAMETER
;
904 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
906 // Delay 100us to simulate the blocking time out checking.
908 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
909 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
910 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
911 gBS
->RestoreTPL (OldTpl
);
915 MicroSecondDelay (100);
918 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
920 // Mark the Task to indicate that it has been started.
923 Task
->IsStart
= TRUE
;
924 Task
->RetryTimes
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
927 Flag
= EfiPciIoOperationBusMasterWrite
;
929 Flag
= EfiPciIoOperationBusMasterRead
;
933 // Construct command list and command table with pci bus address.
935 MapLength
= DataCount
;
936 Status
= PciIo
->Map (
945 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
946 return EFI_BAD_BUFFER_SIZE
;
953 // Package read needed
955 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
957 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
959 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
960 CmdList
.AhciCmdW
= Read
? 0 : 1;
972 (VOID
*)(UINTN
)PhyAddr
,
976 Status
= AhciStartCommand (
982 if (EFI_ERROR (Status
)) {
988 // Wait for command compelte
990 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
991 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
996 Status
= AhciCheckMemSet (
998 EFI_AHCI_FIS_TYPE_MASK
,
999 EFI_AHCI_FIS_REGISTER_D2H
,
1000 (UINTN
*) (&Task
->RetryTimes
)
1003 Status
= AhciWaitMemSet (
1005 EFI_AHCI_FIS_TYPE_MASK
,
1006 EFI_AHCI_FIS_REGISTER_D2H
,
1011 if (EFI_ERROR (Status
)) {
1015 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1016 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1017 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1018 Status
= EFI_DEVICE_ERROR
;
1023 // For Blocking mode, the command should be stopped, the Fis should be disabled
1024 // and the PciIo should be unmapped.
1025 // For non-blocking mode, only when a error is happened (if the return status is
1026 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1027 // context cleanup, then set the packet's Asb status.
1030 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1038 AhciDisableFisReceive (
1046 (Task
!= NULL
) ? Task
->Map
: Map
1050 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1054 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1059 Start a non data transfer on specific port.
1061 @param[in] PciIo The PCI IO protocol instance.
1062 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1063 @param[in] Port The number of port.
1064 @param[in] PortMultiplier The timeout value of stop.
1065 @param[in] AtapiCommand The atapi command will be used for the
1067 @param[in] AtapiCommandLength The length of the atapi command.
1068 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1069 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1070 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1071 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1072 used by non-blocking mode.
1074 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1075 @retval EFI_TIMEOUT The operation is time out.
1076 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1077 @retval EFI_SUCCESS The non data transfer executes successfully.
1082 AhciNonDataTransfer (
1083 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1084 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1086 IN UINT8 PortMultiplier
,
1087 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1088 IN UINT8 AtapiCommandLength
,
1089 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1090 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1092 IN ATA_NONBLOCK_TASK
*Task
1099 EFI_AHCI_COMMAND_FIS CFis
;
1100 EFI_AHCI_COMMAND_LIST CmdList
;
1103 // Package read needed
1105 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1107 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1109 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1125 Status
= AhciStartCommand (
1131 if (EFI_ERROR (Status
)) {
1136 // Wait device sends the Response Fis
1138 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1139 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1140 Status
= AhciWaitMemSet (
1142 EFI_AHCI_FIS_TYPE_MASK
,
1143 EFI_AHCI_FIS_REGISTER_D2H
,
1147 if (EFI_ERROR (Status
)) {
1151 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1152 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1153 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1154 Status
= EFI_DEVICE_ERROR
;
1164 AhciDisableFisReceive (
1170 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1176 Stop command running for giving port
1178 @param PciIo The PCI IO protocol instance.
1179 @param Port The number of port.
1180 @param Timeout The timeout value of stop, uses 100ns as a unit.
1182 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1183 @retval EFI_TIMEOUT The operation is time out.
1184 @retval EFI_SUCCESS The command stop successfully.
1190 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1198 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1199 Data
= AhciReadReg (PciIo
, Offset
);
1201 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1205 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1206 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1209 return AhciWaitMmioSet (
1212 EFI_AHCI_PORT_CMD_CR
,
1219 Start command for give slot on specific port.
1221 @param PciIo The PCI IO protocol instance.
1222 @param Port The number of port.
1223 @param CommandSlot The number of Command Slot.
1224 @param Timeout The timeout value of start, uses 100ns as a unit.
1226 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1227 @retval EFI_TIMEOUT The operation is time out.
1228 @retval EFI_SUCCESS The command start successfully.
1234 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1236 IN UINT8 CommandSlot
,
1249 // Collect AHCI controller information
1251 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1253 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1255 AhciClearPortStatus (
1260 Status
= AhciEnableFisReceive (
1266 if (EFI_ERROR (Status
)) {
1270 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1271 PortStatus
= AhciReadReg (PciIo
, Offset
);
1274 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1275 StartCmd
= AhciReadReg (PciIo
, Offset
);
1276 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1277 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1280 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1281 PortTfd
= AhciReadReg (PciIo
, Offset
);
1283 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1284 if ((Capability
& BIT24
) != 0) {
1285 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1286 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1291 EFI_AHCI_PORT_CMD_CLO
,
1298 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1299 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1302 // Setting the command
1304 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1305 AhciAndReg (PciIo
, Offset
, 0);
1306 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1308 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1309 AhciAndReg (PciIo
, Offset
, 0);
1310 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1318 @param PciIo The PCI IO protocol instance.
1319 @param Port The number of port.
1320 @param Timeout The timeout value of reset, uses 100ns as a unit.
1322 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1323 @retval EFI_TIMEOUT The reset operation is time out.
1324 @retval EFI_SUCCESS The port reset successfully.
1330 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1338 AhciClearPortStatus (PciIo
, Port
);
1340 AhciStopCommand (PciIo
, Port
, Timeout
);
1342 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1344 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1346 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1348 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1351 // wait 5 millisecond before de-assert DET
1353 MicroSecondDelay (5000);
1355 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1358 // wait 5 millisecond before de-assert DET
1360 MicroSecondDelay (5000);
1363 // Wait for communication to be re-established
1365 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1366 Status
= AhciWaitMmioSet (
1369 EFI_AHCI_PORT_SSTS_DET_MASK
,
1370 EFI_AHCI_PORT_SSTS_DET_PCE
,
1374 if (EFI_ERROR (Status
)) {
1378 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1379 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1387 @param PciIo The PCI IO protocol instance.
1388 @param Timeout The timeout value of reset, uses 100ns as a unit.
1390 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1391 @retval EFI_TIMEOUT The reset operation is time out.
1392 @retval EFI_SUCCESS AHCI controller is reset successfully.
1398 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1405 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1407 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1409 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1412 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1414 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1419 // Stall for 100 microseconds.
1421 MicroSecondDelay(100);
1424 } while (Delay
> 0);
1434 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1436 @param PciIo The PCI IO protocol instance.
1437 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1438 @param Port The number of port.
1439 @param PortMultiplier The timeout value of stop.
1440 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1442 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1443 @retval Others Fail to get return status data.
1448 AhciAtaSmartReturnStatusCheck (
1449 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1450 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1452 IN UINT8 PortMultiplier
,
1453 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1457 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1463 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1465 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1466 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1467 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1468 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1471 // Send S.M.A.R.T Read Return Status command to device
1473 Status
= AhciNonDataTransfer (
1477 (UINT8
)PortMultiplier
,
1486 if (EFI_ERROR (Status
)) {
1487 return EFI_DEVICE_ERROR
;
1490 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1492 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1494 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1495 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1496 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1498 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1500 // The threshold exceeded condition is not detected by the device
1502 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1504 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1506 // The threshold exceeded condition is detected by the device
1508 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1516 Enable SMART command of the disk if supported.
1518 @param PciIo The PCI IO protocol instance.
1519 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1520 @param Port The number of port.
1521 @param PortMultiplier The timeout value of stop.
1522 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1523 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1528 AhciAtaSmartSupport (
1529 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1530 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1532 IN UINT8 PortMultiplier
,
1533 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1534 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1538 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1541 // Detect if the device supports S.M.A.R.T.
1543 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1545 // S.M.A.R.T is not supported by the device
1547 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1548 Port
, PortMultiplier
));
1551 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1553 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1554 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1556 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1557 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1558 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1559 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1562 // Send S.M.A.R.T Enable command to device
1564 Status
= AhciNonDataTransfer (
1568 (UINT8
)PortMultiplier
,
1578 if (!EFI_ERROR (Status
)) {
1580 // Send S.M.A.R.T AutoSave command to device
1582 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1584 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1585 AtaCommandBlock
.AtaFeatures
= 0xD2;
1586 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1587 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1588 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1590 Status
= AhciNonDataTransfer (
1594 (UINT8
)PortMultiplier
,
1603 if (!EFI_ERROR (Status
)) {
1604 Status
= AhciAtaSmartReturnStatusCheck (
1608 (UINT8
)PortMultiplier
,
1614 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1615 Port
, PortMultiplier
));
1622 Send Buffer cmd to specific device.
1624 @param PciIo The PCI IO protocol instance.
1625 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1626 @param Port The number of port.
1627 @param PortMultiplier The timeout value of stop.
1628 @param Buffer The data buffer to store IDENTIFY PACKET data.
1630 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1631 @retval EFI_TIMEOUT The operation is time out.
1632 @retval EFI_UNSUPPORTED The device is not ready for executing.
1633 @retval EFI_SUCCESS The cmd executes successfully.
1639 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1640 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1642 IN UINT8 PortMultiplier
,
1643 IN OUT EFI_IDENTIFY_DATA
*Buffer
1647 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1648 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1650 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1651 return EFI_INVALID_PARAMETER
;
1654 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1655 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1657 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1658 AtaCommandBlock
.AtaSectorCount
= 1;
1660 Status
= AhciPioTransfer (
1671 sizeof (EFI_IDENTIFY_DATA
),
1680 Send Buffer cmd to specific device.
1682 @param PciIo The PCI IO protocol instance.
1683 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1684 @param Port The number of port.
1685 @param PortMultiplier The timeout value of stop.
1686 @param Buffer The data buffer to store IDENTIFY PACKET data.
1688 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1689 @retval EFI_TIMEOUT The operation is time out.
1690 @retval EFI_UNSUPPORTED The device is not ready for executing.
1691 @retval EFI_SUCCESS The cmd executes successfully.
1696 AhciIdentifyPacket (
1697 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1698 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1700 IN UINT8 PortMultiplier
,
1701 IN OUT EFI_IDENTIFY_DATA
*Buffer
1705 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1706 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1708 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1709 return EFI_INVALID_PARAMETER
;
1712 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1713 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1715 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1716 AtaCommandBlock
.AtaSectorCount
= 1;
1718 Status
= AhciPioTransfer (
1729 sizeof (EFI_IDENTIFY_DATA
),
1738 Send SET FEATURE cmd on specific device.
1740 @param PciIo The PCI IO protocol instance.
1741 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1742 @param Port The number of port.
1743 @param PortMultiplier The timeout value of stop.
1744 @param Feature The data to send Feature register.
1745 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1747 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1748 @retval EFI_TIMEOUT The operation is time out.
1749 @retval EFI_UNSUPPORTED The device is not ready for executing.
1750 @retval EFI_SUCCESS The cmd executes successfully.
1755 AhciDeviceSetFeature (
1756 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1757 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1759 IN UINT8 PortMultiplier
,
1761 IN UINT32 FeatureSpecificData
1765 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1766 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1768 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1769 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1771 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1772 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1773 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1774 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1775 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1776 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1777 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1779 Status
= AhciNonDataTransfer (
1783 (UINT8
)PortMultiplier
,
1796 This function is used to send out ATAPI commands conforms to the Packet Command
1799 @param PciIo The PCI IO protocol instance.
1800 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1801 @param Port The number of port.
1802 @param PortMultiplier The number of port multiplier.
1803 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1805 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1806 and device sends data successfully.
1807 @retval EFI_DEVICE_ERROR the device failed to send data.
1812 AhciPacketCommandExecute (
1813 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1814 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1816 IN UINT8 PortMultiplier
,
1817 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1823 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1824 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1827 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1828 return EFI_INVALID_PARAMETER
;
1831 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1832 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1833 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1837 AtaCommandBlock
.AtaFeatures
= 0x00;
1839 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1840 // determine how many data should be transferred.
1842 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1843 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1845 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1846 Buffer
= Packet
->InDataBuffer
;
1847 Length
= Packet
->InTransferLength
;
1850 Buffer
= Packet
->OutDataBuffer
;
1851 Length
= Packet
->OutTransferLength
;
1856 Status
= AhciNonDataTransfer (
1869 Status
= AhciPioTransfer (
1889 Allocate transfer-related data struct which is used at AHCI mode.
1891 @param PciIo The PCI IO protocol instance.
1892 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1897 AhciCreateTransferDescriptor (
1898 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1899 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1907 UINT8 MaxPortNumber
;
1908 UINT8 MaxCommandSlotNumber
;
1909 BOOLEAN Support64Bit
;
1910 UINT64 MaxReceiveFisSize
;
1911 UINT64 MaxCommandListSize
;
1912 UINT64 MaxCommandTableSize
;
1913 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1914 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1915 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1919 // Collect AHCI controller information
1921 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1922 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1924 // Get the number of command slots per port supported by this HBA.
1926 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1927 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1929 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1930 Status
= PciIo
->AllocateBuffer (
1933 EfiBootServicesData
,
1934 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1939 if (EFI_ERROR (Status
)) {
1940 return EFI_OUT_OF_RESOURCES
;
1943 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1945 AhciRegisters
->AhciRFis
= Buffer
;
1946 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1947 Bytes
= (UINTN
)MaxReceiveFisSize
;
1949 Status
= PciIo
->Map (
1951 EfiPciIoOperationBusMasterCommonBuffer
,
1955 &AhciRegisters
->MapRFis
1958 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1960 // Map error or unable to map the whole RFis buffer into a contiguous region.
1962 Status
= EFI_OUT_OF_RESOURCES
;
1966 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1968 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1970 Status
= EFI_DEVICE_ERROR
;
1973 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1976 // Allocate memory for command list
1977 // Note that the implemenation is a single task model which only use a command list for all ports.
1980 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1981 Status
= PciIo
->AllocateBuffer (
1984 EfiBootServicesData
,
1985 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
1990 if (EFI_ERROR (Status
)) {
1992 // Free mapped resource.
1994 Status
= EFI_OUT_OF_RESOURCES
;
1998 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2000 AhciRegisters
->AhciCmdList
= Buffer
;
2001 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2002 Bytes
= (UINTN
)MaxCommandListSize
;
2004 Status
= PciIo
->Map (
2006 EfiPciIoOperationBusMasterCommonBuffer
,
2009 &AhciCmdListPciAddr
,
2010 &AhciRegisters
->MapCmdList
2013 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2015 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2017 Status
= EFI_OUT_OF_RESOURCES
;
2021 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2023 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2025 Status
= EFI_DEVICE_ERROR
;
2028 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2031 // Allocate memory for command table
2032 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2035 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2037 Status
= PciIo
->AllocateBuffer (
2040 EfiBootServicesData
,
2041 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2046 if (EFI_ERROR (Status
)) {
2048 // Free mapped resource.
2050 Status
= EFI_OUT_OF_RESOURCES
;
2054 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2056 AhciRegisters
->AhciCommandTable
= Buffer
;
2057 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2058 Bytes
= (UINTN
)MaxCommandTableSize
;
2060 Status
= PciIo
->Map (
2062 EfiPciIoOperationBusMasterCommonBuffer
,
2065 &AhciCommandTablePciAddr
,
2066 &AhciRegisters
->MapCommandTable
2069 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2071 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2073 Status
= EFI_OUT_OF_RESOURCES
;
2077 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2079 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2081 Status
= EFI_DEVICE_ERROR
;
2084 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2088 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2093 AhciRegisters
->MapCommandTable
2098 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2099 AhciRegisters
->AhciCommandTable
2104 AhciRegisters
->MapCmdList
2109 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2110 AhciRegisters
->AhciCmdList
2115 AhciRegisters
->MapRFis
2120 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2121 AhciRegisters
->AhciRFis
2128 Initialize ATA host controller at AHCI mode.
2130 The function is designed to initialize ATA host controller.
2132 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2137 AhciModeInitialization (
2138 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2142 EFI_PCI_IO_PROTOCOL
*PciIo
;
2143 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2145 UINT8 MaxPortNumber
;
2146 UINT32 PortImplementBitMap
;
2148 EFI_AHCI_REGISTERS
*AhciRegisters
;
2154 EFI_IDENTIFY_DATA Buffer
;
2155 EFI_ATA_DEVICE_TYPE DeviceType
;
2156 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2157 EFI_ATA_TRANSFER_MODE TransferMode
;
2158 UINT32 PhyDetectDelay
;
2160 if (Instance
== NULL
) {
2161 return EFI_INVALID_PARAMETER
;
2164 PciIo
= Instance
->PciIo
;
2165 IdeInit
= Instance
->IdeControllerInit
;
2167 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2169 if (EFI_ERROR (Status
)) {
2170 return EFI_DEVICE_ERROR
;
2174 // Enable AE before accessing any AHCI registers
2176 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2179 // Collect AHCI controller information
2181 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2184 // Get the number of command slots per port supported by this HBA.
2186 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2189 // Get the bit map of those ports exposed by this HBA.
2190 // It indicates which ports that the HBA supports are available for software to use.
2192 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2194 AhciRegisters
= &Instance
->AhciRegisters
;
2195 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2197 if (EFI_ERROR (Status
)) {
2198 return EFI_OUT_OF_RESOURCES
;
2201 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
2202 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2203 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2206 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2208 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2209 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2210 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2211 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2212 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2214 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2215 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2216 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2217 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2218 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2220 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2221 Data
= AhciReadReg (PciIo
, Offset
);
2222 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2223 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2226 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2227 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2231 // Disable aggressive power management.
2233 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2234 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2236 // Disable the reporting of the corresponding interrupt to system software.
2238 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2239 AhciAndReg (PciIo
, Offset
, 0);
2242 // Now inform the IDE Controller Init Module.
2244 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2247 // Enable FIS Receive DMA engine for the first D2H FIS.
2249 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2250 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2251 Status
= AhciWaitMmioSet (
2254 EFI_AHCI_PORT_CMD_FR
,
2255 EFI_AHCI_PORT_CMD_FR
,
2256 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2258 if (EFI_ERROR (Status
)) {
2263 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2264 // It's the requirment from SATA1.0a spec section 5.2.
2266 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2267 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2269 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2270 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2274 MicroSecondDelay (1000);
2276 } while (PhyDetectDelay
> 0);
2278 if (PhyDetectDelay
== 0) {
2280 // No device detected at this port.
2286 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2287 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2289 PhyDetectDelay
= 16 * 1000;
2291 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2292 if (AhciReadReg(PciIo
, Offset
) != 0) {
2293 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2295 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2297 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2302 MicroSecondDelay (1000);
2304 } while (PhyDetectDelay
> 0);
2306 if (PhyDetectDelay
== 0) {
2311 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2313 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2314 Status
= AhciWaitMmioSet (
2319 EFI_TIMER_PERIOD_SECONDS(16)
2321 if (EFI_ERROR (Status
)) {
2325 Data
= AhciReadReg (PciIo
, Offset
);
2326 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2327 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2329 if (EFI_ERROR (Status
)) {
2333 DeviceType
= EfiIdeCdrom
;
2334 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2335 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2337 if (EFI_ERROR (Status
)) {
2338 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2342 DeviceType
= EfiIdeHarddisk
;
2346 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2347 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2350 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2352 if (DeviceType
== EfiIdeHarddisk
) {
2353 AhciAtaSmartSupport (
2364 // Submit identify data to IDE controller init driver
2366 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2369 // Now start to config ide device parameter and transfer mode.
2371 Status
= IdeInit
->CalculateMode (
2377 if (EFI_ERROR (Status
)) {
2378 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2383 // Set best supported PIO mode on this IDE device
2385 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2386 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2388 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2391 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2394 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2395 // be set together. Only one DMA mode can be set to a device. If setting
2396 // DMA mode operation fails, we can continue moving on because we only use
2397 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2399 if (SupportedModes
->UdmaMode
.Valid
) {
2400 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2401 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2402 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2403 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2404 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2407 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2408 if (EFI_ERROR (Status
)) {
2409 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2414 // Found a ATA or ATAPI device, add it into the device list.
2416 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2417 if (DeviceType
== EfiIdeHarddisk
) {
2418 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));