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 Prints contents of the ATA command block into the debug port.
852 @param[in] AtaCommandBlock AtaCommandBlock to print.
853 @param[in] DebugLevel Debug level on which to print.
856 AhciPrintCommandBlock (
857 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
861 DEBUG ((DebugLevel
, "ATA COMMAND BLOCK:\n"));
862 DEBUG ((DebugLevel
, "AtaCommand: %d\n", AtaCommandBlock
->AtaCommand
));
863 DEBUG ((DebugLevel
, "AtaFeatures: %X\n", AtaCommandBlock
->AtaFeatures
));
864 DEBUG ((DebugLevel
, "AtaSectorNumber: %d\n", AtaCommandBlock
->AtaSectorNumber
));
865 DEBUG ((DebugLevel
, "AtaCylinderLow: %X\n", AtaCommandBlock
->AtaCylinderHigh
));
866 DEBUG ((DebugLevel
, "AtaCylinderHigh: %X\n", AtaCommandBlock
->AtaCylinderHigh
));
867 DEBUG ((DebugLevel
, "AtaDeviceHead: %d\n", AtaCommandBlock
->AtaDeviceHead
));
868 DEBUG ((DebugLevel
, "AtaSectorNumberExp: %d\n", AtaCommandBlock
->AtaSectorNumberExp
));
869 DEBUG ((DebugLevel
, "AtaCylinderLowExp: %X\n", AtaCommandBlock
->AtaCylinderLowExp
));
870 DEBUG ((DebugLevel
, "AtaCylinderHighExp: %X\n", AtaCommandBlock
->AtaCylinderHighExp
));
871 DEBUG ((DebugLevel
, "AtaFeaturesExp: %X\n", AtaCommandBlock
->AtaFeaturesExp
));
872 DEBUG ((DebugLevel
, "AtaSectorCount: %d\n", AtaCommandBlock
->AtaSectorCount
));
873 DEBUG ((DebugLevel
, "AtaSectorCountExp: %d\n", AtaCommandBlock
->AtaSectorCountExp
));
877 Prints contents of the ATA status block into the debug port.
879 @param[in] AtaStatusBlock AtaStatusBlock to print.
880 @param[in] DebugLevel Debug level on which to print.
883 AhciPrintStatusBlock (
884 IN EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
889 // Only print status and error since we have all of the rest printed as
890 // a part of command block print.
892 DEBUG ((DebugLevel
, "ATA STATUS BLOCK:\n"));
893 DEBUG ((DebugLevel
, "AtaStatus: %d\n", AtaStatusBlock
->AtaStatus
));
894 DEBUG ((DebugLevel
, "AtaError: %d\n", AtaStatusBlock
->AtaError
));
898 Start a PIO data transfer on specific port.
900 @param[in] PciIo The PCI IO protocol instance.
901 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
902 @param[in] Port The number of port.
903 @param[in] PortMultiplier The timeout value of stop.
904 @param[in] AtapiCommand The atapi command will be used for the
906 @param[in] AtapiCommandLength The length of the atapi command.
907 @param[in] Read The transfer direction.
908 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
909 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
910 @param[in, out] MemoryAddr The pointer to the data buffer.
911 @param[in] DataCount The data count to be transferred.
912 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
913 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
914 used by non-blocking mode.
916 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
917 @retval EFI_TIMEOUT The operation is time out.
918 @retval EFI_UNSUPPORTED The device is not ready for transfer.
919 @retval EFI_SUCCESS The PIO data transfer executes successfully.
925 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
926 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
928 IN UINT8 PortMultiplier
,
929 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
930 IN UINT8 AtapiCommandLength
,
932 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
933 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
934 IN OUT VOID
*MemoryAddr
,
937 IN ATA_NONBLOCK_TASK
*Task
941 EFI_PHYSICAL_ADDRESS PhyAddr
;
944 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
945 EFI_AHCI_COMMAND_FIS CFis
;
946 EFI_AHCI_COMMAND_LIST CmdList
;
951 Flag
= EfiPciIoOperationBusMasterWrite
;
953 Flag
= EfiPciIoOperationBusMasterRead
;
957 // construct command list and command table with pci bus address
959 MapLength
= DataCount
;
960 Status
= PciIo
->Map (
969 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
970 return EFI_BAD_BUFFER_SIZE
;
974 // Package read needed
976 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
978 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
980 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
981 CmdList
.AhciCmdW
= Read
? 0 : 1;
983 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
994 (VOID
*)(UINTN
)PhyAddr
,
998 DEBUG ((DEBUG_VERBOSE
, "Starting command for PIO transfer:\n"));
999 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1000 Status
= AhciStartCommand (
1006 if (EFI_ERROR (Status
)) {
1010 if (Read
&& (AtapiCommand
== 0)) {
1011 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisPioSetup
);
1012 if (Status
== EFI_SUCCESS
) {
1013 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
1014 if (PrdCount
== DataCount
) {
1015 Status
= EFI_SUCCESS
;
1017 Status
= EFI_DEVICE_ERROR
;
1021 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1024 if (Status
== EFI_DEVICE_ERROR
) {
1025 DEBUG ((DEBUG_ERROR
, "PIO command failed at retry %d\n", Retry
));
1026 Status
= AhciRecoverPortError (PciIo
, Port
);
1027 if (EFI_ERROR (Status
)) {
1041 AhciDisableFisReceive (
1052 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1054 if (Status
== EFI_DEVICE_ERROR
) {
1055 DEBUG ((DEBUG_ERROR
, "Failed to execute command for PIO transfer:\n"));
1057 // Repeat command block here to make sure it is printed on
1058 // device error debug level.
1060 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1061 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1063 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1070 Start a DMA data transfer on specific port
1072 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
1073 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1074 @param[in] Port The number of port.
1075 @param[in] PortMultiplier The timeout value of stop.
1076 @param[in] AtapiCommand The atapi command will be used for the
1078 @param[in] AtapiCommandLength The length of the atapi command.
1079 @param[in] Read The transfer direction.
1080 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1081 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1082 @param[in, out] MemoryAddr The pointer to the data buffer.
1083 @param[in] DataCount The data count to be transferred.
1084 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1085 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1086 used by non-blocking mode.
1088 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
1089 @retval EFI_TIMEOUT The operation is time out.
1090 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1091 @retval EFI_SUCCESS The DMA data transfer executes successfully.
1097 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
1098 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1100 IN UINT8 PortMultiplier
,
1101 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1102 IN UINT8 AtapiCommandLength
,
1104 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1105 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1106 IN OUT VOID
*MemoryAddr
,
1107 IN UINT32 DataCount
,
1109 IN ATA_NONBLOCK_TASK
*Task
1113 EFI_PHYSICAL_ADDRESS PhyAddr
;
1116 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
1117 EFI_AHCI_COMMAND_FIS CFis
;
1118 EFI_AHCI_COMMAND_LIST CmdList
;
1119 EFI_PCI_IO_PROTOCOL
*PciIo
;
1124 PciIo
= Instance
->PciIo
;
1126 if (PciIo
== NULL
) {
1127 return EFI_INVALID_PARAMETER
;
1131 // Set Status to suppress incorrect compiler/analyzer warnings
1133 Status
= EFI_SUCCESS
;
1136 // DMA buffer allocation. Needs to be done only once for both sync and async
1137 // DMA transfers irrespective of number of retries.
1139 if ((Task
== NULL
) || ((Task
!= NULL
) && (Task
->Map
== NULL
))) {
1141 Flag
= EfiPciIoOperationBusMasterWrite
;
1143 Flag
= EfiPciIoOperationBusMasterRead
;
1146 MapLength
= DataCount
;
1147 Status
= PciIo
->Map (
1156 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
1157 return EFI_BAD_BUFFER_SIZE
;
1164 if (Task
== NULL
|| (Task
!= NULL
&& !Task
->IsStart
)) {
1165 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1167 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1169 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1170 CmdList
.AhciCmdW
= Read
? 0 : 1;
1175 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
1177 // Delay 100us to simulate the blocking time out checking.
1179 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1180 while (!IsListEmpty (&Instance
->NonBlockingTaskList
)) {
1181 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
1185 MicroSecondDelay (100);
1187 gBS
->RestoreTPL (OldTpl
);
1188 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1199 (VOID
*)(UINTN
)PhyAddr
,
1203 DEBUG ((DEBUG_VERBOSE
, "Starting command for sync DMA transfer:\n"));
1204 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1205 Status
= AhciStartCommand (
1211 if (EFI_ERROR (Status
)) {
1214 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1215 if (Status
== EFI_DEVICE_ERROR
) {
1216 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Retry
));
1217 Status
= AhciRecoverPortError (PciIo
, Port
);
1218 if (EFI_ERROR (Status
)) {
1226 if (!Task
->IsStart
) {
1237 (VOID
*)(UINTN
)PhyAddr
,
1241 DEBUG ((DEBUG_VERBOSE
, "Starting command for async DMA transfer:\n"));
1242 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1243 Status
= AhciStartCommand (
1249 if (!EFI_ERROR (Status
)) {
1250 Task
->IsStart
= TRUE
;
1253 if (Task
->IsStart
) {
1254 Status
= AhciCheckFisReceived (PciIo
, Port
, SataFisD2H
);
1255 if (Status
== EFI_DEVICE_ERROR
) {
1256 DEBUG ((DEBUG_ERROR
, "DMA command failed at retry: %d\n", Task
->RetryTimes
));
1257 Status
= AhciRecoverPortError (PciIo
, Port
);
1259 // If recovery passed mark the Task as not started and change the status
1260 // to EFI_NOT_READY. This will make the higher level call this function again
1261 // and on next call the command will be re-issued due to IsStart being FALSE.
1262 // This also makes the next condition decrement the RetryTimes.
1264 if (Status
== EFI_SUCCESS
) {
1265 Task
->IsStart
= FALSE
;
1266 Status
= EFI_NOT_READY
;
1270 if (Status
== EFI_NOT_READY
) {
1271 if (!Task
->InfiniteWait
&& Task
->RetryTimes
== 0) {
1272 Status
= EFI_TIMEOUT
;
1281 // For Blocking mode, the command should be stopped, the Fis should be disabled
1282 // and the PciIo should be unmapped.
1283 // For non-blocking mode, only when a error is happened (if the return status is
1284 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1285 // context cleanup, then set the packet's Asb status.
1288 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1296 AhciDisableFisReceive (
1304 (Task
!= NULL
) ? Task
->Map
: Map
1308 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1312 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1314 if (Status
== EFI_DEVICE_ERROR
) {
1315 DEBUG ((DEBUG_ERROR
, "Failed to execute command for DMA transfer:\n"));
1317 // Repeat command block here to make sure it is printed on
1318 // device error debug level.
1320 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1321 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1323 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1330 Start a non data transfer on specific port.
1332 @param[in] PciIo The PCI IO protocol instance.
1333 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1334 @param[in] Port The number of port.
1335 @param[in] PortMultiplier The timeout value of stop.
1336 @param[in] AtapiCommand The atapi command will be used for the
1338 @param[in] AtapiCommandLength The length of the atapi command.
1339 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1340 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1341 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1342 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1343 used by non-blocking mode.
1345 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1346 @retval EFI_TIMEOUT The operation is time out.
1347 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1348 @retval EFI_SUCCESS The non data transfer executes successfully.
1353 AhciNonDataTransfer (
1354 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1355 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1357 IN UINT8 PortMultiplier
,
1358 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1359 IN UINT8 AtapiCommandLength
,
1360 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1361 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1363 IN ATA_NONBLOCK_TASK
*Task
1367 EFI_AHCI_COMMAND_FIS CFis
;
1368 EFI_AHCI_COMMAND_LIST CmdList
;
1372 // Package read needed
1374 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1376 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1378 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1380 for (Retry
= 0; Retry
< AHCI_COMMAND_RETRIES
; Retry
++) {
1395 DEBUG ((DEBUG_VERBOSE
, "Starting command for non data transfer:\n"));
1396 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_VERBOSE
);
1397 Status
= AhciStartCommand (
1403 if (EFI_ERROR (Status
)) {
1407 Status
= AhciWaitUntilFisReceived (PciIo
, Port
, Timeout
, SataFisD2H
);
1408 if (Status
== EFI_DEVICE_ERROR
) {
1409 DEBUG ((DEBUG_ERROR
, "Non data transfer failed at retry %d\n", Retry
));
1410 Status
= AhciRecoverPortError (PciIo
, Port
);
1411 if (EFI_ERROR (Status
)) {
1425 AhciDisableFisReceive (
1431 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1433 if (Status
== EFI_DEVICE_ERROR
) {
1434 DEBUG ((DEBUG_ERROR
, "Failed to execute command for non data transfer:\n"));
1436 // Repeat command block here to make sure it is printed on
1437 // device error debug level.
1439 AhciPrintCommandBlock (AtaCommandBlock
, DEBUG_ERROR
);
1440 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_ERROR
);
1442 AhciPrintStatusBlock (AtaStatusBlock
, DEBUG_VERBOSE
);
1449 Stop command running for giving port
1451 @param PciIo The PCI IO protocol instance.
1452 @param Port The number of port.
1453 @param Timeout The timeout value of stop, uses 100ns as a unit.
1455 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1456 @retval EFI_TIMEOUT The operation is time out.
1457 @retval EFI_SUCCESS The command stop successfully.
1463 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1471 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1472 Data
= AhciReadReg (PciIo
, Offset
);
1474 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1478 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1479 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1482 return AhciWaitMmioSet (
1485 EFI_AHCI_PORT_CMD_CR
,
1492 Start command for give slot on specific port.
1494 @param PciIo The PCI IO protocol instance.
1495 @param Port The number of port.
1496 @param CommandSlot The number of Command Slot.
1497 @param Timeout The timeout value of start, uses 100ns as a unit.
1499 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1500 @retval EFI_TIMEOUT The operation is time out.
1501 @retval EFI_SUCCESS The command start successfully.
1507 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1509 IN UINT8 CommandSlot
,
1522 // Collect AHCI controller information
1524 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1526 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1528 AhciClearPortStatus (
1533 Status
= AhciEnableFisReceive (
1539 if (EFI_ERROR (Status
)) {
1543 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1544 PortStatus
= AhciReadReg (PciIo
, Offset
);
1547 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1548 StartCmd
= AhciReadReg (PciIo
, Offset
);
1549 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1550 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1553 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1554 PortTfd
= AhciReadReg (PciIo
, Offset
);
1556 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1557 if ((Capability
& BIT24
) != 0) {
1558 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1559 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1564 EFI_AHCI_PORT_CMD_CLO
,
1571 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1572 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1575 // Setting the command
1577 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1578 AhciAndReg (PciIo
, Offset
, 0);
1579 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1588 @param PciIo The PCI IO protocol instance.
1589 @param Timeout The timeout value of reset, uses 100ns as a unit.
1591 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1592 @retval EFI_TIMEOUT The reset operation is time out.
1593 @retval EFI_SUCCESS AHCI controller is reset successfully.
1599 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1607 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1609 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1611 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
1612 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1615 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1617 Delay
= DivU64x32(Timeout
, 1000) + 1;
1620 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1622 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1627 // Stall for 100 microseconds.
1629 MicroSecondDelay(100);
1632 } while (Delay
> 0);
1642 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1644 @param PciIo The PCI IO protocol instance.
1645 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1646 @param Port The number of port.
1647 @param PortMultiplier The port multiplier port number.
1648 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1650 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1651 @retval Others Fail to get return status data.
1656 AhciAtaSmartReturnStatusCheck (
1657 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1658 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1660 IN UINT8 PortMultiplier
,
1661 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1665 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1671 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1673 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1674 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1675 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1676 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1679 // Send S.M.A.R.T Read Return Status command to device
1681 Status
= AhciNonDataTransfer (
1685 (UINT8
)PortMultiplier
,
1694 if (EFI_ERROR (Status
)) {
1695 REPORT_STATUS_CODE (
1696 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1697 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1699 return EFI_DEVICE_ERROR
;
1702 REPORT_STATUS_CODE (
1704 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1707 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1709 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1711 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1712 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1713 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1715 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1717 // The threshold exceeded condition is not detected by the device
1719 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1720 REPORT_STATUS_CODE (
1722 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1724 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1726 // The threshold exceeded condition is detected by the device
1728 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1729 REPORT_STATUS_CODE (
1731 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1740 Enable SMART command of the disk if supported.
1742 @param PciIo The PCI IO protocol instance.
1743 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1744 @param Port The number of port.
1745 @param PortMultiplier The port multiplier port number.
1746 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1747 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1752 AhciAtaSmartSupport (
1753 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1754 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1756 IN UINT8 PortMultiplier
,
1757 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1758 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1762 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1765 // Detect if the device supports S.M.A.R.T.
1767 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1769 // S.M.A.R.T is not supported by the device
1771 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1772 Port
, PortMultiplier
));
1773 REPORT_STATUS_CODE (
1774 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1775 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1779 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1781 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1783 REPORT_STATUS_CODE (
1785 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1788 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1790 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1791 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1792 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1793 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1796 // Send S.M.A.R.T Enable command to device
1798 Status
= AhciNonDataTransfer (
1802 (UINT8
)PortMultiplier
,
1812 if (!EFI_ERROR (Status
)) {
1814 // Send S.M.A.R.T AutoSave command to device
1816 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1818 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1819 AtaCommandBlock
.AtaFeatures
= 0xD2;
1820 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1821 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1822 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1824 Status
= AhciNonDataTransfer (
1828 (UINT8
)PortMultiplier
,
1837 if (!EFI_ERROR (Status
)) {
1838 Status
= AhciAtaSmartReturnStatusCheck (
1842 (UINT8
)PortMultiplier
,
1848 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1849 Port
, PortMultiplier
));
1856 Send Buffer cmd to specific device.
1858 @param PciIo The PCI IO protocol instance.
1859 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1860 @param Port The number of port.
1861 @param PortMultiplier The port multiplier port number.
1862 @param Buffer The data buffer to store IDENTIFY PACKET data.
1864 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1865 @retval EFI_TIMEOUT The operation is time out.
1866 @retval EFI_UNSUPPORTED The device is not ready for executing.
1867 @retval EFI_SUCCESS The cmd executes successfully.
1873 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1874 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1876 IN UINT8 PortMultiplier
,
1877 IN OUT EFI_IDENTIFY_DATA
*Buffer
1881 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1882 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1884 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1885 return EFI_INVALID_PARAMETER
;
1888 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1889 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1891 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1892 AtaCommandBlock
.AtaSectorCount
= 1;
1894 Status
= AhciPioTransfer (
1905 sizeof (EFI_IDENTIFY_DATA
),
1914 Send Buffer cmd to specific device.
1916 @param PciIo The PCI IO protocol instance.
1917 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1918 @param Port The number of port.
1919 @param PortMultiplier The port multiplier port number.
1920 @param Buffer The data buffer to store IDENTIFY PACKET data.
1922 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1923 @retval EFI_TIMEOUT The operation is time out.
1924 @retval EFI_UNSUPPORTED The device is not ready for executing.
1925 @retval EFI_SUCCESS The cmd executes successfully.
1930 AhciIdentifyPacket (
1931 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1932 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1934 IN UINT8 PortMultiplier
,
1935 IN OUT EFI_IDENTIFY_DATA
*Buffer
1939 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1940 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1942 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1943 return EFI_INVALID_PARAMETER
;
1946 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1947 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1949 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1950 AtaCommandBlock
.AtaSectorCount
= 1;
1952 Status
= AhciPioTransfer (
1963 sizeof (EFI_IDENTIFY_DATA
),
1972 Send SET FEATURE cmd on specific device.
1974 @param PciIo The PCI IO protocol instance.
1975 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1976 @param Port The number of port.
1977 @param PortMultiplier The port multiplier port number.
1978 @param Feature The data to send Feature register.
1979 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1980 @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1982 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1983 @retval EFI_TIMEOUT The operation is time out.
1984 @retval EFI_UNSUPPORTED The device is not ready for executing.
1985 @retval EFI_SUCCESS The cmd executes successfully.
1990 AhciDeviceSetFeature (
1991 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1992 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1994 IN UINT8 PortMultiplier
,
1996 IN UINT32 FeatureSpecificData
,
2001 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2002 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2004 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2005 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2007 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
2008 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
2009 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
2010 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
2011 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
2012 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
2013 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
2015 Status
= AhciNonDataTransfer (
2019 (UINT8
)PortMultiplier
,
2032 This function is used to send out ATAPI commands conforms to the Packet Command
2035 @param PciIo The PCI IO protocol instance.
2036 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2037 @param Port The number of port.
2038 @param PortMultiplier The number of port multiplier.
2039 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
2041 @retval EFI_SUCCESS send out the ATAPI packet command successfully
2042 and device sends data successfully.
2043 @retval EFI_DEVICE_ERROR the device failed to send data.
2048 AhciPacketCommandExecute (
2049 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2050 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2052 IN UINT8 PortMultiplier
,
2053 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
2059 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2060 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2063 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
2064 return EFI_INVALID_PARAMETER
;
2067 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2068 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2069 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
2073 AtaCommandBlock
.AtaFeatures
= 0x00;
2075 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
2076 // determine how many data should be transferred.
2078 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
2079 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
2081 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
2082 Buffer
= Packet
->InDataBuffer
;
2083 Length
= Packet
->InTransferLength
;
2086 Buffer
= Packet
->OutDataBuffer
;
2087 Length
= Packet
->OutTransferLength
;
2092 Status
= AhciNonDataTransfer (
2105 Status
= AhciPioTransfer (
2125 Allocate transfer-related data struct which is used at AHCI mode.
2127 @param PciIo The PCI IO protocol instance.
2128 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2133 AhciCreateTransferDescriptor (
2134 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2135 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
2143 UINT32 PortImplementBitMap
;
2144 UINT8 MaxPortNumber
;
2145 UINT8 MaxCommandSlotNumber
;
2146 BOOLEAN Support64Bit
;
2147 UINT64 MaxReceiveFisSize
;
2148 UINT64 MaxCommandListSize
;
2149 UINT64 MaxCommandTableSize
;
2150 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
2151 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
2152 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
2156 // Collect AHCI controller information
2158 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2160 // Get the number of command slots per port supported by this HBA.
2162 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2163 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2165 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2167 // Get the highest bit of implemented ports which decides how many bytes are allocated for received FIS.
2169 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2170 if (MaxPortNumber
== 0) {
2171 return EFI_DEVICE_ERROR
;
2174 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2175 Status
= PciIo
->AllocateBuffer (
2178 EfiBootServicesData
,
2179 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2184 if (EFI_ERROR (Status
)) {
2185 return EFI_OUT_OF_RESOURCES
;
2188 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2190 AhciRegisters
->AhciRFis
= Buffer
;
2191 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2192 Bytes
= (UINTN
)MaxReceiveFisSize
;
2194 Status
= PciIo
->Map (
2196 EfiPciIoOperationBusMasterCommonBuffer
,
2200 &AhciRegisters
->MapRFis
2203 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2205 // Map error or unable to map the whole RFis buffer into a contiguous region.
2207 Status
= EFI_OUT_OF_RESOURCES
;
2211 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2213 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2215 Status
= EFI_DEVICE_ERROR
;
2218 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2221 // Allocate memory for command list
2222 // Note that the implementation is a single task model which only use a command list for all ports.
2225 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2226 Status
= PciIo
->AllocateBuffer (
2229 EfiBootServicesData
,
2230 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2235 if (EFI_ERROR (Status
)) {
2237 // Free mapped resource.
2239 Status
= EFI_OUT_OF_RESOURCES
;
2243 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2245 AhciRegisters
->AhciCmdList
= Buffer
;
2246 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2247 Bytes
= (UINTN
)MaxCommandListSize
;
2249 Status
= PciIo
->Map (
2251 EfiPciIoOperationBusMasterCommonBuffer
,
2254 &AhciCmdListPciAddr
,
2255 &AhciRegisters
->MapCmdList
2258 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2260 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2262 Status
= EFI_OUT_OF_RESOURCES
;
2266 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2268 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2270 Status
= EFI_DEVICE_ERROR
;
2273 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2276 // Allocate memory for command table
2277 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2280 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2282 Status
= PciIo
->AllocateBuffer (
2285 EfiBootServicesData
,
2286 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2291 if (EFI_ERROR (Status
)) {
2293 // Free mapped resource.
2295 Status
= EFI_OUT_OF_RESOURCES
;
2299 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2301 AhciRegisters
->AhciCommandTable
= Buffer
;
2302 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2303 Bytes
= (UINTN
)MaxCommandTableSize
;
2305 Status
= PciIo
->Map (
2307 EfiPciIoOperationBusMasterCommonBuffer
,
2310 &AhciCommandTablePciAddr
,
2311 &AhciRegisters
->MapCommandTable
2314 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2316 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2318 Status
= EFI_OUT_OF_RESOURCES
;
2322 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2324 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2326 Status
= EFI_DEVICE_ERROR
;
2329 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2333 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2338 AhciRegisters
->MapCommandTable
2343 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2344 AhciRegisters
->AhciCommandTable
2349 AhciRegisters
->MapCmdList
2354 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2355 AhciRegisters
->AhciCmdList
2360 AhciRegisters
->MapRFis
2365 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2366 AhciRegisters
->AhciRFis
2373 Read logs from SATA device.
2375 @param PciIo The PCI IO protocol instance.
2376 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2377 @param Port The number of port.
2378 @param PortMultiplier The multiplier of port.
2379 @param Buffer The data buffer to store SATA logs.
2380 @param LogNumber The address of the log.
2381 @param PageNumber The page number of the log.
2383 @retval EFI_INVALID_PARAMETER PciIo, AhciRegisters or Buffer is NULL.
2384 @retval others Return status of AhciPioTransfer().
2388 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2389 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2391 IN UINT8 PortMultiplier
,
2392 IN OUT UINT8
*Buffer
,
2397 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2398 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2400 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
2401 return EFI_INVALID_PARAMETER
;
2405 /// Read log from device
2407 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2408 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2409 ZeroMem (Buffer
, 512);
2411 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_LOG_EXT
;
2412 AtaCommandBlock
.AtaSectorCount
= 1;
2413 AtaCommandBlock
.AtaSectorNumber
= LogNumber
;
2414 AtaCommandBlock
.AtaCylinderLow
= PageNumber
;
2416 return AhciPioTransfer (
2434 Enable DEVSLP of the disk if supported.
2436 @param PciIo The PCI IO protocol instance.
2437 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2438 @param Port The number of port.
2439 @param PortMultiplier The multiplier of port.
2440 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2442 @retval EFI_SUCCESS The DEVSLP is enabled per policy successfully.
2443 @retval EFI_UNSUPPORTED The DEVSLP isn't supported by the controller/device and policy requires to enable it.
2447 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2448 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2450 IN UINT8 PortMultiplier
,
2451 IN EFI_IDENTIFY_DATA
*IdentifyData
2458 DEVSLP_TIMING_VARIABLES DevSlpTiming
;
2462 if (mAtaAtapiPolicy
->DeviceSleepEnable
!= 1) {
2467 // Do not enable DevSlp if DevSlp is not supported.
2469 Capability2
= AhciReadReg (PciIo
, AHCI_CAPABILITY2_OFFSET
);
2470 DEBUG ((DEBUG_INFO
, "AHCI CAPABILITY2 = %08x\n", Capability2
));
2471 if ((Capability2
& AHCI_CAP2_SDS
) == 0) {
2472 return EFI_UNSUPPORTED
;
2476 // Do not enable DevSlp if DevSlp is not present
2477 // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2479 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
;
2480 PortCmd
= AhciReadReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
);
2481 PortDevSlp
= AhciReadReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
);
2482 DEBUG ((DEBUG_INFO
, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd
, PortDevSlp
));
2483 if (((PortDevSlp
& AHCI_PORT_DEVSLP_DSP
) == 0) ||
2484 ((PortCmd
& (EFI_AHCI_PORT_CMD_HPCP
| EFI_AHCI_PORT_CMD_MPSP
)) != 0)
2486 return EFI_UNSUPPORTED
;
2490 // Do not enable DevSlp if the device doesn't support DevSlp
2492 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2493 IdentifyData
->AtaData
.reserved_77
,
2494 IdentifyData
->AtaData
.serial_ata_features_supported
, IdentifyData
->AtaData
.serial_ata_features_enabled
));
2495 if ((IdentifyData
->AtaData
.serial_ata_features_supported
& BIT8
) == 0) {
2496 DEBUG ((DEBUG_INFO
, "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2497 Port
, PortMultiplier
));
2498 return EFI_UNSUPPORTED
;
2502 // Enable DevSlp when it is not enabled.
2504 if ((IdentifyData
->AtaData
.serial_ata_features_enabled
& BIT8
) != 0) {
2505 Status
= AhciDeviceSetFeature (
2506 PciIo
, AhciRegisters
, Port
, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE
, 0x09, ATA_ATAPI_TIMEOUT
2508 DEBUG ((DEBUG_INFO
, "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2509 Port
, PortMultiplier
, Status
));
2510 if (EFI_ERROR (Status
)) {
2515 Status
= AhciReadLogExt(PciIo
, AhciRegisters
, Port
, PortMultiplier
, LogData
, 0x30, 0x08);
2518 // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2520 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
& ~EFI_AHCI_PORT_CMD_ST
);
2521 PortDevSlp
&= ~AHCI_PORT_DEVSLP_ADSE
;
2522 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2525 // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2527 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DETO_MASK
;
2528 PortDevSlp
&= ~AHCI_PORT_DEVSLP_MDAT_MASK
;
2529 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2530 DEBUG ((DEBUG_INFO
, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port
, PortMultiplier
, Status
));
2531 if (EFI_ERROR (Status
)) {
2533 // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2535 ZeroMem (&DevSlpTiming
, sizeof (DevSlpTiming
));
2537 CopyMem (&DevSlpTiming
, &LogData
[48], sizeof (DevSlpTiming
));
2538 DEBUG ((DEBUG_INFO
, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2539 DevSlpTiming
.Supported
, DevSlpTiming
.Deto
, DevSlpTiming
.Madt
));
2543 // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2545 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Deto
== 0)) {
2546 DevSlpTiming
.Deto
= 20;
2550 // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2552 if ((DevSlpTiming
.Supported
== 0) || (DevSlpTiming
.Madt
== 0)) {
2553 DevSlpTiming
.Madt
= 10;
2556 PortDevSlp
|= DevSlpTiming
.Deto
<< 2;
2557 PortDevSlp
|= DevSlpTiming
.Madt
<< 10;
2558 AhciOrReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2560 if (mAtaAtapiPolicy
->AggressiveDeviceSleepEnable
== 1) {
2561 if ((Capability2
& AHCI_CAP2_SADM
) != 0) {
2562 PortDevSlp
&= ~AHCI_PORT_DEVSLP_DITO_MASK
;
2563 PortDevSlp
|= (625 << 15);
2564 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2566 PortDevSlp
|= AHCI_PORT_DEVSLP_ADSE
;
2567 AhciWriteReg (PciIo
, Offset
+ AHCI_PORT_DEVSLP
, PortDevSlp
);
2572 AhciWriteReg (PciIo
, Offset
+ EFI_AHCI_PORT_CMD
, PortCmd
);
2574 DEBUG ((DEBUG_INFO
, "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2575 Port
, PortMultiplier
, PortCmd
, PortDevSlp
));
2581 Spin-up disk if IDD was incomplete or PUIS feature is enabled
2583 @param PciIo The PCI IO protocol instance.
2584 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2585 @param Port The number of port.
2586 @param PortMultiplier The multiplier of port.
2587 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2592 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2593 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2595 IN UINT8 PortMultiplier
,
2596 IN OUT EFI_IDENTIFY_DATA
*IdentifyData
2600 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2601 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2604 if (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
) {
2606 // Use SET_FEATURE subcommand to spin up the device.
2608 Status
= AhciDeviceSetFeature (
2609 PciIo
, AhciRegisters
, Port
, PortMultiplier
,
2610 ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
, 0x00, ATA_SPINUP_TIMEOUT
2612 DEBUG ((DEBUG_INFO
, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2613 Port
, PortMultiplier
, Status
));
2614 if (EFI_ERROR (Status
)) {
2618 ASSERT (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
);
2621 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2623 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2624 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2626 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2628 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_SECTORS
;
2629 AtaCommandBlock
.AtaSectorCount
= 0x1;
2631 Status
= AhciPioTransfer (
2646 DEBUG ((DEBUG_INFO
, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2647 Port
, PortMultiplier
, Status
));
2648 if (EFI_ERROR (Status
)) {
2654 // Read the complete IDENTIFY DEVICE data.
2656 ZeroMem (IdentifyData
, sizeof (*IdentifyData
));
2657 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, PortMultiplier
, IdentifyData
);
2658 if (EFI_ERROR (Status
)) {
2659 DEBUG ((DEBUG_ERROR
, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2660 Port
, PortMultiplier
, Status
));
2664 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2665 IdentifyData
->AtaData
.config
, IdentifyData
->AtaData
.specific_config
,
2666 IdentifyData
->AtaData
.command_set_supported_83
, IdentifyData
->AtaData
.command_set_feature_enb_86
));
2668 // Check if IDD is incomplete
2670 if ((IdentifyData
->AtaData
.config
& BIT2
) != 0) {
2671 return EFI_DEVICE_ERROR
;
2678 Enable/disable/skip PUIS of the disk according to policy.
2680 @param PciIo The PCI IO protocol instance.
2681 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2682 @param Port The number of port.
2683 @param PortMultiplier The multiplier of port.
2688 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2689 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2691 IN UINT8 PortMultiplier
2696 Status
= EFI_SUCCESS
;
2697 if (mAtaAtapiPolicy
->PuisEnable
== 0) {
2698 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_DISABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2699 } else if (mAtaAtapiPolicy
->PuisEnable
== 1) {
2700 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_ENABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2702 DEBUG ((DEBUG_INFO
, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2703 (mAtaAtapiPolicy
->PuisEnable
== 0) ? "Disable" : (
2704 (mAtaAtapiPolicy
->PuisEnable
== 1) ? "Enable" : "Skip"
2705 ), Port
, PortMultiplier
, Status
));
2710 Initialize ATA host controller at AHCI mode.
2712 The function is designed to initialize ATA host controller.
2714 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2719 AhciModeInitialization (
2720 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2724 EFI_PCI_IO_PROTOCOL
*PciIo
;
2725 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2727 UINT8 MaxPortNumber
;
2728 UINT32 PortImplementBitMap
;
2730 EFI_AHCI_REGISTERS
*AhciRegisters
;
2736 EFI_IDENTIFY_DATA Buffer
;
2737 EFI_ATA_DEVICE_TYPE DeviceType
;
2738 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2739 EFI_ATA_TRANSFER_MODE TransferMode
;
2740 UINT32 PhyDetectDelay
;
2743 if (Instance
== NULL
) {
2744 return EFI_INVALID_PARAMETER
;
2747 PciIo
= Instance
->PciIo
;
2748 IdeInit
= Instance
->IdeControllerInit
;
2750 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2752 if (EFI_ERROR (Status
)) {
2753 return EFI_DEVICE_ERROR
;
2757 // Collect AHCI controller information
2759 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2762 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2764 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
2766 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
2767 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2771 // Enable 64-bit DMA support in the PCI layer if this controller
2774 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2775 Status
= PciIo
->Attributes (
2777 EfiPciIoAttributeOperationEnable
,
2778 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2781 if (EFI_ERROR (Status
)) {
2783 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2789 // Get the number of command slots per port supported by this HBA.
2791 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2794 // Get the bit map of those ports exposed by this HBA.
2795 // It indicates which ports that the HBA supports are available for software to use.
2797 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2799 AhciRegisters
= &Instance
->AhciRegisters
;
2800 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2802 if (EFI_ERROR (Status
)) {
2803 return EFI_OUT_OF_RESOURCES
;
2806 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2807 if ((PortImplementBitMap
& (((UINT32
)BIT0
) << Port
)) != 0) {
2809 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2811 if ((MaxPortNumber
--) == 0) {
2813 // Should never be here.
2819 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2822 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2824 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2825 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2826 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2827 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2828 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2830 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2831 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2832 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2833 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2834 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2836 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2837 Data
= AhciReadReg (PciIo
, Offset
);
2838 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2839 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2842 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2843 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2847 // Disable aggressive power management.
2849 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2850 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2852 // Disable the reporting of the corresponding interrupt to system software.
2854 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2855 AhciAndReg (PciIo
, Offset
, 0);
2858 // Now inform the IDE Controller Init Module.
2860 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2863 // Enable FIS Receive DMA engine for the first D2H FIS.
2865 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2866 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2869 // Wait for the Phy to detect the presence of a device.
2871 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2872 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2874 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2875 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2879 MicroSecondDelay (1000);
2881 } while (PhyDetectDelay
> 0);
2883 if (PhyDetectDelay
== 0) {
2885 // No device detected at this port.
2886 // Clear PxCMD.SUD for those ports at which there are no device present.
2888 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2889 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2893 Status
= AhciWaitDeviceReady (PciIo
, Port
);
2894 if (EFI_ERROR (Status
)) {
2899 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2901 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2902 Status
= AhciWaitMmioSet (
2907 EFI_TIMER_PERIOD_SECONDS(16)
2909 if (EFI_ERROR (Status
)) {
2913 Data
= AhciReadReg (PciIo
, Offset
);
2914 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2915 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2917 if (EFI_ERROR (Status
)) {
2921 DeviceType
= EfiIdeCdrom
;
2922 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2923 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2925 if (EFI_ERROR (Status
)) {
2926 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2931 DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2932 Buffer
.AtaData
.config
, Buffer
.AtaData
.specific_config
,
2933 Buffer
.AtaData
.command_set_supported_83
, Buffer
.AtaData
.command_set_feature_enb_86
2935 if ((Buffer
.AtaData
.config
& BIT2
) != 0) {
2937 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
2939 Status
= AhciSpinUpDisk (
2946 if (EFI_ERROR (Status
)) {
2947 DEBUG ((DEBUG_ERROR
, "Spin up standby device failed - %r\n", Status
));
2952 DeviceType
= EfiIdeHarddisk
;
2956 DEBUG ((DEBUG_INFO
, "port [%d] port multitplier [%d] has a [%a]\n",
2957 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2960 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2962 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2963 AhciAtaSmartSupport (
2974 // Submit identify data to IDE controller init driver
2976 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2979 // Now start to config ide device parameter and transfer mode.
2981 Status
= IdeInit
->CalculateMode (
2987 if (EFI_ERROR (Status
)) {
2988 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2993 // Set best supported PIO mode on this IDE device
2995 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2996 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2998 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
3001 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
3004 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA can't
3005 // be set together. Only one DMA mode can be set to a device. If setting
3006 // DMA mode operation fails, we can continue moving on because we only use
3007 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
3009 if (SupportedModes
->UdmaMode
.Valid
) {
3010 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
3011 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
3012 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
3013 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
3014 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
3017 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
), ATA_ATAPI_TIMEOUT
);
3018 if (EFI_ERROR (Status
)) {
3019 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
3024 // Found a ATA or ATAPI device, add it into the device list.
3026 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
3027 if (DeviceType
== EfiIdeHarddisk
) {
3028 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));
3039 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
3041 if ((Buffer
.AtaData
.command_set_supported_83
& BIT5
) != 0) {
3042 Status
= AhciPuisEnable (
3048 if (EFI_ERROR (Status
)) {
3049 DEBUG ((DEBUG_ERROR
, "PUIS enable/disable failed, Status = %r\n", Status
));