2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2016, 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
);
434 Disable the FIS running for giving port.
436 @param PciIo The PCI IO protocol instance.
437 @param Port The number of port.
438 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
440 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
441 @retval EFI_TIMEOUT The FIS disable setting is time out.
442 @retval EFI_UNSUPPORTED The port is in running state.
443 @retval EFI_SUCCESS The FIS disable successfully.
448 AhciDisableFisReceive (
449 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
457 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
458 Data
= AhciReadReg (PciIo
, Offset
);
461 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
463 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
464 return EFI_UNSUPPORTED
;
468 // Check if the Fis receive DMA engine for the port is running.
470 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
474 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
476 return AhciWaitMmioSet (
479 EFI_AHCI_PORT_CMD_FR
,
488 Build the command list, command table and prepare the fis receiver.
490 @param PciIo The PCI IO protocol instance.
491 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
492 @param Port The number of port.
493 @param PortMultiplier The timeout value of stop.
494 @param CommandFis The control fis will be used for the transfer.
495 @param CommandList The command list will be used for the transfer.
496 @param AtapiCommand The atapi command will be used for the transfer.
497 @param AtapiCommandLength The length of the atapi command.
498 @param CommandSlotNumber The command slot will be used for the transfer.
499 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
500 @param DataLength The data count to be transferred.
506 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
507 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
509 IN UINT8 PortMultiplier
,
510 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
511 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
512 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
513 IN UINT8 AtapiCommandLength
,
514 IN UINT8 CommandSlotNumber
,
515 IN OUT VOID
*DataPhysicalAddr
,
530 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
533 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
534 // It also limits that the maximum amount of the PRDT entry in the command table
537 ASSERT (PrdtNumber
<= 65535);
539 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
541 BaseAddr
= Data64
.Uint64
;
543 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
545 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
547 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
549 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
551 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
552 if (AtapiCommand
!= NULL
) {
554 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
559 CommandList
->AhciCmdA
= 1;
560 CommandList
->AhciCmdP
= 1;
562 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
564 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
567 RemainedData
= (UINTN
) DataLength
;
568 MemAddr
= (UINTN
) DataPhysicalAddr
;
569 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
571 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
572 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
573 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
575 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
578 Data64
.Uint64
= (UINT64
)MemAddr
;
579 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
580 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
581 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
582 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
586 // Set the last PRDT to Interrupt On Complete
588 if (PrdtNumber
> 0) {
589 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
593 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
595 sizeof (EFI_AHCI_COMMAND_LIST
)
598 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
599 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
600 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
601 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
608 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
609 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
614 AhciBuildCommandFis (
615 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
616 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
619 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
621 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
623 // Indicator it's a command
625 CmdFis
->AhciCFisCmdInd
= 0x1;
626 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
628 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
629 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
631 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
632 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
634 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
635 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
637 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
638 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
640 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
641 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
643 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
647 Start a PIO data transfer on specific port.
649 @param[in] PciIo The PCI IO protocol instance.
650 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
651 @param[in] Port The number of port.
652 @param[in] PortMultiplier The timeout value of stop.
653 @param[in] AtapiCommand The atapi command will be used for the
655 @param[in] AtapiCommandLength The length of the atapi command.
656 @param[in] Read The transfer direction.
657 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
658 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
659 @param[in, out] MemoryAddr The pointer to the data buffer.
660 @param[in] DataCount The data count to be transferred.
661 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
662 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
663 used by non-blocking mode.
665 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
666 @retval EFI_TIMEOUT The operation is time out.
667 @retval EFI_UNSUPPORTED The device is not ready for transfer.
668 @retval EFI_SUCCESS The PIO data transfer executes successfully.
674 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
675 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
677 IN UINT8 PortMultiplier
,
678 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
679 IN UINT8 AtapiCommandLength
,
681 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
682 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
683 IN OUT VOID
*MemoryAddr
,
686 IN ATA_NONBLOCK_TASK
*Task
692 EFI_PHYSICAL_ADDRESS PhyAddr
;
695 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
697 EFI_AHCI_COMMAND_FIS CFis
;
698 EFI_AHCI_COMMAND_LIST CmdList
;
701 BOOLEAN InfiniteWait
;
702 BOOLEAN PioFisReceived
;
703 BOOLEAN D2hFisReceived
;
708 InfiniteWait
= FALSE
;
712 Flag
= EfiPciIoOperationBusMasterWrite
;
714 Flag
= EfiPciIoOperationBusMasterRead
;
718 // construct command list and command table with pci bus address
720 MapLength
= DataCount
;
721 Status
= PciIo
->Map (
730 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
731 return EFI_BAD_BUFFER_SIZE
;
735 // Package read needed
737 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
739 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
741 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
742 CmdList
.AhciCmdW
= Read
? 0 : 1;
754 (VOID
*)(UINTN
)PhyAddr
,
758 Status
= AhciStartCommand (
764 if (EFI_ERROR (Status
)) {
769 // Check the status and wait the driver sending data
771 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
773 if (Read
&& (AtapiCommand
== 0)) {
775 // Wait device sends the PIO setup fis before data transfer
777 Status
= EFI_TIMEOUT
;
778 Delay
= DivU64x32 (Timeout
, 1000) + 1;
780 PioFisReceived
= FALSE
;
781 D2hFisReceived
= FALSE
;
782 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
783 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, NULL
);
784 if (!EFI_ERROR (Status
)) {
785 PioFisReceived
= TRUE
;
788 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
789 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
790 // after the transaction is finished successfully.
791 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
792 // By this way, we can know if there is a real error happened.
794 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
795 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
796 if (!EFI_ERROR (Status
)) {
797 D2hFisReceived
= TRUE
;
800 if (PioFisReceived
|| D2hFisReceived
) {
801 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
802 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
804 // PxTFD will be updated if there is a D2H or SetupFIS received.
806 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
807 Status
= EFI_DEVICE_ERROR
;
811 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
812 if (PrdCount
== DataCount
) {
813 Status
= EFI_SUCCESS
;
819 // Stall for 100 microseconds.
821 MicroSecondDelay(100);
825 Status
= EFI_TIMEOUT
;
827 } while (InfiniteWait
|| (Delay
> 0));
830 // Wait for D2H Fis is received
832 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
833 Status
= AhciWaitMemSet (
835 EFI_AHCI_FIS_TYPE_MASK
,
836 EFI_AHCI_FIS_REGISTER_D2H
,
840 if (EFI_ERROR (Status
)) {
844 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
845 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
846 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
847 Status
= EFI_DEVICE_ERROR
;
858 AhciDisableFisReceive (
869 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
875 Start a DMA data transfer on specific port
877 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
878 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
879 @param[in] Port The number of port.
880 @param[in] PortMultiplier The timeout value of stop.
881 @param[in] AtapiCommand The atapi command will be used for the
883 @param[in] AtapiCommandLength The length of the atapi command.
884 @param[in] Read The transfer direction.
885 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
886 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
887 @param[in, out] MemoryAddr The pointer to the data buffer.
888 @param[in] DataCount The data count to be transferred.
889 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
890 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
891 used by non-blocking mode.
893 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
894 @retval EFI_TIMEOUT The operation is time out.
895 @retval EFI_UNSUPPORTED The device is not ready for transfer.
896 @retval EFI_SUCCESS The DMA data transfer executes successfully.
902 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
903 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
905 IN UINT8 PortMultiplier
,
906 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
907 IN UINT8 AtapiCommandLength
,
909 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
910 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
911 IN OUT VOID
*MemoryAddr
,
914 IN ATA_NONBLOCK_TASK
*Task
919 EFI_PHYSICAL_ADDRESS PhyAddr
;
922 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
923 EFI_AHCI_COMMAND_FIS CFis
;
924 EFI_AHCI_COMMAND_LIST CmdList
;
928 EFI_PCI_IO_PROTOCOL
*PciIo
;
932 PciIo
= Instance
->PciIo
;
935 return EFI_INVALID_PARAMETER
;
939 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
941 // Delay 100us to simulate the blocking time out checking.
943 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
944 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
945 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
949 MicroSecondDelay (100);
951 gBS
->RestoreTPL (OldTpl
);
953 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
955 // Mark the Task to indicate that it has been started.
958 Task
->IsStart
= TRUE
;
961 Flag
= EfiPciIoOperationBusMasterWrite
;
963 Flag
= EfiPciIoOperationBusMasterRead
;
967 // Construct command list and command table with pci bus address.
969 MapLength
= DataCount
;
970 Status
= PciIo
->Map (
979 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
980 return EFI_BAD_BUFFER_SIZE
;
987 // Package read needed
989 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
991 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
993 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
994 CmdList
.AhciCmdW
= Read
? 0 : 1;
1006 (VOID
*)(UINTN
)PhyAddr
,
1010 Status
= AhciStartCommand (
1016 if (EFI_ERROR (Status
)) {
1022 // Wait for command compelte
1024 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1025 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1030 Status
= AhciCheckMemSet (
1032 EFI_AHCI_FIS_TYPE_MASK
,
1033 EFI_AHCI_FIS_REGISTER_D2H
,
1037 Status
= AhciWaitMemSet (
1039 EFI_AHCI_FIS_TYPE_MASK
,
1040 EFI_AHCI_FIS_REGISTER_D2H
,
1045 if (EFI_ERROR (Status
)) {
1049 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1050 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1051 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1052 Status
= EFI_DEVICE_ERROR
;
1057 // For Blocking mode, the command should be stopped, the Fis should be disabled
1058 // and the PciIo should be unmapped.
1059 // For non-blocking mode, only when a error is happened (if the return status is
1060 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1061 // context cleanup, then set the packet's Asb status.
1064 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1072 AhciDisableFisReceive (
1080 (Task
!= NULL
) ? Task
->Map
: Map
1084 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1088 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1093 Start a non data transfer on specific port.
1095 @param[in] PciIo The PCI IO protocol instance.
1096 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1097 @param[in] Port The number of port.
1098 @param[in] PortMultiplier The timeout value of stop.
1099 @param[in] AtapiCommand The atapi command will be used for the
1101 @param[in] AtapiCommandLength The length of the atapi command.
1102 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1103 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1104 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1105 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1106 used by non-blocking mode.
1108 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1109 @retval EFI_TIMEOUT The operation is time out.
1110 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1111 @retval EFI_SUCCESS The non data transfer executes successfully.
1116 AhciNonDataTransfer (
1117 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1118 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1120 IN UINT8 PortMultiplier
,
1121 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1122 IN UINT8 AtapiCommandLength
,
1123 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1124 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1126 IN ATA_NONBLOCK_TASK
*Task
1133 EFI_AHCI_COMMAND_FIS CFis
;
1134 EFI_AHCI_COMMAND_LIST CmdList
;
1137 // Package read needed
1139 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1141 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1143 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1159 Status
= AhciStartCommand (
1165 if (EFI_ERROR (Status
)) {
1170 // Wait device sends the Response Fis
1172 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1173 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1174 Status
= AhciWaitMemSet (
1176 EFI_AHCI_FIS_TYPE_MASK
,
1177 EFI_AHCI_FIS_REGISTER_D2H
,
1181 if (EFI_ERROR (Status
)) {
1185 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1186 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1187 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1188 Status
= EFI_DEVICE_ERROR
;
1198 AhciDisableFisReceive (
1204 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1210 Stop command running for giving port
1212 @param PciIo The PCI IO protocol instance.
1213 @param Port The number of port.
1214 @param Timeout The timeout value of stop, uses 100ns as a unit.
1216 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1217 @retval EFI_TIMEOUT The operation is time out.
1218 @retval EFI_SUCCESS The command stop successfully.
1224 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1232 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1233 Data
= AhciReadReg (PciIo
, Offset
);
1235 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1239 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1240 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1243 return AhciWaitMmioSet (
1246 EFI_AHCI_PORT_CMD_CR
,
1253 Start command for give slot on specific port.
1255 @param PciIo The PCI IO protocol instance.
1256 @param Port The number of port.
1257 @param CommandSlot The number of Command Slot.
1258 @param Timeout The timeout value of start, uses 100ns as a unit.
1260 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1261 @retval EFI_TIMEOUT The operation is time out.
1262 @retval EFI_SUCCESS The command start successfully.
1268 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1270 IN UINT8 CommandSlot
,
1283 // Collect AHCI controller information
1285 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1287 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1289 AhciClearPortStatus (
1294 Status
= AhciEnableFisReceive (
1300 if (EFI_ERROR (Status
)) {
1304 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1305 PortStatus
= AhciReadReg (PciIo
, Offset
);
1308 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1309 StartCmd
= AhciReadReg (PciIo
, Offset
);
1310 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1311 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1314 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1315 PortTfd
= AhciReadReg (PciIo
, Offset
);
1317 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1318 if ((Capability
& BIT24
) != 0) {
1319 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1320 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1325 EFI_AHCI_PORT_CMD_CLO
,
1332 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1333 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1336 // Setting the command
1338 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1339 AhciAndReg (PciIo
, Offset
, 0);
1340 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1348 @param PciIo The PCI IO protocol instance.
1349 @param Port The number of port.
1350 @param Timeout The timeout value of reset, uses 100ns as a unit.
1352 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1353 @retval EFI_TIMEOUT The reset operation is time out.
1354 @retval EFI_SUCCESS The port reset successfully.
1360 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1368 AhciClearPortStatus (PciIo
, Port
);
1370 AhciStopCommand (PciIo
, Port
, Timeout
);
1372 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1374 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1376 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1378 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1381 // wait 5 millisecond before de-assert DET
1383 MicroSecondDelay (5000);
1385 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1388 // wait 5 millisecond before de-assert DET
1390 MicroSecondDelay (5000);
1393 // Wait for communication to be re-established
1395 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1396 Status
= AhciWaitMmioSet (
1399 EFI_AHCI_PORT_SSTS_DET_MASK
,
1400 EFI_AHCI_PORT_SSTS_DET_PCE
,
1404 if (EFI_ERROR (Status
)) {
1405 DEBUG ((EFI_D_ERROR
, "Port %d COMRESET failed: %r\n", Port
, Status
));
1409 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1410 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1418 @param PciIo The PCI IO protocol instance.
1419 @param Timeout The timeout value of reset, uses 100ns as a unit.
1421 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1422 @retval EFI_TIMEOUT The reset operation is time out.
1423 @retval EFI_SUCCESS AHCI controller is reset successfully.
1429 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1438 // Collect AHCI controller information
1440 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1443 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1445 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
1446 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1449 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1451 Delay
= DivU64x32(Timeout
, 1000) + 1;
1454 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1456 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1461 // Stall for 100 microseconds.
1463 MicroSecondDelay(100);
1466 } while (Delay
> 0);
1476 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1478 @param PciIo The PCI IO protocol instance.
1479 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1480 @param Port The number of port.
1481 @param PortMultiplier The port multiplier port number.
1482 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1484 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1485 @retval Others Fail to get return status data.
1490 AhciAtaSmartReturnStatusCheck (
1491 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1492 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1494 IN UINT8 PortMultiplier
,
1495 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1499 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1505 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1507 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1508 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1509 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1510 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1513 // Send S.M.A.R.T Read Return Status command to device
1515 Status
= AhciNonDataTransfer (
1519 (UINT8
)PortMultiplier
,
1528 if (EFI_ERROR (Status
)) {
1529 REPORT_STATUS_CODE (
1530 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1531 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1533 return EFI_DEVICE_ERROR
;
1536 REPORT_STATUS_CODE (
1538 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1541 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1543 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1545 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1546 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1547 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1549 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1551 // The threshold exceeded condition is not detected by the device
1553 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1554 REPORT_STATUS_CODE (
1556 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1558 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1560 // The threshold exceeded condition is detected by the device
1562 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1563 REPORT_STATUS_CODE (
1565 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1574 Enable SMART command of the disk if supported.
1576 @param PciIo The PCI IO protocol instance.
1577 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1578 @param Port The number of port.
1579 @param PortMultiplier The port multiplier port number.
1580 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1581 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1586 AhciAtaSmartSupport (
1587 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1588 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1590 IN UINT8 PortMultiplier
,
1591 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1592 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1596 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1599 // Detect if the device supports S.M.A.R.T.
1601 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1603 // S.M.A.R.T is not supported by the device
1605 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1606 Port
, PortMultiplier
));
1607 REPORT_STATUS_CODE (
1608 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1609 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1613 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1615 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1617 REPORT_STATUS_CODE (
1619 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1622 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1624 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1625 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1626 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1627 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1630 // Send S.M.A.R.T Enable command to device
1632 Status
= AhciNonDataTransfer (
1636 (UINT8
)PortMultiplier
,
1646 if (!EFI_ERROR (Status
)) {
1648 // Send S.M.A.R.T AutoSave command to device
1650 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1652 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1653 AtaCommandBlock
.AtaFeatures
= 0xD2;
1654 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1655 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1656 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1658 Status
= AhciNonDataTransfer (
1662 (UINT8
)PortMultiplier
,
1671 if (!EFI_ERROR (Status
)) {
1672 Status
= AhciAtaSmartReturnStatusCheck (
1676 (UINT8
)PortMultiplier
,
1682 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1683 Port
, PortMultiplier
));
1690 Send Buffer cmd to specific device.
1692 @param PciIo The PCI IO protocol instance.
1693 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1694 @param Port The number of port.
1695 @param PortMultiplier The port multiplier port number.
1696 @param Buffer The data buffer to store IDENTIFY PACKET data.
1698 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1699 @retval EFI_TIMEOUT The operation is time out.
1700 @retval EFI_UNSUPPORTED The device is not ready for executing.
1701 @retval EFI_SUCCESS The cmd executes successfully.
1707 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1708 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1710 IN UINT8 PortMultiplier
,
1711 IN OUT EFI_IDENTIFY_DATA
*Buffer
1715 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1716 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1718 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1719 return EFI_INVALID_PARAMETER
;
1722 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1723 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1725 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1726 AtaCommandBlock
.AtaSectorCount
= 1;
1728 Status
= AhciPioTransfer (
1739 sizeof (EFI_IDENTIFY_DATA
),
1748 Send Buffer cmd to specific device.
1750 @param PciIo The PCI IO protocol instance.
1751 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1752 @param Port The number of port.
1753 @param PortMultiplier The port multiplier port number.
1754 @param Buffer The data buffer to store IDENTIFY PACKET data.
1756 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1757 @retval EFI_TIMEOUT The operation is time out.
1758 @retval EFI_UNSUPPORTED The device is not ready for executing.
1759 @retval EFI_SUCCESS The cmd executes successfully.
1764 AhciIdentifyPacket (
1765 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1766 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1768 IN UINT8 PortMultiplier
,
1769 IN OUT EFI_IDENTIFY_DATA
*Buffer
1773 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1774 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1776 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1777 return EFI_INVALID_PARAMETER
;
1780 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1781 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1783 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1784 AtaCommandBlock
.AtaSectorCount
= 1;
1786 Status
= AhciPioTransfer (
1797 sizeof (EFI_IDENTIFY_DATA
),
1806 Send SET FEATURE cmd on specific device.
1808 @param PciIo The PCI IO protocol instance.
1809 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1810 @param Port The number of port.
1811 @param PortMultiplier The port multiplier port number.
1812 @param Feature The data to send Feature register.
1813 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1815 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1816 @retval EFI_TIMEOUT The operation is time out.
1817 @retval EFI_UNSUPPORTED The device is not ready for executing.
1818 @retval EFI_SUCCESS The cmd executes successfully.
1823 AhciDeviceSetFeature (
1824 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1825 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1827 IN UINT8 PortMultiplier
,
1829 IN UINT32 FeatureSpecificData
1833 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1834 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1836 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1837 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1839 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1840 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1841 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1842 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1843 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1844 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1845 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1847 Status
= AhciNonDataTransfer (
1851 (UINT8
)PortMultiplier
,
1864 This function is used to send out ATAPI commands conforms to the Packet Command
1867 @param PciIo The PCI IO protocol instance.
1868 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1869 @param Port The number of port.
1870 @param PortMultiplier The number of port multiplier.
1871 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1873 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1874 and device sends data successfully.
1875 @retval EFI_DEVICE_ERROR the device failed to send data.
1880 AhciPacketCommandExecute (
1881 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1882 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1884 IN UINT8 PortMultiplier
,
1885 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1891 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1892 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1895 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1896 return EFI_INVALID_PARAMETER
;
1899 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1900 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1901 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1905 AtaCommandBlock
.AtaFeatures
= 0x00;
1907 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1908 // determine how many data should be transferred.
1910 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1911 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1913 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1914 Buffer
= Packet
->InDataBuffer
;
1915 Length
= Packet
->InTransferLength
;
1918 Buffer
= Packet
->OutDataBuffer
;
1919 Length
= Packet
->OutTransferLength
;
1924 Status
= AhciNonDataTransfer (
1937 Status
= AhciPioTransfer (
1957 Allocate transfer-related data struct which is used at AHCI mode.
1959 @param PciIo The PCI IO protocol instance.
1960 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1965 AhciCreateTransferDescriptor (
1966 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1967 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1975 UINT32 PortImplementBitMap
;
1976 UINT8 MaxPortNumber
;
1977 UINT8 MaxCommandSlotNumber
;
1978 BOOLEAN Support64Bit
;
1979 UINT64 MaxReceiveFisSize
;
1980 UINT64 MaxCommandListSize
;
1981 UINT64 MaxCommandTableSize
;
1982 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1983 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1984 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1988 // Collect AHCI controller information
1990 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1992 // Get the number of command slots per port supported by this HBA.
1994 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1995 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1997 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
1999 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
2001 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2002 if (MaxPortNumber
== 0) {
2003 return EFI_DEVICE_ERROR
;
2006 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2007 Status
= PciIo
->AllocateBuffer (
2010 EfiBootServicesData
,
2011 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2016 if (EFI_ERROR (Status
)) {
2017 return EFI_OUT_OF_RESOURCES
;
2020 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2022 AhciRegisters
->AhciRFis
= Buffer
;
2023 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2024 Bytes
= (UINTN
)MaxReceiveFisSize
;
2026 Status
= PciIo
->Map (
2028 EfiPciIoOperationBusMasterCommonBuffer
,
2032 &AhciRegisters
->MapRFis
2035 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2037 // Map error or unable to map the whole RFis buffer into a contiguous region.
2039 Status
= EFI_OUT_OF_RESOURCES
;
2043 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2045 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2047 Status
= EFI_DEVICE_ERROR
;
2050 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2053 // Allocate memory for command list
2054 // Note that the implemenation is a single task model which only use a command list for all ports.
2057 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2058 Status
= PciIo
->AllocateBuffer (
2061 EfiBootServicesData
,
2062 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2067 if (EFI_ERROR (Status
)) {
2069 // Free mapped resource.
2071 Status
= EFI_OUT_OF_RESOURCES
;
2075 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2077 AhciRegisters
->AhciCmdList
= Buffer
;
2078 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2079 Bytes
= (UINTN
)MaxCommandListSize
;
2081 Status
= PciIo
->Map (
2083 EfiPciIoOperationBusMasterCommonBuffer
,
2086 &AhciCmdListPciAddr
,
2087 &AhciRegisters
->MapCmdList
2090 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2092 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2094 Status
= EFI_OUT_OF_RESOURCES
;
2098 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2100 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2102 Status
= EFI_DEVICE_ERROR
;
2105 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2108 // Allocate memory for command table
2109 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2112 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2114 Status
= PciIo
->AllocateBuffer (
2117 EfiBootServicesData
,
2118 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2123 if (EFI_ERROR (Status
)) {
2125 // Free mapped resource.
2127 Status
= EFI_OUT_OF_RESOURCES
;
2131 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2133 AhciRegisters
->AhciCommandTable
= Buffer
;
2134 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2135 Bytes
= (UINTN
)MaxCommandTableSize
;
2137 Status
= PciIo
->Map (
2139 EfiPciIoOperationBusMasterCommonBuffer
,
2142 &AhciCommandTablePciAddr
,
2143 &AhciRegisters
->MapCommandTable
2146 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2148 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2150 Status
= EFI_OUT_OF_RESOURCES
;
2154 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2156 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2158 Status
= EFI_DEVICE_ERROR
;
2161 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2165 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2170 AhciRegisters
->MapCommandTable
2175 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2176 AhciRegisters
->AhciCommandTable
2181 AhciRegisters
->MapCmdList
2186 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2187 AhciRegisters
->AhciCmdList
2192 AhciRegisters
->MapRFis
2197 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2198 AhciRegisters
->AhciRFis
2205 Initialize ATA host controller at AHCI mode.
2207 The function is designed to initialize ATA host controller.
2209 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2214 AhciModeInitialization (
2215 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2219 EFI_PCI_IO_PROTOCOL
*PciIo
;
2220 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2222 UINT8 MaxPortNumber
;
2223 UINT32 PortImplementBitMap
;
2225 EFI_AHCI_REGISTERS
*AhciRegisters
;
2231 EFI_IDENTIFY_DATA Buffer
;
2232 EFI_ATA_DEVICE_TYPE DeviceType
;
2233 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2234 EFI_ATA_TRANSFER_MODE TransferMode
;
2235 UINT32 PhyDetectDelay
;
2237 if (Instance
== NULL
) {
2238 return EFI_INVALID_PARAMETER
;
2241 PciIo
= Instance
->PciIo
;
2242 IdeInit
= Instance
->IdeControllerInit
;
2244 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2246 if (EFI_ERROR (Status
)) {
2247 return EFI_DEVICE_ERROR
;
2251 // Collect AHCI controller information
2253 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2256 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
2258 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
2259 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2263 // Enable 64-bit DMA support in the PCI layer if this controller
2266 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2267 Status
= PciIo
->Attributes (
2269 EfiPciIoAttributeOperationEnable
,
2270 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2273 if (EFI_ERROR (Status
)) {
2275 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2281 // Get the number of command slots per port supported by this HBA.
2283 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2286 // Get the bit map of those ports exposed by this HBA.
2287 // It indicates which ports that the HBA supports are available for software to use.
2289 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2291 AhciRegisters
= &Instance
->AhciRegisters
;
2292 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2294 if (EFI_ERROR (Status
)) {
2295 return EFI_OUT_OF_RESOURCES
;
2298 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2299 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2301 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2303 if ((MaxPortNumber
--) == 0) {
2305 // Should never be here.
2311 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2314 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2316 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2317 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2318 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2319 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2320 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2322 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2323 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2324 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2325 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2326 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2328 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2329 Data
= AhciReadReg (PciIo
, Offset
);
2330 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2331 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2334 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2335 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2339 // Disable aggressive power management.
2341 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2342 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2344 // Disable the reporting of the corresponding interrupt to system software.
2346 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2347 AhciAndReg (PciIo
, Offset
, 0);
2350 // Now inform the IDE Controller Init Module.
2352 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2355 // Enable FIS Receive DMA engine for the first D2H FIS.
2357 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2358 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2361 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2362 // It's the requirment from SATA1.0a spec section 5.2.
2364 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2365 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2367 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2368 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2372 MicroSecondDelay (1000);
2374 } while (PhyDetectDelay
> 0);
2376 if (PhyDetectDelay
== 0) {
2378 // No device detected at this port.
2379 // Clear PxCMD.SUD for those ports at which there are no device present.
2381 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2382 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2387 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2388 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2390 PhyDetectDelay
= 16 * 1000;
2392 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2393 if (AhciReadReg(PciIo
, Offset
) != 0) {
2394 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2396 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2398 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2403 MicroSecondDelay (1000);
2405 } while (PhyDetectDelay
> 0);
2407 if (PhyDetectDelay
== 0) {
2408 DEBUG ((EFI_D_ERROR
, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port
, Data
));
2413 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2415 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2416 Status
= AhciWaitMmioSet (
2421 EFI_TIMER_PERIOD_SECONDS(16)
2423 if (EFI_ERROR (Status
)) {
2427 Data
= AhciReadReg (PciIo
, Offset
);
2428 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2429 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2431 if (EFI_ERROR (Status
)) {
2435 DeviceType
= EfiIdeCdrom
;
2436 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2437 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2439 if (EFI_ERROR (Status
)) {
2440 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2444 DeviceType
= EfiIdeHarddisk
;
2448 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2449 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2452 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2454 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2455 AhciAtaSmartSupport (
2466 // Submit identify data to IDE controller init driver
2468 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2471 // Now start to config ide device parameter and transfer mode.
2473 Status
= IdeInit
->CalculateMode (
2479 if (EFI_ERROR (Status
)) {
2480 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2485 // Set best supported PIO mode on this IDE device
2487 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2488 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2490 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2493 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2496 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2497 // be set together. Only one DMA mode can be set to a device. If setting
2498 // DMA mode operation fails, we can continue moving on because we only use
2499 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2501 if (SupportedModes
->UdmaMode
.Valid
) {
2502 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2503 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2504 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2505 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2506 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2509 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2510 if (EFI_ERROR (Status
)) {
2511 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2516 // Found a ATA or ATAPI device, add it into the device list.
2518 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
2519 if (DeviceType
== EfiIdeHarddisk
) {
2520 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));