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);
181 } while (InfiniteWait
|| (Delay
> 0));
187 Wait for the value of the specified system memory set to the test value.
189 @param Address The system memory address to test.
190 @param MaskValue The mask value of memory.
191 @param TestValue The test value of memory.
192 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
194 @retval EFI_TIMEOUT The system memory setting is time out.
195 @retval EFI_SUCCESS The system memory is correct set.
201 IN EFI_PHYSICAL_ADDRESS Address
,
209 BOOLEAN InfiniteWait
;
214 InfiniteWait
= FALSE
;
217 Delay
= DivU64x32 (Timeout
, 1000) + 1;
221 // Access system memory to see if the value is the tested one.
223 // The system memory pointed by Address will be updated by the
224 // SATA Host Controller, "volatile" is introduced to prevent
225 // compiler from optimizing the access to the memory address
226 // to only read once.
228 Value
= *(volatile UINT32
*)(UINTN
)Address
;
231 if (Value
== TestValue
) {
236 // Stall for 100 microseconds.
238 MicroSecondDelay (100);
241 } while (InfiniteWait
|| (Delay
> 0));
247 Check the memory status to the test value.
249 @param[in] Address The memory address to test.
250 @param[in] MaskValue The mask value of memory.
251 @param[in] TestValue The test value of memory.
253 @retval EFI_NOT_READY The memory is not set.
254 @retval EFI_SUCCESS The memory is correct set.
266 Value
= *(volatile UINT32
*)Address
;
269 if (Value
== TestValue
) {
273 return EFI_NOT_READY
;
278 Clear the port interrupt and error status. It will also clear
279 HBA interrupt status.
281 @param PciIo The PCI IO protocol instance.
282 @param Port The number of port.
287 AhciClearPortStatus (
288 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
295 // Clear any error status
297 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
298 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
301 // Clear any port interrupt status
303 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
304 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
307 // Clear any HBA interrupt status
309 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
313 This function is used to dump the Status Registers and if there is ERR bit set
314 in the Status Register, the Error Register's value is also be dumped.
316 @param PciIo The PCI IO protocol instance.
317 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
318 @param Port The number of port.
319 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
325 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
326 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
328 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
336 ASSERT (PciIo
!= NULL
);
338 if (AtaStatusBlock
!= NULL
) {
339 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
341 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
342 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
344 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
);
345 if (!EFI_ERROR (Status
)) {
347 // If D2H FIS is received, update StatusBlock with its content.
349 CopyMem (AtaStatusBlock
, (UINT8
*)Offset
, sizeof (EFI_ATA_STATUS_BLOCK
));
352 // If D2H FIS is not received, only update Status & Error field through PxTFD
353 // as there is no other way to get the content of the Shadow Register Block.
355 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
356 Data
= AhciReadReg (PciIo
, (UINT32
)Offset
);
358 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
359 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
360 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
367 Enable the FIS running for giving port.
369 @param PciIo The PCI IO protocol instance.
370 @param Port The number of port.
371 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
373 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
374 @retval EFI_TIMEOUT The FIS enable setting is time out.
375 @retval EFI_SUCCESS The FIS enable successfully.
380 AhciEnableFisReceive (
381 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
388 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
389 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
395 Disable the FIS running for giving port.
397 @param PciIo The PCI IO protocol instance.
398 @param Port The number of port.
399 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
401 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
402 @retval EFI_TIMEOUT The FIS disable setting is time out.
403 @retval EFI_UNSUPPORTED The port is in running state.
404 @retval EFI_SUCCESS The FIS disable successfully.
409 AhciDisableFisReceive (
410 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
418 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
419 Data
= AhciReadReg (PciIo
, Offset
);
422 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
424 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
425 return EFI_UNSUPPORTED
;
429 // Check if the Fis receive DMA engine for the port is running.
431 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
435 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_FRE
));
437 return AhciWaitMmioSet (
440 EFI_AHCI_PORT_CMD_FR
,
447 Build the command list, command table and prepare the fis receiver.
449 @param PciIo The PCI IO protocol instance.
450 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
451 @param Port The number of port.
452 @param PortMultiplier The timeout value of stop.
453 @param CommandFis The control fis will be used for the transfer.
454 @param CommandList The command list will be used for the transfer.
455 @param AtapiCommand The atapi command will be used for the transfer.
456 @param AtapiCommandLength The length of the atapi command.
457 @param CommandSlotNumber The command slot will be used for the transfer.
458 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
459 @param DataLength The data count to be transferred.
465 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
466 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
468 IN UINT8 PortMultiplier
,
469 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
470 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
471 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
472 IN UINT8 AtapiCommandLength
,
473 IN UINT8 CommandSlotNumber
,
474 IN OUT VOID
*DataPhysicalAddr
,
489 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
492 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
493 // It also limits that the maximum amount of the PRDT entry in the command table
496 ASSERT (PrdtNumber
<= 65535);
498 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
500 BaseAddr
= Data64
.Uint64
;
502 ZeroMem ((VOID
*)((UINTN
)BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
504 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
506 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
508 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
510 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
511 if (AtapiCommand
!= NULL
) {
513 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
518 CommandList
->AhciCmdA
= 1;
519 CommandList
->AhciCmdP
= 1;
521 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
523 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
526 RemainedData
= (UINTN
)DataLength
;
527 MemAddr
= (UINTN
)DataPhysicalAddr
;
528 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
530 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
531 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
532 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
534 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
537 Data64
.Uint64
= (UINT64
)MemAddr
;
538 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
539 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
540 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
541 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
545 // Set the last PRDT to Interrupt On Complete
547 if (PrdtNumber
> 0) {
548 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
552 (VOID
*)((UINTN
)AhciRegisters
->AhciCmdList
+ (UINTN
)CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
554 sizeof (EFI_AHCI_COMMAND_LIST
)
557 Data64
.Uint64
= (UINT64
)(UINTN
)AhciRegisters
->AhciCommandTablePciAddr
;
558 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
559 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
560 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
566 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
567 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
572 AhciBuildCommandFis (
573 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
574 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
577 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
579 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
581 // Indicator it's a command
583 CmdFis
->AhciCFisCmdInd
= 0x1;
584 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
586 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
587 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
589 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
590 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
592 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
593 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
595 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
596 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
598 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
599 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
601 CmdFis
->AhciCFisDevHead
= (UINT8
)(AtaCommandBlock
->AtaDeviceHead
| 0xE0);
605 Wait until SATA device reports it is ready for operation.
607 @param[in] PciIo Pointer to AHCI controller PciIo.
608 @param[in] Port SATA port index on which to reset.
610 @retval EFI_SUCCESS Device ready for operation.
611 @retval EFI_TIMEOUT Device failed to get ready within required period.
614 AhciWaitDeviceReady (
615 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
619 UINT32 PhyDetectDelay
;
624 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
625 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
627 PhyDetectDelay
= 16 * 1000;
629 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
630 if (AhciReadReg (PciIo
, Offset
) != 0) {
631 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
634 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
636 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
641 MicroSecondDelay (1000);
643 } while (PhyDetectDelay
> 0);
645 if (PhyDetectDelay
== 0) {
646 DEBUG ((DEBUG_ERROR
, "Port %d Device not ready (TFD=0x%X)\n", Port
, Data
));
654 Reset the SATA port. Algorithm follows AHCI spec 1.3.1 section 10.4.2
656 @param[in] PciIo Pointer to AHCI controller PciIo.
657 @param[in] Port SATA port index on which to reset.
659 @retval EFI_SUCCESS Port reset.
660 @retval Others Failed to reset the port.
664 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
671 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
672 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
674 // SW is required to keep DET set to 0x1 at least for 1 milisecond to ensure that
675 // at least one COMRESET signal is sent.
677 MicroSecondDelay (1000);
678 AhciAndReg (PciIo
, Offset
, ~(UINT32
)EFI_AHCI_PORT_SSTS_DET_MASK
);
680 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
681 Status
= AhciWaitMmioSet (PciIo
, Offset
, EFI_AHCI_PORT_SSTS_DET_MASK
, EFI_AHCI_PORT_SSTS_DET_PCE
, ATA_ATAPI_TIMEOUT
);
682 if (EFI_ERROR (Status
)) {
686 return AhciWaitDeviceReady (PciIo
, Port
);
690 Recovers the SATA port from error condition.
691 This function implements algorithm described in
692 AHCI spec 1.3.1 section 6.2.2
694 @param[in] PciIo Pointer to AHCI controller PciIo.
695 @param[in] Port SATA port index on which to check.
697 @retval EFI_SUCCESS Port recovered.
698 @retval Others Failed to recover port.
701 AhciRecoverPortError (
702 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
707 UINT32 PortInterrupt
;
711 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
712 PortInterrupt
= AhciReadReg (PciIo
, Offset
);
713 if ((PortInterrupt
& EFI_AHCI_PORT_IS_FATAL_ERROR_MASK
) == 0) {
715 // No fatal error detected. Exit with success as port should still be operational.
716 // No need to clear IS as it will be cleared when the next command starts.
721 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
722 AhciAndReg (PciIo
, Offset
, ~(UINT32
)EFI_AHCI_PORT_CMD_ST
);
724 Status
= AhciWaitMmioSet (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CR
, 0, ATA_ATAPI_TIMEOUT
);
725 if (EFI_ERROR (Status
)) {
726 DEBUG ((DEBUG_ERROR
, "Ahci port %d is in hung state, aborting recovery\n", Port
));
731 // If TFD.BSY or TFD.DRQ is still set it means that drive is hung and software has
732 // to reset it before sending any additional commands.
734 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
735 PortTfd
= AhciReadReg (PciIo
, Offset
);
736 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
737 Status
= AhciResetPort (PciIo
, Port
);
738 if (EFI_ERROR (Status
)) {
739 DEBUG ((DEBUG_ERROR
, "Failed to reset the port %d\n", Port
));
747 Checks if specified FIS has been received.
749 @param[in] PciIo Pointer to AHCI controller PciIo.
750 @param[in] Port SATA port index on which to check.
751 @param[in] FisType FIS type for which to check.
753 @retval EFI_SUCCESS FIS received.
754 @retval EFI_NOT_READY FIS not received yet.
755 @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
758 AhciCheckFisReceived (
759 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
761 IN SATA_FIS_TYPE FisType
765 UINT32 PortInterrupt
;
768 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
769 PortInterrupt
= AhciReadReg (PciIo
, Offset
);
770 if ((PortInterrupt
& EFI_AHCI_PORT_IS_ERROR_MASK
) != 0) {
771 DEBUG ((DEBUG_ERROR
, "AHCI: Error interrupt reported PxIS: %X\n", PortInterrupt
));
772 return EFI_DEVICE_ERROR
;
776 // For PIO setup FIS - According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
777 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
778 // after the transaction is finished successfully.
779 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
780 // By this way, we can know if there is a real error happened.
782 if (((FisType
== SataFisD2H
) && ((PortInterrupt
& EFI_AHCI_PORT_IS_DHRS
) != 0)) ||
783 ((FisType
== SataFisPioSetup
) && ((PortInterrupt
& (EFI_AHCI_PORT_IS_PSS
| EFI_AHCI_PORT_IS_DHRS
)) != 0)) ||
784 ((FisType
== SataFisDmaSetup
) && ((PortInterrupt
& (EFI_AHCI_PORT_IS_DSS
| EFI_AHCI_PORT_IS_DHRS
)) != 0)))
786 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
787 PortTfd
= AhciReadReg (PciIo
, (UINT32
)Offset
);
788 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
789 return EFI_DEVICE_ERROR
;
795 return EFI_NOT_READY
;
799 Waits until specified FIS has been received.
801 @param[in] PciIo Pointer to AHCI controller PciIo.
802 @param[in] Port SATA port index on which to check.
803 @param[in] Timeout Time after which function should stop polling.
804 @param[in] FisType FIS type for which to check.
806 @retval EFI_SUCCESS FIS received.
807 @retval EFI_TIMEOUT FIS failed to arrive within a specified time period.
808 @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
811 AhciWaitUntilFisReceived (
812 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
815 IN SATA_FIS_TYPE FisType
819 BOOLEAN InfiniteWait
;
822 Delay
= DivU64x32 (Timeout
, 1000) + 1;
826 InfiniteWait
= FALSE
;
830 Status
= AhciCheckFisReceived (PciIo
, Port
, FisType
);
831 if (Status
!= EFI_NOT_READY
) {
836 // Stall for 100 microseconds.
838 MicroSecondDelay (100);
840 } while (InfiniteWait
|| (Delay
> 0));
846 Prints contents of the ATA command block into the debug port.
848 @param[in] AtaCommandBlock AtaCommandBlock to print.
849 @param[in] DebugLevel Debug level on which to print.
852 AhciPrintCommandBlock (
853 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
857 DEBUG ((DebugLevel
, "ATA COMMAND BLOCK:\n"));
858 DEBUG ((DebugLevel
, "AtaCommand: %d\n", AtaCommandBlock
->AtaCommand
));
859 DEBUG ((DebugLevel
, "AtaFeatures: %X\n", AtaCommandBlock
->AtaFeatures
));
860 DEBUG ((DebugLevel
, "AtaSectorNumber: %d\n", AtaCommandBlock
->AtaSectorNumber
));
861 DEBUG ((DebugLevel
, "AtaCylinderLow: %X\n", AtaCommandBlock
->AtaCylinderHigh
));
862 DEBUG ((DebugLevel
, "AtaCylinderHigh: %X\n", AtaCommandBlock
->AtaCylinderHigh
));
863 DEBUG ((DebugLevel
, "AtaDeviceHead: %d\n", AtaCommandBlock
->AtaDeviceHead
));
864 DEBUG ((DebugLevel
, "AtaSectorNumberExp: %d\n", AtaCommandBlock
->AtaSectorNumberExp
));
865 DEBUG ((DebugLevel
, "AtaCylinderLowExp: %X\n", AtaCommandBlock
->AtaCylinderLowExp
));
866 DEBUG ((DebugLevel
, "AtaCylinderHighExp: %X\n", AtaCommandBlock
->AtaCylinderHighExp
));
867 DEBUG ((DebugLevel
, "AtaFeaturesExp: %X\n", AtaCommandBlock
->AtaFeaturesExp
));
868 DEBUG ((DebugLevel
, "AtaSectorCount: %d\n", AtaCommandBlock
->AtaSectorCount
));
869 DEBUG ((DebugLevel
, "AtaSectorCountExp: %d\n", AtaCommandBlock
->AtaSectorCountExp
));
873 Prints contents of the ATA status block into the debug port.
875 @param[in] AtaStatusBlock AtaStatusBlock to print.
876 @param[in] DebugLevel Debug level on which to print.
879 AhciPrintStatusBlock (
880 IN EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
887 if (AtaStatusBlock
== NULL
) {
892 // Only print status and error since we have all of the rest printed as
893 // a part of command block print.
895 DEBUG ((DebugLevel
, "ATA STATUS BLOCK:\n"));
896 DEBUG ((DebugLevel
, "AtaStatus: %d\n", AtaStatusBlock
->AtaStatus
));
897 DEBUG ((DebugLevel
, "AtaError: %d\n", AtaStatusBlock
->AtaError
));
901 Start a PIO data transfer on specific port.
903 @param[in] PciIo The PCI IO protocol instance.
904 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
905 @param[in] Port The number of port.
906 @param[in] PortMultiplier The timeout value of stop.
907 @param[in] AtapiCommand The atapi command will be used for the
909 @param[in] AtapiCommandLength The length of the atapi command.
910 @param[in] Read The transfer direction.
911 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
912 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
913 @param[in, out] MemoryAddr The pointer to the data buffer.
914 @param[in] DataCount The data count to be transferred.
915 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
916 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
917 used by non-blocking mode.
919 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
920 @retval EFI_TIMEOUT The operation is time out.
921 @retval EFI_UNSUPPORTED The device is not ready for transfer.
922 @retval EFI_SUCCESS The PIO data transfer executes successfully.
928 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
929 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
931 IN UINT8 PortMultiplier
,
932 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
933 IN UINT8 AtapiCommandLength
,
935 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
936 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
937 IN OUT VOID
*MemoryAddr
,
940 IN ATA_NONBLOCK_TASK
*Task
944 EFI_PHYSICAL_ADDRESS PhyAddr
;
947 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
948 EFI_AHCI_COMMAND_FIS CFis
;
949 EFI_AHCI_COMMAND_LIST CmdList
;
952 EFI_STATUS RecoveryStatus
;
955 Flag
= EfiPciIoOperationBusMasterWrite
;
957 Flag
= EfiPciIoOperationBusMasterRead
;
961 // construct command list and command table with pci bus address
963 MapLength
= DataCount
;
964 Status
= PciIo
->Map (
973 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
974 return EFI_BAD_BUFFER_SIZE
;
978 // Package read needed
980 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
982 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
984 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
985 CmdList
.AhciCmdW
= Read
? 0 : 1;
987 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
998 (VOID
*)(UINTN
)PhyAddr
,
1002 DEBUG ((DEBUG_VERBOSE
, "Starting command for PIO transfer:\n"));
1003 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1004 Status
= AhciStartCommand (
1010 if (EFI_ERROR (Status
)) {
1014 if (Read
&& (AtapiCommand
== 0)) {
1015 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisPioSetup
);
1016 if (Status
== EFI_SUCCESS
) {
1017 PrdCount
= *(volatile UINT32
*)(&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
1018 if (PrdCount
== DataCount
) {
1019 Status
= EFI_SUCCESS
;
1021 Status
= EFI_DEVICE_ERROR
;
1025 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1028 if (Status
== EFI_DEVICE_ERROR
) {
1029 DEBUG ((DEBUG_ERROR
, "PIO command failed at retry %d\n", Retry
));
1030 RecoveryStatus
= AhciRecoverPortError (PciIo
, Port
);
1031 if (EFI_ERROR (RecoveryStatus
)) {
1045 AhciDisableFisReceive (
1056 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1058 if (Status
== EFI_DEVICE_ERROR
) {
1059 DEBUG ((DEBUG_ERROR
, "Failed to execute command for PIO transfer:\n"));
1061 // Repeat command block here to make sure it is printed on
1062 // device error debug level.
1064 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1065 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1067 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1074 Start a DMA data transfer on specific port
1076 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
1077 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1078 @param[in] Port The number of port.
1079 @param[in] PortMultiplier The timeout value of stop.
1080 @param[in] AtapiCommand The atapi command will be used for the
1082 @param[in] AtapiCommandLength The length of the atapi command.
1083 @param[in] Read The transfer direction.
1084 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1085 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1086 @param[in, out] MemoryAddr The pointer to the data buffer.
1087 @param[in] DataCount The data count to be transferred.
1088 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1089 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1090 used by non-blocking mode.
1092 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
1093 @retval EFI_TIMEOUT The operation is time out.
1094 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1095 @retval EFI_SUCCESS The DMA data transfer executes successfully.
1101 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
1102 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1104 IN UINT8 PortMultiplier
,
1105 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1106 IN UINT8 AtapiCommandLength
,
1108 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1109 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1110 IN OUT VOID
*MemoryAddr
,
1111 IN UINT32 DataCount
,
1113 IN ATA_NONBLOCK_TASK
*Task
1117 EFI_PHYSICAL_ADDRESS PhyAddr
;
1120 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
1121 EFI_AHCI_COMMAND_FIS CFis
;
1122 EFI_AHCI_COMMAND_LIST CmdList
;
1123 EFI_PCI_IO_PROTOCOL
*PciIo
;
1126 EFI_STATUS RecoveryStatus
;
1129 PciIo
= Instance
->PciIo
;
1131 if (PciIo
== NULL
) {
1132 return EFI_INVALID_PARAMETER
;
1136 // Set Status to suppress incorrect compiler/analyzer warnings
1138 Status
= EFI_SUCCESS
;
1141 // DMA buffer allocation. Needs to be done only once for both sync and async
1142 // DMA transfers irrespective of number of retries.
1144 if ((Task
== NULL
) || ((Task
!= NULL
) && (Task
->Map
== NULL
))) {
1146 Flag
= EfiPciIoOperationBusMasterWrite
;
1148 Flag
= EfiPciIoOperationBusMasterRead
;
1151 MapLength
= DataCount
;
1152 Status
= PciIo
->Map (
1161 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
1162 return EFI_BAD_BUFFER_SIZE
;
1170 if ((Task
== NULL
) || ((Task
!= NULL
) && !Task
->IsStart
)) {
1171 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1173 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1175 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1176 CmdList
.AhciCmdW
= Read
? 0 : 1;
1181 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
1183 // Delay 100us to simulate the blocking time out checking.
1185 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1186 while (!IsListEmpty (&Instance
->NonBlockingTaskList
)) {
1187 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
1191 MicroSecondDelay (100);
1194 gBS
->RestoreTPL (OldTpl
);
1195 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1206 (VOID
*)(UINTN
)PhyAddr
,
1210 DEBUG ((DEBUG_VERBOSE
, "Starting command for sync DMA transfer:\n"));
1211 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1212 Status
= AhciStartCommand (
1218 if (EFI_ERROR (Status
)) {
1222 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1223 if (Status
== EFI_DEVICE_ERROR
) {
1224 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Retry
));
1225 RecoveryStatus
= AhciRecoverPortError (PciIo
, Port
);
1226 if (EFI_ERROR (RecoveryStatus
)) {
1234 if (!Task
->IsStart
) {
1245 (VOID
*)(UINTN
)PhyAddr
,
1249 DEBUG ((DEBUG_VERBOSE
, "Starting command for async DMA transfer:\n"));
1250 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1251 Status
= AhciStartCommand (
1257 if (!EFI_ERROR (Status
)) {
1258 Task
->IsStart
= TRUE
;
1262 if (Task
->IsStart
) {
1263 Status
= AhciCheckFisReceived (PciIo
, Port
, SataFisD2H
);
1264 if (Status
== EFI_DEVICE_ERROR
) {
1265 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Task
->RetryTimes
));
1266 RecoveryStatus
= AhciRecoverPortError (PciIo
, Port
);
1268 // If recovery passed mark the Task as not started and change the status
1269 // to EFI_NOT_READY. This will make the higher level call this function again
1270 // and on next call the command will be re-issued due to IsStart being FALSE.
1271 // This also makes the next condition decrement the RetryTimes.
1273 if (RecoveryStatus
== EFI_SUCCESS
) {
1274 Task
->IsStart
= FALSE
;
1275 Status
= EFI_NOT_READY
;
1279 if (Status
== EFI_NOT_READY
) {
1280 if (!Task
->InfiniteWait
&& (Task
->RetryTimes
== 0)) {
1281 Status
= EFI_TIMEOUT
;
1290 // For Blocking mode, the command should be stopped, the Fis should be disabled
1291 // and the PciIo should be unmapped.
1292 // For non-blocking mode, only when a error is happened (if the return status is
1293 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1294 // context cleanup, then set the packet's Asb status.
1296 if ((Task
== NULL
) ||
1297 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1306 AhciDisableFisReceive (
1314 (Task
!= NULL
) ? Task
->Map
: Map
1318 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1322 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1324 if (Status
== EFI_DEVICE_ERROR
) {
1325 DEBUG ((DEBUG_ERROR
, "Failed to execute command for DMA transfer:\n"));
1327 // Repeat command block here to make sure it is printed on
1328 // device error debug level.
1330 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1331 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1333 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1340 Start a non data transfer on specific port.
1342 @param[in] PciIo The PCI IO protocol instance.
1343 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1344 @param[in] Port The number of port.
1345 @param[in] PortMultiplier The timeout value of stop.
1346 @param[in] AtapiCommand The atapi command will be used for the
1348 @param[in] AtapiCommandLength The length of the atapi command.
1349 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1350 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1351 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1352 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1353 used by non-blocking mode.
1355 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1356 @retval EFI_TIMEOUT The operation is time out.
1357 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1358 @retval EFI_SUCCESS The non data transfer executes successfully.
1363 AhciNonDataTransfer (
1364 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1365 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1367 IN UINT8 PortMultiplier
,
1368 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1369 IN UINT8 AtapiCommandLength
,
1370 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1371 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1373 IN ATA_NONBLOCK_TASK
*Task
1377 EFI_AHCI_COMMAND_FIS CFis
;
1378 EFI_AHCI_COMMAND_LIST CmdList
;
1380 EFI_STATUS RecoveryStatus
;
1383 // Package read needed
1385 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1387 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1389 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1391 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1406 DEBUG ((DEBUG_VERBOSE
, "Starting command for non data transfer:\n"));
1407 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1408 Status
= AhciStartCommand (
1414 if (EFI_ERROR (Status
)) {
1418 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1419 if (Status
== EFI_DEVICE_ERROR
) {
1420 DEBUG ((DEBUG_ERROR
, "Non data transfer failed at retry %d\n", Retry
));
1421 RecoveryStatus
= AhciRecoverPortError (PciIo
, Port
);
1422 if (EFI_ERROR (RecoveryStatus
)) {
1436 AhciDisableFisReceive (
1442 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1444 if (Status
== EFI_DEVICE_ERROR
) {
1445 DEBUG ((DEBUG_ERROR
, "Failed to execute command for non data transfer:\n"));
1447 // Repeat command block here to make sure it is printed on
1448 // device error debug level.
1450 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1451 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1453 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1460 Stop command running for giving port
1462 @param PciIo The PCI IO protocol instance.
1463 @param Port The number of port.
1464 @param Timeout The timeout value of stop, uses 100ns as a unit.
1466 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1467 @retval EFI_TIMEOUT The operation is time out.
1468 @retval EFI_SUCCESS The command stop successfully.
1474 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1482 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1483 Data
= AhciReadReg (PciIo
, Offset
);
1485 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1489 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1490 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_ST
));
1493 return AhciWaitMmioSet (
1496 EFI_AHCI_PORT_CMD_CR
,
1503 Start command for give slot on specific port.
1505 @param PciIo The PCI IO protocol instance.
1506 @param Port The number of port.
1507 @param CommandSlot The number of Command Slot.
1508 @param Timeout The timeout value of start, uses 100ns as a unit.
1510 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1511 @retval EFI_TIMEOUT The operation is time out.
1512 @retval EFI_SUCCESS The command start successfully.
1518 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1520 IN UINT8 CommandSlot
,
1533 // Collect AHCI controller information
1535 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1537 CmdSlotBit
= (UINT32
)(1 << CommandSlot
);
1539 AhciClearPortStatus (
1544 Status
= AhciEnableFisReceive (
1550 if (EFI_ERROR (Status
)) {
1554 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1555 PortStatus
= AhciReadReg (PciIo
, Offset
);
1558 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1559 StartCmd
= AhciReadReg (PciIo
, Offset
);
1560 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1561 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1564 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1565 PortTfd
= AhciReadReg (PciIo
, Offset
);
1567 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1568 if ((Capability
& BIT24
) != 0) {
1569 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1570 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1575 EFI_AHCI_PORT_CMD_CLO
,
1582 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1583 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1586 // Setting the command
1588 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1589 AhciAndReg (PciIo
, Offset
, 0);
1590 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1598 @param PciIo The PCI IO protocol instance.
1599 @param Timeout The timeout value of reset, uses 100ns as a unit.
1601 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1602 @retval EFI_TIMEOUT The reset operation is time out.
1603 @retval EFI_SUCCESS AHCI controller is reset successfully.
1609 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1617 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1619 Value
= AhciReadReg (PciIo
, EFI_AHCI_GHC_OFFSET
);
1621 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
1622 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1625 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1627 Delay
= DivU64x32 (Timeout
, 1000) + 1;
1630 Value
= AhciReadReg (PciIo
, EFI_AHCI_GHC_OFFSET
);
1632 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1637 // Stall for 100 microseconds.
1639 MicroSecondDelay (100);
1642 } while (Delay
> 0);
1652 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1654 @param PciIo The PCI IO protocol instance.
1655 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1656 @param Port The number of port.
1657 @param PortMultiplier The port multiplier port number.
1658 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1660 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1661 @retval Others Fail to get return status data.
1666 AhciAtaSmartReturnStatusCheck (
1667 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1668 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1670 IN UINT8 PortMultiplier
,
1671 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1675 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1681 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1683 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1684 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1685 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1686 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1689 // Send S.M.A.R.T Read Return Status command to device
1691 Status
= AhciNonDataTransfer (
1695 (UINT8
)PortMultiplier
,
1704 if (EFI_ERROR (Status
)) {
1705 REPORT_STATUS_CODE (
1706 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1707 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1709 return EFI_DEVICE_ERROR
;
1712 REPORT_STATUS_CODE (
1714 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1717 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1719 Value
= *(UINT32
*)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1721 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1722 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1723 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1725 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1727 // The threshold exceeded condition is not detected by the device
1729 DEBUG ((DEBUG_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1730 REPORT_STATUS_CODE (
1732 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1734 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1736 // The threshold exceeded condition is detected by the device
1738 DEBUG ((DEBUG_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1739 REPORT_STATUS_CODE (
1741 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1750 Enable SMART command of the disk if supported.
1752 @param PciIo The PCI IO protocol instance.
1753 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1754 @param Port The number of port.
1755 @param PortMultiplier The port multiplier port number.
1756 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1757 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1762 AhciAtaSmartSupport (
1763 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1764 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1766 IN UINT8 PortMultiplier
,
1767 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1768 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1772 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1775 // Detect if the device supports S.M.A.R.T.
1777 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1779 // S.M.A.R.T is not supported by the device
1783 "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1787 REPORT_STATUS_CODE (
1788 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1789 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1793 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1795 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1796 REPORT_STATUS_CODE (
1798 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1801 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1803 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1804 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1805 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1806 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1809 // Send S.M.A.R.T Enable command to device
1811 Status
= AhciNonDataTransfer (
1815 (UINT8
)PortMultiplier
,
1824 if (!EFI_ERROR (Status
)) {
1826 // Send S.M.A.R.T AutoSave command to device
1828 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1830 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1831 AtaCommandBlock
.AtaFeatures
= 0xD2;
1832 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1833 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1834 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1836 Status
= AhciNonDataTransfer (
1840 (UINT8
)PortMultiplier
,
1851 AhciAtaSmartReturnStatusCheck (
1855 (UINT8
)PortMultiplier
,
1861 "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1871 Send Buffer cmd to specific device.
1873 @param PciIo The PCI IO protocol instance.
1874 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1875 @param Port The number of port.
1876 @param PortMultiplier The port multiplier port number.
1877 @param Buffer The data buffer to store IDENTIFY PACKET data.
1879 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1880 @retval EFI_TIMEOUT The operation is time out.
1881 @retval EFI_UNSUPPORTED The device is not ready for executing.
1882 @retval EFI_SUCCESS The cmd executes successfully.
1888 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1889 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1891 IN UINT8 PortMultiplier
,
1892 IN OUT EFI_IDENTIFY_DATA
*Buffer
1896 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1897 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1899 if ((PciIo
== NULL
) || (AhciRegisters
== NULL
) || (Buffer
== NULL
)) {
1900 return EFI_INVALID_PARAMETER
;
1903 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1904 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1906 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1907 AtaCommandBlock
.AtaSectorCount
= 1;
1909 Status
= AhciPioTransfer (
1920 sizeof (EFI_IDENTIFY_DATA
),
1929 Send Buffer cmd to specific device.
1931 @param PciIo The PCI IO protocol instance.
1932 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1933 @param Port The number of port.
1934 @param PortMultiplier The port multiplier port number.
1935 @param Buffer The data buffer to store IDENTIFY PACKET data.
1937 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1938 @retval EFI_TIMEOUT The operation is time out.
1939 @retval EFI_UNSUPPORTED The device is not ready for executing.
1940 @retval EFI_SUCCESS The cmd executes successfully.
1945 AhciIdentifyPacket (
1946 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1947 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1949 IN UINT8 PortMultiplier
,
1950 IN OUT EFI_IDENTIFY_DATA
*Buffer
1954 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1955 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1957 if ((PciIo
== NULL
) || (AhciRegisters
== NULL
)) {
1958 return EFI_INVALID_PARAMETER
;
1961 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1962 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1964 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1965 AtaCommandBlock
.AtaSectorCount
= 1;
1967 Status
= AhciPioTransfer (
1978 sizeof (EFI_IDENTIFY_DATA
),
1987 Send SET FEATURE cmd on specific device.
1989 @param PciIo The PCI IO protocol instance.
1990 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1991 @param Port The number of port.
1992 @param PortMultiplier The port multiplier port number.
1993 @param Feature The data to send Feature register.
1994 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1995 @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1997 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1998 @retval EFI_TIMEOUT The operation is time out.
1999 @retval EFI_UNSUPPORTED The device is not ready for executing.
2000 @retval EFI_SUCCESS The cmd executes successfully.
2005 AhciDeviceSetFeature (
2006 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2007 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2009 IN UINT8 PortMultiplier
,
2011 IN UINT32 FeatureSpecificData
,
2016 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2017 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2019 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2020 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2022 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
2023 AtaCommandBlock
.AtaFeatures
= (UINT8
)Feature
;
2024 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
)(Feature
>> 8);
2025 AtaCommandBlock
.AtaSectorCount
= (UINT8
)FeatureSpecificData
;
2026 AtaCommandBlock
.AtaSectorNumber
= (UINT8
)(FeatureSpecificData
>> 8);
2027 AtaCommandBlock
.AtaCylinderLow
= (UINT8
)(FeatureSpecificData
>> 16);
2028 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
)(FeatureSpecificData
>> 24);
2030 Status
= AhciNonDataTransfer (
2034 (UINT8
)PortMultiplier
,
2047 This function is used to send out ATAPI commands conforms to the Packet Command
2050 @param PciIo The PCI IO protocol instance.
2051 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2052 @param Port The number of port.
2053 @param PortMultiplier The number of port multiplier.
2054 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
2056 @retval EFI_SUCCESS send out the ATAPI packet command successfully
2057 and device sends data successfully.
2058 @retval EFI_DEVICE_ERROR the device failed to send data.
2063 AhciPacketCommandExecute (
2064 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2065 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2067 IN UINT8 PortMultiplier
,
2068 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
2074 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2075 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2078 if ((Packet
== NULL
) || (Packet
->Cdb
== NULL
)) {
2079 return EFI_INVALID_PARAMETER
;
2082 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2083 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2084 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
2088 AtaCommandBlock
.AtaFeatures
= 0x00;
2090 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
2091 // determine how many data should be transferred.
2093 AtaCommandBlock
.AtaCylinderLow
= (UINT8
)(ATAPI_MAX_BYTE_COUNT
& 0x00ff);
2094 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
)(ATAPI_MAX_BYTE_COUNT
>> 8);
2096 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
2097 Buffer
= Packet
->InDataBuffer
;
2098 Length
= Packet
->InTransferLength
;
2101 Buffer
= Packet
->OutDataBuffer
;
2102 Length
= Packet
->OutTransferLength
;
2107 Status
= AhciNonDataTransfer (
2120 Status
= AhciPioTransfer (
2141 Allocate transfer-related data struct which is used at AHCI mode.
2143 @param PciIo The PCI IO protocol instance.
2144 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2149 AhciCreateTransferDescriptor (
2150 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2151 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
2159 UINT32 PortImplementBitMap
;
2160 UINT8 MaxPortNumber
;
2161 UINT8 MaxCommandSlotNumber
;
2162 BOOLEAN Support64Bit
;
2163 UINT64 MaxReceiveFisSize
;
2164 UINT64 MaxCommandListSize
;
2165 UINT64 MaxCommandTableSize
;
2166 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
2167 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
2168 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
2172 // Collect AHCI controller information
2174 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2176 // Get the number of command slots per port supported by this HBA.
2178 MaxCommandSlotNumber
= (UINT8
)(((Capability
& 0x1F00) >> 8) + 1);
2179 Support64Bit
= (BOOLEAN
)(((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2181 PortImplementBitMap
= AhciReadReg (PciIo
, EFI_AHCI_PI_OFFSET
);
2183 // Get the highest bit of implemented ports which decides how many bytes are allocated for received FIS.
2185 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32 (PortImplementBitMap
) + 1);
2186 if (MaxPortNumber
== 0) {
2187 return EFI_DEVICE_ERROR
;
2190 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2191 Status
= PciIo
->AllocateBuffer (
2194 EfiBootServicesData
,
2195 EFI_SIZE_TO_PAGES ((UINTN
)MaxReceiveFisSize
),
2200 if (EFI_ERROR (Status
)) {
2201 return EFI_OUT_OF_RESOURCES
;
2204 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2206 AhciRegisters
->AhciRFis
= Buffer
;
2207 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2208 Bytes
= (UINTN
)MaxReceiveFisSize
;
2210 Status
= PciIo
->Map (
2212 EfiPciIoOperationBusMasterCommonBuffer
,
2216 &AhciRegisters
->MapRFis
2219 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2221 // Map error or unable to map the whole RFis buffer into a contiguous region.
2223 Status
= EFI_OUT_OF_RESOURCES
;
2227 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2229 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2231 Status
= EFI_DEVICE_ERROR
;
2235 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2238 // Allocate memory for command list
2239 // Note that the implementation is a single task model which only use a command list for all ports.
2242 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2243 Status
= PciIo
->AllocateBuffer (
2246 EfiBootServicesData
,
2247 EFI_SIZE_TO_PAGES ((UINTN
)MaxCommandListSize
),
2252 if (EFI_ERROR (Status
)) {
2254 // Free mapped resource.
2256 Status
= EFI_OUT_OF_RESOURCES
;
2260 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2262 AhciRegisters
->AhciCmdList
= Buffer
;
2263 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2264 Bytes
= (UINTN
)MaxCommandListSize
;
2266 Status
= PciIo
->Map (
2268 EfiPciIoOperationBusMasterCommonBuffer
,
2271 &AhciCmdListPciAddr
,
2272 &AhciRegisters
->MapCmdList
2275 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2277 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2279 Status
= EFI_OUT_OF_RESOURCES
;
2283 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2285 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2287 Status
= EFI_DEVICE_ERROR
;
2291 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2294 // Allocate memory for command table
2295 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2298 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2300 Status
= PciIo
->AllocateBuffer (
2303 EfiBootServicesData
,
2304 EFI_SIZE_TO_PAGES ((UINTN
)MaxCommandTableSize
),
2309 if (EFI_ERROR (Status
)) {
2311 // Free mapped resource.
2313 Status
= EFI_OUT_OF_RESOURCES
;
2317 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2319 AhciRegisters
->AhciCommandTable
= Buffer
;
2320 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2321 Bytes
= (UINTN
)MaxCommandTableSize
;
2323 Status
= PciIo
->Map (
2325 EfiPciIoOperationBusMasterCommonBuffer
,
2328 &AhciCommandTablePciAddr
,
2329 &AhciRegisters
->MapCommandTable
2332 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2334 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2336 Status
= EFI_OUT_OF_RESOURCES
;
2340 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2342 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2344 Status
= EFI_DEVICE_ERROR
;
2348 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2352 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2357 AhciRegisters
->MapCommandTable
2362 EFI_SIZE_TO_PAGES ((UINTN
)MaxCommandTableSize
),
2363 AhciRegisters
->AhciCommandTable
2368 AhciRegisters
->MapCmdList
2373 EFI_SIZE_TO_PAGES ((UINTN
)MaxCommandListSize
),
2374 AhciRegisters
->AhciCmdList
2379 AhciRegisters
->MapRFis
2384 EFI_SIZE_TO_PAGES ((UINTN
)MaxReceiveFisSize
),
2385 AhciRegisters
->AhciRFis
2392 Read logs from SATA device.
2394 @param PciIo The PCI IO protocol instance.
2395 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2396 @param Port The number of port.
2397 @param PortMultiplier The multiplier of port.
2398 @param Buffer The data buffer to store SATA logs.
2399 @param LogNumber The address of the log.
2400 @param PageNumber The page number of the log.
2402 @retval EFI_INVALID_PARAMETER PciIo, AhciRegisters or Buffer is NULL.
2403 @retval others Return status of AhciPioTransfer().
2407 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2408 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2410 IN UINT8 PortMultiplier
,
2411 IN OUT UINT8
*Buffer
,
2416 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2417 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2419 if ((PciIo
== NULL
) || (AhciRegisters
== NULL
) || (Buffer
== NULL
)) {
2420 return EFI_INVALID_PARAMETER
;
2424 /// Read log from device
2426 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2427 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2428 ZeroMem (Buffer
, 512);
2430 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_LOG_EXT
;
2431 AtaCommandBlock
.AtaSectorCount
= 1;
2432 AtaCommandBlock
.AtaSectorNumber
= LogNumber
;
2433 AtaCommandBlock
.AtaCylinderLow
= PageNumber
;
2435 return AhciPioTransfer (
2453 Enable DEVSLP of the disk if supported.
2455 @param PciIo The PCI IO protocol instance.
2456 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2457 @param Port The number of port.
2458 @param PortMultiplier The multiplier of port.
2459 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2461 @retval EFI_SUCCESS The DEVSLP is enabled per policy successfully.
2462 @retval EFI_UNSUPPORTED The DEVSLP isn't supported by the controller/device and policy requires to enable it.
2466 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2467 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2469 IN UINT8 PortMultiplier
,
2470 IN EFI_IDENTIFY_DATA
*IdentifyData
2477 DEVSLP_TIMING_VARIABLES DevSlpTiming
;
2481 if (mAtaAtapiPolicy
->DeviceSleepEnable
!= 1) {
2486 // Do not enable DevSlp if DevSlp is not supported.
2488 Capability2
= AhciReadReg (PciIo
, AHCI_CAPABILITY2_OFFSET
);
2489 DEBUG ((DEBUG_INFO
, "AHCI CAPABILITY2 = %08x\n", Capability2
));
2490 if ((Capability2
& AHCI_CAP2_SDS
) == 0) {
2491 return EFI_UNSUPPORTED
;
2495 // Do not enable DevSlp if DevSlp is not present
2496 // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2498 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
;
2499 PortCmd
= AhciReadReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
);
2500 PortDevSlp
= AhciReadReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
);
2501 DEBUG ((DEBUG_INFO
, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd
, PortDevSlp
));
2502 if (((PortDevSlp
& AHCI_PORT_DEVSLP_DSP
) == 0) ||
2503 ((PortCmd
& (EFI_AHCI_PORT_CMD_HPCP
| EFI_AHCI_PORT_CMD_MPSP
)) != 0)
2506 return EFI_UNSUPPORTED
;
2510 // Do not enable DevSlp if the device doesn't support DevSlp
2514 "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2515 IdentifyData
->AtaData
.reserved_77
,
2516 IdentifyData
->AtaData
.serial_ata_features_supported
,
2517 IdentifyData
->AtaData
.serial_ata_features_enabled
2519 if ((IdentifyData
->AtaData
.serial_ata_features_supported
& BIT8
) == 0) {
2522 "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2526 return EFI_UNSUPPORTED
;
2530 // Enable DevSlp when it is not enabled.
2532 if ((IdentifyData
->AtaData
.serial_ata_features_enabled
& BIT8
) != 0) {
2533 Status
= AhciDeviceSetFeature (
2538 ATA_SUB_CMD_ENABLE_SATA_FEATURE
,
2544 "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2549 if (EFI_ERROR (Status
)) {
2554 Status
= AhciReadLogExt (PciIo
, AhciRegisters
, Port
, PortMultiplier
, LogData
, 0x30, 0x08);
2557 // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2559 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
& ~EFI_AHCI_PORT_CMD_ST
);
2560 PortDevSlp
&= ~AHCI_PORT_DEVSLP_ADSE
;
2561 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2564 // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2566 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DETO_MASK
;
2567 PortDevSlp
&= ~AHCI_PORT_DEVSLP_MDAT_MASK
;
2568 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2569 DEBUG ((DEBUG_INFO
, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port
, PortMultiplier
, Status
));
2570 if (EFI_ERROR (Status
)) {
2572 // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2574 ZeroMem (&DevSlpTiming
, sizeof (DevSlpTiming
));
2576 CopyMem (&DevSlpTiming
, &LogData
[48], sizeof (DevSlpTiming
));
2579 "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2580 DevSlpTiming
.Supported
,
2587 // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2589 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Deto
== 0)) {
2590 DevSlpTiming
.Deto
= 20;
2594 // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2596 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Madt
== 0)) {
2597 DevSlpTiming
.Madt
= 10;
2600 PortDevSlp
|= DevSlpTiming
.Deto
<< 2;
2601 PortDevSlp
|= DevSlpTiming
.Madt
<< 10;
2602 AhciOrReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2604 if (mAtaAtapiPolicy
->AggressiveDeviceSleepEnable
== 1) {
2605 if ((Capability2
& AHCI_CAP2_SADM
) != 0) {
2606 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DITO_MASK
;
2607 PortDevSlp
|= (625 << 15);
2608 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2610 PortDevSlp
|= AHCI_PORT_DEVSLP_ADSE
;
2611 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2615 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
);
2619 "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2630 Spin-up disk if IDD was incomplete or PUIS feature is enabled
2632 @param PciIo The PCI IO protocol instance.
2633 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2634 @param Port The number of port.
2635 @param PortMultiplier The multiplier of port.
2636 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2641 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2642 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2644 IN UINT8 PortMultiplier
,
2645 IN OUT EFI_IDENTIFY_DATA
*IdentifyData
2649 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2650 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2653 if (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
) {
2655 // Use SET_FEATURE subcommand to spin up the device.
2657 Status
= AhciDeviceSetFeature (
2662 ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
,
2668 "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2673 if (EFI_ERROR (Status
)) {
2677 ASSERT (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
);
2680 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2682 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2683 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2685 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2687 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_SECTORS
;
2688 AtaCommandBlock
.AtaSectorCount
= 0x1;
2690 Status
= AhciPioTransfer (
2707 "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2712 if (EFI_ERROR (Status
)) {
2718 // Read the complete IDENTIFY DEVICE data.
2720 ZeroMem (IdentifyData
, sizeof (*IdentifyData
));
2721 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, PortMultiplier
, IdentifyData
);
2722 if (EFI_ERROR (Status
)) {
2725 "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2735 "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2736 IdentifyData
->AtaData
.config
,
2737 IdentifyData
->AtaData
.specific_config
,
2738 IdentifyData
->AtaData
.command_set_supported_83
,
2739 IdentifyData
->AtaData
.command_set_feature_enb_86
2742 // Check if IDD is incomplete
2744 if ((IdentifyData
->AtaData
.config
& BIT2
) != 0) {
2745 return EFI_DEVICE_ERROR
;
2752 Enable/disable/skip PUIS of the disk according to policy.
2754 @param PciIo The PCI IO protocol instance.
2755 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2756 @param Port The number of port.
2757 @param PortMultiplier The multiplier of port.
2762 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2763 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2765 IN UINT8 PortMultiplier
2770 Status
= EFI_SUCCESS
;
2771 if (mAtaAtapiPolicy
->PuisEnable
== 0) {
2772 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_DISABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2773 } else if (mAtaAtapiPolicy
->PuisEnable
== 1) {
2774 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_ENABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2779 "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2780 (mAtaAtapiPolicy
->PuisEnable
== 0) ? "Disable" : (
2781 (mAtaAtapiPolicy
->PuisEnable
== 1) ? "Enable" : "Skip"
2791 Initialize ATA host controller at AHCI mode.
2793 The function is designed to initialize ATA host controller.
2795 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2800 AhciModeInitialization (
2801 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2805 EFI_PCI_IO_PROTOCOL
*PciIo
;
2806 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2808 UINT8 MaxPortNumber
;
2809 UINT32 PortImplementBitMap
;
2811 EFI_AHCI_REGISTERS
*AhciRegisters
;
2817 EFI_IDENTIFY_DATA Buffer
;
2818 EFI_ATA_DEVICE_TYPE DeviceType
;
2819 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2820 EFI_ATA_TRANSFER_MODE TransferMode
;
2821 UINT32 PhyDetectDelay
;
2824 if (Instance
== NULL
) {
2825 return EFI_INVALID_PARAMETER
;
2828 PciIo
= Instance
->PciIo
;
2829 IdeInit
= Instance
->IdeControllerInit
;
2831 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2833 if (EFI_ERROR (Status
)) {
2834 return EFI_DEVICE_ERROR
;
2838 // Collect AHCI controller information
2840 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2843 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2845 Value
= AhciReadReg (PciIo
, EFI_AHCI_GHC_OFFSET
);
2847 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
2848 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2852 // Enable 64-bit DMA support in the PCI layer if this controller
2855 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2856 Status
= PciIo
->Attributes (
2858 EfiPciIoAttributeOperationEnable
,
2859 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2862 if (EFI_ERROR (Status
)) {
2865 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2872 // Get the number of command slots per port supported by this HBA.
2874 MaxPortNumber
= (UINT8
)((Capability
& 0x1F) + 1);
2877 // Get the bit map of those ports exposed by this HBA.
2878 // It indicates which ports that the HBA supports are available for software to use.
2880 PortImplementBitMap
= AhciReadReg (PciIo
, EFI_AHCI_PI_OFFSET
);
2882 AhciRegisters
= &Instance
->AhciRegisters
;
2883 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2885 if (EFI_ERROR (Status
)) {
2886 return EFI_OUT_OF_RESOURCES
;
2889 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2890 if ((PortImplementBitMap
& (((UINT32
)BIT0
) << Port
)) != 0) {
2892 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2894 if ((MaxPortNumber
--) == 0) {
2896 // Should never be here.
2902 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2905 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2907 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2908 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2909 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2910 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2911 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2913 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciCmdListPciAddr
);
2914 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2915 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2916 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2917 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2919 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2920 Data
= AhciReadReg (PciIo
, Offset
);
2921 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2922 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2925 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2926 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2930 // Disable aggressive power management.
2932 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2933 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2935 // Disable the reporting of the corresponding interrupt to system software.
2937 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2938 AhciAndReg (PciIo
, Offset
, 0);
2941 // Now inform the IDE Controller Init Module.
2943 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2946 // Enable FIS Receive DMA engine for the first D2H FIS.
2948 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2949 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2952 // Wait for the Phy to detect the presence of a device.
2954 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2955 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2957 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2958 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2962 MicroSecondDelay (1000);
2964 } while (PhyDetectDelay
> 0);
2966 if (PhyDetectDelay
== 0) {
2968 // No device detected at this port.
2969 // Clear PxCMD.SUD for those ports at which there are no device present.
2971 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2972 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2976 Status
= AhciWaitDeviceReady (PciIo
, Port
);
2977 if (EFI_ERROR (Status
)) {
2982 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2984 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2985 Status
= AhciWaitMmioSet (
2990 EFI_TIMER_PERIOD_SECONDS (16)
2992 if (EFI_ERROR (Status
)) {
2996 Data
= AhciReadReg (PciIo
, Offset
);
2997 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2998 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
3000 if (EFI_ERROR (Status
)) {
3004 DeviceType
= EfiIdeCdrom
;
3005 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
3006 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
3008 if (EFI_ERROR (Status
)) {
3009 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
3015 "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
3016 Buffer
.AtaData
.config
,
3017 Buffer
.AtaData
.specific_config
,
3018 Buffer
.AtaData
.command_set_supported_83
,
3019 Buffer
.AtaData
.command_set_feature_enb_86
3021 if ((Buffer
.AtaData
.config
& BIT2
) != 0) {
3023 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
3025 Status
= AhciSpinUpDisk (
3032 if (EFI_ERROR (Status
)) {
3033 DEBUG ((DEBUG_ERROR
, "Spin up standby device failed - %r\n", Status
));
3038 DeviceType
= EfiIdeHarddisk
;
3045 "port [%d] port multitplier [%d] has a [%a]\n",
3048 DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"
3052 // If the device is a hard disk, then try to enable S.M.A.R.T feature
3054 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
3055 AhciAtaSmartSupport (
3066 // Submit identify data to IDE controller init driver
3068 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
3071 // Now start to config ide device parameter and transfer mode.
3073 Status
= IdeInit
->CalculateMode (
3079 if (EFI_ERROR (Status
)) {
3080 DEBUG ((DEBUG_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
3085 // Set best supported PIO mode on this IDE device
3087 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
3088 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
3090 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
3093 TransferMode
.ModeNumber
= (UINT8
)(SupportedModes
->PioMode
.Mode
);
3096 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA can't
3097 // be set together. Only one DMA mode can be set to a device. If setting
3098 // DMA mode operation fails, we can continue moving on because we only use
3099 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
3101 if (SupportedModes
->UdmaMode
.Valid
) {
3102 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
3103 TransferMode
.ModeNumber
= (UINT8
)(SupportedModes
->UdmaMode
.Mode
);
3104 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
3105 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
3106 TransferMode
.ModeNumber
= (UINT8
)SupportedModes
->MultiWordDmaMode
.Mode
;
3109 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
), ATA_ATAPI_TIMEOUT
);
3110 if (EFI_ERROR (Status
)) {
3111 DEBUG ((DEBUG_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
3116 // Found a ATA or ATAPI device, add it into the device list.
3118 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
3119 if (DeviceType
== EfiIdeHarddisk
) {
3120 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));
3131 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
3133 if ((Buffer
.AtaData
.command_set_supported_83
& BIT5
) != 0) {
3134 Status
= AhciPuisEnable (
3140 if (EFI_ERROR (Status
)) {
3141 DEBUG ((DEBUG_ERROR
, "PUIS enable/disable failed, Status = %r\n", Status
));