2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "AtaAtapiPassThru.h"
19 Read AHCI Operation register.
21 @param PciIo The PCI IO protocol instance.
22 @param Offset The operation register offset.
24 @return The register content read.
30 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
36 ASSERT (PciIo
!= NULL
);
53 Write AHCI Operation register.
55 @param PciIo The PCI IO protocol instance.
56 @param Offset The operation register offset.
57 @param Data The data used to write down.
63 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
68 ASSERT (PciIo
!= NULL
);
83 Do AND operation with the value of AHCI Operation register.
85 @param PciIo The PCI IO protocol instance.
86 @param Offset The operation register offset.
87 @param AndData The data used to do AND operation.
93 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
100 ASSERT (PciIo
!= NULL
);
102 Data
= AhciReadReg (PciIo
, Offset
);
106 AhciWriteReg (PciIo
, Offset
, Data
);
110 Do OR operation with the value of AHCI Operation register.
112 @param PciIo The PCI IO protocol instance.
113 @param Offset The operation register offset.
114 @param OrData The data used to do OR operation.
120 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
127 ASSERT (PciIo
!= NULL
);
129 Data
= AhciReadReg (PciIo
, Offset
);
133 AhciWriteReg (PciIo
, Offset
, Data
);
137 Wait for the value of the specified MMIO register set to the test value.
139 @param PciIo The PCI IO protocol instance.
140 @param Offset The MMIO address to test.
141 @param MaskValue The mask value of memory.
142 @param TestValue The test value of memory.
143 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
145 @retval EFI_TIMEOUT The MMIO setting is time out.
146 @retval EFI_SUCCESS The MMIO is correct set.
152 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
161 BOOLEAN InfiniteWait
;
166 InfiniteWait
= FALSE
;
169 Delay
= DivU64x32 (Timeout
, 1000) + 1;
173 // Access PCI MMIO space to see if the value is the tested one.
175 Value
= AhciReadReg (PciIo
, (UINT32
) Offset
) & MaskValue
;
177 if (Value
== TestValue
) {
182 // Stall for 100 microseconds.
184 MicroSecondDelay (100);
188 } while (InfiniteWait
|| (Delay
> 0));
194 Wait for the value of the specified system memory set to the test value.
196 @param Address The system memory address to test.
197 @param MaskValue The mask value of memory.
198 @param TestValue The test value of memory.
199 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
201 @retval EFI_TIMEOUT The system memory setting is time out.
202 @retval EFI_SUCCESS The system memory is correct set.
208 IN EFI_PHYSICAL_ADDRESS Address
,
216 BOOLEAN InfiniteWait
;
221 InfiniteWait
= FALSE
;
224 Delay
= DivU64x32 (Timeout
, 1000) + 1;
228 // Access sytem memory to see if the value is the tested one.
230 // The system memory pointed by Address will be updated by the
231 // SATA Host Controller, "volatile" is introduced to prevent
232 // compiler from optimizing the access to the memory address
233 // to only read once.
235 Value
= *(volatile UINT32
*) (UINTN
) Address
;
238 if (Value
== TestValue
) {
243 // Stall for 100 microseconds.
245 MicroSecondDelay (100);
249 } while (InfiniteWait
|| (Delay
> 0));
255 Check the memory status to the test value.
257 @param[in] Address The memory address to test.
258 @param[in] MaskValue The mask value of memory.
259 @param[in] TestValue The test value of memory.
260 @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
261 non-blocking mode. If NULL, then just try once.
263 @retval EFI_NOTREADY The memory is not set.
264 @retval EFI_TIMEOUT The memory setting retry times out.
265 @retval EFI_SUCCESS The memory is correct set.
274 IN OUT ATA_NONBLOCK_TASK
*Task
283 Value
= *(volatile UINT32
*) Address
;
286 if (Value
== TestValue
) {
290 if ((Task
!= NULL
) && !Task
->InfiniteWait
&& (Task
->RetryTimes
== 0)) {
293 return EFI_NOT_READY
;
298 Check if the device is still on port. It also checks if the AHCI controller
299 supports the address and data count will be transferred.
301 @param PciIo The PCI IO protocol instance.
302 @param Port The number of port.
304 @retval EFI_SUCCESS The device is attached to port and the transfer data is
305 supported by AHCI controller.
306 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
308 @retval EFI_NOT_READY The physical communication between AHCI controller and device
314 AhciCheckDeviceStatus (
315 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
322 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
324 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
326 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
330 return EFI_NOT_READY
;
335 Clear the port interrupt and error status. It will also clear
336 HBA interrupt status.
338 @param PciIo The PCI IO protocol instance.
339 @param Port The number of port.
344 AhciClearPortStatus (
345 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
352 // Clear any error status
354 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
355 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
358 // Clear any port interrupt status
360 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
361 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
364 // Clear any HBA interrupt status
366 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
370 This function is used to dump the Status Registers and if there is ERR bit set
371 in the Status Register, the Error Register's value is also be dumped.
373 @param PciIo The PCI IO protocol instance.
374 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
375 @param Port The number of port.
376 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
382 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
383 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
385 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
393 ASSERT (PciIo
!= NULL
);
395 if (AtaStatusBlock
!= NULL
) {
396 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
398 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
399 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
401 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
402 if (!EFI_ERROR (Status
)) {
404 // If D2H FIS is received, update StatusBlock with its content.
406 CopyMem (AtaStatusBlock
, (UINT8
*)Offset
, sizeof (EFI_ATA_STATUS_BLOCK
));
409 // If D2H FIS is not received, only update Status & Error field through PxTFD
410 // as there is no other way to get the content of the Shadow Register Block.
412 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
413 Data
= AhciReadReg (PciIo
, (UINT32
)Offset
);
415 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
416 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
417 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
425 Enable the FIS running for giving port.
427 @param PciIo The PCI IO protocol instance.
428 @param Port The number of port.
429 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
431 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
432 @retval EFI_TIMEOUT The FIS enable setting is time out.
433 @retval EFI_SUCCESS The FIS enable successfully.
438 AhciEnableFisReceive (
439 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
446 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
447 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
453 Disable the FIS running for giving port.
455 @param PciIo The PCI IO protocol instance.
456 @param Port The number of port.
457 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
459 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
460 @retval EFI_TIMEOUT The FIS disable setting is time out.
461 @retval EFI_UNSUPPORTED The port is in running state.
462 @retval EFI_SUCCESS The FIS disable successfully.
467 AhciDisableFisReceive (
468 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
476 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
477 Data
= AhciReadReg (PciIo
, Offset
);
480 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
482 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
483 return EFI_UNSUPPORTED
;
487 // Check if the Fis receive DMA engine for the port is running.
489 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
493 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
495 return AhciWaitMmioSet (
498 EFI_AHCI_PORT_CMD_FR
,
507 Build the command list, command table and prepare the fis receiver.
509 @param PciIo The PCI IO protocol instance.
510 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
511 @param Port The number of port.
512 @param PortMultiplier The timeout value of stop.
513 @param CommandFis The control fis will be used for the transfer.
514 @param CommandList The command list will be used for the transfer.
515 @param AtapiCommand The atapi command will be used for the transfer.
516 @param AtapiCommandLength The length of the atapi command.
517 @param CommandSlotNumber The command slot will be used for the transfer.
518 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
519 @param DataLength The data count to be transferred.
525 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
526 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
528 IN UINT8 PortMultiplier
,
529 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
530 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
531 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
532 IN UINT8 AtapiCommandLength
,
533 IN UINT8 CommandSlotNumber
,
534 IN OUT VOID
*DataPhysicalAddr
,
549 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
552 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
553 // It also limits that the maximum amount of the PRDT entry in the command table
556 ASSERT (PrdtNumber
<= 65535);
558 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
560 BaseAddr
= Data64
.Uint64
;
562 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
564 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
566 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
568 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
570 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
571 if (AtapiCommand
!= NULL
) {
573 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
578 CommandList
->AhciCmdA
= 1;
579 CommandList
->AhciCmdP
= 1;
581 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
583 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
586 RemainedData
= (UINTN
) DataLength
;
587 MemAddr
= (UINTN
) DataPhysicalAddr
;
588 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
590 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
591 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
592 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
594 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
597 Data64
.Uint64
= (UINT64
)MemAddr
;
598 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
599 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
600 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
601 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
605 // Set the last PRDT to Interrupt On Complete
607 if (PrdtNumber
> 0) {
608 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
612 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
614 sizeof (EFI_AHCI_COMMAND_LIST
)
617 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
618 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
619 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
620 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
627 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
628 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
633 AhciBuildCommandFis (
634 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
635 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
638 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
640 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
642 // Indicator it's a command
644 CmdFis
->AhciCFisCmdInd
= 0x1;
645 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
647 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
648 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
650 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
651 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
653 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
654 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
656 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
657 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
659 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
660 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
662 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
666 Start a PIO data transfer on specific port.
668 @param[in] PciIo The PCI IO protocol instance.
669 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
670 @param[in] Port The number of port.
671 @param[in] PortMultiplier The timeout value of stop.
672 @param[in] AtapiCommand The atapi command will be used for the
674 @param[in] AtapiCommandLength The length of the atapi command.
675 @param[in] Read The transfer direction.
676 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
677 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
678 @param[in, out] MemoryAddr The pointer to the data buffer.
679 @param[in] DataCount The data count to be transferred.
680 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
681 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
682 used by non-blocking mode.
684 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
685 @retval EFI_TIMEOUT The operation is time out.
686 @retval EFI_UNSUPPORTED The device is not ready for transfer.
687 @retval EFI_SUCCESS The PIO data transfer executes successfully.
693 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
694 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
696 IN UINT8 PortMultiplier
,
697 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
698 IN UINT8 AtapiCommandLength
,
700 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
701 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
702 IN OUT VOID
*MemoryAddr
,
705 IN ATA_NONBLOCK_TASK
*Task
711 EFI_PHYSICAL_ADDRESS PhyAddr
;
714 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
716 EFI_AHCI_COMMAND_FIS CFis
;
717 EFI_AHCI_COMMAND_LIST CmdList
;
720 BOOLEAN InfiniteWait
;
721 BOOLEAN PioFisReceived
;
722 BOOLEAN D2hFisReceived
;
727 InfiniteWait
= FALSE
;
731 Flag
= EfiPciIoOperationBusMasterWrite
;
733 Flag
= EfiPciIoOperationBusMasterRead
;
737 // construct command list and command table with pci bus address
739 MapLength
= DataCount
;
740 Status
= PciIo
->Map (
749 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
750 return EFI_BAD_BUFFER_SIZE
;
754 // Package read needed
756 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
758 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
760 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
761 CmdList
.AhciCmdW
= Read
? 0 : 1;
773 (VOID
*)(UINTN
)PhyAddr
,
777 Status
= AhciStartCommand (
783 if (EFI_ERROR (Status
)) {
788 // Check the status and wait the driver sending data
790 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
792 if (Read
&& (AtapiCommand
== 0)) {
794 // Wait device sends the PIO setup fis before data transfer
796 Status
= EFI_TIMEOUT
;
797 Delay
= DivU64x32 (Timeout
, 1000) + 1;
799 PioFisReceived
= FALSE
;
800 D2hFisReceived
= FALSE
;
801 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
802 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, NULL
);
803 if (!EFI_ERROR (Status
)) {
804 PioFisReceived
= TRUE
;
807 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
808 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
809 // after the transaction is finished successfully.
810 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
811 // By this way, we can know if there is a real error happened.
813 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
814 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
815 if (!EFI_ERROR (Status
)) {
816 D2hFisReceived
= TRUE
;
819 if (PioFisReceived
|| D2hFisReceived
) {
820 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
821 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
823 // PxTFD will be updated if there is a D2H or SetupFIS received.
825 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
826 Status
= EFI_DEVICE_ERROR
;
830 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
831 if (PrdCount
== DataCount
) {
832 Status
= EFI_SUCCESS
;
838 // Stall for 100 microseconds.
840 MicroSecondDelay(100);
844 Status
= EFI_TIMEOUT
;
846 } while (InfiniteWait
|| (Delay
> 0));
849 // Wait for D2H Fis is received
851 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
852 Status
= AhciWaitMemSet (
854 EFI_AHCI_FIS_TYPE_MASK
,
855 EFI_AHCI_FIS_REGISTER_D2H
,
859 if (EFI_ERROR (Status
)) {
863 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
864 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
865 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
866 Status
= EFI_DEVICE_ERROR
;
877 AhciDisableFisReceive (
888 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
894 Start a DMA data transfer on specific port
896 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
897 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
898 @param[in] Port The number of port.
899 @param[in] PortMultiplier The timeout value of stop.
900 @param[in] AtapiCommand The atapi command will be used for the
902 @param[in] AtapiCommandLength The length of the atapi command.
903 @param[in] Read The transfer direction.
904 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
905 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
906 @param[in, out] MemoryAddr The pointer to the data buffer.
907 @param[in] DataCount The data count to be transferred.
908 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
909 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
910 used by non-blocking mode.
912 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
913 @retval EFI_TIMEOUT The operation is time out.
914 @retval EFI_UNSUPPORTED The device is not ready for transfer.
915 @retval EFI_SUCCESS The DMA data transfer executes successfully.
921 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
922 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
924 IN UINT8 PortMultiplier
,
925 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
926 IN UINT8 AtapiCommandLength
,
928 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
929 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
930 IN OUT VOID
*MemoryAddr
,
933 IN ATA_NONBLOCK_TASK
*Task
938 EFI_PHYSICAL_ADDRESS PhyAddr
;
941 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
942 EFI_AHCI_COMMAND_FIS CFis
;
943 EFI_AHCI_COMMAND_LIST CmdList
;
947 EFI_PCI_IO_PROTOCOL
*PciIo
;
951 PciIo
= Instance
->PciIo
;
954 return EFI_INVALID_PARAMETER
;
958 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
960 // Delay 100us to simulate the blocking time out checking.
962 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
963 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
964 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
968 MicroSecondDelay (100);
970 gBS
->RestoreTPL (OldTpl
);
972 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
974 // Mark the Task to indicate that it has been started.
977 Task
->IsStart
= TRUE
;
980 Flag
= EfiPciIoOperationBusMasterWrite
;
982 Flag
= EfiPciIoOperationBusMasterRead
;
986 // Construct command list and command table with pci bus address.
988 MapLength
= DataCount
;
989 Status
= PciIo
->Map (
998 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
999 return EFI_BAD_BUFFER_SIZE
;
1006 // Package read needed
1008 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1010 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1012 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1013 CmdList
.AhciCmdW
= Read
? 0 : 1;
1025 (VOID
*)(UINTN
)PhyAddr
,
1029 Status
= AhciStartCommand (
1035 if (EFI_ERROR (Status
)) {
1041 // Wait for command compelte
1043 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1044 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1049 Status
= AhciCheckMemSet (
1051 EFI_AHCI_FIS_TYPE_MASK
,
1052 EFI_AHCI_FIS_REGISTER_D2H
,
1056 Status
= AhciWaitMemSet (
1058 EFI_AHCI_FIS_TYPE_MASK
,
1059 EFI_AHCI_FIS_REGISTER_D2H
,
1064 if (EFI_ERROR (Status
)) {
1068 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1069 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1070 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1071 Status
= EFI_DEVICE_ERROR
;
1076 // For Blocking mode, the command should be stopped, the Fis should be disabled
1077 // and the PciIo should be unmapped.
1078 // For non-blocking mode, only when a error is happened (if the return status is
1079 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1080 // context cleanup, then set the packet's Asb status.
1083 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1091 AhciDisableFisReceive (
1099 (Task
!= NULL
) ? Task
->Map
: Map
1103 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1107 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1112 Start a non data transfer on specific port.
1114 @param[in] PciIo The PCI IO protocol instance.
1115 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1116 @param[in] Port The number of port.
1117 @param[in] PortMultiplier The timeout value of stop.
1118 @param[in] AtapiCommand The atapi command will be used for the
1120 @param[in] AtapiCommandLength The length of the atapi command.
1121 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1122 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1123 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1124 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1125 used by non-blocking mode.
1127 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1128 @retval EFI_TIMEOUT The operation is time out.
1129 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1130 @retval EFI_SUCCESS The non data transfer executes successfully.
1135 AhciNonDataTransfer (
1136 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1137 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1139 IN UINT8 PortMultiplier
,
1140 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1141 IN UINT8 AtapiCommandLength
,
1142 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1143 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1145 IN ATA_NONBLOCK_TASK
*Task
1152 EFI_AHCI_COMMAND_FIS CFis
;
1153 EFI_AHCI_COMMAND_LIST CmdList
;
1156 // Package read needed
1158 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1160 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1162 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1178 Status
= AhciStartCommand (
1184 if (EFI_ERROR (Status
)) {
1189 // Wait device sends the Response Fis
1191 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1192 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1193 Status
= AhciWaitMemSet (
1195 EFI_AHCI_FIS_TYPE_MASK
,
1196 EFI_AHCI_FIS_REGISTER_D2H
,
1200 if (EFI_ERROR (Status
)) {
1204 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1205 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1206 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1207 Status
= EFI_DEVICE_ERROR
;
1217 AhciDisableFisReceive (
1223 AhciDumpPortStatus (PciIo
, AhciRegisters
, Port
, AtaStatusBlock
);
1229 Stop command running for giving port
1231 @param PciIo The PCI IO protocol instance.
1232 @param Port The number of port.
1233 @param Timeout The timeout value of stop, uses 100ns as a unit.
1235 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1236 @retval EFI_TIMEOUT The operation is time out.
1237 @retval EFI_SUCCESS The command stop successfully.
1243 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1251 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1252 Data
= AhciReadReg (PciIo
, Offset
);
1254 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1258 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1259 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1262 return AhciWaitMmioSet (
1265 EFI_AHCI_PORT_CMD_CR
,
1272 Start command for give slot on specific port.
1274 @param PciIo The PCI IO protocol instance.
1275 @param Port The number of port.
1276 @param CommandSlot The number of Command Slot.
1277 @param Timeout The timeout value of start, uses 100ns as a unit.
1279 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1280 @retval EFI_TIMEOUT The operation is time out.
1281 @retval EFI_SUCCESS The command start successfully.
1287 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1289 IN UINT8 CommandSlot
,
1302 // Collect AHCI controller information
1304 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1306 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1308 AhciClearPortStatus (
1313 Status
= AhciEnableFisReceive (
1319 if (EFI_ERROR (Status
)) {
1323 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1324 PortStatus
= AhciReadReg (PciIo
, Offset
);
1327 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1328 StartCmd
= AhciReadReg (PciIo
, Offset
);
1329 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1330 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1333 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1334 PortTfd
= AhciReadReg (PciIo
, Offset
);
1336 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1337 if ((Capability
& BIT24
) != 0) {
1338 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1339 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1344 EFI_AHCI_PORT_CMD_CLO
,
1351 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1352 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1355 // Setting the command
1357 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1358 AhciAndReg (PciIo
, Offset
, 0);
1359 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1367 @param PciIo The PCI IO protocol instance.
1368 @param Port The number of port.
1369 @param Timeout The timeout value of reset, uses 100ns as a unit.
1371 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1372 @retval EFI_TIMEOUT The reset operation is time out.
1373 @retval EFI_SUCCESS The port reset successfully.
1379 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1387 AhciClearPortStatus (PciIo
, Port
);
1389 AhciStopCommand (PciIo
, Port
, Timeout
);
1391 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1393 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1395 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1397 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1400 // wait 5 millisecond before de-assert DET
1402 MicroSecondDelay (5000);
1404 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1407 // wait 5 millisecond before de-assert DET
1409 MicroSecondDelay (5000);
1412 // Wait for communication to be re-established
1414 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1415 Status
= AhciWaitMmioSet (
1418 EFI_AHCI_PORT_SSTS_DET_MASK
,
1419 EFI_AHCI_PORT_SSTS_DET_PCE
,
1423 if (EFI_ERROR (Status
)) {
1424 DEBUG ((EFI_D_ERROR
, "Port %d COMRESET failed: %r\n", Port
, Status
));
1428 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1429 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1437 @param PciIo The PCI IO protocol instance.
1438 @param Timeout The timeout value of reset, uses 100ns as a unit.
1440 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1441 @retval EFI_TIMEOUT The reset operation is time out.
1442 @retval EFI_SUCCESS AHCI controller is reset successfully.
1448 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1456 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1458 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1460 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
1461 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1464 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1466 Delay
= DivU64x32(Timeout
, 1000) + 1;
1469 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1471 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1476 // Stall for 100 microseconds.
1478 MicroSecondDelay(100);
1481 } while (Delay
> 0);
1491 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1493 @param PciIo The PCI IO protocol instance.
1494 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1495 @param Port The number of port.
1496 @param PortMultiplier The port multiplier port number.
1497 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1499 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1500 @retval Others Fail to get return status data.
1505 AhciAtaSmartReturnStatusCheck (
1506 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1507 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1509 IN UINT8 PortMultiplier
,
1510 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1514 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1520 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1522 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1523 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1524 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1525 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1528 // Send S.M.A.R.T Read Return Status command to device
1530 Status
= AhciNonDataTransfer (
1534 (UINT8
)PortMultiplier
,
1543 if (EFI_ERROR (Status
)) {
1544 REPORT_STATUS_CODE (
1545 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1546 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1548 return EFI_DEVICE_ERROR
;
1551 REPORT_STATUS_CODE (
1553 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1556 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1558 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1560 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1561 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1562 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1564 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1566 // The threshold exceeded condition is not detected by the device
1568 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1569 REPORT_STATUS_CODE (
1571 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1573 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1575 // The threshold exceeded condition is detected by the device
1577 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1578 REPORT_STATUS_CODE (
1580 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1589 Enable SMART command of the disk if supported.
1591 @param PciIo The PCI IO protocol instance.
1592 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1593 @param Port The number of port.
1594 @param PortMultiplier The port multiplier port number.
1595 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1596 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1601 AhciAtaSmartSupport (
1602 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1603 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1605 IN UINT8 PortMultiplier
,
1606 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1607 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1611 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1614 // Detect if the device supports S.M.A.R.T.
1616 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1618 // S.M.A.R.T is not supported by the device
1620 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1621 Port
, PortMultiplier
));
1622 REPORT_STATUS_CODE (
1623 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1624 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1628 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1630 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1632 REPORT_STATUS_CODE (
1634 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1637 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1639 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1640 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1641 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1642 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1645 // Send S.M.A.R.T Enable command to device
1647 Status
= AhciNonDataTransfer (
1651 (UINT8
)PortMultiplier
,
1661 if (!EFI_ERROR (Status
)) {
1663 // Send S.M.A.R.T AutoSave command to device
1665 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1667 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1668 AtaCommandBlock
.AtaFeatures
= 0xD2;
1669 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1670 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1671 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1673 Status
= AhciNonDataTransfer (
1677 (UINT8
)PortMultiplier
,
1686 if (!EFI_ERROR (Status
)) {
1687 Status
= AhciAtaSmartReturnStatusCheck (
1691 (UINT8
)PortMultiplier
,
1697 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1698 Port
, PortMultiplier
));
1705 Send Buffer cmd to specific device.
1707 @param PciIo The PCI IO protocol instance.
1708 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1709 @param Port The number of port.
1710 @param PortMultiplier The port multiplier port number.
1711 @param Buffer The data buffer to store IDENTIFY PACKET data.
1713 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1714 @retval EFI_TIMEOUT The operation is time out.
1715 @retval EFI_UNSUPPORTED The device is not ready for executing.
1716 @retval EFI_SUCCESS The cmd executes successfully.
1722 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1723 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1725 IN UINT8 PortMultiplier
,
1726 IN OUT EFI_IDENTIFY_DATA
*Buffer
1730 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1731 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1733 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1734 return EFI_INVALID_PARAMETER
;
1737 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1738 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1740 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1741 AtaCommandBlock
.AtaSectorCount
= 1;
1743 Status
= AhciPioTransfer (
1754 sizeof (EFI_IDENTIFY_DATA
),
1763 Send Buffer cmd to specific device.
1765 @param PciIo The PCI IO protocol instance.
1766 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1767 @param Port The number of port.
1768 @param PortMultiplier The port multiplier port number.
1769 @param Buffer The data buffer to store IDENTIFY PACKET data.
1771 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1772 @retval EFI_TIMEOUT The operation is time out.
1773 @retval EFI_UNSUPPORTED The device is not ready for executing.
1774 @retval EFI_SUCCESS The cmd executes successfully.
1779 AhciIdentifyPacket (
1780 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1781 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1783 IN UINT8 PortMultiplier
,
1784 IN OUT EFI_IDENTIFY_DATA
*Buffer
1788 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1789 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1791 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1792 return EFI_INVALID_PARAMETER
;
1795 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1796 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1798 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1799 AtaCommandBlock
.AtaSectorCount
= 1;
1801 Status
= AhciPioTransfer (
1812 sizeof (EFI_IDENTIFY_DATA
),
1821 Send SET FEATURE cmd on specific device.
1823 @param PciIo The PCI IO protocol instance.
1824 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1825 @param Port The number of port.
1826 @param PortMultiplier The port multiplier port number.
1827 @param Feature The data to send Feature register.
1828 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1829 @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1831 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1832 @retval EFI_TIMEOUT The operation is time out.
1833 @retval EFI_UNSUPPORTED The device is not ready for executing.
1834 @retval EFI_SUCCESS The cmd executes successfully.
1839 AhciDeviceSetFeature (
1840 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1841 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1843 IN UINT8 PortMultiplier
,
1845 IN UINT32 FeatureSpecificData
,
1850 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1851 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1853 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1854 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1856 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1857 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1858 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1859 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1860 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1861 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1862 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1864 Status
= AhciNonDataTransfer (
1868 (UINT8
)PortMultiplier
,
1881 This function is used to send out ATAPI commands conforms to the Packet Command
1884 @param PciIo The PCI IO protocol instance.
1885 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1886 @param Port The number of port.
1887 @param PortMultiplier The number of port multiplier.
1888 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1890 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1891 and device sends data successfully.
1892 @retval EFI_DEVICE_ERROR the device failed to send data.
1897 AhciPacketCommandExecute (
1898 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1899 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1901 IN UINT8 PortMultiplier
,
1902 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1908 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1909 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1912 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1913 return EFI_INVALID_PARAMETER
;
1916 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1917 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1918 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1922 AtaCommandBlock
.AtaFeatures
= 0x00;
1924 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1925 // determine how many data should be transferred.
1927 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1928 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1930 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1931 Buffer
= Packet
->InDataBuffer
;
1932 Length
= Packet
->InTransferLength
;
1935 Buffer
= Packet
->OutDataBuffer
;
1936 Length
= Packet
->OutTransferLength
;
1941 Status
= AhciNonDataTransfer (
1954 Status
= AhciPioTransfer (
1974 Allocate transfer-related data struct which is used at AHCI mode.
1976 @param PciIo The PCI IO protocol instance.
1977 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1982 AhciCreateTransferDescriptor (
1983 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1984 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1992 UINT32 PortImplementBitMap
;
1993 UINT8 MaxPortNumber
;
1994 UINT8 MaxCommandSlotNumber
;
1995 BOOLEAN Support64Bit
;
1996 UINT64 MaxReceiveFisSize
;
1997 UINT64 MaxCommandListSize
;
1998 UINT64 MaxCommandTableSize
;
1999 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
2000 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
2001 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
2005 // Collect AHCI controller information
2007 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2009 // Get the number of command slots per port supported by this HBA.
2011 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2012 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2014 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2016 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
2018 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2019 if (MaxPortNumber
== 0) {
2020 return EFI_DEVICE_ERROR
;
2023 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2024 Status
= PciIo
->AllocateBuffer (
2027 EfiBootServicesData
,
2028 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2033 if (EFI_ERROR (Status
)) {
2034 return EFI_OUT_OF_RESOURCES
;
2037 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2039 AhciRegisters
->AhciRFis
= Buffer
;
2040 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2041 Bytes
= (UINTN
)MaxReceiveFisSize
;
2043 Status
= PciIo
->Map (
2045 EfiPciIoOperationBusMasterCommonBuffer
,
2049 &AhciRegisters
->MapRFis
2052 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2054 // Map error or unable to map the whole RFis buffer into a contiguous region.
2056 Status
= EFI_OUT_OF_RESOURCES
;
2060 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2062 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2064 Status
= EFI_DEVICE_ERROR
;
2067 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2070 // Allocate memory for command list
2071 // Note that the implemenation is a single task model which only use a command list for all ports.
2074 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2075 Status
= PciIo
->AllocateBuffer (
2078 EfiBootServicesData
,
2079 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2084 if (EFI_ERROR (Status
)) {
2086 // Free mapped resource.
2088 Status
= EFI_OUT_OF_RESOURCES
;
2092 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2094 AhciRegisters
->AhciCmdList
= Buffer
;
2095 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2096 Bytes
= (UINTN
)MaxCommandListSize
;
2098 Status
= PciIo
->Map (
2100 EfiPciIoOperationBusMasterCommonBuffer
,
2103 &AhciCmdListPciAddr
,
2104 &AhciRegisters
->MapCmdList
2107 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2109 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2111 Status
= EFI_OUT_OF_RESOURCES
;
2115 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2117 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2119 Status
= EFI_DEVICE_ERROR
;
2122 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2125 // Allocate memory for command table
2126 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2129 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2131 Status
= PciIo
->AllocateBuffer (
2134 EfiBootServicesData
,
2135 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2140 if (EFI_ERROR (Status
)) {
2142 // Free mapped resource.
2144 Status
= EFI_OUT_OF_RESOURCES
;
2148 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2150 AhciRegisters
->AhciCommandTable
= Buffer
;
2151 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2152 Bytes
= (UINTN
)MaxCommandTableSize
;
2154 Status
= PciIo
->Map (
2156 EfiPciIoOperationBusMasterCommonBuffer
,
2159 &AhciCommandTablePciAddr
,
2160 &AhciRegisters
->MapCommandTable
2163 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2165 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2167 Status
= EFI_OUT_OF_RESOURCES
;
2171 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2173 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2175 Status
= EFI_DEVICE_ERROR
;
2178 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2182 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2187 AhciRegisters
->MapCommandTable
2192 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2193 AhciRegisters
->AhciCommandTable
2198 AhciRegisters
->MapCmdList
2203 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2204 AhciRegisters
->AhciCmdList
2209 AhciRegisters
->MapRFis
2214 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2215 AhciRegisters
->AhciRFis
2223 Spin-up disk if IDD was incomplete or PUIS feature is enabled
2225 @param PciIo The PCI IO protocol instance.
2226 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2227 @param Port The number of port.
2228 @param PortMultiplier The multiplier of port.
2229 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
2234 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2235 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2237 IN UINT8 PortMultiplier
,
2238 IN OUT EFI_IDENTIFY_DATA
*IdentifyData
2242 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
2243 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
2246 if (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
) {
2248 // Use SET_FEATURE subcommand to spin up the device.
2250 Status
= AhciDeviceSetFeature (
2251 PciIo
, AhciRegisters
, Port
, PortMultiplier
,
2252 ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
, 0x00, ATA_SPINUP_TIMEOUT
2254 DEBUG ((DEBUG_INFO
, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2255 Port
, PortMultiplier
, Status
));
2256 if (EFI_ERROR (Status
)) {
2260 ASSERT (IdentifyData
->AtaData
.specific_config
== ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
);
2263 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2265 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2266 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
2268 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2270 AtaCommandBlock
.AtaCommand
= ATA_CMD_READ_SECTORS
;
2271 AtaCommandBlock
.AtaSectorCount
= 0x1;
2273 Status
= AhciPioTransfer (
2288 DEBUG ((DEBUG_INFO
, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2289 Port
, PortMultiplier
, Status
));
2290 if (EFI_ERROR (Status
)) {
2296 // Read the complete IDENTIFY DEVICE data.
2298 ZeroMem (IdentifyData
, sizeof (*IdentifyData
));
2299 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, PortMultiplier
, IdentifyData
);
2300 if (EFI_ERROR (Status
)) {
2301 DEBUG ((DEBUG_ERROR
, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2302 Port
, PortMultiplier
, Status
));
2306 DEBUG ((DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2307 IdentifyData
->AtaData
.config
, IdentifyData
->AtaData
.specific_config
,
2308 IdentifyData
->AtaData
.command_set_supported_83
, IdentifyData
->AtaData
.command_set_feature_enb_86
));
2310 // Check if IDD is incomplete
2312 if ((IdentifyData
->AtaData
.config
& BIT2
) != 0) {
2313 return EFI_DEVICE_ERROR
;
2320 Enable/disable/skip PUIS of the disk according to policy.
2322 @param PciIo The PCI IO protocol instance.
2323 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
2324 @param Port The number of port.
2325 @param PortMultiplier The multiplier of port.
2330 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2331 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
2333 IN UINT8 PortMultiplier
2338 Status
= EFI_SUCCESS
;
2339 if (mAtaAtapiPolicy
->PuisEnable
== 0) {
2340 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_DISABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2341 } else if (mAtaAtapiPolicy
->PuisEnable
== 1) {
2342 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, PortMultiplier
, ATA_SUB_CMD_ENABLE_PUIS
, 0x00, ATA_ATAPI_TIMEOUT
);
2344 DEBUG ((DEBUG_INFO
, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2345 (mAtaAtapiPolicy
->PuisEnable
== 0) ? "Disable" : (
2346 (mAtaAtapiPolicy
->PuisEnable
== 1) ? "Enable" : "Skip"
2347 ), Port
, PortMultiplier
, Status
));
2352 Initialize ATA host controller at AHCI mode.
2354 The function is designed to initialize ATA host controller.
2356 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2361 AhciModeInitialization (
2362 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2366 EFI_PCI_IO_PROTOCOL
*PciIo
;
2367 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2369 UINT8 MaxPortNumber
;
2370 UINT32 PortImplementBitMap
;
2372 EFI_AHCI_REGISTERS
*AhciRegisters
;
2378 EFI_IDENTIFY_DATA Buffer
;
2379 EFI_ATA_DEVICE_TYPE DeviceType
;
2380 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2381 EFI_ATA_TRANSFER_MODE TransferMode
;
2382 UINT32 PhyDetectDelay
;
2385 if (Instance
== NULL
) {
2386 return EFI_INVALID_PARAMETER
;
2389 PciIo
= Instance
->PciIo
;
2390 IdeInit
= Instance
->IdeControllerInit
;
2392 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2394 if (EFI_ERROR (Status
)) {
2395 return EFI_DEVICE_ERROR
;
2399 // Collect AHCI controller information
2401 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2404 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2406 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
2408 if ((Value
& EFI_AHCI_GHC_ENABLE
) == 0) {
2409 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2413 // Enable 64-bit DMA support in the PCI layer if this controller
2416 if ((Capability
& EFI_AHCI_CAP_S64A
) != 0) {
2417 Status
= PciIo
->Attributes (
2419 EfiPciIoAttributeOperationEnable
,
2420 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
,
2423 if (EFI_ERROR (Status
)) {
2425 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2431 // Get the number of command slots per port supported by this HBA.
2433 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2436 // Get the bit map of those ports exposed by this HBA.
2437 // It indicates which ports that the HBA supports are available for software to use.
2439 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2441 AhciRegisters
= &Instance
->AhciRegisters
;
2442 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2444 if (EFI_ERROR (Status
)) {
2445 return EFI_OUT_OF_RESOURCES
;
2448 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2449 if ((PortImplementBitMap
& (((UINT32
)BIT0
) << Port
)) != 0) {
2451 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2453 if ((MaxPortNumber
--) == 0) {
2455 // Should never be here.
2461 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2464 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2466 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2467 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2468 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2469 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2470 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2472 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2473 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2474 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2475 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2476 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2478 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2479 Data
= AhciReadReg (PciIo
, Offset
);
2480 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2481 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2484 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2485 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2489 // Disable aggressive power management.
2491 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2492 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2494 // Disable the reporting of the corresponding interrupt to system software.
2496 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2497 AhciAndReg (PciIo
, Offset
, 0);
2500 // Now inform the IDE Controller Init Module.
2502 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2505 // Enable FIS Receive DMA engine for the first D2H FIS.
2507 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2508 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2511 // Wait for the Phy to detect the presence of a device.
2513 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2514 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2516 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2517 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2521 MicroSecondDelay (1000);
2523 } while (PhyDetectDelay
> 0);
2525 if (PhyDetectDelay
== 0) {
2527 // No device detected at this port.
2528 // Clear PxCMD.SUD for those ports at which there are no device present.
2530 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2531 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2536 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2537 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2539 PhyDetectDelay
= 16 * 1000;
2541 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2542 if (AhciReadReg(PciIo
, Offset
) != 0) {
2543 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2545 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2547 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2552 MicroSecondDelay (1000);
2554 } while (PhyDetectDelay
> 0);
2556 if (PhyDetectDelay
== 0) {
2557 DEBUG ((EFI_D_ERROR
, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port
, Data
));
2562 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2564 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2565 Status
= AhciWaitMmioSet (
2570 EFI_TIMER_PERIOD_SECONDS(16)
2572 if (EFI_ERROR (Status
)) {
2576 Data
= AhciReadReg (PciIo
, Offset
);
2577 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2578 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2580 if (EFI_ERROR (Status
)) {
2584 DeviceType
= EfiIdeCdrom
;
2585 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2586 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2588 if (EFI_ERROR (Status
)) {
2589 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2594 DEBUG_INFO
, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2595 Buffer
.AtaData
.config
, Buffer
.AtaData
.specific_config
,
2596 Buffer
.AtaData
.command_set_supported_83
, Buffer
.AtaData
.command_set_feature_enb_86
2598 if ((Buffer
.AtaData
.config
& BIT2
) != 0) {
2600 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
2602 Status
= AhciSpinUpDisk (
2609 if (EFI_ERROR (Status
)) {
2610 DEBUG ((DEBUG_ERROR
, "Spin up standby device failed - %r\n", Status
));
2615 DeviceType
= EfiIdeHarddisk
;
2619 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2620 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2623 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2625 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2626 AhciAtaSmartSupport (
2637 // Submit identify data to IDE controller init driver
2639 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2642 // Now start to config ide device parameter and transfer mode.
2644 Status
= IdeInit
->CalculateMode (
2650 if (EFI_ERROR (Status
)) {
2651 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2656 // Set best supported PIO mode on this IDE device
2658 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2659 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2661 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2664 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2667 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2668 // be set together. Only one DMA mode can be set to a device. If setting
2669 // DMA mode operation fails, we can continue moving on because we only use
2670 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2672 if (SupportedModes
->UdmaMode
.Valid
) {
2673 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2674 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2675 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2676 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2677 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2680 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
), ATA_ATAPI_TIMEOUT
);
2681 if (EFI_ERROR (Status
)) {
2682 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2687 // Found a ATA or ATAPI device, add it into the device list.
2689 CreateNewDeviceInfo (Instance
, Port
, 0xFFFF, DeviceType
, &Buffer
);
2690 if (DeviceType
== EfiIdeHarddisk
) {
2691 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));
2695 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
2697 if ((Buffer
.AtaData
.command_set_supported_83
& BIT5
) != 0) {
2698 Status
= AhciPuisEnable (
2704 if (EFI_ERROR (Status
)) {
2705 DEBUG ((DEBUG_ERROR
, "PUIS enable/disable failed, Status = %r\n", Status
));