2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "AtaAtapiPassThru.h"
19 Read AHCI Operation register.
21 @param PciIo The PCI IO protocol instance.
22 @param Offset The operation register offset.
24 @return The register content read.
30 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
36 ASSERT (PciIo
!= NULL
);
53 Write AHCI Operation register.
55 @param PciIo The PCI IO protocol instance.
56 @param Offset The operation register offset.
57 @param Data The data used to write down.
63 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
68 ASSERT (PciIo
!= NULL
);
83 Do AND operation with the value of AHCI Operation register.
85 @param PciIo The PCI IO protocol instance.
86 @param Offset The operation register offset.
87 @param AndData The data used to do AND operation.
93 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
100 ASSERT (PciIo
!= NULL
);
102 Data
= AhciReadReg (PciIo
, Offset
);
106 AhciWriteReg (PciIo
, Offset
, Data
);
110 Do OR operation with the value of AHCI Operation register.
112 @param PciIo The PCI IO protocol instance.
113 @param Offset The operation register offset.
114 @param OrData The data used to do OR operation.
120 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
127 ASSERT (PciIo
!= NULL
);
129 Data
= AhciReadReg (PciIo
, Offset
);
133 AhciWriteReg (PciIo
, Offset
, Data
);
137 Wait for the value of the specified MMIO register set to the test value.
139 @param PciIo The PCI IO protocol instance.
140 @param Offset The MMIO address to test.
141 @param MaskValue The mask value of memory.
142 @param TestValue The test value of memory.
143 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
145 @retval EFI_TIMEOUT The MMIO setting is time out.
146 @retval EFI_SUCCESS The MMIO is correct set.
152 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
161 BOOLEAN InfiniteWait
;
166 InfiniteWait
= FALSE
;
169 Delay
= DivU64x32 (Timeout
, 1000) + 1;
173 // Access PCI MMIO space to see if the value is the tested one.
175 Value
= AhciReadReg (PciIo
, (UINT32
) Offset
) & MaskValue
;
177 if (Value
== TestValue
) {
182 // Stall for 100 microseconds.
184 MicroSecondDelay (100);
188 } while (InfiniteWait
|| (Delay
> 0));
194 Wait for the value of the specified system memory set to the test value.
196 @param Address The system memory address to test.
197 @param MaskValue The mask value of memory.
198 @param TestValue The test value of memory.
199 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
201 @retval EFI_TIMEOUT The system memory setting is time out.
202 @retval EFI_SUCCESS The system memory is correct set.
208 IN EFI_PHYSICAL_ADDRESS Address
,
216 BOOLEAN InfiniteWait
;
221 InfiniteWait
= FALSE
;
224 Delay
= DivU64x32 (Timeout
, 1000) + 1;
228 // Access sytem memory to see if the value is the tested one.
230 // The system memory pointed by Address will be updated by the
231 // SATA Host Controller, "volatile" is introduced to prevent
232 // compiler from optimizing the access to the memory address
233 // to only read once.
235 Value
= *(volatile UINT32
*) (UINTN
) Address
;
238 if (Value
== TestValue
) {
243 // Stall for 100 microseconds.
245 MicroSecondDelay (100);
249 } while (InfiniteWait
|| (Delay
> 0));
255 Check the memory status to the test value.
257 @param[in] Address The memory address to test.
258 @param[in] MaskValue The mask value of memory.
259 @param[in] TestValue The test value of memory.
260 @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
261 non-blocking mode. If NULL, then just try once.
263 @retval EFI_NOTREADY The memory is not set.
264 @retval EFI_TIMEOUT The memory setting retry times out.
265 @retval EFI_SUCCESS The memory is correct set.
274 IN OUT ATA_NONBLOCK_TASK
*Task
283 Value
= *(volatile UINT32
*) Address
;
286 if (Value
== TestValue
) {
290 if ((Task
!= NULL
) && !Task
->InfiniteWait
&& (Task
->RetryTimes
== 0)) {
293 return EFI_NOT_READY
;
298 Check if the device is still on port. It also checks if the AHCI controller
299 supports the address and data count will be transferred.
301 @param PciIo The PCI IO protocol instance.
302 @param Port The number of port.
304 @retval EFI_SUCCESS The device is attached to port and the transfer data is
305 supported by AHCI controller.
306 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
308 @retval EFI_NOT_READY The physical communication between AHCI controller and device
314 AhciCheckDeviceStatus (
315 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
322 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
324 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
326 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
330 return EFI_NOT_READY
;
335 Clear the port interrupt and error status. It will also clear
336 HBA interrupt status.
338 @param PciIo The PCI IO protocol instance.
339 @param Port The number of port.
344 AhciClearPortStatus (
345 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
352 // Clear any error status
354 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
355 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
358 // Clear any port interrupt status
360 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
361 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
364 // Clear any HBA interrupt status
366 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
370 This function is used to dump the Status Registers and if there is ERR bit set
371 in the Status Register, the Error Register's value is also be dumped.
373 @param PciIo The PCI IO protocol instance.
374 @param Port The number of port.
375 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
381 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
383 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
389 ASSERT (PciIo
!= NULL
);
391 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
392 Data
= AhciReadReg (PciIo
, Offset
);
394 if (AtaStatusBlock
!= NULL
) {
395 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
397 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
398 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
399 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
406 Enable the FIS running for giving port.
408 @param PciIo The PCI IO protocol instance.
409 @param Port The number of port.
410 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
412 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
413 @retval EFI_TIMEOUT The FIS enable setting is time out.
414 @retval EFI_SUCCESS The FIS enable successfully.
419 AhciEnableFisReceive (
420 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
427 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
428 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
430 return AhciWaitMmioSet (
433 EFI_AHCI_PORT_CMD_FR
,
434 EFI_AHCI_PORT_CMD_FR
,
440 Disable the FIS running for giving port.
442 @param PciIo The PCI IO protocol instance.
443 @param Port The number of port.
444 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
446 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
447 @retval EFI_TIMEOUT The FIS disable setting is time out.
448 @retval EFI_UNSUPPORTED The port is in running state.
449 @retval EFI_SUCCESS The FIS disable successfully.
454 AhciDisableFisReceive (
455 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
463 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
464 Data
= AhciReadReg (PciIo
, Offset
);
467 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
469 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
470 return EFI_UNSUPPORTED
;
474 // Check if the Fis receive DMA engine for the port is running.
476 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
480 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
482 return AhciWaitMmioSet (
485 EFI_AHCI_PORT_CMD_FR
,
494 Build the command list, command table and prepare the fis receiver.
496 @param PciIo The PCI IO protocol instance.
497 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
498 @param Port The number of port.
499 @param PortMultiplier The timeout value of stop.
500 @param CommandFis The control fis will be used for the transfer.
501 @param CommandList The command list will be used for the transfer.
502 @param AtapiCommand The atapi command will be used for the transfer.
503 @param AtapiCommandLength The length of the atapi command.
504 @param CommandSlotNumber The command slot will be used for the transfer.
505 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
506 @param DataLength The data count to be transferred.
512 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
513 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
515 IN UINT8 PortMultiplier
,
516 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
517 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
518 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
519 IN UINT8 AtapiCommandLength
,
520 IN UINT8 CommandSlotNumber
,
521 IN OUT VOID
*DataPhysicalAddr
,
536 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
539 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
540 // It also limits that the maximum amount of the PRDT entry in the command table
543 ASSERT (PrdtNumber
<= 65535);
545 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
547 BaseAddr
= Data64
.Uint64
;
549 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
551 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
553 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
555 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
557 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
558 if (AtapiCommand
!= NULL
) {
560 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
565 CommandList
->AhciCmdA
= 1;
566 CommandList
->AhciCmdP
= 1;
568 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
570 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
573 RemainedData
= (UINTN
) DataLength
;
574 MemAddr
= (UINTN
) DataPhysicalAddr
;
575 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
577 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
578 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
579 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
581 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
584 Data64
.Uint64
= (UINT64
)MemAddr
;
585 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
586 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
587 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
588 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
592 // Set the last PRDT to Interrupt On Complete
594 if (PrdtNumber
> 0) {
595 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
599 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
601 sizeof (EFI_AHCI_COMMAND_LIST
)
604 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
605 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
606 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
607 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
614 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
615 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
620 AhciBuildCommandFis (
621 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
622 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
625 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
627 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
629 // Indicator it's a command
631 CmdFis
->AhciCFisCmdInd
= 0x1;
632 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
634 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
635 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
637 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
638 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
640 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
641 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
643 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
644 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
646 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
647 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
649 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
653 Start a PIO data transfer on specific port.
655 @param[in] PciIo The PCI IO protocol instance.
656 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
657 @param[in] Port The number of port.
658 @param[in] PortMultiplier The timeout value of stop.
659 @param[in] AtapiCommand The atapi command will be used for the
661 @param[in] AtapiCommandLength The length of the atapi command.
662 @param[in] Read The transfer direction.
663 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
664 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
665 @param[in, out] MemoryAddr The pointer to the data buffer.
666 @param[in] DataCount The data count to be transferred.
667 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
668 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
669 used by non-blocking mode.
671 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
672 @retval EFI_TIMEOUT The operation is time out.
673 @retval EFI_UNSUPPORTED The device is not ready for transfer.
674 @retval EFI_SUCCESS The PIO data transfer executes successfully.
680 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
681 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
683 IN UINT8 PortMultiplier
,
684 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
685 IN UINT8 AtapiCommandLength
,
687 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
688 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
689 IN OUT VOID
*MemoryAddr
,
692 IN ATA_NONBLOCK_TASK
*Task
698 EFI_PHYSICAL_ADDRESS PhyAddr
;
701 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
703 EFI_AHCI_COMMAND_FIS CFis
;
704 EFI_AHCI_COMMAND_LIST CmdList
;
707 BOOLEAN InfiniteWait
;
708 BOOLEAN PioFisReceived
;
709 BOOLEAN D2hFisReceived
;
714 InfiniteWait
= FALSE
;
718 Flag
= EfiPciIoOperationBusMasterWrite
;
720 Flag
= EfiPciIoOperationBusMasterRead
;
724 // construct command list and command table with pci bus address
726 MapLength
= DataCount
;
727 Status
= PciIo
->Map (
736 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
737 return EFI_BAD_BUFFER_SIZE
;
741 // Package read needed
743 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
745 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
747 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
748 CmdList
.AhciCmdW
= Read
? 0 : 1;
760 (VOID
*)(UINTN
)PhyAddr
,
764 Status
= AhciStartCommand (
770 if (EFI_ERROR (Status
)) {
775 // Check the status and wait the driver sending data
777 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
779 if (Read
&& (AtapiCommand
== 0)) {
781 // Wait device sends the PIO setup fis before data transfer
783 Status
= EFI_TIMEOUT
;
784 Delay
= DivU64x32 (Timeout
, 1000) + 1;
786 PioFisReceived
= FALSE
;
787 D2hFisReceived
= FALSE
;
788 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
789 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, NULL
);
790 if (!EFI_ERROR (Status
)) {
791 PioFisReceived
= TRUE
;
794 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
795 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
796 // after the transaction is finished successfully.
797 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
798 // By this way, we can know if there is a real error happened.
800 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
801 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
802 if (!EFI_ERROR (Status
)) {
803 D2hFisReceived
= TRUE
;
806 if (PioFisReceived
|| D2hFisReceived
) {
807 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
808 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
810 // PxTFD will be updated if there is a D2H or SetupFIS received.
812 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
813 Status
= EFI_DEVICE_ERROR
;
817 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
818 if (PrdCount
== DataCount
) {
819 Status
= EFI_SUCCESS
;
825 // Stall for 100 microseconds.
827 MicroSecondDelay(100);
831 Status
= EFI_TIMEOUT
;
833 } while (InfiniteWait
|| (Delay
> 0));
836 // Wait for D2H Fis is received
838 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
839 Status
= AhciWaitMemSet (
841 EFI_AHCI_FIS_TYPE_MASK
,
842 EFI_AHCI_FIS_REGISTER_D2H
,
846 if (EFI_ERROR (Status
)) {
850 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
851 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
852 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
853 Status
= EFI_DEVICE_ERROR
;
864 AhciDisableFisReceive (
875 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
881 Start a DMA data transfer on specific port
883 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
884 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
885 @param[in] Port The number of port.
886 @param[in] PortMultiplier The timeout value of stop.
887 @param[in] AtapiCommand The atapi command will be used for the
889 @param[in] AtapiCommandLength The length of the atapi command.
890 @param[in] Read The transfer direction.
891 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
892 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
893 @param[in, out] MemoryAddr The pointer to the data buffer.
894 @param[in] DataCount The data count to be transferred.
895 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
896 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
897 used by non-blocking mode.
899 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
900 @retval EFI_TIMEOUT The operation is time out.
901 @retval EFI_UNSUPPORTED The device is not ready for transfer.
902 @retval EFI_SUCCESS The DMA data transfer executes successfully.
908 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
909 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
911 IN UINT8 PortMultiplier
,
912 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
913 IN UINT8 AtapiCommandLength
,
915 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
916 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
917 IN OUT VOID
*MemoryAddr
,
920 IN ATA_NONBLOCK_TASK
*Task
925 EFI_PHYSICAL_ADDRESS PhyAddr
;
928 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
929 EFI_AHCI_COMMAND_FIS CFis
;
930 EFI_AHCI_COMMAND_LIST CmdList
;
934 EFI_PCI_IO_PROTOCOL
*PciIo
;
938 PciIo
= Instance
->PciIo
;
941 return EFI_INVALID_PARAMETER
;
945 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
947 // Delay 100us to simulate the blocking time out checking.
949 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
950 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
951 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
955 MicroSecondDelay (100);
957 gBS
->RestoreTPL (OldTpl
);
959 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
961 // Mark the Task to indicate that it has been started.
964 Task
->IsStart
= TRUE
;
967 Flag
= EfiPciIoOperationBusMasterWrite
;
969 Flag
= EfiPciIoOperationBusMasterRead
;
973 // Construct command list and command table with pci bus address.
975 MapLength
= DataCount
;
976 Status
= PciIo
->Map (
985 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
986 return EFI_BAD_BUFFER_SIZE
;
993 // Package read needed
995 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
997 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
999 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1000 CmdList
.AhciCmdW
= Read
? 0 : 1;
1012 (VOID
*)(UINTN
)PhyAddr
,
1016 Status
= AhciStartCommand (
1022 if (EFI_ERROR (Status
)) {
1028 // Wait for command compelte
1030 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1031 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1036 Status
= AhciCheckMemSet (
1038 EFI_AHCI_FIS_TYPE_MASK
,
1039 EFI_AHCI_FIS_REGISTER_D2H
,
1043 Status
= AhciWaitMemSet (
1045 EFI_AHCI_FIS_TYPE_MASK
,
1046 EFI_AHCI_FIS_REGISTER_D2H
,
1051 if (EFI_ERROR (Status
)) {
1055 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1056 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1057 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1058 Status
= EFI_DEVICE_ERROR
;
1063 // For Blocking mode, the command should be stopped, the Fis should be disabled
1064 // and the PciIo should be unmapped.
1065 // For non-blocking mode, only when a error is happened (if the return status is
1066 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1067 // context cleanup, then set the packet's Asb status.
1070 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1078 AhciDisableFisReceive (
1086 (Task
!= NULL
) ? Task
->Map
: Map
1090 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1094 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1099 Start a non data transfer on specific port.
1101 @param[in] PciIo The PCI IO protocol instance.
1102 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1103 @param[in] Port The number of port.
1104 @param[in] PortMultiplier The timeout value of stop.
1105 @param[in] AtapiCommand The atapi command will be used for the
1107 @param[in] AtapiCommandLength The length of the atapi command.
1108 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1109 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1110 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1111 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1112 used by non-blocking mode.
1114 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1115 @retval EFI_TIMEOUT The operation is time out.
1116 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1117 @retval EFI_SUCCESS The non data transfer executes successfully.
1122 AhciNonDataTransfer (
1123 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1124 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1126 IN UINT8 PortMultiplier
,
1127 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1128 IN UINT8 AtapiCommandLength
,
1129 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1130 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1132 IN ATA_NONBLOCK_TASK
*Task
1139 EFI_AHCI_COMMAND_FIS CFis
;
1140 EFI_AHCI_COMMAND_LIST CmdList
;
1143 // Package read needed
1145 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1147 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1149 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1165 Status
= AhciStartCommand (
1171 if (EFI_ERROR (Status
)) {
1176 // Wait device sends the Response Fis
1178 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1179 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1180 Status
= AhciWaitMemSet (
1182 EFI_AHCI_FIS_TYPE_MASK
,
1183 EFI_AHCI_FIS_REGISTER_D2H
,
1187 if (EFI_ERROR (Status
)) {
1191 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1192 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1193 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1194 Status
= EFI_DEVICE_ERROR
;
1204 AhciDisableFisReceive (
1210 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1216 Stop command running for giving port
1218 @param PciIo The PCI IO protocol instance.
1219 @param Port The number of port.
1220 @param Timeout The timeout value of stop, uses 100ns as a unit.
1222 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1223 @retval EFI_TIMEOUT The operation is time out.
1224 @retval EFI_SUCCESS The command stop successfully.
1230 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1238 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1239 Data
= AhciReadReg (PciIo
, Offset
);
1241 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1245 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1246 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1249 return AhciWaitMmioSet (
1252 EFI_AHCI_PORT_CMD_CR
,
1259 Start command for give slot on specific port.
1261 @param PciIo The PCI IO protocol instance.
1262 @param Port The number of port.
1263 @param CommandSlot The number of Command Slot.
1264 @param Timeout The timeout value of start, uses 100ns as a unit.
1266 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1267 @retval EFI_TIMEOUT The operation is time out.
1268 @retval EFI_SUCCESS The command start successfully.
1274 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1276 IN UINT8 CommandSlot
,
1289 // Collect AHCI controller information
1291 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1293 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1295 AhciClearPortStatus (
1300 Status
= AhciEnableFisReceive (
1306 if (EFI_ERROR (Status
)) {
1310 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1311 PortStatus
= AhciReadReg (PciIo
, Offset
);
1314 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1315 StartCmd
= AhciReadReg (PciIo
, Offset
);
1316 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1317 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1320 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1321 PortTfd
= AhciReadReg (PciIo
, Offset
);
1323 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1324 if ((Capability
& BIT24
) != 0) {
1325 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1326 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1331 EFI_AHCI_PORT_CMD_CLO
,
1338 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1339 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1342 // Setting the command
1344 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1345 AhciAndReg (PciIo
, Offset
, 0);
1346 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1354 @param PciIo The PCI IO protocol instance.
1355 @param Port The number of port.
1356 @param Timeout The timeout value of reset, uses 100ns as a unit.
1358 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1359 @retval EFI_TIMEOUT The reset operation is time out.
1360 @retval EFI_SUCCESS The port reset successfully.
1366 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1374 AhciClearPortStatus (PciIo
, Port
);
1376 AhciStopCommand (PciIo
, Port
, Timeout
);
1378 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1380 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1382 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1384 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1387 // wait 5 millisecond before de-assert DET
1389 MicroSecondDelay (5000);
1391 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1394 // wait 5 millisecond before de-assert DET
1396 MicroSecondDelay (5000);
1399 // Wait for communication to be re-established
1401 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1402 Status
= AhciWaitMmioSet (
1405 EFI_AHCI_PORT_SSTS_DET_MASK
,
1406 EFI_AHCI_PORT_SSTS_DET_PCE
,
1410 if (EFI_ERROR (Status
)) {
1411 DEBUG ((EFI_D_ERROR
, "Port %d COMRESET failed: %r\n", Port
, Status
));
1415 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1416 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1424 @param PciIo The PCI IO protocol instance.
1425 @param Timeout The timeout value of reset, uses 100ns as a unit.
1427 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1428 @retval EFI_TIMEOUT The reset operation is time out.
1429 @retval EFI_SUCCESS AHCI controller is reset successfully.
1435 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1444 // Collect AHCI controller information
1446 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1449 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1451 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
1452 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1455 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1457 Delay
= DivU64x32(Timeout
, 1000) + 1;
1460 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1462 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1467 // Stall for 100 microseconds.
1469 MicroSecondDelay(100);
1472 } while (Delay
> 0);
1482 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1484 @param PciIo The PCI IO protocol instance.
1485 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1486 @param Port The number of port.
1487 @param PortMultiplier The timeout value of stop.
1488 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1490 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1491 @retval Others Fail to get return status data.
1496 AhciAtaSmartReturnStatusCheck (
1497 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1498 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1500 IN UINT8 PortMultiplier
,
1501 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1505 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1511 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1513 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1514 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1515 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1516 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1519 // Send S.M.A.R.T Read Return Status command to device
1521 Status
= AhciNonDataTransfer (
1525 (UINT8
)PortMultiplier
,
1534 if (EFI_ERROR (Status
)) {
1535 REPORT_STATUS_CODE (
1536 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1537 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1539 return EFI_DEVICE_ERROR
;
1542 REPORT_STATUS_CODE (
1544 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1547 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1549 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1551 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1552 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1553 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1555 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1557 // The threshold exceeded condition is not detected by the device
1559 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1560 REPORT_STATUS_CODE (
1562 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1564 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1566 // The threshold exceeded condition is detected by the device
1568 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1569 REPORT_STATUS_CODE (
1571 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1580 Enable SMART command of the disk if supported.
1582 @param PciIo The PCI IO protocol instance.
1583 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1584 @param Port The number of port.
1585 @param PortMultiplier The timeout value of stop.
1586 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1587 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1592 AhciAtaSmartSupport (
1593 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1594 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1596 IN UINT8 PortMultiplier
,
1597 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1598 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1602 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1605 // Detect if the device supports S.M.A.R.T.
1607 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1609 // S.M.A.R.T is not supported by the device
1611 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1612 Port
, PortMultiplier
));
1613 REPORT_STATUS_CODE (
1614 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1615 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1619 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1621 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1623 REPORT_STATUS_CODE (
1625 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1628 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1630 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1631 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1632 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1633 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1636 // Send S.M.A.R.T Enable command to device
1638 Status
= AhciNonDataTransfer (
1642 (UINT8
)PortMultiplier
,
1652 if (!EFI_ERROR (Status
)) {
1654 // Send S.M.A.R.T AutoSave command to device
1656 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1658 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1659 AtaCommandBlock
.AtaFeatures
= 0xD2;
1660 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1661 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1662 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1664 Status
= AhciNonDataTransfer (
1668 (UINT8
)PortMultiplier
,
1677 if (!EFI_ERROR (Status
)) {
1678 Status
= AhciAtaSmartReturnStatusCheck (
1682 (UINT8
)PortMultiplier
,
1688 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1689 Port
, PortMultiplier
));
1696 Send Buffer cmd to specific device.
1698 @param PciIo The PCI IO protocol instance.
1699 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1700 @param Port The number of port.
1701 @param PortMultiplier The timeout value of stop.
1702 @param Buffer The data buffer to store IDENTIFY PACKET data.
1704 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1705 @retval EFI_TIMEOUT The operation is time out.
1706 @retval EFI_UNSUPPORTED The device is not ready for executing.
1707 @retval EFI_SUCCESS The cmd executes successfully.
1713 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1714 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1716 IN UINT8 PortMultiplier
,
1717 IN OUT EFI_IDENTIFY_DATA
*Buffer
1721 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1722 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1724 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1725 return EFI_INVALID_PARAMETER
;
1728 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1729 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1731 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1732 AtaCommandBlock
.AtaSectorCount
= 1;
1734 Status
= AhciPioTransfer (
1745 sizeof (EFI_IDENTIFY_DATA
),
1754 Send Buffer cmd to specific device.
1756 @param PciIo The PCI IO protocol instance.
1757 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1758 @param Port The number of port.
1759 @param PortMultiplier The timeout value of stop.
1760 @param Buffer The data buffer to store IDENTIFY PACKET data.
1762 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1763 @retval EFI_TIMEOUT The operation is time out.
1764 @retval EFI_UNSUPPORTED The device is not ready for executing.
1765 @retval EFI_SUCCESS The cmd executes successfully.
1770 AhciIdentifyPacket (
1771 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1772 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1774 IN UINT8 PortMultiplier
,
1775 IN OUT EFI_IDENTIFY_DATA
*Buffer
1779 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1780 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1782 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1783 return EFI_INVALID_PARAMETER
;
1786 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1787 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1789 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1790 AtaCommandBlock
.AtaSectorCount
= 1;
1792 Status
= AhciPioTransfer (
1803 sizeof (EFI_IDENTIFY_DATA
),
1812 Send SET FEATURE cmd on specific device.
1814 @param PciIo The PCI IO protocol instance.
1815 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1816 @param Port The number of port.
1817 @param PortMultiplier The timeout value of stop.
1818 @param Feature The data to send Feature register.
1819 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1821 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1822 @retval EFI_TIMEOUT The operation is time out.
1823 @retval EFI_UNSUPPORTED The device is not ready for executing.
1824 @retval EFI_SUCCESS The cmd executes successfully.
1829 AhciDeviceSetFeature (
1830 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1831 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1833 IN UINT8 PortMultiplier
,
1835 IN UINT32 FeatureSpecificData
1839 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1840 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1842 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1843 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1845 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1846 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1847 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1848 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1849 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1850 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1851 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1853 Status
= AhciNonDataTransfer (
1857 (UINT8
)PortMultiplier
,
1870 This function is used to send out ATAPI commands conforms to the Packet Command
1873 @param PciIo The PCI IO protocol instance.
1874 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1875 @param Port The number of port.
1876 @param PortMultiplier The number of port multiplier.
1877 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1879 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1880 and device sends data successfully.
1881 @retval EFI_DEVICE_ERROR the device failed to send data.
1886 AhciPacketCommandExecute (
1887 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1888 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1890 IN UINT8 PortMultiplier
,
1891 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1897 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1898 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1901 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1902 return EFI_INVALID_PARAMETER
;
1905 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1906 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1907 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1911 AtaCommandBlock
.AtaFeatures
= 0x00;
1913 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1914 // determine how many data should be transferred.
1916 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1917 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1919 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1920 Buffer
= Packet
->InDataBuffer
;
1921 Length
= Packet
->InTransferLength
;
1924 Buffer
= Packet
->OutDataBuffer
;
1925 Length
= Packet
->OutTransferLength
;
1930 Status
= AhciNonDataTransfer (
1943 Status
= AhciPioTransfer (
1963 Allocate transfer-related data struct which is used at AHCI mode.
1965 @param PciIo The PCI IO protocol instance.
1966 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1971 AhciCreateTransferDescriptor (
1972 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1973 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1981 UINT32 PortImplementBitMap
;
1982 UINT8 MaxPortNumber
;
1983 UINT8 MaxCommandSlotNumber
;
1984 BOOLEAN Support64Bit
;
1985 UINT64 MaxReceiveFisSize
;
1986 UINT64 MaxCommandListSize
;
1987 UINT64 MaxCommandTableSize
;
1988 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1989 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1990 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1994 // Collect AHCI controller information
1996 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1998 // Get the number of command slots per port supported by this HBA.
2000 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2001 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2003 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2005 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
2007 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2008 if (MaxPortNumber
== 0) {
2009 return EFI_DEVICE_ERROR
;
2012 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2013 Status
= PciIo
->AllocateBuffer (
2016 EfiBootServicesData
,
2017 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2022 if (EFI_ERROR (Status
)) {
2023 return EFI_OUT_OF_RESOURCES
;
2026 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2028 AhciRegisters
->AhciRFis
= Buffer
;
2029 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2030 Bytes
= (UINTN
)MaxReceiveFisSize
;
2032 Status
= PciIo
->Map (
2034 EfiPciIoOperationBusMasterCommonBuffer
,
2038 &AhciRegisters
->MapRFis
2041 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2043 // Map error or unable to map the whole RFis buffer into a contiguous region.
2045 Status
= EFI_OUT_OF_RESOURCES
;
2049 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2051 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2053 Status
= EFI_DEVICE_ERROR
;
2056 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2059 // Allocate memory for command list
2060 // Note that the implemenation is a single task model which only use a command list for all ports.
2063 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2064 Status
= PciIo
->AllocateBuffer (
2067 EfiBootServicesData
,
2068 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2073 if (EFI_ERROR (Status
)) {
2075 // Free mapped resource.
2077 Status
= EFI_OUT_OF_RESOURCES
;
2081 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2083 AhciRegisters
->AhciCmdList
= Buffer
;
2084 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2085 Bytes
= (UINTN
)MaxCommandListSize
;
2087 Status
= PciIo
->Map (
2089 EfiPciIoOperationBusMasterCommonBuffer
,
2092 &AhciCmdListPciAddr
,
2093 &AhciRegisters
->MapCmdList
2096 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2098 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2100 Status
= EFI_OUT_OF_RESOURCES
;
2104 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2106 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2108 Status
= EFI_DEVICE_ERROR
;
2111 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2114 // Allocate memory for command table
2115 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2118 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2120 Status
= PciIo
->AllocateBuffer (
2123 EfiBootServicesData
,
2124 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2129 if (EFI_ERROR (Status
)) {
2131 // Free mapped resource.
2133 Status
= EFI_OUT_OF_RESOURCES
;
2137 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2139 AhciRegisters
->AhciCommandTable
= Buffer
;
2140 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2141 Bytes
= (UINTN
)MaxCommandTableSize
;
2143 Status
= PciIo
->Map (
2145 EfiPciIoOperationBusMasterCommonBuffer
,
2148 &AhciCommandTablePciAddr
,
2149 &AhciRegisters
->MapCommandTable
2152 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2154 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2156 Status
= EFI_OUT_OF_RESOURCES
;
2160 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2162 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2164 Status
= EFI_DEVICE_ERROR
;
2167 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2171 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2176 AhciRegisters
->MapCommandTable
2181 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2182 AhciRegisters
->AhciCommandTable
2187 AhciRegisters
->MapCmdList
2192 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2193 AhciRegisters
->AhciCmdList
2198 AhciRegisters
->MapRFis
2203 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2204 AhciRegisters
->AhciRFis
2211 Initialize ATA host controller at AHCI mode.
2213 The function is designed to initialize ATA host controller.
2215 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2220 AhciModeInitialization (
2221 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2225 EFI_PCI_IO_PROTOCOL
*PciIo
;
2226 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2228 UINT8 MaxPortNumber
;
2229 UINT32 PortImplementBitMap
;
2231 EFI_AHCI_REGISTERS
*AhciRegisters
;
2237 EFI_IDENTIFY_DATA Buffer
;
2238 EFI_ATA_DEVICE_TYPE DeviceType
;
2239 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2240 EFI_ATA_TRANSFER_MODE TransferMode
;
2241 UINT32 PhyDetectDelay
;
2243 if (Instance
== NULL
) {
2244 return EFI_INVALID_PARAMETER
;
2247 PciIo
= Instance
->PciIo
;
2248 IdeInit
= Instance
->IdeControllerInit
;
2250 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2252 if (EFI_ERROR (Status
)) {
2253 return EFI_DEVICE_ERROR
;
2257 // Collect AHCI controller information
2259 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2262 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
2264 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
2265 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2269 // Get the number of command slots per port supported by this HBA.
2271 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2274 // Get the bit map of those ports exposed by this HBA.
2275 // It indicates which ports that the HBA supports are available for software to use.
2277 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2279 AhciRegisters
= &Instance
->AhciRegisters
;
2280 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2282 if (EFI_ERROR (Status
)) {
2283 return EFI_OUT_OF_RESOURCES
;
2286 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2287 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2289 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2291 if ((MaxPortNumber
--) == 0) {
2293 // Should never be here.
2299 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2302 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2304 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2305 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2306 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2307 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2308 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2310 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2311 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2312 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2313 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2314 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2316 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2317 Data
= AhciReadReg (PciIo
, Offset
);
2318 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2319 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2322 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2323 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2327 // Disable aggressive power management.
2329 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2330 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2332 // Disable the reporting of the corresponding interrupt to system software.
2334 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2335 AhciAndReg (PciIo
, Offset
, 0);
2338 // Now inform the IDE Controller Init Module.
2340 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2343 // Enable FIS Receive DMA engine for the first D2H FIS.
2345 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2346 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2347 Status
= AhciWaitMmioSet (
2350 EFI_AHCI_PORT_CMD_FR
,
2351 EFI_AHCI_PORT_CMD_FR
,
2352 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2354 if (EFI_ERROR (Status
)) {
2359 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2360 // It's the requirment from SATA1.0a spec section 5.2.
2362 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2363 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2365 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2366 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2370 MicroSecondDelay (1000);
2372 } while (PhyDetectDelay
> 0);
2374 if (PhyDetectDelay
== 0) {
2376 // No device detected at this port.
2377 // Clear PxCMD.SUD for those ports at which there are no device present.
2379 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2380 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2385 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2386 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2388 PhyDetectDelay
= 16 * 1000;
2390 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2391 if (AhciReadReg(PciIo
, Offset
) != 0) {
2392 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2394 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2396 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2401 MicroSecondDelay (1000);
2403 } while (PhyDetectDelay
> 0);
2405 if (PhyDetectDelay
== 0) {
2406 DEBUG ((EFI_D_ERROR
, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port
, Data
));
2411 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2413 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2414 Status
= AhciWaitMmioSet (
2419 EFI_TIMER_PERIOD_SECONDS(16)
2421 if (EFI_ERROR (Status
)) {
2425 Data
= AhciReadReg (PciIo
, Offset
);
2426 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2427 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2429 if (EFI_ERROR (Status
)) {
2433 DeviceType
= EfiIdeCdrom
;
2434 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2435 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2437 if (EFI_ERROR (Status
)) {
2438 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2442 DeviceType
= EfiIdeHarddisk
;
2446 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2447 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2450 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2452 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2453 AhciAtaSmartSupport (
2464 // Submit identify data to IDE controller init driver
2466 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2469 // Now start to config ide device parameter and transfer mode.
2471 Status
= IdeInit
->CalculateMode (
2477 if (EFI_ERROR (Status
)) {
2478 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2483 // Set best supported PIO mode on this IDE device
2485 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2486 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2488 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2491 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2494 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2495 // be set together. Only one DMA mode can be set to a device. If setting
2496 // DMA mode operation fails, we can continue moving on because we only use
2497 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2499 if (SupportedModes
->UdmaMode
.Valid
) {
2500 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2501 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2502 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2503 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2504 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2507 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2508 if (EFI_ERROR (Status
)) {
2509 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2514 // Found a ATA or ATAPI device, add it into the device list.
2516 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2517 if (DeviceType
== EfiIdeHarddisk
) {
2518 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));