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
;
902 Flag
= EfiPciIoOperationBusMasterWrite
;
904 Flag
= EfiPciIoOperationBusMasterRead
;
908 // construct command list and command table with pci bus address
910 MapLength
= DataCount
;
911 Status
= PciIo
->Map (
920 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
921 return EFI_BAD_BUFFER_SIZE
;
925 // Package read needed
927 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
929 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
931 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
932 CmdList
.AhciCmdW
= Read
? 0 : 1;
944 (VOID
*)(UINTN
)PhyAddr
,
948 Status
= AhciStartCommand (
954 if (EFI_ERROR (Status
)) {
958 if (Read
&& (AtapiCommand
== 0)) {
959 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisPioSetup
);
960 if (Status
== EFI_SUCCESS
) {
961 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
962 if (PrdCount
== DataCount
) {
963 Status
= EFI_SUCCESS
;
965 Status
= EFI_DEVICE_ERROR
;
969 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
972 if (Status
== EFI_DEVICE_ERROR
) {
973 AhciRecoverPortError (PciIo
, Port
);
983 AhciDisableFisReceive (
994 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1000 Start a DMA data transfer on specific port
1002 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
1003 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1004 @param[in] Port The number of port.
1005 @param[in] PortMultiplier The timeout value of stop.
1006 @param[in] AtapiCommand The atapi command will be used for the
1008 @param[in] AtapiCommandLength The length of the atapi command.
1009 @param[in] Read The transfer direction.
1010 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1011 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1012 @param[in, out] MemoryAddr The pointer to the data buffer.
1013 @param[in] DataCount The data count to be transferred.
1014 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1015 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1016 used by non-blocking mode.
1018 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
1019 @retval EFI_TIMEOUT The operation is time out.
1020 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1021 @retval EFI_SUCCESS The DMA data transfer executes successfully.
1027 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
1028 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1030 IN UINT8 PortMultiplier
,
1031 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1032 IN UINT8 AtapiCommandLength
,
1034 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1035 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1036 IN OUT VOID
*MemoryAddr
,
1037 IN UINT32 DataCount
,
1039 IN ATA_NONBLOCK_TASK
*Task
1043 EFI_PHYSICAL_ADDRESS PhyAddr
;
1046 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
1047 EFI_AHCI_COMMAND_FIS CFis
;
1048 EFI_AHCI_COMMAND_LIST CmdList
;
1050 EFI_PCI_IO_PROTOCOL
*PciIo
;
1054 PciIo
= Instance
->PciIo
;
1056 if (PciIo
== NULL
) {
1057 return EFI_INVALID_PARAMETER
;
1061 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
1063 // Delay 100us to simulate the blocking time out checking.
1065 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1066 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
1067 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
1071 MicroSecondDelay (100);
1073 gBS
->RestoreTPL (OldTpl
);
1075 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
1077 // Mark the Task to indicate that it has been started.
1080 Task
->IsStart
= TRUE
;
1083 Flag
= EfiPciIoOperationBusMasterWrite
;
1085 Flag
= EfiPciIoOperationBusMasterRead
;
1089 // Construct command list and command table with pci bus address.
1091 MapLength
= DataCount
;
1092 Status
= PciIo
->Map (
1101 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
1102 return EFI_BAD_BUFFER_SIZE
;
1109 // Package read needed
1111 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1113 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1115 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1116 CmdList
.AhciCmdW
= Read
? 0 : 1;
1128 (VOID
*)(UINTN
)PhyAddr
,
1132 Status
= AhciStartCommand (
1138 if (EFI_ERROR (Status
)) {
1144 Status
= AhciCheckFisReceived (PciIo
, Port
, SataFisD2H
);
1145 if (Status
== EFI_NOT_READY
) {
1146 if (!Task
->InfiniteWait
&& Task
->RetryTimes
== 0) {
1147 Status
= EFI_TIMEOUT
;
1153 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1156 if (Status
== EFI_DEVICE_ERROR
) {
1157 AhciRecoverPortError (PciIo
, Port
);
1162 // For Blocking mode, the command should be stopped, the Fis should be disabled
1163 // and the PciIo should be unmapped.
1164 // For non-blocking mode, only when a error is happened (if the return status is
1165 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1166 // context cleanup, then set the packet's Asb status.
1169 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1177 AhciDisableFisReceive (
1185 (Task
!= NULL
) ? Task
->Map
: Map
1189 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1193 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1198 Start a non data transfer on specific port.
1200 @param[in] PciIo The PCI IO protocol instance.
1201 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1202 @param[in] Port The number of port.
1203 @param[in] PortMultiplier The timeout value of stop.
1204 @param[in] AtapiCommand The atapi command will be used for the
1206 @param[in] AtapiCommandLength The length of the atapi command.
1207 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1208 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1209 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1210 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1211 used by non-blocking mode.
1213 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1214 @retval EFI_TIMEOUT The operation is time out.
1215 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1216 @retval EFI_SUCCESS The non data transfer executes successfully.
1221 AhciNonDataTransfer (
1222 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1223 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1225 IN UINT8 PortMultiplier
,
1226 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1227 IN UINT8 AtapiCommandLength
,
1228 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1229 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1231 IN ATA_NONBLOCK_TASK
*Task
1235 EFI_AHCI_COMMAND_FIS CFis
;
1236 EFI_AHCI_COMMAND_LIST CmdList
;
1239 // Package read needed
1241 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1243 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1245 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1261 Status
= AhciStartCommand (
1267 if (EFI_ERROR (Status
)) {
1271 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1272 if (Status
== EFI_DEVICE_ERROR
) {
1273 AhciRecoverPortError (PciIo
, Port
);
1283 AhciDisableFisReceive (
1289 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1295 Stop command running for giving port
1297 @param PciIo The PCI IO protocol instance.
1298 @param Port The number of port.
1299 @param Timeout The timeout value of stop, uses 100ns as a unit.
1301 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1302 @retval EFI_TIMEOUT The operation is time out.
1303 @retval EFI_SUCCESS The command stop successfully.
1309 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1317 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1318 Data
= AhciReadReg (PciIo
, Offset
);
1320 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1324 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1325 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1328 return AhciWaitMmioSet (
1331 EFI_AHCI_PORT_CMD_CR
,
1338 Start command for give slot on specific port.
1340 @param PciIo The PCI IO protocol instance.
1341 @param Port The number of port.
1342 @param CommandSlot The number of Command Slot.
1343 @param Timeout The timeout value of start, uses 100ns as a unit.
1345 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1346 @retval EFI_TIMEOUT The operation is time out.
1347 @retval EFI_SUCCESS The command start successfully.
1353 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1355 IN UINT8 CommandSlot
,
1368 // Collect AHCI controller information
1370 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1372 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1374 AhciClearPortStatus (
1379 Status
= AhciEnableFisReceive (
1385 if (EFI_ERROR (Status
)) {
1389 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1390 PortStatus
= AhciReadReg (PciIo
, Offset
);
1393 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1394 StartCmd
= AhciReadReg (PciIo
, Offset
);
1395 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1396 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1399 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1400 PortTfd
= AhciReadReg (PciIo
, Offset
);
1402 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1403 if ((Capability
& BIT24
) != 0) {
1404 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1405 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1410 EFI_AHCI_PORT_CMD_CLO
,
1417 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1418 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1421 // Setting the command
1423 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1424 AhciAndReg (PciIo
, Offset
, 0);
1425 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1434 @param PciIo The PCI IO protocol instance.
1435 @param Timeout The timeout value of reset, uses 100ns as a unit.
1437 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1438 @retval EFI_TIMEOUT The reset operation is time out.
1439 @retval EFI_SUCCESS AHCI controller is reset successfully.
1445 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1453 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1455 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1457 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
1458 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1461 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1463 Delay
= DivU64x32(Timeout
, 1000) + 1;
1466 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1468 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1473 // Stall for 100 microseconds.
1475 MicroSecondDelay(100);
1478 } while (Delay
> 0);
1488 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1490 @param PciIo The PCI IO protocol instance.
1491 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1492 @param Port The number of port.
1493 @param PortMultiplier The port multiplier port number.
1494 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1496 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1497 @retval Others Fail to get return status data.
1502 AhciAtaSmartReturnStatusCheck (
1503 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1504 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1506 IN UINT8 PortMultiplier
,
1507 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1511 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1517 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1519 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1520 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1521 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1522 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1525 // Send S.M.A.R.T Read Return Status command to device
1527 Status
= AhciNonDataTransfer (
1531 (UINT8
)PortMultiplier
,
1540 if (EFI_ERROR (Status
)) {
1541 REPORT_STATUS_CODE (
1542 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1543 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1545 return EFI_DEVICE_ERROR
;
1548 REPORT_STATUS_CODE (
1550 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1553 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1555 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1557 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1558 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1559 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1561 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1563 // The threshold exceeded condition is not detected by the device
1565 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1566 REPORT_STATUS_CODE (
1568 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1570 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1572 // The threshold exceeded condition is detected by the device
1574 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1575 REPORT_STATUS_CODE (
1577 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1586 Enable SMART command of the disk if supported.
1588 @param PciIo The PCI IO protocol instance.
1589 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1590 @param Port The number of port.
1591 @param PortMultiplier The port multiplier port number.
1592 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1593 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1598 AhciAtaSmartSupport (
1599 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1600 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1602 IN UINT8 PortMultiplier
,
1603 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1604 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1608 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1611 // Detect if the device supports S.M.A.R.T.
1613 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1615 // S.M.A.R.T is not supported by the device
1617 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1618 Port
, PortMultiplier
));
1619 REPORT_STATUS_CODE (
1620 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1621 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1625 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1627 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1629 REPORT_STATUS_CODE (
1631 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1634 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1636 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1637 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1638 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1639 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1642 // Send S.M.A.R.T Enable command to device
1644 Status
= AhciNonDataTransfer (
1648 (UINT8
)PortMultiplier
,
1658 if (!EFI_ERROR (Status
)) {
1660 // Send S.M.A.R.T AutoSave command to device
1662 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1664 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1665 AtaCommandBlock
.AtaFeatures
= 0xD2;
1666 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1667 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1668 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1670 Status
= AhciNonDataTransfer (
1674 (UINT8
)PortMultiplier
,
1683 if (!EFI_ERROR (Status
)) {
1684 Status
= AhciAtaSmartReturnStatusCheck (
1688 (UINT8
)PortMultiplier
,
1694 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1695 Port
, PortMultiplier
));
1702 Send Buffer cmd to specific device.
1704 @param PciIo The PCI IO protocol instance.
1705 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1706 @param Port The number of port.
1707 @param PortMultiplier The port multiplier port number.
1708 @param Buffer The data buffer to store IDENTIFY PACKET data.
1710 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1711 @retval EFI_TIMEOUT The operation is time out.
1712 @retval EFI_UNSUPPORTED The device is not ready for executing.
1713 @retval EFI_SUCCESS The cmd executes successfully.
1719 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1720 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1722 IN UINT8 PortMultiplier
,
1723 IN OUT EFI_IDENTIFY_DATA
*Buffer
1727 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1728 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1730 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1731 return EFI_INVALID_PARAMETER
;
1734 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1735 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1737 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1738 AtaCommandBlock
.AtaSectorCount
= 1;
1740 Status
= AhciPioTransfer (
1751 sizeof (EFI_IDENTIFY_DATA
),
1760 Send Buffer cmd to specific device.
1762 @param PciIo The PCI IO protocol instance.
1763 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1764 @param Port The number of port.
1765 @param PortMultiplier The port multiplier port number.
1766 @param Buffer The data buffer to store IDENTIFY PACKET data.
1768 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1769 @retval EFI_TIMEOUT The operation is time out.
1770 @retval EFI_UNSUPPORTED The device is not ready for executing.
1771 @retval EFI_SUCCESS The cmd executes successfully.
1776 AhciIdentifyPacket (
1777 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1778 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1780 IN UINT8 PortMultiplier
,
1781 IN OUT EFI_IDENTIFY_DATA
*Buffer
1785 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1786 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1788 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1789 return EFI_INVALID_PARAMETER
;
1792 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1793 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1795 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1796 AtaCommandBlock
.AtaSectorCount
= 1;
1798 Status
= AhciPioTransfer (
1809 sizeof (EFI_IDENTIFY_DATA
),
1818 Send SET FEATURE cmd on specific device.
1820 @param PciIo The PCI IO protocol instance.
1821 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1822 @param Port The number of port.
1823 @param PortMultiplier The port multiplier port number.
1824 @param Feature The data to send Feature register.
1825 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1826 @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1828 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1829 @retval EFI_TIMEOUT The operation is time out.
1830 @retval EFI_UNSUPPORTED The device is not ready for executing.
1831 @retval EFI_SUCCESS The cmd executes successfully.
1836 AhciDeviceSetFeature (
1837 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1838 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1840 IN UINT8 PortMultiplier
,
1842 IN UINT32 FeatureSpecificData
,
1847 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1848 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1850 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1851 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1853 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1854 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1855 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1856 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1857 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1858 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1859 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1861 Status
= AhciNonDataTransfer (
1865 (UINT8
)PortMultiplier
,
1878 This function is used to send out ATAPI commands conforms to the Packet Command
1881 @param PciIo The PCI IO protocol instance.
1882 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1883 @param Port The number of port.
1884 @param PortMultiplier The number of port multiplier.
1885 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1887 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1888 and device sends data successfully.
1889 @retval EFI_DEVICE_ERROR the device failed to send data.
1894 AhciPacketCommandExecute (
1895 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1896 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1898 IN UINT8 PortMultiplier
,
1899 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1905 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1906 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1909 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1910 return EFI_INVALID_PARAMETER
;
1913 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1914 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1915 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1919 AtaCommandBlock
.AtaFeatures
= 0x00;
1921 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1922 // determine how many data should be transferred.
1924 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1925 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1927 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1928 Buffer
= Packet
->InDataBuffer
;
1929 Length
= Packet
->InTransferLength
;
1932 Buffer
= Packet
->OutDataBuffer
;
1933 Length
= Packet
->OutTransferLength
;
1938 Status
= AhciNonDataTransfer (
1951 Status
= AhciPioTransfer (
1971 Allocate transfer-related data struct which is used at AHCI mode.
1973 @param PciIo The PCI IO protocol instance.
1974 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1979 AhciCreateTransferDescriptor (
1980 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1981 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1989 UINT32 PortImplementBitMap
;
1990 UINT8 MaxPortNumber
;
1991 UINT8 MaxCommandSlotNumber
;
1992 BOOLEAN Support64Bit
;
1993 UINT64 MaxReceiveFisSize
;
1994 UINT64 MaxCommandListSize
;
1995 UINT64 MaxCommandTableSize
;
1996 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1997 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1998 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
2002 // Collect AHCI controller information
2004 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2006 // Get the number of command slots per port supported by this HBA.
2008 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2009 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2011 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2013 // Get the highest bit of implemented ports which decides how many bytes are allocated for received FIS.
2015 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2016 if (MaxPortNumber
== 0) {
2017 return EFI_DEVICE_ERROR
;
2020 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2021 Status
= PciIo
->AllocateBuffer (
2024 EfiBootServicesData
,
2025 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2030 if (EFI_ERROR (Status
)) {
2031 return EFI_OUT_OF_RESOURCES
;
2034 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2036 AhciRegisters
->AhciRFis
= Buffer
;
2037 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2038 Bytes
= (UINTN
)MaxReceiveFisSize
;
2040 Status
= PciIo
->Map (
2042 EfiPciIoOperationBusMasterCommonBuffer
,
2046 &AhciRegisters
->MapRFis
2049 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2051 // Map error or unable to map the whole RFis buffer into a contiguous region.
2053 Status
= EFI_OUT_OF_RESOURCES
;
2057 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2059 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2061 Status
= EFI_DEVICE_ERROR
;
2064 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2067 // Allocate memory for command list
2068 // Note that the implementation is a single task model which only use a command list for all ports.
2071 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2072 Status
= PciIo
->AllocateBuffer (
2075 EfiBootServicesData
,
2076 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2081 if (EFI_ERROR (Status
)) {
2083 // Free mapped resource.
2085 Status
= EFI_OUT_OF_RESOURCES
;
2089 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2091 AhciRegisters
->AhciCmdList
= Buffer
;
2092 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2093 Bytes
= (UINTN
)MaxCommandListSize
;
2095 Status
= PciIo
->Map (
2097 EfiPciIoOperationBusMasterCommonBuffer
,
2100 &AhciCmdListPciAddr
,
2101 &AhciRegisters
->MapCmdList
2104 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2106 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2108 Status
= EFI_OUT_OF_RESOURCES
;
2112 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 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
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2122 // Allocate memory for command table
2123 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2126 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2128 Status
= PciIo
->AllocateBuffer (
2131 EfiBootServicesData
,
2132 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2137 if (EFI_ERROR (Status
)) {
2139 // Free mapped resource.
2141 Status
= EFI_OUT_OF_RESOURCES
;
2145 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2147 AhciRegisters
->AhciCommandTable
= Buffer
;
2148 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2149 Bytes
= (UINTN
)MaxCommandTableSize
;
2151 Status
= PciIo
->Map (
2153 EfiPciIoOperationBusMasterCommonBuffer
,
2156 &AhciCommandTablePciAddr
,
2157 &AhciRegisters
->MapCommandTable
2160 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2162 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2164 Status
= EFI_OUT_OF_RESOURCES
;
2168 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2170 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2172 Status
= EFI_DEVICE_ERROR
;
2175 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2179 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2184 AhciRegisters
->MapCommandTable
2189 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2190 AhciRegisters
->AhciCommandTable
2195 AhciRegisters
->MapCmdList
2200 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2201 AhciRegisters
->AhciCmdList
2206 AhciRegisters
->MapRFis
2211 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2212 AhciRegisters
->AhciRFis
2219 Read logs from SATA device.
2221 @param PciIo The PCI IO protocol instance.
2222 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2223 @param Port The number of port.
2224 @param PortMultiplier The multiplier of port.
2225 @param Buffer The data buffer to store SATA logs.
2226 @param LogNumber The address of the log.
2227 @param PageNumber The page number of the log.
2229 @retval EFI_INVALID_PARAMETER PciIo, AhciRegisters or Buffer is NULL.
2230 @retval others Return status of AhciPioTransfer().
2234 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2235 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2237 IN UINT8 PortMultiplier
,
2238 IN OUT UINT8
*Buffer
,
2243 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2244 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2246 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
2247 return EFI_INVALID_PARAMETER
;
2251 /// Read log from device
2253 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2254 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2255 ZeroMem (Buffer
, 512);
2257 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_LOG_EXT
;
2258 AtaCommandBlock
.AtaSectorCount
= 1;
2259 AtaCommandBlock
.AtaSectorNumber
= LogNumber
;
2260 AtaCommandBlock
.AtaCylinderLow
= PageNumber
;
2262 return AhciPioTransfer (
2280 Enable DEVSLP of the disk if supported.
2282 @param PciIo The PCI IO protocol instance.
2283 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2284 @param Port The number of port.
2285 @param PortMultiplier The multiplier of port.
2286 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2288 @retval EFI_SUCCESS The DEVSLP is enabled per policy successfully.
2289 @retval EFI_UNSUPPORTED The DEVSLP isn't supported by the controller/device and policy requires to enable it.
2293 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2294 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2296 IN UINT8 PortMultiplier
,
2297 IN EFI_IDENTIFY_DATA
*IdentifyData
2304 DEVSLP_TIMING_VARIABLES DevSlpTiming
;
2308 if (mAtaAtapiPolicy
->DeviceSleepEnable
!= 1) {
2313 // Do not enable DevSlp if DevSlp is not supported.
2315 Capability2
= AhciReadReg (PciIo
, AHCI_CAPABILITY2_OFFSET
);
2316 DEBUG ((DEBUG_INFO
, "AHCI CAPABILITY2 = %08x\n", Capability2
));
2317 if ((Capability2
& AHCI_CAP2_SDS
) == 0) {
2318 return EFI_UNSUPPORTED
;
2322 // Do not enable DevSlp if DevSlp is not present
2323 // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2325 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
;
2326 PortCmd
= AhciReadReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
);
2327 PortDevSlp
= AhciReadReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
);
2328 DEBUG ((DEBUG_INFO
, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd
, PortDevSlp
));
2329 if (((PortDevSlp
& AHCI_PORT_DEVSLP_DSP
) == 0) ||
2330 ((PortCmd
& (EFI_AHCI_PORT_CMD_HPCP
| EFI_AHCI_PORT_CMD_MPSP
)) != 0)
2332 return EFI_UNSUPPORTED
;
2336 // Do not enable DevSlp if the device doesn't support DevSlp
2338 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2339 IdentifyData
->AtaData
.reserved_77
,
2340 IdentifyData
->AtaData
.serial_ata_features_supported
, IdentifyData
->AtaData
.serial_ata_features_enabled
));
2341 if ((IdentifyData
->AtaData
.serial_ata_features_supported
& BIT8
) == 0) {
2342 DEBUG ((DEBUG_INFO
, "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2343 Port
, PortMultiplier
));
2344 return EFI_UNSUPPORTED
;
2348 // Enable DevSlp when it is not enabled.
2350 if ((IdentifyData
->AtaData
.serial_ata_features_enabled
& BIT8
) != 0) {
2351 Status
= AhciDeviceSetFeature (
2352 PciIo
, AhciRegisters
, Port
, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE
, 0x09, ATA_ATAPI_TIMEOUT
2354 DEBUG ((DEBUG_INFO
, "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2355 Port
, PortMultiplier
, Status
));
2356 if (EFI_ERROR (Status
)) {
2361 Status
= AhciReadLogExt(PciIo
, AhciRegisters
, Port
, PortMultiplier
, LogData
, 0x30, 0x08);
2364 // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2366 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
& ~EFI_AHCI_PORT_CMD_ST
);
2367 PortDevSlp
&= ~AHCI_PORT_DEVSLP_ADSE
;
2368 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2371 // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2373 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DETO_MASK
;
2374 PortDevSlp
&= ~AHCI_PORT_DEVSLP_MDAT_MASK
;
2375 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2376 DEBUG ((DEBUG_INFO
, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port
, PortMultiplier
, Status
));
2377 if (EFI_ERROR (Status
)) {
2379 // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2381 ZeroMem (&DevSlpTiming
, sizeof (DevSlpTiming
));
2383 CopyMem (&DevSlpTiming
, &LogData
[48], sizeof (DevSlpTiming
));
2384 DEBUG ((DEBUG_INFO
, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2385 DevSlpTiming
.Supported
, DevSlpTiming
.Deto
, DevSlpTiming
.Madt
));
2389 // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2391 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Deto
== 0)) {
2392 DevSlpTiming
.Deto
= 20;
2396 // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2398 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Madt
== 0)) {
2399 DevSlpTiming
.Madt
= 10;
2402 PortDevSlp
|= DevSlpTiming
.Deto
<< 2;
2403 PortDevSlp
|= DevSlpTiming
.Madt
<< 10;
2404 AhciOrReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2406 if (mAtaAtapiPolicy
->AggressiveDeviceSleepEnable
== 1) {
2407 if ((Capability2
& AHCI_CAP2_SADM
) != 0) {
2408 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DITO_MASK
;
2409 PortDevSlp
|= (625 << 15);
2410 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2412 PortDevSlp
|= AHCI_PORT_DEVSLP_ADSE
;
2413 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2418 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
);
2420 DEBUG ((DEBUG_INFO
, "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2421 Port
, PortMultiplier
, PortCmd
, PortDevSlp
));
2427 Spin-up disk if IDD was incomplete or PUIS feature is enabled
2429 @param PciIo The PCI IO protocol instance.
2430 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2431 @param Port The number of port.
2432 @param PortMultiplier The multiplier of port.
2433 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2438 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2439 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2441 IN UINT8 PortMultiplier
,
2442 IN OUT EFI_IDENTIFY_DATA
*IdentifyData
2446 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2447 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2450 if (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
) {
2452 // Use SET_FEATURE subcommand to spin up the device.
2454 Status
= AhciDeviceSetFeature (
2455 PciIo
, AhciRegisters
, Port
, PortMultiplier
,
2456 ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
, 0x00, ATA_SPINUP_TIMEOUT
2458 DEBUG ((DEBUG_INFO
, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2459 Port
, PortMultiplier
, Status
));
2460 if (EFI_ERROR (Status
)) {
2464 ASSERT (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
);
2467 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2469 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2470 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2472 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2474 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_SECTORS
;
2475 AtaCommandBlock
.AtaSectorCount
= 0x1;
2477 Status
= AhciPioTransfer (
2492 DEBUG ((DEBUG_INFO
, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2493 Port
, PortMultiplier
, Status
));
2494 if (EFI_ERROR (Status
)) {
2500 // Read the complete IDENTIFY DEVICE data.
2502 ZeroMem (IdentifyData
, sizeof (*IdentifyData
));
2503 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, PortMultiplier
, IdentifyData
);
2504 if (EFI_ERROR (Status
)) {
2505 DEBUG ((DEBUG_ERROR
, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2506 Port
, PortMultiplier
, Status
));
2510 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2511 IdentifyData
->AtaData
.config
, IdentifyData
->AtaData
.specific_config
,
2512 IdentifyData
->AtaData
.command_set_supported_83
, IdentifyData
->AtaData
.command_set_feature_enb_86
));
2514 // Check if IDD is incomplete
2516 if ((IdentifyData
->AtaData
.config
& BIT2
) != 0) {
2517 return EFI_DEVICE_ERROR
;
2524 Enable/disable/skip PUIS of the disk according to policy.
2526 @param PciIo The PCI IO protocol instance.
2527 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2528 @param Port The number of port.
2529 @param PortMultiplier The multiplier of port.
2534 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2535 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2537 IN UINT8 PortMultiplier
2542 Status
= EFI_SUCCESS
;
2543 if (mAtaAtapiPolicy
->PuisEnable
== 0) {
2544 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_DISABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2545 } else if (mAtaAtapiPolicy
->PuisEnable
== 1) {
2546 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_ENABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2548 DEBUG ((DEBUG_INFO
, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2549 (mAtaAtapiPolicy
->PuisEnable
== 0) ? "Disable" : (
2550 (mAtaAtapiPolicy
->PuisEnable
== 1) ? "Enable" : "Skip"
2551 ), Port
, PortMultiplier
, Status
));
2556 Initialize ATA host controller at AHCI mode.
2558 The function is designed to initialize ATA host controller.
2560 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2565 AhciModeInitialization (
2566 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2570 EFI_PCI_IO_PROTOCOL
*PciIo
;
2571 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2573 UINT8 MaxPortNumber
;
2574 UINT32 PortImplementBitMap
;
2576 EFI_AHCI_REGISTERS
*AhciRegisters
;
2582 EFI_IDENTIFY_DATA Buffer
;
2583 EFI_ATA_DEVICE_TYPE DeviceType
;
2584 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2585 EFI_ATA_TRANSFER_MODE TransferMode
;
2586 UINT32 PhyDetectDelay
;
2589 if (Instance
== NULL
) {
2590 return EFI_INVALID_PARAMETER
;
2593 PciIo
= Instance
->PciIo
;
2594 IdeInit
= Instance
->IdeControllerInit
;
2596 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2598 if (EFI_ERROR (Status
)) {
2599 return EFI_DEVICE_ERROR
;
2603 // Collect AHCI controller information
2605 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2608 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2610 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
2612 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
2613 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2617 // Enable 64-bit DMA support in the PCI layer if this controller
2620 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2621 Status
= PciIo
->Attributes (
2623 EfiPciIoAttributeOperationEnable
,
2624 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2627 if (EFI_ERROR (Status
)) {
2629 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2635 // Get the number of command slots per port supported by this HBA.
2637 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2640 // Get the bit map of those ports exposed by this HBA.
2641 // It indicates which ports that the HBA supports are available for software to use.
2643 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2645 AhciRegisters
= &Instance
->AhciRegisters
;
2646 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2648 if (EFI_ERROR (Status
)) {
2649 return EFI_OUT_OF_RESOURCES
;
2652 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2653 if ((PortImplementBitMap
& (((UINT32
)BIT0
) << Port
)) != 0) {
2655 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2657 if ((MaxPortNumber
--) == 0) {
2659 // Should never be here.
2665 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2668 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2670 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2671 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2672 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2673 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2674 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2676 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2677 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2678 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2679 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2680 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2682 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2683 Data
= AhciReadReg (PciIo
, Offset
);
2684 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2685 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2688 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2689 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2693 // Disable aggressive power management.
2695 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2696 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2698 // Disable the reporting of the corresponding interrupt to system software.
2700 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2701 AhciAndReg (PciIo
, Offset
, 0);
2704 // Now inform the IDE Controller Init Module.
2706 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2709 // Enable FIS Receive DMA engine for the first D2H FIS.
2711 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2712 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2715 // Wait for the Phy to detect the presence of a device.
2717 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2718 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2720 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2721 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2725 MicroSecondDelay (1000);
2727 } while (PhyDetectDelay
> 0);
2729 if (PhyDetectDelay
== 0) {
2731 // No device detected at this port.
2732 // Clear PxCMD.SUD for those ports at which there are no device present.
2734 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2735 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2739 Status
= AhciWaitDeviceReady (PciIo
, Port
);
2740 if (EFI_ERROR (Status
)) {
2745 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2747 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2748 Status
= AhciWaitMmioSet (
2753 EFI_TIMER_PERIOD_SECONDS(16)
2755 if (EFI_ERROR (Status
)) {
2759 Data
= AhciReadReg (PciIo
, Offset
);
2760 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2761 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2763 if (EFI_ERROR (Status
)) {
2767 DeviceType
= EfiIdeCdrom
;
2768 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2769 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2771 if (EFI_ERROR (Status
)) {
2772 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2777 DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2778 Buffer
.AtaData
.config
, Buffer
.AtaData
.specific_config
,
2779 Buffer
.AtaData
.command_set_supported_83
, Buffer
.AtaData
.command_set_feature_enb_86
2781 if ((Buffer
.AtaData
.config
& BIT2
) != 0) {
2783 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
2785 Status
= AhciSpinUpDisk (
2792 if (EFI_ERROR (Status
)) {
2793 DEBUG ((DEBUG_ERROR
, "Spin up standby device failed - %r\n", Status
));
2798 DeviceType
= EfiIdeHarddisk
;
2802 DEBUG ((DEBUG_INFO
, "port [%d] port multitplier [%d] has a [%a]\n",
2803 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2806 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2808 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2809 AhciAtaSmartSupport (
2820 // Submit identify data to IDE controller init driver
2822 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2825 // Now start to config ide device parameter and transfer mode.
2827 Status
= IdeInit
->CalculateMode (
2833 if (EFI_ERROR (Status
)) {
2834 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2839 // Set best supported PIO mode on this IDE device
2841 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2842 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2844 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2847 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2850 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA can't
2851 // be set together. Only one DMA mode can be set to a device. If setting
2852 // DMA mode operation fails, we can continue moving on because we only use
2853 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2855 if (SupportedModes
->UdmaMode
.Valid
) {
2856 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2857 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2858 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2859 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2860 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2863 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
), ATA_ATAPI_TIMEOUT
);
2864 if (EFI_ERROR (Status
)) {
2865 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2870 // Found a ATA or ATAPI device, add it into the device list.
2872 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
2873 if (DeviceType
== EfiIdeHarddisk
) {
2874 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));
2885 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
2887 if ((Buffer
.AtaData
.command_set_supported_83
& BIT5
) != 0) {
2888 Status
= AhciPuisEnable (
2894 if (EFI_ERROR (Status
)) {
2895 DEBUG ((DEBUG_ERROR
, "PUIS enable/disable failed, Status = %r\n", Status
));