2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "AtaAtapiPassThru.h"
13 Read AHCI Operation register.
15 @param PciIo The PCI IO protocol instance.
16 @param Offset The operation register offset.
18 @return The register content read.
24 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
30 ASSERT (PciIo
!= NULL
);
47 Write AHCI Operation register.
49 @param PciIo The PCI IO protocol instance.
50 @param Offset The operation register offset.
51 @param Data The data used to write down.
57 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
62 ASSERT (PciIo
!= NULL
);
77 Do AND operation with the value of AHCI Operation register.
79 @param PciIo The PCI IO protocol instance.
80 @param Offset The operation register offset.
81 @param AndData The data used to do AND operation.
87 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
94 ASSERT (PciIo
!= NULL
);
96 Data
= AhciReadReg (PciIo
, Offset
);
100 AhciWriteReg (PciIo
, Offset
, Data
);
104 Do OR operation with the value of AHCI Operation register.
106 @param PciIo The PCI IO protocol instance.
107 @param Offset The operation register offset.
108 @param OrData The data used to do OR operation.
114 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
121 ASSERT (PciIo
!= NULL
);
123 Data
= AhciReadReg (PciIo
, Offset
);
127 AhciWriteReg (PciIo
, Offset
, Data
);
131 Wait for the value of the specified MMIO register set to the test value.
133 @param PciIo The PCI IO protocol instance.
134 @param Offset The MMIO address to test.
135 @param MaskValue The mask value of memory.
136 @param TestValue The test value of memory.
137 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
139 @retval EFI_TIMEOUT The MMIO setting is time out.
140 @retval EFI_SUCCESS The MMIO is correct set.
146 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
155 BOOLEAN InfiniteWait
;
160 InfiniteWait
= FALSE
;
163 Delay
= DivU64x32 (Timeout
, 1000) + 1;
167 // Access PCI MMIO space to see if the value is the tested one.
169 Value
= AhciReadReg (PciIo
, (UINT32
) Offset
) & MaskValue
;
171 if (Value
== TestValue
) {
176 // Stall for 100 microseconds.
178 MicroSecondDelay (100);
182 } while (InfiniteWait
|| (Delay
> 0));
188 Wait for the value of the specified system memory set to the test value.
190 @param Address The system memory address to test.
191 @param MaskValue The mask value of memory.
192 @param TestValue The test value of memory.
193 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
195 @retval EFI_TIMEOUT The system memory setting is time out.
196 @retval EFI_SUCCESS The system memory is correct set.
202 IN EFI_PHYSICAL_ADDRESS Address
,
210 BOOLEAN InfiniteWait
;
215 InfiniteWait
= FALSE
;
218 Delay
= DivU64x32 (Timeout
, 1000) + 1;
222 // Access system memory to see if the value is the tested one.
224 // The system memory pointed by Address will be updated by the
225 // SATA Host Controller, "volatile" is introduced to prevent
226 // compiler from optimizing the access to the memory address
227 // to only read once.
229 Value
= *(volatile UINT32
*) (UINTN
) Address
;
232 if (Value
== TestValue
) {
237 // Stall for 100 microseconds.
239 MicroSecondDelay (100);
243 } while (InfiniteWait
|| (Delay
> 0));
249 Check the memory status to the test value.
251 @param[in] Address The memory address to test.
252 @param[in] MaskValue The mask value of memory.
253 @param[in] TestValue The test value of memory.
255 @retval EFI_NOT_READY The memory is not set.
256 @retval EFI_SUCCESS The memory is correct set.
268 Value
= *(volatile UINT32
*) Address
;
271 if (Value
== TestValue
) {
275 return EFI_NOT_READY
;
281 Clear the port interrupt and error status. It will also clear
282 HBA interrupt status.
284 @param PciIo The PCI IO protocol instance.
285 @param Port The number of port.
290 AhciClearPortStatus (
291 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
298 // Clear any error status
300 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
301 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
304 // Clear any port interrupt status
306 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
307 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
310 // Clear any HBA interrupt status
312 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
316 This function is used to dump the Status Registers and if there is ERR bit set
317 in the Status Register, the Error Register's value is also be dumped.
319 @param PciIo The PCI IO protocol instance.
320 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
321 @param Port The number of port.
322 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
328 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
329 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
331 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
339 ASSERT (PciIo
!= NULL
);
341 if (AtaStatusBlock
!= NULL
) {
342 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
344 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
345 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
347 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
);
348 if (!EFI_ERROR (Status
)) {
350 // If D2H FIS is received, update StatusBlock with its content.
352 CopyMem (AtaStatusBlock
, (UINT8
*)Offset
, sizeof (EFI_ATA_STATUS_BLOCK
));
355 // If D2H FIS is not received, only update Status & Error field through PxTFD
356 // as there is no other way to get the content of the Shadow Register Block.
358 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
359 Data
= AhciReadReg (PciIo
, (UINT32
)Offset
);
361 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
362 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
363 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
371 Enable the FIS running for giving port.
373 @param PciIo The PCI IO protocol instance.
374 @param Port The number of port.
375 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
377 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
378 @retval EFI_TIMEOUT The FIS enable setting is time out.
379 @retval EFI_SUCCESS The FIS enable successfully.
384 AhciEnableFisReceive (
385 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
392 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
393 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
399 Disable the FIS running for giving port.
401 @param PciIo The PCI IO protocol instance.
402 @param Port The number of port.
403 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
405 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
406 @retval EFI_TIMEOUT The FIS disable setting is time out.
407 @retval EFI_UNSUPPORTED The port is in running state.
408 @retval EFI_SUCCESS The FIS disable successfully.
413 AhciDisableFisReceive (
414 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
422 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
423 Data
= AhciReadReg (PciIo
, Offset
);
426 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
428 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
429 return EFI_UNSUPPORTED
;
433 // Check if the Fis receive DMA engine for the port is running.
435 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
439 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
441 return AhciWaitMmioSet (
444 EFI_AHCI_PORT_CMD_FR
,
453 Build the command list, command table and prepare the fis receiver.
455 @param PciIo The PCI IO protocol instance.
456 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
457 @param Port The number of port.
458 @param PortMultiplier The timeout value of stop.
459 @param CommandFis The control fis will be used for the transfer.
460 @param CommandList The command list will be used for the transfer.
461 @param AtapiCommand The atapi command will be used for the transfer.
462 @param AtapiCommandLength The length of the atapi command.
463 @param CommandSlotNumber The command slot will be used for the transfer.
464 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
465 @param DataLength The data count to be transferred.
471 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
472 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
474 IN UINT8 PortMultiplier
,
475 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
476 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
477 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
478 IN UINT8 AtapiCommandLength
,
479 IN UINT8 CommandSlotNumber
,
480 IN OUT VOID
*DataPhysicalAddr
,
495 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
498 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
499 // It also limits that the maximum amount of the PRDT entry in the command table
502 ASSERT (PrdtNumber
<= 65535);
504 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
506 BaseAddr
= Data64
.Uint64
;
508 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
510 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
512 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
514 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
516 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
517 if (AtapiCommand
!= NULL
) {
519 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
524 CommandList
->AhciCmdA
= 1;
525 CommandList
->AhciCmdP
= 1;
527 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
529 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
532 RemainedData
= (UINTN
) DataLength
;
533 MemAddr
= (UINTN
) DataPhysicalAddr
;
534 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
536 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
537 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
538 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
540 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
543 Data64
.Uint64
= (UINT64
)MemAddr
;
544 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
545 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
546 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
547 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
551 // Set the last PRDT to Interrupt On Complete
553 if (PrdtNumber
> 0) {
554 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
558 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
560 sizeof (EFI_AHCI_COMMAND_LIST
)
563 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
564 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
565 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
566 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
573 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
574 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
579 AhciBuildCommandFis (
580 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
581 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
584 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
586 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
588 // Indicator it's a command
590 CmdFis
->AhciCFisCmdInd
= 0x1;
591 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
593 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
594 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
596 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
597 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
599 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
600 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
602 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
603 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
605 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
606 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
608 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
612 Wait until SATA device reports it is ready for operation.
614 @param[in] PciIo Pointer to AHCI controller PciIo.
615 @param[in] Port SATA port index on which to reset.
617 @retval EFI_SUCCESS Device ready for operation.
618 @retval EFI_TIMEOUT Device failed to get ready within required period.
621 AhciWaitDeviceReady (
622 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
626 UINT32 PhyDetectDelay
;
631 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
632 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
634 PhyDetectDelay
= 16 * 1000;
636 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
637 if (AhciReadReg(PciIo
, Offset
) != 0) {
638 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
640 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
642 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
647 MicroSecondDelay (1000);
649 } while (PhyDetectDelay
> 0);
651 if (PhyDetectDelay
== 0) {
652 DEBUG ((DEBUG_ERROR
, "Port %d Device not ready (TFD=0x%X)\n", Port
, Data
));
661 Reset the SATA port. Algorithm follows AHCI spec 1.3.1 section 10.4.2
663 @param[in] PciIo Pointer to AHCI controller PciIo.
664 @param[in] Port SATA port index on which to reset.
666 @retval EFI_SUCCESS Port reset.
667 @retval Others Failed to reset the port.
671 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
678 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
679 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
681 // SW is required to keep DET set to 0x1 at least for 1 milisecond to ensure that
682 // at least one COMRESET signal is sent.
684 MicroSecondDelay(1000);
685 AhciAndReg (PciIo
, Offset
, ~(UINT32
)EFI_AHCI_PORT_SSTS_DET_MASK
);
687 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
688 Status
= AhciWaitMmioSet (PciIo
, Offset
, EFI_AHCI_PORT_SSTS_DET_MASK
, EFI_AHCI_PORT_SSTS_DET_PCE
, ATA_ATAPI_TIMEOUT
);
689 if (EFI_ERROR (Status
)) {
693 return AhciWaitDeviceReady (PciIo
, Port
);
697 Recovers the SATA port from error condition.
698 This function implements algorithm described in
699 AHCI spec 1.3.1 section 6.2.2
701 @param[in] PciIo Pointer to AHCI controller PciIo.
702 @param[in] Port SATA port index on which to check.
704 @retval EFI_SUCCESS Port recovered.
705 @retval Others Failed to recover port.
708 AhciRecoverPortError (
709 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
714 UINT32 PortInterrupt
;
718 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
719 PortInterrupt
= AhciReadReg (PciIo
, Offset
);
720 if ((PortInterrupt
& EFI_AHCI_PORT_IS_FATAL_ERROR_MASK
) == 0) {
722 // No fatal error detected. Exit with success as port should still be operational.
723 // No need to clear IS as it will be cleared when the next command starts.
728 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
729 AhciAndReg (PciIo
, Offset
, ~(UINT32
)EFI_AHCI_PORT_CMD_ST
);
731 Status
= AhciWaitMmioSet (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CR
, 0, ATA_ATAPI_TIMEOUT
);
732 if (EFI_ERROR (Status
)) {
733 DEBUG ((DEBUG_ERROR
, "Ahci port %d is in hung state, aborting recovery\n", Port
));
738 // If TFD.BSY or TFD.DRQ is still set it means that drive is hung and software has
739 // to reset it before sending any additional commands.
741 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
742 PortTfd
= AhciReadReg (PciIo
, Offset
);
743 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
744 Status
= AhciResetPort (PciIo
, Port
);
745 if (EFI_ERROR (Status
)) {
746 DEBUG ((DEBUG_ERROR
, "Failed to reset the port %d\n", Port
));
754 Checks if specified FIS has been received.
756 @param[in] PciIo Pointer to AHCI controller PciIo.
757 @param[in] Port SATA port index on which to check.
758 @param[in] FisType FIS type for which to check.
760 @retval EFI_SUCCESS FIS received.
761 @retval EFI_NOT_READY FIS not received yet.
762 @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
765 AhciCheckFisReceived (
766 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
768 IN SATA_FIS_TYPE FisType
772 UINT32 PortInterrupt
;
775 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
776 PortInterrupt
= AhciReadReg (PciIo
, Offset
);
777 if ((PortInterrupt
& EFI_AHCI_PORT_IS_ERROR_MASK
) != 0) {
778 DEBUG ((DEBUG_ERROR
, "AHCI: Error interrupt reported PxIS: %X\n", PortInterrupt
));
779 return EFI_DEVICE_ERROR
;
782 // For PIO setup FIS - According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
783 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
784 // after the transaction is finished successfully.
785 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
786 // By this way, we can know if there is a real error happened.
788 if (((FisType
== SataFisD2H
) && ((PortInterrupt
& EFI_AHCI_PORT_IS_DHRS
) != 0)) ||
789 ((FisType
== SataFisPioSetup
) && (PortInterrupt
& (EFI_AHCI_PORT_IS_PSS
| EFI_AHCI_PORT_IS_DHRS
)) != 0) ||
790 ((FisType
== SataFisDmaSetup
) && (PortInterrupt
& (EFI_AHCI_PORT_IS_DSS
| EFI_AHCI_PORT_IS_DHRS
)) != 0)) {
791 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
792 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
793 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
794 return EFI_DEVICE_ERROR
;
800 return EFI_NOT_READY
;
804 Waits until specified FIS has been received.
806 @param[in] PciIo Pointer to AHCI controller PciIo.
807 @param[in] Port SATA port index on which to check.
808 @param[in] Timeout Time after which function should stop polling.
809 @param[in] FisType FIS type for which to check.
811 @retval EFI_SUCCESS FIS received.
812 @retval EFI_TIMEOUT FIS failed to arrive within a specified time period.
813 @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
816 AhciWaitUntilFisReceived (
817 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
820 IN SATA_FIS_TYPE FisType
824 BOOLEAN InfiniteWait
;
827 Delay
= DivU64x32 (Timeout
, 1000) + 1;
831 InfiniteWait
= FALSE
;
835 Status
= AhciCheckFisReceived (PciIo
, Port
, FisType
);
836 if (Status
!= EFI_NOT_READY
) {
840 // Stall for 100 microseconds.
842 MicroSecondDelay (100);
844 } while (InfiniteWait
|| (Delay
> 0));
850 Start a PIO data transfer on specific port.
852 @param[in] PciIo The PCI IO protocol instance.
853 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
854 @param[in] Port The number of port.
855 @param[in] PortMultiplier The timeout value of stop.
856 @param[in] AtapiCommand The atapi command will be used for the
858 @param[in] AtapiCommandLength The length of the atapi command.
859 @param[in] Read The transfer direction.
860 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
861 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
862 @param[in, out] MemoryAddr The pointer to the data buffer.
863 @param[in] DataCount The data count to be transferred.
864 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
865 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
866 used by non-blocking mode.
868 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
869 @retval EFI_TIMEOUT The operation is time out.
870 @retval EFI_UNSUPPORTED The device is not ready for transfer.
871 @retval EFI_SUCCESS The PIO data transfer executes successfully.
877 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
878 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
880 IN UINT8 PortMultiplier
,
881 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
882 IN UINT8 AtapiCommandLength
,
884 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
885 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
886 IN OUT VOID
*MemoryAddr
,
889 IN ATA_NONBLOCK_TASK
*Task
893 EFI_PHYSICAL_ADDRESS PhyAddr
;
896 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
897 EFI_AHCI_COMMAND_FIS CFis
;
898 EFI_AHCI_COMMAND_LIST CmdList
;
903 Flag
= EfiPciIoOperationBusMasterWrite
;
905 Flag
= EfiPciIoOperationBusMasterRead
;
909 // construct command list and command table with pci bus address
911 MapLength
= DataCount
;
912 Status
= PciIo
->Map (
921 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
922 return EFI_BAD_BUFFER_SIZE
;
926 // Package read needed
928 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
930 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
932 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
933 CmdList
.AhciCmdW
= Read
? 0 : 1;
935 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
946 (VOID
*)(UINTN
)PhyAddr
,
950 Status
= AhciStartCommand (
956 if (EFI_ERROR (Status
)) {
960 if (Read
&& (AtapiCommand
== 0)) {
961 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisPioSetup
);
962 if (Status
== EFI_SUCCESS
) {
963 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
964 if (PrdCount
== DataCount
) {
965 Status
= EFI_SUCCESS
;
967 Status
= EFI_DEVICE_ERROR
;
971 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
974 if (Status
== EFI_DEVICE_ERROR
) {
975 DEBUG ((DEBUG_ERROR
, "PIO command failed at retry %d\n", Retry
));
976 Status
= AhciRecoverPortError (PciIo
, Port
);
977 if (EFI_ERROR (Status
)) {
991 AhciDisableFisReceive (
1002 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1007 Start a DMA data transfer on specific port
1009 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
1010 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1011 @param[in] Port The number of port.
1012 @param[in] PortMultiplier The timeout value of stop.
1013 @param[in] AtapiCommand The atapi command will be used for the
1015 @param[in] AtapiCommandLength The length of the atapi command.
1016 @param[in] Read The transfer direction.
1017 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1018 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1019 @param[in, out] MemoryAddr The pointer to the data buffer.
1020 @param[in] DataCount The data count to be transferred.
1021 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1022 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1023 used by non-blocking mode.
1025 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
1026 @retval EFI_TIMEOUT The operation is time out.
1027 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1028 @retval EFI_SUCCESS The DMA data transfer executes successfully.
1034 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
1035 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1037 IN UINT8 PortMultiplier
,
1038 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1039 IN UINT8 AtapiCommandLength
,
1041 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1042 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1043 IN OUT VOID
*MemoryAddr
,
1044 IN UINT32 DataCount
,
1046 IN ATA_NONBLOCK_TASK
*Task
1050 EFI_PHYSICAL_ADDRESS PhyAddr
;
1053 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
1054 EFI_AHCI_COMMAND_FIS CFis
;
1055 EFI_AHCI_COMMAND_LIST CmdList
;
1056 EFI_PCI_IO_PROTOCOL
*PciIo
;
1061 PciIo
= Instance
->PciIo
;
1063 if (PciIo
== NULL
) {
1064 return EFI_INVALID_PARAMETER
;
1068 // DMA buffer allocation. Needs to be done only once for both sync and async
1069 // DMA transfers irrespective of number of retries.
1071 if ((Task
== NULL
) || ((Task
!= NULL
) && (Task
->Map
== NULL
))) {
1073 Flag
= EfiPciIoOperationBusMasterWrite
;
1075 Flag
= EfiPciIoOperationBusMasterRead
;
1078 MapLength
= DataCount
;
1079 Status
= PciIo
->Map (
1088 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
1089 return EFI_BAD_BUFFER_SIZE
;
1096 if (Task
== NULL
|| (Task
!= NULL
&& !Task
->IsStart
)) {
1097 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1099 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1101 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1102 CmdList
.AhciCmdW
= Read
? 0 : 1;
1107 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
1109 // Delay 100us to simulate the blocking time out checking.
1111 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1112 while (!IsListEmpty (&Instance
->NonBlockingTaskList
)) {
1113 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
1117 MicroSecondDelay (100);
1119 gBS
->RestoreTPL (OldTpl
);
1120 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1131 (VOID
*)(UINTN
)PhyAddr
,
1135 Status
= AhciStartCommand (
1141 if (EFI_ERROR (Status
)) {
1144 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1145 if (Status
== EFI_DEVICE_ERROR
) {
1146 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Retry
));
1147 Status
= AhciRecoverPortError (PciIo
, Port
);
1148 if (EFI_ERROR (Status
)) {
1156 if (!Task
->IsStart
) {
1167 (VOID
*)(UINTN
)PhyAddr
,
1171 Status
= AhciStartCommand (
1177 if (!EFI_ERROR (Status
)) {
1178 Task
->IsStart
= TRUE
;
1181 if (Task
->IsStart
) {
1182 Status
= AhciCheckFisReceived (PciIo
, Port
, SataFisD2H
);
1183 if (Status
== EFI_DEVICE_ERROR
) {
1184 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Task
->RetryTimes
));
1185 Status
= AhciRecoverPortError (PciIo
, Port
);
1187 // If recovery passed mark the Task as not started and change the status
1188 // to EFI_NOT_READY. This will make the higher level call this function again
1189 // and on next call the command will be re-issued due to IsStart being FALSE.
1190 // This also makes the next condition decrement the RetryTimes.
1192 if (Status
== EFI_SUCCESS
) {
1193 Task
->IsStart
= FALSE
;
1194 Status
= EFI_NOT_READY
;
1198 if (Status
== EFI_NOT_READY
) {
1199 if (!Task
->InfiniteWait
&& Task
->RetryTimes
== 0) {
1200 Status
= EFI_TIMEOUT
;
1209 // For Blocking mode, the command should be stopped, the Fis should be disabled
1210 // and the PciIo should be unmapped.
1211 // For non-blocking mode, only when a error is happened (if the return status is
1212 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1213 // context cleanup, then set the packet's Asb status.
1216 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1224 AhciDisableFisReceive (
1232 (Task
!= NULL
) ? Task
->Map
: Map
1236 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1240 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1245 Start a non data transfer on specific port.
1247 @param[in] PciIo The PCI IO protocol instance.
1248 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1249 @param[in] Port The number of port.
1250 @param[in] PortMultiplier The timeout value of stop.
1251 @param[in] AtapiCommand The atapi command will be used for the
1253 @param[in] AtapiCommandLength The length of the atapi command.
1254 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1255 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1256 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1257 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1258 used by non-blocking mode.
1260 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1261 @retval EFI_TIMEOUT The operation is time out.
1262 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1263 @retval EFI_SUCCESS The non data transfer executes successfully.
1268 AhciNonDataTransfer (
1269 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1270 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1272 IN UINT8 PortMultiplier
,
1273 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1274 IN UINT8 AtapiCommandLength
,
1275 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1276 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1278 IN ATA_NONBLOCK_TASK
*Task
1282 EFI_AHCI_COMMAND_FIS CFis
;
1283 EFI_AHCI_COMMAND_LIST CmdList
;
1287 // Package read needed
1289 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1291 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1293 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1295 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1310 Status
= AhciStartCommand (
1316 if (EFI_ERROR (Status
)) {
1320 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1321 if (Status
== EFI_DEVICE_ERROR
) {
1322 DEBUG ((DEBUG_ERROR
, "Non data transfer failed at retry %d\n", Retry
));
1323 Status
= AhciRecoverPortError (PciIo
, Port
);
1324 if (EFI_ERROR (Status
)) {
1338 AhciDisableFisReceive (
1344 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1350 Stop command running for giving port
1352 @param PciIo The PCI IO protocol instance.
1353 @param Port The number of port.
1354 @param Timeout The timeout value of stop, uses 100ns as a unit.
1356 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1357 @retval EFI_TIMEOUT The operation is time out.
1358 @retval EFI_SUCCESS The command stop successfully.
1364 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1372 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1373 Data
= AhciReadReg (PciIo
, Offset
);
1375 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1379 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1380 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1383 return AhciWaitMmioSet (
1386 EFI_AHCI_PORT_CMD_CR
,
1393 Start command for give slot on specific port.
1395 @param PciIo The PCI IO protocol instance.
1396 @param Port The number of port.
1397 @param CommandSlot The number of Command Slot.
1398 @param Timeout The timeout value of start, uses 100ns as a unit.
1400 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1401 @retval EFI_TIMEOUT The operation is time out.
1402 @retval EFI_SUCCESS The command start successfully.
1408 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1410 IN UINT8 CommandSlot
,
1423 // Collect AHCI controller information
1425 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1427 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1429 AhciClearPortStatus (
1434 Status
= AhciEnableFisReceive (
1440 if (EFI_ERROR (Status
)) {
1444 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1445 PortStatus
= AhciReadReg (PciIo
, Offset
);
1448 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1449 StartCmd
= AhciReadReg (PciIo
, Offset
);
1450 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1451 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1454 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1455 PortTfd
= AhciReadReg (PciIo
, Offset
);
1457 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1458 if ((Capability
& BIT24
) != 0) {
1459 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1460 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1465 EFI_AHCI_PORT_CMD_CLO
,
1472 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1473 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1476 // Setting the command
1478 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1479 AhciAndReg (PciIo
, Offset
, 0);
1480 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1489 @param PciIo The PCI IO protocol instance.
1490 @param Timeout The timeout value of reset, uses 100ns as a unit.
1492 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1493 @retval EFI_TIMEOUT The reset operation is time out.
1494 @retval EFI_SUCCESS AHCI controller is reset successfully.
1500 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1508 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1510 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1512 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
1513 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1516 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1518 Delay
= DivU64x32(Timeout
, 1000) + 1;
1521 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1523 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1528 // Stall for 100 microseconds.
1530 MicroSecondDelay(100);
1533 } while (Delay
> 0);
1543 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1545 @param PciIo The PCI IO protocol instance.
1546 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1547 @param Port The number of port.
1548 @param PortMultiplier The port multiplier port number.
1549 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1551 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1552 @retval Others Fail to get return status data.
1557 AhciAtaSmartReturnStatusCheck (
1558 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1559 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1561 IN UINT8 PortMultiplier
,
1562 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1566 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1572 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1574 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1575 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1576 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1577 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1580 // Send S.M.A.R.T Read Return Status command to device
1582 Status
= AhciNonDataTransfer (
1586 (UINT8
)PortMultiplier
,
1595 if (EFI_ERROR (Status
)) {
1596 REPORT_STATUS_CODE (
1597 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1598 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1600 return EFI_DEVICE_ERROR
;
1603 REPORT_STATUS_CODE (
1605 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1608 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1610 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1612 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1613 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1614 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1616 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1618 // The threshold exceeded condition is not detected by the device
1620 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1621 REPORT_STATUS_CODE (
1623 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1625 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1627 // The threshold exceeded condition is detected by the device
1629 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1630 REPORT_STATUS_CODE (
1632 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1641 Enable SMART command of the disk if supported.
1643 @param PciIo The PCI IO protocol instance.
1644 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1645 @param Port The number of port.
1646 @param PortMultiplier The port multiplier port number.
1647 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1648 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1653 AhciAtaSmartSupport (
1654 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1655 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1657 IN UINT8 PortMultiplier
,
1658 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1659 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1663 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1666 // Detect if the device supports S.M.A.R.T.
1668 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1670 // S.M.A.R.T is not supported by the device
1672 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1673 Port
, PortMultiplier
));
1674 REPORT_STATUS_CODE (
1675 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1676 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1680 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1682 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1684 REPORT_STATUS_CODE (
1686 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1689 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1691 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1692 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1693 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1694 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1697 // Send S.M.A.R.T Enable command to device
1699 Status
= AhciNonDataTransfer (
1703 (UINT8
)PortMultiplier
,
1713 if (!EFI_ERROR (Status
)) {
1715 // Send S.M.A.R.T AutoSave command to device
1717 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1719 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1720 AtaCommandBlock
.AtaFeatures
= 0xD2;
1721 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1722 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1723 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1725 Status
= AhciNonDataTransfer (
1729 (UINT8
)PortMultiplier
,
1738 if (!EFI_ERROR (Status
)) {
1739 Status
= AhciAtaSmartReturnStatusCheck (
1743 (UINT8
)PortMultiplier
,
1749 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1750 Port
, PortMultiplier
));
1757 Send Buffer cmd to specific device.
1759 @param PciIo The PCI IO protocol instance.
1760 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1761 @param Port The number of port.
1762 @param PortMultiplier The port multiplier port number.
1763 @param Buffer The data buffer to store IDENTIFY PACKET data.
1765 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1766 @retval EFI_TIMEOUT The operation is time out.
1767 @retval EFI_UNSUPPORTED The device is not ready for executing.
1768 @retval EFI_SUCCESS The cmd executes successfully.
1774 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1775 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1777 IN UINT8 PortMultiplier
,
1778 IN OUT EFI_IDENTIFY_DATA
*Buffer
1782 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1783 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1785 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1786 return EFI_INVALID_PARAMETER
;
1789 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1790 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1792 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1793 AtaCommandBlock
.AtaSectorCount
= 1;
1795 Status
= AhciPioTransfer (
1806 sizeof (EFI_IDENTIFY_DATA
),
1815 Send Buffer cmd to specific device.
1817 @param PciIo The PCI IO protocol instance.
1818 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1819 @param Port The number of port.
1820 @param PortMultiplier The port multiplier port number.
1821 @param Buffer The data buffer to store IDENTIFY PACKET data.
1823 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1824 @retval EFI_TIMEOUT The operation is time out.
1825 @retval EFI_UNSUPPORTED The device is not ready for executing.
1826 @retval EFI_SUCCESS The cmd executes successfully.
1831 AhciIdentifyPacket (
1832 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1833 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1835 IN UINT8 PortMultiplier
,
1836 IN OUT EFI_IDENTIFY_DATA
*Buffer
1840 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1841 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1843 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1844 return EFI_INVALID_PARAMETER
;
1847 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1848 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1850 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1851 AtaCommandBlock
.AtaSectorCount
= 1;
1853 Status
= AhciPioTransfer (
1864 sizeof (EFI_IDENTIFY_DATA
),
1873 Send SET FEATURE cmd on specific device.
1875 @param PciIo The PCI IO protocol instance.
1876 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1877 @param Port The number of port.
1878 @param PortMultiplier The port multiplier port number.
1879 @param Feature The data to send Feature register.
1880 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1881 @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1883 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1884 @retval EFI_TIMEOUT The operation is time out.
1885 @retval EFI_UNSUPPORTED The device is not ready for executing.
1886 @retval EFI_SUCCESS The cmd executes successfully.
1891 AhciDeviceSetFeature (
1892 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1893 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1895 IN UINT8 PortMultiplier
,
1897 IN UINT32 FeatureSpecificData
,
1902 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1903 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1905 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1906 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1908 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1909 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1910 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1911 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1912 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1913 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1914 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1916 Status
= AhciNonDataTransfer (
1920 (UINT8
)PortMultiplier
,
1933 This function is used to send out ATAPI commands conforms to the Packet Command
1936 @param PciIo The PCI IO protocol instance.
1937 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1938 @param Port The number of port.
1939 @param PortMultiplier The number of port multiplier.
1940 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1942 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1943 and device sends data successfully.
1944 @retval EFI_DEVICE_ERROR the device failed to send data.
1949 AhciPacketCommandExecute (
1950 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1951 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1953 IN UINT8 PortMultiplier
,
1954 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1960 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1961 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1964 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1965 return EFI_INVALID_PARAMETER
;
1968 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1969 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1970 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1974 AtaCommandBlock
.AtaFeatures
= 0x00;
1976 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1977 // determine how many data should be transferred.
1979 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1980 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1982 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1983 Buffer
= Packet
->InDataBuffer
;
1984 Length
= Packet
->InTransferLength
;
1987 Buffer
= Packet
->OutDataBuffer
;
1988 Length
= Packet
->OutTransferLength
;
1993 Status
= AhciNonDataTransfer (
2006 Status
= AhciPioTransfer (
2026 Allocate transfer-related data struct which is used at AHCI mode.
2028 @param PciIo The PCI IO protocol instance.
2029 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2034 AhciCreateTransferDescriptor (
2035 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2036 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
2044 UINT32 PortImplementBitMap
;
2045 UINT8 MaxPortNumber
;
2046 UINT8 MaxCommandSlotNumber
;
2047 BOOLEAN Support64Bit
;
2048 UINT64 MaxReceiveFisSize
;
2049 UINT64 MaxCommandListSize
;
2050 UINT64 MaxCommandTableSize
;
2051 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
2052 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
2053 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
2057 // Collect AHCI controller information
2059 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2061 // Get the number of command slots per port supported by this HBA.
2063 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2064 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2066 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2068 // Get the highest bit of implemented ports which decides how many bytes are allocated for received FIS.
2070 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2071 if (MaxPortNumber
== 0) {
2072 return EFI_DEVICE_ERROR
;
2075 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2076 Status
= PciIo
->AllocateBuffer (
2079 EfiBootServicesData
,
2080 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2085 if (EFI_ERROR (Status
)) {
2086 return EFI_OUT_OF_RESOURCES
;
2089 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2091 AhciRegisters
->AhciRFis
= Buffer
;
2092 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2093 Bytes
= (UINTN
)MaxReceiveFisSize
;
2095 Status
= PciIo
->Map (
2097 EfiPciIoOperationBusMasterCommonBuffer
,
2101 &AhciRegisters
->MapRFis
2104 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2106 // Map error or unable to map the whole RFis buffer into a contiguous region.
2108 Status
= EFI_OUT_OF_RESOURCES
;
2112 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2114 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2116 Status
= EFI_DEVICE_ERROR
;
2119 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2122 // Allocate memory for command list
2123 // Note that the implementation is a single task model which only use a command list for all ports.
2126 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2127 Status
= PciIo
->AllocateBuffer (
2130 EfiBootServicesData
,
2131 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2136 if (EFI_ERROR (Status
)) {
2138 // Free mapped resource.
2140 Status
= EFI_OUT_OF_RESOURCES
;
2144 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2146 AhciRegisters
->AhciCmdList
= Buffer
;
2147 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2148 Bytes
= (UINTN
)MaxCommandListSize
;
2150 Status
= PciIo
->Map (
2152 EfiPciIoOperationBusMasterCommonBuffer
,
2155 &AhciCmdListPciAddr
,
2156 &AhciRegisters
->MapCmdList
2159 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2161 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2163 Status
= EFI_OUT_OF_RESOURCES
;
2167 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2169 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2171 Status
= EFI_DEVICE_ERROR
;
2174 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2177 // Allocate memory for command table
2178 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2181 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2183 Status
= PciIo
->AllocateBuffer (
2186 EfiBootServicesData
,
2187 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2192 if (EFI_ERROR (Status
)) {
2194 // Free mapped resource.
2196 Status
= EFI_OUT_OF_RESOURCES
;
2200 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2202 AhciRegisters
->AhciCommandTable
= Buffer
;
2203 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2204 Bytes
= (UINTN
)MaxCommandTableSize
;
2206 Status
= PciIo
->Map (
2208 EfiPciIoOperationBusMasterCommonBuffer
,
2211 &AhciCommandTablePciAddr
,
2212 &AhciRegisters
->MapCommandTable
2215 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2217 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2219 Status
= EFI_OUT_OF_RESOURCES
;
2223 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2225 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2227 Status
= EFI_DEVICE_ERROR
;
2230 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2234 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2239 AhciRegisters
->MapCommandTable
2244 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2245 AhciRegisters
->AhciCommandTable
2250 AhciRegisters
->MapCmdList
2255 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2256 AhciRegisters
->AhciCmdList
2261 AhciRegisters
->MapRFis
2266 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2267 AhciRegisters
->AhciRFis
2274 Read logs from SATA device.
2276 @param PciIo The PCI IO protocol instance.
2277 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2278 @param Port The number of port.
2279 @param PortMultiplier The multiplier of port.
2280 @param Buffer The data buffer to store SATA logs.
2281 @param LogNumber The address of the log.
2282 @param PageNumber The page number of the log.
2284 @retval EFI_INVALID_PARAMETER PciIo, AhciRegisters or Buffer is NULL.
2285 @retval others Return status of AhciPioTransfer().
2289 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2290 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2292 IN UINT8 PortMultiplier
,
2293 IN OUT UINT8
*Buffer
,
2298 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2299 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2301 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
2302 return EFI_INVALID_PARAMETER
;
2306 /// Read log from device
2308 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2309 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2310 ZeroMem (Buffer
, 512);
2312 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_LOG_EXT
;
2313 AtaCommandBlock
.AtaSectorCount
= 1;
2314 AtaCommandBlock
.AtaSectorNumber
= LogNumber
;
2315 AtaCommandBlock
.AtaCylinderLow
= PageNumber
;
2317 return AhciPioTransfer (
2335 Enable DEVSLP of the disk if supported.
2337 @param PciIo The PCI IO protocol instance.
2338 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2339 @param Port The number of port.
2340 @param PortMultiplier The multiplier of port.
2341 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2343 @retval EFI_SUCCESS The DEVSLP is enabled per policy successfully.
2344 @retval EFI_UNSUPPORTED The DEVSLP isn't supported by the controller/device and policy requires to enable it.
2348 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2349 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2351 IN UINT8 PortMultiplier
,
2352 IN EFI_IDENTIFY_DATA
*IdentifyData
2359 DEVSLP_TIMING_VARIABLES DevSlpTiming
;
2363 if (mAtaAtapiPolicy
->DeviceSleepEnable
!= 1) {
2368 // Do not enable DevSlp if DevSlp is not supported.
2370 Capability2
= AhciReadReg (PciIo
, AHCI_CAPABILITY2_OFFSET
);
2371 DEBUG ((DEBUG_INFO
, "AHCI CAPABILITY2 = %08x\n", Capability2
));
2372 if ((Capability2
& AHCI_CAP2_SDS
) == 0) {
2373 return EFI_UNSUPPORTED
;
2377 // Do not enable DevSlp if DevSlp is not present
2378 // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2380 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
;
2381 PortCmd
= AhciReadReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
);
2382 PortDevSlp
= AhciReadReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
);
2383 DEBUG ((DEBUG_INFO
, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd
, PortDevSlp
));
2384 if (((PortDevSlp
& AHCI_PORT_DEVSLP_DSP
) == 0) ||
2385 ((PortCmd
& (EFI_AHCI_PORT_CMD_HPCP
| EFI_AHCI_PORT_CMD_MPSP
)) != 0)
2387 return EFI_UNSUPPORTED
;
2391 // Do not enable DevSlp if the device doesn't support DevSlp
2393 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2394 IdentifyData
->AtaData
.reserved_77
,
2395 IdentifyData
->AtaData
.serial_ata_features_supported
, IdentifyData
->AtaData
.serial_ata_features_enabled
));
2396 if ((IdentifyData
->AtaData
.serial_ata_features_supported
& BIT8
) == 0) {
2397 DEBUG ((DEBUG_INFO
, "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2398 Port
, PortMultiplier
));
2399 return EFI_UNSUPPORTED
;
2403 // Enable DevSlp when it is not enabled.
2405 if ((IdentifyData
->AtaData
.serial_ata_features_enabled
& BIT8
) != 0) {
2406 Status
= AhciDeviceSetFeature (
2407 PciIo
, AhciRegisters
, Port
, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE
, 0x09, ATA_ATAPI_TIMEOUT
2409 DEBUG ((DEBUG_INFO
, "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2410 Port
, PortMultiplier
, Status
));
2411 if (EFI_ERROR (Status
)) {
2416 Status
= AhciReadLogExt(PciIo
, AhciRegisters
, Port
, PortMultiplier
, LogData
, 0x30, 0x08);
2419 // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2421 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
& ~EFI_AHCI_PORT_CMD_ST
);
2422 PortDevSlp
&= ~AHCI_PORT_DEVSLP_ADSE
;
2423 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2426 // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2428 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DETO_MASK
;
2429 PortDevSlp
&= ~AHCI_PORT_DEVSLP_MDAT_MASK
;
2430 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2431 DEBUG ((DEBUG_INFO
, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port
, PortMultiplier
, Status
));
2432 if (EFI_ERROR (Status
)) {
2434 // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2436 ZeroMem (&DevSlpTiming
, sizeof (DevSlpTiming
));
2438 CopyMem (&DevSlpTiming
, &LogData
[48], sizeof (DevSlpTiming
));
2439 DEBUG ((DEBUG_INFO
, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2440 DevSlpTiming
.Supported
, DevSlpTiming
.Deto
, DevSlpTiming
.Madt
));
2444 // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2446 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Deto
== 0)) {
2447 DevSlpTiming
.Deto
= 20;
2451 // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2453 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Madt
== 0)) {
2454 DevSlpTiming
.Madt
= 10;
2457 PortDevSlp
|= DevSlpTiming
.Deto
<< 2;
2458 PortDevSlp
|= DevSlpTiming
.Madt
<< 10;
2459 AhciOrReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2461 if (mAtaAtapiPolicy
->AggressiveDeviceSleepEnable
== 1) {
2462 if ((Capability2
& AHCI_CAP2_SADM
) != 0) {
2463 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DITO_MASK
;
2464 PortDevSlp
|= (625 << 15);
2465 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2467 PortDevSlp
|= AHCI_PORT_DEVSLP_ADSE
;
2468 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2473 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
);
2475 DEBUG ((DEBUG_INFO
, "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2476 Port
, PortMultiplier
, PortCmd
, PortDevSlp
));
2482 Spin-up disk if IDD was incomplete or PUIS feature is enabled
2484 @param PciIo The PCI IO protocol instance.
2485 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2486 @param Port The number of port.
2487 @param PortMultiplier The multiplier of port.
2488 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2493 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2494 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2496 IN UINT8 PortMultiplier
,
2497 IN OUT EFI_IDENTIFY_DATA
*IdentifyData
2501 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2502 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2505 if (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
) {
2507 // Use SET_FEATURE subcommand to spin up the device.
2509 Status
= AhciDeviceSetFeature (
2510 PciIo
, AhciRegisters
, Port
, PortMultiplier
,
2511 ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
, 0x00, ATA_SPINUP_TIMEOUT
2513 DEBUG ((DEBUG_INFO
, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2514 Port
, PortMultiplier
, Status
));
2515 if (EFI_ERROR (Status
)) {
2519 ASSERT (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
);
2522 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2524 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2525 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2527 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2529 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_SECTORS
;
2530 AtaCommandBlock
.AtaSectorCount
= 0x1;
2532 Status
= AhciPioTransfer (
2547 DEBUG ((DEBUG_INFO
, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2548 Port
, PortMultiplier
, Status
));
2549 if (EFI_ERROR (Status
)) {
2555 // Read the complete IDENTIFY DEVICE data.
2557 ZeroMem (IdentifyData
, sizeof (*IdentifyData
));
2558 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, PortMultiplier
, IdentifyData
);
2559 if (EFI_ERROR (Status
)) {
2560 DEBUG ((DEBUG_ERROR
, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2561 Port
, PortMultiplier
, Status
));
2565 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2566 IdentifyData
->AtaData
.config
, IdentifyData
->AtaData
.specific_config
,
2567 IdentifyData
->AtaData
.command_set_supported_83
, IdentifyData
->AtaData
.command_set_feature_enb_86
));
2569 // Check if IDD is incomplete
2571 if ((IdentifyData
->AtaData
.config
& BIT2
) != 0) {
2572 return EFI_DEVICE_ERROR
;
2579 Enable/disable/skip PUIS of the disk according to policy.
2581 @param PciIo The PCI IO protocol instance.
2582 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2583 @param Port The number of port.
2584 @param PortMultiplier The multiplier of port.
2589 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2590 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2592 IN UINT8 PortMultiplier
2597 Status
= EFI_SUCCESS
;
2598 if (mAtaAtapiPolicy
->PuisEnable
== 0) {
2599 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_DISABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2600 } else if (mAtaAtapiPolicy
->PuisEnable
== 1) {
2601 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_ENABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2603 DEBUG ((DEBUG_INFO
, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2604 (mAtaAtapiPolicy
->PuisEnable
== 0) ? "Disable" : (
2605 (mAtaAtapiPolicy
->PuisEnable
== 1) ? "Enable" : "Skip"
2606 ), Port
, PortMultiplier
, Status
));
2611 Initialize ATA host controller at AHCI mode.
2613 The function is designed to initialize ATA host controller.
2615 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2620 AhciModeInitialization (
2621 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2625 EFI_PCI_IO_PROTOCOL
*PciIo
;
2626 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2628 UINT8 MaxPortNumber
;
2629 UINT32 PortImplementBitMap
;
2631 EFI_AHCI_REGISTERS
*AhciRegisters
;
2637 EFI_IDENTIFY_DATA Buffer
;
2638 EFI_ATA_DEVICE_TYPE DeviceType
;
2639 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2640 EFI_ATA_TRANSFER_MODE TransferMode
;
2641 UINT32 PhyDetectDelay
;
2644 if (Instance
== NULL
) {
2645 return EFI_INVALID_PARAMETER
;
2648 PciIo
= Instance
->PciIo
;
2649 IdeInit
= Instance
->IdeControllerInit
;
2651 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2653 if (EFI_ERROR (Status
)) {
2654 return EFI_DEVICE_ERROR
;
2658 // Collect AHCI controller information
2660 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2663 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2665 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
2667 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
2668 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2672 // Enable 64-bit DMA support in the PCI layer if this controller
2675 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2676 Status
= PciIo
->Attributes (
2678 EfiPciIoAttributeOperationEnable
,
2679 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2682 if (EFI_ERROR (Status
)) {
2684 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2690 // Get the number of command slots per port supported by this HBA.
2692 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2695 // Get the bit map of those ports exposed by this HBA.
2696 // It indicates which ports that the HBA supports are available for software to use.
2698 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2700 AhciRegisters
= &Instance
->AhciRegisters
;
2701 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2703 if (EFI_ERROR (Status
)) {
2704 return EFI_OUT_OF_RESOURCES
;
2707 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2708 if ((PortImplementBitMap
& (((UINT32
)BIT0
) << Port
)) != 0) {
2710 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2712 if ((MaxPortNumber
--) == 0) {
2714 // Should never be here.
2720 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2723 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2725 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2726 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2727 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2728 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2729 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2731 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2732 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2733 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2734 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2735 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2737 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2738 Data
= AhciReadReg (PciIo
, Offset
);
2739 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2740 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2743 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2744 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2748 // Disable aggressive power management.
2750 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2751 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2753 // Disable the reporting of the corresponding interrupt to system software.
2755 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2756 AhciAndReg (PciIo
, Offset
, 0);
2759 // Now inform the IDE Controller Init Module.
2761 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2764 // Enable FIS Receive DMA engine for the first D2H FIS.
2766 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2767 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2770 // Wait for the Phy to detect the presence of a device.
2772 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2773 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2775 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2776 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2780 MicroSecondDelay (1000);
2782 } while (PhyDetectDelay
> 0);
2784 if (PhyDetectDelay
== 0) {
2786 // No device detected at this port.
2787 // Clear PxCMD.SUD for those ports at which there are no device present.
2789 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2790 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2794 Status
= AhciWaitDeviceReady (PciIo
, Port
);
2795 if (EFI_ERROR (Status
)) {
2800 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2802 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2803 Status
= AhciWaitMmioSet (
2808 EFI_TIMER_PERIOD_SECONDS(16)
2810 if (EFI_ERROR (Status
)) {
2814 Data
= AhciReadReg (PciIo
, Offset
);
2815 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2816 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2818 if (EFI_ERROR (Status
)) {
2822 DeviceType
= EfiIdeCdrom
;
2823 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2824 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2826 if (EFI_ERROR (Status
)) {
2827 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2832 DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2833 Buffer
.AtaData
.config
, Buffer
.AtaData
.specific_config
,
2834 Buffer
.AtaData
.command_set_supported_83
, Buffer
.AtaData
.command_set_feature_enb_86
2836 if ((Buffer
.AtaData
.config
& BIT2
) != 0) {
2838 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
2840 Status
= AhciSpinUpDisk (
2847 if (EFI_ERROR (Status
)) {
2848 DEBUG ((DEBUG_ERROR
, "Spin up standby device failed - %r\n", Status
));
2853 DeviceType
= EfiIdeHarddisk
;
2857 DEBUG ((DEBUG_INFO
, "port [%d] port multitplier [%d] has a [%a]\n",
2858 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2861 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2863 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2864 AhciAtaSmartSupport (
2875 // Submit identify data to IDE controller init driver
2877 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2880 // Now start to config ide device parameter and transfer mode.
2882 Status
= IdeInit
->CalculateMode (
2888 if (EFI_ERROR (Status
)) {
2889 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2894 // Set best supported PIO mode on this IDE device
2896 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2897 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2899 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2902 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2905 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA can't
2906 // be set together. Only one DMA mode can be set to a device. If setting
2907 // DMA mode operation fails, we can continue moving on because we only use
2908 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2910 if (SupportedModes
->UdmaMode
.Valid
) {
2911 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2912 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2913 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2914 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2915 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2918 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
), ATA_ATAPI_TIMEOUT
);
2919 if (EFI_ERROR (Status
)) {
2920 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2925 // Found a ATA or ATAPI device, add it into the device list.
2927 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
2928 if (DeviceType
== EfiIdeHarddisk
) {
2929 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));
2940 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
2942 if ((Buffer
.AtaData
.command_set_supported_83
& BIT5
) != 0) {
2943 Status
= AhciPuisEnable (
2949 if (EFI_ERROR (Status
)) {
2950 DEBUG ((DEBUG_ERROR
, "PUIS enable/disable failed, Status = %r\n", Status
));