2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #define ATA_CMD_TRUST_NON_DATA 0x5B
14 #define ATA_CMD_TRUST_RECEIVE 0x5C
15 #define ATA_CMD_TRUST_SEND 0x5E
18 // Look up table (IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
20 EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols
[2] = {
21 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN
,
22 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
26 // Look up table (Lba48Bit, IsIsWrite) for ATA_CMD
28 UINT8 mAtaCommands
[2][2] = {
30 ATA_CMD_READ_SECTORS
, // 28-bit LBA; PIO read
31 ATA_CMD_WRITE_SECTORS
// 28-bit LBA; PIO write
34 ATA_CMD_READ_SECTORS_EXT
, // 48-bit LBA; PIO read
35 ATA_CMD_WRITE_SECTORS_EXT
// 48-bit LBA; PIO write
40 // Look up table (IsTrustSend) for ATA_CMD
42 UINT8 mAtaTrustCommands
[2] = {
43 ATA_CMD_TRUST_RECEIVE
, // PIO read
44 ATA_CMD_TRUST_SEND
// PIO write
48 // Look up table (Lba48Bit) for maximum transfer block number
50 #define MAX_28BIT_TRANSFER_BLOCK_NUM 0x100
51 #define MAX_48BIT_TRANSFER_BLOCK_NUM 0xFFFF
53 UINT32 mMaxTransferBlockNumber
[2] = {
54 MAX_28BIT_TRANSFER_BLOCK_NUM
,
55 MAX_48BIT_TRANSFER_BLOCK_NUM
59 // The maximum total sectors count in 28 bit addressing mode
61 #define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
65 Read AHCI Operation register.
67 @param[in] AhciBar AHCI bar address.
68 @param[in] Offset The operation register offset.
70 @return The register content read.
82 Data
= MmioRead32 (AhciBar
+ Offset
);
88 Write AHCI Operation register.
90 @param[in] AhciBar AHCI bar address.
91 @param[in] Offset The operation register offset.
92 @param[in] Data The Data used to write down.
102 MmioWrite32 (AhciBar
+ Offset
, Data
);
106 Do AND operation with the value of AHCI Operation register.
108 @param[in] AhciBar AHCI bar address.
109 @param[in] Offset The operation register offset.
110 @param[in] AndData The data used to do AND operation.
122 Data
= AhciReadReg (AhciBar
, Offset
);
125 AhciWriteReg (AhciBar
, Offset
, Data
);
129 Do OR operation with the Value of AHCI Operation register.
131 @param[in] AhciBar AHCI bar address.
132 @param[in] Offset The operation register offset.
133 @param[in] OrData The Data used to do OR operation.
145 Data
= AhciReadReg (AhciBar
, Offset
);
148 AhciWriteReg (AhciBar
, Offset
, Data
);
152 Wait for memory set to the test Value.
154 @param[in] AhciBar AHCI bar address.
155 @param[in] Offset The memory offset to test.
156 @param[in] MaskValue The mask Value of memory.
157 @param[in] TestValue The test Value of memory.
158 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
160 @retval EFI_DEVICE_ERROR The memory is not set.
161 @retval EFI_TIMEOUT The memory setting is time out.
162 @retval EFI_SUCCESS The memory is correct set.
178 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
181 Value
= AhciReadReg (AhciBar
, Offset
) & MaskValue
;
183 if (Value
== TestValue
) {
188 // Stall for 100 microseconds.
190 MicroSecondDelay (100);
200 Check the memory status to the test value.
202 @param[in] Address The memory address to test.
203 @param[in] MaskValue The mask value of memory.
204 @param[in] TestValue The test value of memory.
206 @retval EFI_NOT_READY The memory is not set.
207 @retval EFI_SUCCESS The memory is correct set.
219 Value
= *(volatile UINT32
*) Address
;
222 if (Value
== TestValue
) {
225 return EFI_NOT_READY
;
230 Wait for the value of the specified system memory set to the test value.
232 @param[in] Address The system memory address to test.
233 @param[in] MaskValue The mask value of memory.
234 @param[in] TestValue The test value of memory.
235 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
237 @retval EFI_TIMEOUT The system memory setting is time out.
238 @retval EFI_SUCCESS The system memory is correct set.
243 IN EFI_PHYSICAL_ADDRESS Address
,
251 BOOLEAN InfiniteWait
;
256 InfiniteWait
= FALSE
;
259 Delay
= DivU64x32 (Timeout
, 1000) + 1;
263 // Access sytem memory to see if the value is the tested one.
265 // The system memory pointed by Address will be updated by the
266 // SATA Host Controller, "volatile" is introduced to prevent
267 // compiler from optimizing the access to the memory address
268 // to only read once.
270 Value
= *(volatile UINT32
*) (UINTN
) Address
;
273 if (Value
== TestValue
) {
278 // Stall for 100 microseconds.
280 MicroSecondDelay (100);
284 } while (InfiniteWait
|| (Delay
> 0));
291 Clear the port interrupt and error status. It will also clear HBA interrupt
294 @param[in] AhciBar AHCI bar address.
295 @param[in] Port The number of port.
299 AhciClearPortStatus (
307 // Clear any error status
309 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
310 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
313 // Clear any port interrupt status
315 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IS
;
316 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
319 // Clear any HBA interrupt status
321 AhciWriteReg (AhciBar
, AHCI_IS_OFFSET
, AhciReadReg (AhciBar
, AHCI_IS_OFFSET
));
325 Enable the FIS running for giving port.
327 @param[in] AhciBar AHCI bar address.
328 @param[in] Port The number of port.
329 @param[in] Timeout The timeout, in 100ns units, to enabling FIS.
331 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
332 @retval EFI_TIMEOUT The FIS enable setting is time out.
333 @retval EFI_SUCCESS The FIS enable successfully.
337 AhciEnableFisReceive (
345 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
346 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
352 Disable the FIS running for giving port.
354 @param[in] AhciBar AHCI bar address.
355 @param[in] Port The number of port.
356 @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit.
358 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
359 @retval EFI_TIMEOUT The FIS disable setting is time out.
360 @retval EFI_UNSUPPORTED The port is in running state.
361 @retval EFI_SUCCESS The FIS disable successfully.
365 AhciDisableFisReceive (
374 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
375 Data
= AhciReadReg (AhciBar
, Offset
);
378 // Before disabling Fis receive, the DMA engine of the port should NOT be in
381 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) != 0) {
382 return EFI_UNSUPPORTED
;
386 // Check if the Fis receive DMA engine for the port is running.
388 if ((Data
& AHCI_PORT_CMD_FR
) != AHCI_PORT_CMD_FR
) {
392 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_FRE
));
394 return AhciWaitMmioSet (
404 Build the command list, command table and prepare the fis receiver.
406 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
407 @param[in] Port The number of port.
408 @param[in] PortMultiplier The number of port multiplier.
409 @param[in] FisIndex The offset index of the FIS base address.
410 @param[in] CommandFis The control fis will be used for the transfer.
411 @param[in] CommandList The command list will be used for the transfer.
412 @param[in] CommandSlotNumber The command slot will be used for the transfer.
413 @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master
415 @param[in] DataLength The data count to be transferred.
420 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
422 IN UINT8 PortMultiplier
,
424 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
425 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
426 IN UINT8 CommandSlotNumber
,
427 IN OUT VOID
*DataPhysicalAddr
,
431 EFI_AHCI_REGISTERS
*AhciRegisters
;
441 AhciRegisters
= &Private
->AhciRegisters
;
442 AhciBar
= Private
->MmioBase
;
447 PrdtNumber
= (UINT32
)DivU64x32 (
448 (UINT64
)DataLength
+ AHCI_MAX_DATA_PER_PRDT
- 1,
449 AHCI_MAX_DATA_PER_PRDT
453 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
454 // It also limits that the maximum amount of the PRDT entry in the command table
456 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
459 ASSERT (PrdtNumber
<= AHCI_MAX_PRDT_NUMBER
);
460 if (PrdtNumber
> AHCI_MAX_PRDT_NUMBER
) {
464 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
466 BaseAddr
= Data64
.Uint64
;
468 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
470 ZeroMem (AhciRegisters
->AhciCmdTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
472 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
474 CopyMem (&AhciRegisters
->AhciCmdTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
476 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
477 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_DLAE
| AHCI_PORT_CMD_ATAPI
));
479 RemainedData
= (UINTN
) DataLength
;
480 MemAddr
= (UINTN
) DataPhysicalAddr
;
481 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
483 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
484 if (RemainedData
< AHCI_MAX_DATA_PER_PRDT
) {
485 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
487 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= AHCI_MAX_DATA_PER_PRDT
- 1;
490 Data64
.Uint64
= (UINT64
)MemAddr
;
491 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
492 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
493 RemainedData
-= AHCI_MAX_DATA_PER_PRDT
;
494 MemAddr
+= AHCI_MAX_DATA_PER_PRDT
;
498 // Set the last PRDT to Interrupt On Complete
500 if (PrdtNumber
> 0) {
501 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
505 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
507 sizeof (EFI_AHCI_COMMAND_LIST
)
510 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCmdTable
;
511 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
512 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
513 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
519 @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data
521 @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data
526 AhciBuildCommandFis (
527 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
528 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
531 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
533 CmdFis
->AhciCFisType
= AHCI_FIS_REGISTER_H2D
;
535 // Indicator it's a command
537 CmdFis
->AhciCFisCmdInd
= 0x1;
538 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
540 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
541 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
543 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
544 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
546 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
547 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
549 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
550 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
552 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
553 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
555 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
559 Stop command running for giving port
561 @param[in] AhciBar AHCI bar address.
562 @param[in] Port The number of port.
563 @param[in] Timeout The timeout value, in 100ns units, to stop.
565 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
566 @retval EFI_TIMEOUT The operation is time out.
567 @retval EFI_SUCCESS The command stop successfully.
580 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
581 Data
= AhciReadReg (AhciBar
, Offset
);
583 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) == 0) {
587 if ((Data
& AHCI_PORT_CMD_ST
) != 0) {
588 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_ST
));
591 return AhciWaitMmioSet (
601 Start command for give slot on specific port.
603 @param[in] AhciBar AHCI bar address.
604 @param[in] Port The number of port.
605 @param[in] CommandSlot The number of Command Slot.
606 @param[in] Timeout The timeout value, in 100ns units, to start.
608 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
609 @retval EFI_TIMEOUT The operation is time out.
610 @retval EFI_SUCCESS The command start successfully.
617 IN UINT8 CommandSlot
,
630 // Collect AHCI controller information
632 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
634 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
636 AhciClearPortStatus (
641 Status
= AhciEnableFisReceive (
646 if (EFI_ERROR (Status
)) {
650 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
651 PortStatus
= AhciReadReg (AhciBar
, Offset
);
654 if ((PortStatus
& AHCI_PORT_CMD_ALPE
) != 0) {
655 StartCmd
= AhciReadReg (AhciBar
, Offset
);
656 StartCmd
&= ~AHCI_PORT_CMD_ICC_MASK
;
657 StartCmd
|= AHCI_PORT_CMD_ACTIVE
;
660 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
661 PortTfd
= AhciReadReg (AhciBar
, Offset
);
663 if ((PortTfd
& (AHCI_PORT_TFD_BSY
| AHCI_PORT_TFD_DRQ
)) != 0) {
664 if ((Capability
& BIT24
) != 0) {
665 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
666 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_CLO
);
678 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
679 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_ST
| StartCmd
);
682 // Setting the command
684 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CI
;
685 AhciAndReg (AhciBar
, Offset
, 0);
686 AhciOrReg (AhciBar
, Offset
, CmdSlotBit
);
692 Start a PIO Data transfer on specific port.
694 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
695 @param[in] Port The number of port.
696 @param[in] PortMultiplier The number of port multiplier.
697 @param[in] FisIndex The offset index of the FIS base address.
698 @param[in] Read The transfer direction.
699 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
700 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
701 @param[in,out] MemoryAddr The pointer to the data buffer.
702 @param[in] DataCount The data count to be transferred.
703 @param[in] Timeout The timeout value of PIO data transfer, uses
706 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
707 @retval EFI_TIMEOUT The operation is time out.
708 @retval EFI_UNSUPPORTED The device is not ready for transfer.
709 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
710 @retval EFI_SUCCESS The PIO data transfer executes successfully.
715 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
717 IN UINT8 PortMultiplier
,
720 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
721 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
722 IN OUT VOID
*MemoryAddr
,
728 EDKII_IOMMU_OPERATION MapOp
;
730 EFI_PHYSICAL_ADDRESS PhyAddr
;
732 EFI_AHCI_REGISTERS
*AhciRegisters
;
734 BOOLEAN InfiniteWait
;
743 EFI_AHCI_COMMAND_FIS CFis
;
744 EFI_AHCI_COMMAND_LIST CmdList
;
747 BOOLEAN PioFisReceived
;
748 BOOLEAN D2hFisReceived
;
751 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
754 if (DataCount
/ (UINT32
)AHCI_MAX_PRDT_NUMBER
> AHCI_MAX_DATA_PER_PRDT
) {
757 "%a: Driver only support a maximum of 0x%x PRDT entries, "
758 "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n",
759 __FUNCTION__
, AHCI_MAX_PRDT_NUMBER
, DataCount
,
760 AHCI_MAX_PRDT_NUMBER
* AHCI_MAX_DATA_PER_PRDT
762 return EFI_UNSUPPORTED
;
765 MapOp
= Read
? EdkiiIoMmuOperationBusMasterWrite
:
766 EdkiiIoMmuOperationBusMasterRead
;
767 MapLength
= DataCount
;
775 if (EFI_ERROR (Status
) || (MapLength
!= DataCount
)) {
776 DEBUG ((DEBUG_ERROR
, "%a: Fail to map data buffer.\n", __FUNCTION__
));
777 return EFI_OUT_OF_RESOURCES
;
780 AhciRegisters
= &Private
->AhciRegisters
;
781 AhciBar
= Private
->MmioBase
;
782 InfiniteWait
= (Timeout
== 0) ? TRUE
: FALSE
;
785 // Fill FIS base address register
787 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
788 OldRfisLo
= AhciReadReg (AhciBar
, Offset
);
789 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
790 OldRfisHi
= AhciReadReg (AhciBar
, Offset
);
791 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
792 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
793 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
794 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
795 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
798 // Single task envrionment, we only use one command table for all port
800 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
801 OldCmdListLo
= AhciReadReg (AhciBar
, Offset
);
802 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
803 OldCmdListHi
= AhciReadReg (AhciBar
, Offset
);
804 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdList
);
805 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
806 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
807 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
808 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
811 // Package read needed
813 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
815 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
817 CmdList
.AhciCmdCfl
= AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
818 CmdList
.AhciCmdW
= Read
? 0 : 1;
828 (VOID
*)(UINTN
)PhyAddr
,
832 Status
= AhciStartCommand (
838 if (EFI_ERROR (Status
)) {
843 // Checking the status and wait the driver sending Data
845 FisBaseAddr
= (UINT32
)(UINTN
)AhciRegisters
->AhciRFis
+ sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
848 // Wait device sends the PIO setup fis before data transfer
850 Status
= EFI_TIMEOUT
;
851 Delay
= (UINT32
) DivU64x32 (Timeout
, 1000) + 1;
853 PioFisReceived
= FALSE
;
854 D2hFisReceived
= FALSE
;
855 Offset
= FisBaseAddr
+ AHCI_PIO_FIS_OFFSET
;
856 Status
= AhciCheckMemSet (Offset
, AHCI_FIS_TYPE_MASK
, AHCI_FIS_PIO_SETUP
);
857 if (!EFI_ERROR (Status
)) {
858 DEBUG ((DEBUG_INFO
, "%a: PioFisReceived.\n", __FUNCTION__
));
859 PioFisReceived
= TRUE
;
862 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
863 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from
864 // device after the transaction is finished successfully.
865 // To get better device compatibilities, we further check if the PxTFD's
866 // ERR bit is set. By this way, we can know if there is a real error happened.
868 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
869 Status
= AhciCheckMemSet (Offset
, AHCI_FIS_TYPE_MASK
, AHCI_FIS_REGISTER_D2H
);
870 if (!EFI_ERROR (Status
)) {
871 DEBUG ((DEBUG_INFO
, "%a: D2hFisReceived.\n", __FUNCTION__
));
872 D2hFisReceived
= TRUE
;
875 if (PioFisReceived
|| D2hFisReceived
) {
876 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
877 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
879 // PxTFD will be updated if there is a D2H or SetupFIS received.
881 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
882 Status
= EFI_DEVICE_ERROR
;
886 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
887 if (PrdCount
== DataCount
) {
888 Status
= EFI_SUCCESS
;
894 // Stall for 100 microseconds.
896 MicroSecondDelay(100);
900 Status
= EFI_TIMEOUT
;
902 } while (InfiniteWait
|| (Delay
> 0));
905 // Wait for D2H Fis is received
907 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
908 Status
= AhciWaitMemSet (
911 AHCI_FIS_REGISTER_D2H
,
914 if (EFI_ERROR (Status
)) {
915 DEBUG ((DEBUG_ERROR
, "%a: AhciWaitMemSet (%r)\n", __FUNCTION__
, Status
));
919 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
920 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
921 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
922 Status
= EFI_DEVICE_ERROR
;
933 AhciDisableFisReceive (
939 if (MapData
!= NULL
) {
940 IoMmuUnmap (MapData
);
943 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
944 AhciWriteReg (AhciBar
, Offset
, OldRfisLo
);
945 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
946 AhciWriteReg (AhciBar
, Offset
, OldRfisHi
);
948 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
949 AhciWriteReg (AhciBar
, Offset
, OldCmdListLo
);
950 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
951 AhciWriteReg (AhciBar
, Offset
, OldCmdListHi
);
957 Start a non data transfer on specific port.
959 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
960 @param[in] Port The number of port.
961 @param[in] PortMultiplier The number of port multiplier.
962 @param[in] FisIndex The offset index of the FIS base address.
963 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
964 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
965 @param[in] Timeout The timeout value of non data transfer, uses
968 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
969 @retval EFI_TIMEOUT The operation is time out.
970 @retval EFI_UNSUPPORTED The device is not ready for transfer.
971 @retval EFI_SUCCESS The non data transfer executes successfully.
975 AhciNonDataTransfer (
976 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
978 IN UINT8 PortMultiplier
,
980 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
981 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
987 EFI_AHCI_REGISTERS
*AhciRegisters
;
991 EFI_AHCI_COMMAND_FIS CFis
;
992 EFI_AHCI_COMMAND_LIST CmdList
;
994 AhciBar
= Private
->MmioBase
;
995 AhciRegisters
= &Private
->AhciRegisters
;
998 // Package read needed
1000 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1002 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1004 CmdList
.AhciCmdCfl
= AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1018 Status
= AhciStartCommand (
1024 if (EFI_ERROR (Status
)) {
1029 // Wait device sends the Response Fis
1031 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
1032 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
1033 Status
= AhciWaitMemSet (
1036 AHCI_FIS_REGISTER_D2H
,
1040 if (EFI_ERROR (Status
)) {
1044 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
1045 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
1046 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
1047 Status
= EFI_DEVICE_ERROR
;
1057 AhciDisableFisReceive (
1069 @param[in] AhciBar AHCI bar address.
1070 @param[in] Timeout The timeout, in 100ns units, to reset.
1072 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1073 @retval EFI_TIMEOUT The reset operation is time out.
1074 @retval EFI_SUCCESS AHCI controller is reset successfully.
1088 // Collect AHCI controller information
1090 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1093 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1095 if ((Capability
& AHCI_CAP_SAM
) == 0) {
1096 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_ENABLE
);
1099 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_RESET
);
1101 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1104 Value
= AhciReadReg(AhciBar
, AHCI_GHC_OFFSET
);
1105 if ((Value
& AHCI_GHC_RESET
) == 0) {
1110 // Stall for 100 microseconds.
1112 MicroSecondDelay(100);
1115 } while (Delay
> 0);
1121 Send Identify Drive command to a specific device.
1123 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
1124 @param[in] Port The number of port.
1125 @param[in] PortMultiplier The port multiplier port number.
1126 @param[in] FisIndex The offset index of the FIS base address.
1127 @param[in] Buffer The data buffer to store IDENTIFY PACKET data.
1129 @retval EFI_SUCCESS The cmd executes successfully.
1130 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1131 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1132 @retval EFI_TIMEOUT The operation is time out.
1133 @retval EFI_UNSUPPORTED The device is not ready for executing.
1138 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
1140 IN UINT8 PortMultiplier
,
1142 IN ATA_IDENTIFY_DATA
*Buffer
1146 EFI_ATA_COMMAND_BLOCK Acb
;
1147 EFI_ATA_STATUS_BLOCK Asb
;
1149 if (Buffer
== NULL
) {
1150 return EFI_INVALID_PARAMETER
;
1153 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1154 ZeroMem (&Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1156 Acb
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1157 Acb
.AtaSectorCount
= 1;
1159 Status
= AhciPioTransfer (
1168 sizeof (ATA_IDENTIFY_DATA
),
1177 Collect the number of bits set within a port bitmap.
1179 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1181 @retval The number of bits set in the bitmap.
1185 AhciGetNumberOfPortsFromMap (
1186 IN UINT32 PortBitMap
1189 UINT8 NumberOfPorts
;
1193 while (PortBitMap
!= 0) {
1194 if ((PortBitMap
& ((UINT32
)BIT0
)) != 0) {
1197 PortBitMap
= PortBitMap
>> 1;
1200 return NumberOfPorts
;
1204 Get the specified port number from a port bitmap.
1206 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1207 @param[in] PortIndex The specified port index.
1208 @param[out] Port The port number of the port specified by PortIndex.
1210 @retval EFI_SUCCESS The specified port is found and its port number is
1212 @retval EFI_NOT_FOUND Cannot find the specified port within the port bitmap.
1216 AhciGetPortFromMap (
1217 IN UINT32 PortBitMap
,
1222 if (PortIndex
== 0) {
1223 return EFI_NOT_FOUND
;
1228 while (PortBitMap
!= 0) {
1229 if ((PortBitMap
& ((UINT32
)BIT0
)) != 0) {
1233 // Found the port specified by PortIndex.
1235 if (PortIndex
== 0) {
1239 PortBitMap
= PortBitMap
>> 1;
1243 return EFI_NOT_FOUND
;
1247 Allocate transfer-related data struct which is used at AHCI mode.
1249 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1251 @retval EFI_SUCCESS Data structures are allocated successfully.
1252 @retval Others Data structures are not allocated successfully.
1256 AhciCreateTransferDescriptor (
1257 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1262 EFI_AHCI_REGISTERS
*AhciRegisters
;
1263 EFI_PHYSICAL_ADDRESS DeviceAddress
;
1267 UINT32 PortImplementBitMap
;
1268 UINT8 MaxPortNumber
;
1269 UINT8 MaxCommandSlotNumber
;
1271 UINTN MaxCmdListSize
;
1272 UINTN MaxCmdTableSize
;
1274 AhciBar
= Private
->MmioBase
;
1275 AhciRegisters
= &Private
->AhciRegisters
;
1278 // Collect AHCI controller information
1280 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1283 // Get the number of command slots per port supported by this HBA.
1285 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1286 ASSERT (MaxCommandSlotNumber
> 0);
1287 if (MaxCommandSlotNumber
== 0) {
1288 return EFI_DEVICE_ERROR
;
1292 // Get the highest bit of implemented ports which decides how many bytes are
1293 // allocated for recived FIS.
1295 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1296 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
1297 if (MaxPortNumber
== 0) {
1298 return EFI_DEVICE_ERROR
;
1301 // Get the number of ports that actually needed to be initialized.
1303 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1306 // Allocate memory for received FIS.
1308 MaxRFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1309 Status
= IoMmuAllocateBuffer (
1310 EFI_SIZE_TO_PAGES (MaxRFisSize
),
1315 if (EFI_ERROR (Status
)) {
1316 return EFI_OUT_OF_RESOURCES
;
1318 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1319 AhciRegisters
->AhciRFis
= Base
;
1320 AhciRegisters
->AhciRFisMap
= Mapping
;
1321 AhciRegisters
->MaxRFisSize
= MaxRFisSize
;
1322 ZeroMem (AhciRegisters
->AhciRFis
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxRFisSize
));
1325 // Allocate memory for command list.
1326 // Note that the implemenation is a single task model which only use a command
1327 // list for each port.
1329 MaxCmdListSize
= 1 * sizeof (EFI_AHCI_COMMAND_LIST
);
1330 Status
= IoMmuAllocateBuffer (
1331 EFI_SIZE_TO_PAGES (MaxCmdListSize
),
1336 if (EFI_ERROR (Status
)) {
1337 Status
= EFI_OUT_OF_RESOURCES
;
1340 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1341 AhciRegisters
->AhciCmdList
= Base
;
1342 AhciRegisters
->AhciCmdListMap
= Mapping
;
1343 AhciRegisters
->MaxCmdListSize
= MaxCmdListSize
;
1344 ZeroMem (AhciRegisters
->AhciCmdList
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdListSize
));
1347 // Allocate memory for command table
1348 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1350 MaxCmdTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
1351 Status
= IoMmuAllocateBuffer (
1352 EFI_SIZE_TO_PAGES (MaxCmdTableSize
),
1357 if (EFI_ERROR (Status
)) {
1358 Status
= EFI_OUT_OF_RESOURCES
;
1361 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1362 AhciRegisters
->AhciCmdTable
= Base
;
1363 AhciRegisters
->AhciCmdTableMap
= Mapping
;
1364 AhciRegisters
->MaxCmdTableSize
= MaxCmdTableSize
;
1365 ZeroMem (AhciRegisters
->AhciCmdTable
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdTableSize
));
1370 if (AhciRegisters
->AhciRFisMap
!= NULL
) {
1372 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxRFisSize
),
1373 AhciRegisters
->AhciRFis
,
1374 AhciRegisters
->AhciRFisMap
1376 AhciRegisters
->AhciRFis
= NULL
;
1379 if (AhciRegisters
->AhciCmdListMap
!= NULL
) {
1381 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxCmdListSize
),
1382 AhciRegisters
->AhciCmdList
,
1383 AhciRegisters
->AhciCmdListMap
1385 AhciRegisters
->AhciCmdList
= NULL
;
1392 Gets ATA device Capacity according to ATA 6.
1394 This function returns the capacity of the ATA device if it follows
1395 ATA 6 to support 48 bit addressing.
1397 @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure.
1399 @return The capacity of the ATA device or 0 if the device does not support
1400 48-bit addressing defined in ATA 6.
1405 IN ATA_IDENTIFY_DATA
*IdentifyData
1412 if ((IdentifyData
->command_set_supported_83
& BIT10
) == 0) {
1414 // The device doesn't support 48 bit addressing
1420 // 48 bit address feature set is supported, get maximum capacity
1423 for (Index
= 0; Index
< 4; Index
++) {
1425 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
1427 TmpLba
= IdentifyData
->maximum_lba_for_48bit_addressing
[Index
];
1428 Capacity
|= LShiftU64 (TmpLba
, 16 * Index
);
1435 Identifies ATA device via the Identify data.
1437 This function identifies the ATA device and initializes the media information.
1439 @attention This is boundary function that may receive untrusted input.
1440 @attention The input is from peripheral hardware device.
1442 The Identify Drive command response data from an ATA device is the peripheral
1443 hardware input, so this routine will do basic validation for the Identify Drive
1444 command response data.
1446 @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1448 @retval EFI_SUCCESS The device is successfully identified and media
1449 information is correctly initialized.
1450 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
1455 IN OUT PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
1458 ATA_IDENTIFY_DATA
*IdentifyData
;
1459 EFI_PEI_BLOCK_IO2_MEDIA
*Media
;
1461 UINT32 MaxSectorCount
;
1462 UINT16 PhyLogicSectorSupport
;
1464 IdentifyData
= DeviceData
->IdentifyData
;
1465 Media
= &DeviceData
->Media
;
1467 if ((IdentifyData
->config
& BIT15
) != 0) {
1469 DEBUG_ERROR
, "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n",
1470 __FUNCTION__
, DeviceData
->Port
, DeviceData
->PortMultiplier
1472 return EFI_UNSUPPORTED
;
1476 DEBUG_INFO
, "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n",
1477 __FUNCTION__
, DeviceData
->Port
, DeviceData
->PortMultiplier
1481 // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the
1482 // driver only support PIO data transfer for now.
1486 // Get the capacity information of the device.
1488 Capacity
= GetAtapi6Capacity (IdentifyData
);
1489 if (Capacity
> MAX_28BIT_ADDRESSING_CAPACITY
) {
1491 // Capacity exceeds 120GB. 48-bit addressing is really needed
1493 DeviceData
->Lba48Bit
= TRUE
;
1496 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
1498 Capacity
= ((UINT32
)IdentifyData
->user_addressable_sectors_hi
<< 16) |
1499 IdentifyData
->user_addressable_sectors_lo
;
1500 DeviceData
->Lba48Bit
= FALSE
;
1503 if (Capacity
== 0) {
1504 DEBUG ((DEBUG_ERROR
, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__
));
1505 return EFI_UNSUPPORTED
;
1507 Media
->LastBlock
= (EFI_PEI_LBA
) (Capacity
- 1);
1509 Media
->BlockSize
= 0x200;
1511 // Check whether Long Physical Sector Feature is supported
1513 PhyLogicSectorSupport
= IdentifyData
->phy_logic_sector_support
;
1515 DEBUG_INFO
, "%a: PhyLogicSectorSupport = 0x%x\n",
1516 __FUNCTION__
, PhyLogicSectorSupport
1518 if ((PhyLogicSectorSupport
& (BIT14
| BIT15
)) == BIT14
) {
1520 // Check logical block size
1522 if ((PhyLogicSectorSupport
& BIT12
) != 0) {
1523 Media
->BlockSize
= (UINT32
) (((IdentifyData
->logic_sector_size_hi
<< 16) |
1524 IdentifyData
->logic_sector_size_lo
) * sizeof (UINT16
));
1529 // Check BlockSize validity
1531 MaxSectorCount
= mMaxTransferBlockNumber
[DeviceData
->Lba48Bit
];
1532 if ((Media
->BlockSize
== 0) || (Media
->BlockSize
> MAX_UINT32
/ MaxSectorCount
)) {
1533 DEBUG ((DEBUG_ERROR
, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__
, Media
->BlockSize
));
1534 return EFI_UNSUPPORTED
;
1538 DEBUG_INFO
, "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n",
1539 __FUNCTION__
, Media
->BlockSize
, Media
->LastBlock
1542 if ((IdentifyData
->trusted_computing_support
& BIT0
) != 0) {
1543 DEBUG ((DEBUG_INFO
, "%a: Found Trust Computing feature support.\n", __FUNCTION__
));
1544 DeviceData
->TrustComputing
= TRUE
;
1547 Media
->InterfaceType
= MSG_SATA_DP
;
1548 Media
->RemovableMedia
= FALSE
;
1549 Media
->MediaPresent
= TRUE
;
1550 Media
->ReadOnly
= FALSE
;
1556 Allocate device information data structure to contain device information.
1557 And insert the data structure to the tail of device list for tracing.
1559 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
1561 @param[in] DeviceIndex The device index.
1562 @param[in] Port The port number of the ATA device to send
1564 @param[in] PortMultiplierPort The port multiplier port number of the ATA
1565 device to send the command.
1566 If there is no port multiplier, then specify
1568 @param[in] FisIndex The index of the FIS of the ATA device to
1570 @param[in] IdentifyData The data buffer to store the output of the
1573 @retval EFI_SUCCESS Successfully insert the ATA device to the
1574 tail of device list.
1575 @retval EFI_OUT_OF_RESOURCES Not enough resource.
1580 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
1581 IN UINTN DeviceIndex
,
1583 IN UINT16 PortMultiplier
,
1585 IN ATA_IDENTIFY_DATA
*IdentifyData
1588 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
1591 DeviceData
= AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA
));
1592 if (DeviceData
== NULL
) {
1593 return EFI_OUT_OF_RESOURCES
;
1596 if (IdentifyData
!= NULL
) {
1597 DeviceData
->IdentifyData
= AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA
), IdentifyData
);
1598 if (DeviceData
->IdentifyData
== NULL
) {
1599 return EFI_OUT_OF_RESOURCES
;
1603 DeviceData
->Signature
= AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE
;
1604 DeviceData
->Port
= Port
;
1605 DeviceData
->PortMultiplier
= PortMultiplier
;
1606 DeviceData
->FisIndex
= FisIndex
;
1607 DeviceData
->DeviceIndex
= DeviceIndex
;
1608 DeviceData
->Private
= Private
;
1610 Status
= IdentifyAtaDevice (DeviceData
);
1611 if (EFI_ERROR (Status
)) {
1615 if (DeviceData
->TrustComputing
) {
1616 Private
->TrustComputingDevices
++;
1617 DeviceData
->TrustComputingDeviceIndex
= Private
->TrustComputingDevices
;
1619 Private
->ActiveDevices
++;
1620 InsertTailList (&Private
->DeviceList
, &DeviceData
->Link
);
1626 Initialize ATA host controller at AHCI mode.
1628 The function is designed to initialize ATA host controller.
1630 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1632 @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully.
1633 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing
1635 @retval Others A device error occurred while initializing the
1640 AhciModeInitialization (
1641 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1648 UINT8 MaxPortNumber
;
1649 UINT32 PortImplementBitMap
;
1650 UINT32 PortInitializeBitMap
;
1651 EFI_AHCI_REGISTERS
*AhciRegisters
;
1657 UINT32 PhyDetectDelay
;
1659 ATA_IDENTIFY_DATA IdentifyData
;
1661 AhciBar
= Private
->MmioBase
;
1663 Status
= AhciReset (AhciBar
, AHCI_PEI_RESET_TIMEOUT
);
1664 if (EFI_ERROR (Status
)) {
1665 DEBUG ((DEBUG_ERROR
, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__
, Status
));
1666 return EFI_DEVICE_ERROR
;
1670 // Collect AHCI controller information
1672 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1675 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1677 Value
= AhciReadReg (AhciBar
, AHCI_GHC_OFFSET
);
1678 if ((Value
& AHCI_GHC_ENABLE
) == 0) {
1679 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_ENABLE
);
1682 Status
= AhciCreateTransferDescriptor (Private
);
1683 if (EFI_ERROR (Status
)) {
1686 "%a: Transfer-related data allocation failed with %r.\n",
1687 __FUNCTION__
, Status
1689 return EFI_OUT_OF_RESOURCES
;
1693 // Get the number of command slots per port supported by this HBA.
1695 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1698 // Get the bit map of those ports exposed by this HBA.
1699 // It indicates which ports that the HBA supports are available for software
1702 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1705 // Get the number of ports that actually needed to be initialized.
1707 MaxPortNumber
= MIN (MaxPortNumber
, (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1));
1708 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1710 PortInitializeBitMap
= Private
->PortBitMap
;
1711 AhciRegisters
= &Private
->AhciRegisters
;
1714 // Enumerate ATA ports
1716 for (PortIndex
= 1; PortIndex
<= MaxPortNumber
; PortIndex
++) {
1717 Status
= AhciGetPortFromMap (PortInitializeBitMap
, PortIndex
, &Port
);
1718 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
1720 // Initialize FIS Base Address Register and Command List Base Address
1721 // Register for use.
1723 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) +
1724 sizeof (EFI_AHCI_RECEIVED_FIS
) * (PortIndex
- 1);
1725 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
1726 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1727 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
1728 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1730 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdList
);
1731 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
1732 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1733 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
1734 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1736 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1737 Data
= AhciReadReg (AhciBar
, Offset
);
1738 if ((Data
& AHCI_PORT_CMD_CPD
) != 0) {
1739 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_POD
);
1742 if ((Capability
& AHCI_CAP_SSS
) != 0) {
1743 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_SUD
);
1747 // Disable aggressive power management.
1749 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SCTL
;
1750 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_SCTL_IPM_INIT
);
1752 // Disable the reporting of the corresponding interrupt to system software.
1754 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IE
;
1755 AhciAndReg (AhciBar
, Offset
, 0);
1758 // Enable FIS Receive DMA engine for the first D2H FIS.
1760 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1761 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
1764 // Wait no longer than 15 ms to wait the Phy to detect the presence of a device.
1766 PhyDetectDelay
= AHCI_BUS_PHY_DETECT_TIMEOUT
;
1767 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SSTS
;
1769 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_SSTS_DET_MASK
;
1770 if ((Data
== AHCI_PORT_SSTS_DET_PCE
) || (Data
== AHCI_PORT_SSTS_DET
)) {
1774 MicroSecondDelay (1000);
1776 } while (PhyDetectDelay
> 0);
1778 if (PhyDetectDelay
== 0) {
1780 // No device detected at this port.
1781 // Clear PxCMD.SUD for those ports at which there are no device present.
1783 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1784 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_SUD
));
1785 DEBUG ((DEBUG_ERROR
, "%a: No device detected at Port %d.\n", __FUNCTION__
, Port
));
1790 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
1791 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
1793 PhyDetectDelay
= 16 * 1000;
1795 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
1796 if (AhciReadReg(AhciBar
, Offset
) != 0) {
1797 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
1799 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
1801 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_TFD_MASK
;
1806 MicroSecondDelay (1000);
1808 } while (PhyDetectDelay
> 0);
1810 if (PhyDetectDelay
== 0) {
1813 "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n",
1814 __FUNCTION__
, Port
, Data
1820 // When the first D2H register FIS is received, the content of PxSIG register is updated.
1822 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SIG
;
1823 Status
= AhciWaitMmioSet (
1830 if (EFI_ERROR (Status
)) {
1833 "%a: Error occured when waiting for the first D2H register FIS - %r\n",
1834 __FUNCTION__
, Status
1839 Data
= AhciReadReg (AhciBar
, Offset
);
1840 if ((Data
& AHCI_ATAPI_SIG_MASK
) == AHCI_ATA_DEVICE_SIG
) {
1841 Status
= AhciIdentify (Private
, Port
, 0, PortIndex
- 1, &IdentifyData
);
1842 if (EFI_ERROR (Status
)) {
1843 DEBUG ((DEBUG_ERROR
, "%a: AhciIdentify() failed with %r\n", __FUNCTION__
, Status
));
1846 DEBUG ((DEBUG_INFO
, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__
, Port
));
1852 // Found an ATA hard disk device, add it into the device list.
1870 Trust transfer data from/to ATA device.
1872 This function performs one ATA pass through transaction to do a trust transfer
1873 from/to ATA device. It chooses the appropriate ATA command and protocol to invoke
1874 PassThru interface of ATA pass through.
1876 @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1877 @param[in,out] Buffer The pointer to the current transaction buffer.
1878 @param[in] SecurityProtocolId
1879 The value of the "Security Protocol" parameter
1880 of the security protocol command to be sent.
1881 @param[in] SecurityProtocolSpecificData
1882 The value of the "Security Protocol Specific"
1883 parameter of the security protocol command to
1885 @param[in] TransferLength The block number or sector count of the transfer.
1886 @param[in] IsTrustSend Indicates whether it is a trust send operation
1888 @param[in] Timeout The timeout, in 100ns units, to use for the execution
1889 of the security protocol command. A Timeout value
1890 of 0 means that this function will wait indefinitely
1891 for the security protocol command to execute. If
1892 Timeout is greater than zero, then this function
1893 will return EFI_TIMEOUT if the time required to
1894 execute the receive data command is greater than
1896 @param[out] TransferLengthOut
1897 A pointer to a buffer to store the size in bytes
1898 of the data written to the buffer. Ignore it when
1899 IsTrustSend is TRUE.
1901 @retval EFI_SUCCESS The data transfer is complete successfully.
1902 @return others Some error occurs when transferring data.
1906 TrustTransferAtaDevice (
1907 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
1908 IN OUT VOID
*Buffer
,
1909 IN UINT8 SecurityProtocolId
,
1910 IN UINT16 SecurityProtocolSpecificData
,
1911 IN UINTN TransferLength
,
1912 IN BOOLEAN IsTrustSend
,
1914 OUT UINTN
*TransferLengthOut
1917 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
1918 EDKII_PEI_ATA_PASS_THRU_PPI
*AtaPassThru
;
1919 EFI_ATA_COMMAND_BLOCK Acb
;
1920 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1924 Private
= DeviceData
->Private
;
1925 AtaPassThru
= &Private
->AtaPassThruPpi
;
1928 // Ensure IsTrustSend are valid boolean values
1930 ASSERT ((UINTN
) IsTrustSend
< 2);
1931 if ((UINTN
) IsTrustSend
>= 2) {
1932 return EFI_INVALID_PARAMETER
;
1936 // Prepare for ATA command block.
1938 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1939 if (TransferLength
== 0) {
1940 Acb
.AtaCommand
= ATA_CMD_TRUST_NON_DATA
;
1942 Acb
.AtaCommand
= mAtaTrustCommands
[IsTrustSend
];
1944 Acb
.AtaFeatures
= SecurityProtocolId
;
1945 Acb
.AtaSectorCount
= (UINT8
) (TransferLength
/ 512);
1946 Acb
.AtaSectorNumber
= (UINT8
) ((TransferLength
/ 512) >> 8);
1948 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
1949 // Here use big endian for Cylinder register.
1951 Acb
.AtaCylinderHigh
= (UINT8
) SecurityProtocolSpecificData
;
1952 Acb
.AtaCylinderLow
= (UINT8
) (SecurityProtocolSpecificData
>> 8);
1953 Acb
.AtaDeviceHead
= (UINT8
) (BIT7
| BIT6
| BIT5
|
1954 (DeviceData
->PortMultiplier
== 0xFFFF ?
1955 0 : (DeviceData
->PortMultiplier
<< 4)));
1958 // Prepare for ATA pass through packet.
1960 ZeroMem (&Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
1961 if (TransferLength
== 0) {
1962 Packet
.InTransferLength
= 0;
1963 Packet
.OutTransferLength
= 0;
1964 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
1965 } else if (IsTrustSend
) {
1967 // Check the alignment of the incoming buffer prior to invoking underlying
1968 // ATA PassThru PPI.
1970 if ((AtaPassThru
->Mode
->IoAlign
> 1) &&
1971 !IS_ALIGNED (Buffer
, AtaPassThru
->Mode
->IoAlign
)) {
1972 NewBuffer
= AllocateAlignedPages (
1973 EFI_SIZE_TO_PAGES (TransferLength
),
1974 AtaPassThru
->Mode
->IoAlign
1976 if (NewBuffer
== NULL
) {
1977 return EFI_OUT_OF_RESOURCES
;
1980 CopyMem (NewBuffer
, Buffer
, TransferLength
);
1983 Packet
.OutDataBuffer
= Buffer
;
1984 Packet
.OutTransferLength
= (UINT32
) TransferLength
;
1985 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
1987 Packet
.InDataBuffer
= Buffer
;
1988 Packet
.InTransferLength
= (UINT32
) TransferLength
;
1989 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
1993 Packet
.Timeout
= Timeout
;
1994 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
1996 Status
= AtaPassThru
->PassThru (
1999 DeviceData
->PortMultiplier
,
2002 if (TransferLengthOut
!= NULL
) {
2004 *TransferLengthOut
= Packet
.InTransferLength
;