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
52 // Due to limited resource for VTd PEI DMA buffer on platforms, the driver
53 // limits the maximum transfer block number for 48-bit addressing.
54 // Here, setting to 0x800 means that for device with 512-byte block size, the
55 // maximum buffer for DMA mapping will be 1M bytes in size.
57 #define MAX_48BIT_TRANSFER_BLOCK_NUM 0x800
59 UINT32 mMaxTransferBlockNumber
[2] = {
60 MAX_28BIT_TRANSFER_BLOCK_NUM
,
61 MAX_48BIT_TRANSFER_BLOCK_NUM
65 // The maximum total sectors count in 28 bit addressing mode
67 #define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
71 Read AHCI Operation register.
73 @param[in] AhciBar AHCI bar address.
74 @param[in] Offset The operation register offset.
76 @return The register content read.
88 Data
= MmioRead32 (AhciBar
+ Offset
);
94 Write AHCI Operation register.
96 @param[in] AhciBar AHCI bar address.
97 @param[in] Offset The operation register offset.
98 @param[in] Data The Data used to write down.
108 MmioWrite32 (AhciBar
+ Offset
, Data
);
112 Do AND operation with the value of AHCI Operation register.
114 @param[in] AhciBar AHCI bar address.
115 @param[in] Offset The operation register offset.
116 @param[in] AndData The data used to do AND operation.
128 Data
= AhciReadReg (AhciBar
, Offset
);
131 AhciWriteReg (AhciBar
, Offset
, Data
);
135 Do OR operation with the Value of AHCI Operation register.
137 @param[in] AhciBar AHCI bar address.
138 @param[in] Offset The operation register offset.
139 @param[in] OrData The Data used to do OR operation.
151 Data
= AhciReadReg (AhciBar
, Offset
);
154 AhciWriteReg (AhciBar
, Offset
, Data
);
158 Wait for memory set to the test Value.
160 @param[in] AhciBar AHCI bar address.
161 @param[in] Offset The memory offset to test.
162 @param[in] MaskValue The mask Value of memory.
163 @param[in] TestValue The test Value of memory.
164 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
166 @retval EFI_DEVICE_ERROR The memory is not set.
167 @retval EFI_TIMEOUT The memory setting is time out.
168 @retval EFI_SUCCESS The memory is correct set.
184 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
187 Value
= AhciReadReg (AhciBar
, Offset
) & MaskValue
;
189 if (Value
== TestValue
) {
194 // Stall for 100 microseconds.
196 MicroSecondDelay (100);
206 Check the memory status to the test value.
208 @param[in] Address The memory address to test.
209 @param[in] MaskValue The mask value of memory.
210 @param[in] TestValue The test value of memory.
212 @retval EFI_NOT_READY The memory is not set.
213 @retval EFI_SUCCESS The memory is correct set.
225 Value
= *(volatile UINT32
*) Address
;
228 if (Value
== TestValue
) {
231 return EFI_NOT_READY
;
236 Wait for the value of the specified system memory set to the test value.
238 @param[in] Address The system memory address to test.
239 @param[in] MaskValue The mask value of memory.
240 @param[in] TestValue The test value of memory.
241 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
243 @retval EFI_TIMEOUT The system memory setting is time out.
244 @retval EFI_SUCCESS The system memory is correct set.
249 IN EFI_PHYSICAL_ADDRESS Address
,
257 BOOLEAN InfiniteWait
;
262 InfiniteWait
= FALSE
;
265 Delay
= DivU64x32 (Timeout
, 1000) + 1;
269 // Access sytem memory to see if the value is the tested one.
271 // The system memory pointed by Address will be updated by the
272 // SATA Host Controller, "volatile" is introduced to prevent
273 // compiler from optimizing the access to the memory address
274 // to only read once.
276 Value
= *(volatile UINT32
*) (UINTN
) Address
;
279 if (Value
== TestValue
) {
284 // Stall for 100 microseconds.
286 MicroSecondDelay (100);
290 } while (InfiniteWait
|| (Delay
> 0));
297 Clear the port interrupt and error status. It will also clear HBA interrupt
300 @param[in] AhciBar AHCI bar address.
301 @param[in] Port The number of port.
305 AhciClearPortStatus (
313 // Clear any error status
315 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
316 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
319 // Clear any port interrupt status
321 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IS
;
322 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
325 // Clear any HBA interrupt status
327 AhciWriteReg (AhciBar
, AHCI_IS_OFFSET
, AhciReadReg (AhciBar
, AHCI_IS_OFFSET
));
331 Enable the FIS running for giving port.
333 @param[in] AhciBar AHCI bar address.
334 @param[in] Port The number of port.
335 @param[in] Timeout The timeout, in 100ns units, to enabling FIS.
337 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
338 @retval EFI_TIMEOUT The FIS enable setting is time out.
339 @retval EFI_SUCCESS The FIS enable successfully.
343 AhciEnableFisReceive (
351 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
352 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
358 Disable the FIS running for giving port.
360 @param[in] AhciBar AHCI bar address.
361 @param[in] Port The number of port.
362 @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit.
364 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
365 @retval EFI_TIMEOUT The FIS disable setting is time out.
366 @retval EFI_UNSUPPORTED The port is in running state.
367 @retval EFI_SUCCESS The FIS disable successfully.
371 AhciDisableFisReceive (
380 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
381 Data
= AhciReadReg (AhciBar
, Offset
);
384 // Before disabling Fis receive, the DMA engine of the port should NOT be in
387 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) != 0) {
388 return EFI_UNSUPPORTED
;
392 // Check if the Fis receive DMA engine for the port is running.
394 if ((Data
& AHCI_PORT_CMD_FR
) != AHCI_PORT_CMD_FR
) {
398 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_FRE
));
400 return AhciWaitMmioSet (
410 Build the command list, command table and prepare the fis receiver.
412 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
413 @param[in] Port The number of port.
414 @param[in] PortMultiplier The number of port multiplier.
415 @param[in] FisIndex The offset index of the FIS base address.
416 @param[in] CommandFis The control fis will be used for the transfer.
417 @param[in] CommandList The command list will be used for the transfer.
418 @param[in] CommandSlotNumber The command slot will be used for the transfer.
419 @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master
421 @param[in] DataLength The data count to be transferred.
426 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
428 IN UINT8 PortMultiplier
,
430 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
431 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
432 IN UINT8 CommandSlotNumber
,
433 IN OUT VOID
*DataPhysicalAddr
,
437 EFI_AHCI_REGISTERS
*AhciRegisters
;
447 AhciRegisters
= &Private
->AhciRegisters
;
448 AhciBar
= Private
->MmioBase
;
453 PrdtNumber
= (UINT32
)DivU64x32 (
454 (UINT64
)DataLength
+ AHCI_MAX_DATA_PER_PRDT
- 1,
455 AHCI_MAX_DATA_PER_PRDT
459 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
460 // It also limits that the maximum amount of the PRDT entry in the command table
462 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
465 ASSERT (PrdtNumber
<= AHCI_MAX_PRDT_NUMBER
);
466 if (PrdtNumber
> AHCI_MAX_PRDT_NUMBER
) {
470 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
472 BaseAddr
= Data64
.Uint64
;
474 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
476 ZeroMem (AhciRegisters
->AhciCmdTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
478 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
480 CopyMem (&AhciRegisters
->AhciCmdTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
482 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
483 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_DLAE
| AHCI_PORT_CMD_ATAPI
));
485 RemainedData
= (UINTN
) DataLength
;
486 MemAddr
= (UINTN
) DataPhysicalAddr
;
487 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
489 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
490 if (RemainedData
< AHCI_MAX_DATA_PER_PRDT
) {
491 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
493 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= AHCI_MAX_DATA_PER_PRDT
- 1;
496 Data64
.Uint64
= (UINT64
)MemAddr
;
497 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
498 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
499 RemainedData
-= AHCI_MAX_DATA_PER_PRDT
;
500 MemAddr
+= AHCI_MAX_DATA_PER_PRDT
;
504 // Set the last PRDT to Interrupt On Complete
506 if (PrdtNumber
> 0) {
507 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
511 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
513 sizeof (EFI_AHCI_COMMAND_LIST
)
516 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCmdTable
;
517 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
518 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
519 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
525 @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data
527 @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data
532 AhciBuildCommandFis (
533 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
534 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
537 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
539 CmdFis
->AhciCFisType
= AHCI_FIS_REGISTER_H2D
;
541 // Indicator it's a command
543 CmdFis
->AhciCFisCmdInd
= 0x1;
544 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
546 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
547 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
549 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
550 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
552 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
553 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
555 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
556 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
558 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
559 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
561 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
565 Stop command running for giving port
567 @param[in] AhciBar AHCI bar address.
568 @param[in] Port The number of port.
569 @param[in] Timeout The timeout value, in 100ns units, to stop.
571 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
572 @retval EFI_TIMEOUT The operation is time out.
573 @retval EFI_SUCCESS The command stop successfully.
586 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
587 Data
= AhciReadReg (AhciBar
, Offset
);
589 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) == 0) {
593 if ((Data
& AHCI_PORT_CMD_ST
) != 0) {
594 AhciAndReg (AhciBar
, Offset
, (UINT32
)~(AHCI_PORT_CMD_ST
));
597 return AhciWaitMmioSet (
607 Start command for give slot on specific port.
609 @param[in] AhciBar AHCI bar address.
610 @param[in] Port The number of port.
611 @param[in] CommandSlot The number of Command Slot.
612 @param[in] Timeout The timeout value, in 100ns units, to start.
614 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
615 @retval EFI_TIMEOUT The operation is time out.
616 @retval EFI_SUCCESS The command start successfully.
623 IN UINT8 CommandSlot
,
636 // Collect AHCI controller information
638 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
640 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
642 AhciClearPortStatus (
647 Status
= AhciEnableFisReceive (
652 if (EFI_ERROR (Status
)) {
656 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
657 PortStatus
= AhciReadReg (AhciBar
, Offset
);
660 if ((PortStatus
& AHCI_PORT_CMD_ALPE
) != 0) {
661 StartCmd
= AhciReadReg (AhciBar
, Offset
);
662 StartCmd
&= ~AHCI_PORT_CMD_ICC_MASK
;
663 StartCmd
|= AHCI_PORT_CMD_ACTIVE
;
666 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
667 PortTfd
= AhciReadReg (AhciBar
, Offset
);
669 if ((PortTfd
& (AHCI_PORT_TFD_BSY
| AHCI_PORT_TFD_DRQ
)) != 0) {
670 if ((Capability
& BIT24
) != 0) {
671 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
672 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_CLO
);
684 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
685 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_ST
| StartCmd
);
688 // Setting the command
690 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CI
;
691 AhciAndReg (AhciBar
, Offset
, 0);
692 AhciOrReg (AhciBar
, Offset
, CmdSlotBit
);
698 Start a PIO Data transfer on specific port.
700 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
701 @param[in] Port The number of port.
702 @param[in] PortMultiplier The number of port multiplier.
703 @param[in] FisIndex The offset index of the FIS base address.
704 @param[in] Read The transfer direction.
705 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
706 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
707 @param[in,out] MemoryAddr The pointer to the data buffer.
708 @param[in] DataCount The data count to be transferred.
709 @param[in] Timeout The timeout value of PIO data transfer, uses
712 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
713 @retval EFI_TIMEOUT The operation is time out.
714 @retval EFI_UNSUPPORTED The device is not ready for transfer.
715 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
716 @retval EFI_SUCCESS The PIO data transfer executes successfully.
721 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
723 IN UINT8 PortMultiplier
,
726 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
727 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
728 IN OUT VOID
*MemoryAddr
,
734 EDKII_IOMMU_OPERATION MapOp
;
736 EFI_PHYSICAL_ADDRESS PhyAddr
;
738 EFI_AHCI_REGISTERS
*AhciRegisters
;
740 BOOLEAN InfiniteWait
;
749 EFI_AHCI_COMMAND_FIS CFis
;
750 EFI_AHCI_COMMAND_LIST CmdList
;
753 BOOLEAN PioFisReceived
;
754 BOOLEAN D2hFisReceived
;
757 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
760 if (DataCount
/ (UINT32
)AHCI_MAX_PRDT_NUMBER
> AHCI_MAX_DATA_PER_PRDT
) {
763 "%a: Driver only support a maximum of 0x%x PRDT entries, "
764 "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n",
765 __FUNCTION__
, AHCI_MAX_PRDT_NUMBER
, DataCount
,
766 AHCI_MAX_PRDT_NUMBER
* AHCI_MAX_DATA_PER_PRDT
768 return EFI_UNSUPPORTED
;
771 MapOp
= Read
? EdkiiIoMmuOperationBusMasterWrite
:
772 EdkiiIoMmuOperationBusMasterRead
;
773 MapLength
= DataCount
;
781 if (EFI_ERROR (Status
) || (MapLength
!= DataCount
)) {
782 DEBUG ((DEBUG_ERROR
, "%a: Fail to map data buffer.\n", __FUNCTION__
));
783 return EFI_OUT_OF_RESOURCES
;
786 AhciRegisters
= &Private
->AhciRegisters
;
787 AhciBar
= Private
->MmioBase
;
788 InfiniteWait
= (Timeout
== 0) ? TRUE
: FALSE
;
791 // Fill FIS base address register
793 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
794 OldRfisLo
= AhciReadReg (AhciBar
, Offset
);
795 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
796 OldRfisHi
= AhciReadReg (AhciBar
, Offset
);
797 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
798 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
799 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
800 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
801 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
804 // Single task envrionment, we only use one command table for all port
806 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
807 OldCmdListLo
= AhciReadReg (AhciBar
, Offset
);
808 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
809 OldCmdListHi
= AhciReadReg (AhciBar
, Offset
);
810 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdList
);
811 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
812 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
813 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
814 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
817 // Package read needed
819 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
821 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
823 CmdList
.AhciCmdCfl
= AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
824 CmdList
.AhciCmdW
= Read
? 0 : 1;
834 (VOID
*)(UINTN
)PhyAddr
,
838 Status
= AhciStartCommand (
844 if (EFI_ERROR (Status
)) {
849 // Checking the status and wait the driver sending Data
851 FisBaseAddr
= (UINT32
)(UINTN
)AhciRegisters
->AhciRFis
+ sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
854 // Wait device sends the PIO setup fis before data transfer
856 Status
= EFI_TIMEOUT
;
857 Delay
= (UINT32
) DivU64x32 (Timeout
, 1000) + 1;
859 PioFisReceived
= FALSE
;
860 D2hFisReceived
= FALSE
;
861 Offset
= FisBaseAddr
+ AHCI_PIO_FIS_OFFSET
;
862 Status
= AhciCheckMemSet (Offset
, AHCI_FIS_TYPE_MASK
, AHCI_FIS_PIO_SETUP
);
863 if (!EFI_ERROR (Status
)) {
864 DEBUG ((DEBUG_INFO
, "%a: PioFisReceived.\n", __FUNCTION__
));
865 PioFisReceived
= TRUE
;
868 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
869 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from
870 // device after the transaction is finished successfully.
871 // To get better device compatibilities, we further check if the PxTFD's
872 // ERR bit is set. By this way, we can know if there is a real error happened.
874 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
875 Status
= AhciCheckMemSet (Offset
, AHCI_FIS_TYPE_MASK
, AHCI_FIS_REGISTER_D2H
);
876 if (!EFI_ERROR (Status
)) {
877 DEBUG ((DEBUG_INFO
, "%a: D2hFisReceived.\n", __FUNCTION__
));
878 D2hFisReceived
= TRUE
;
881 if (PioFisReceived
|| D2hFisReceived
) {
882 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
883 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
885 // PxTFD will be updated if there is a D2H or SetupFIS received.
887 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
888 Status
= EFI_DEVICE_ERROR
;
892 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
893 if (PrdCount
== DataCount
) {
894 Status
= EFI_SUCCESS
;
900 // Stall for 100 microseconds.
902 MicroSecondDelay(100);
906 Status
= EFI_TIMEOUT
;
908 } while (InfiniteWait
|| (Delay
> 0));
911 // Wait for D2H Fis is received
913 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
914 Status
= AhciWaitMemSet (
917 AHCI_FIS_REGISTER_D2H
,
920 if (EFI_ERROR (Status
)) {
921 DEBUG ((DEBUG_ERROR
, "%a: AhciWaitMemSet (%r)\n", __FUNCTION__
, Status
));
925 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
926 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
927 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
928 Status
= EFI_DEVICE_ERROR
;
939 AhciDisableFisReceive (
945 if (MapData
!= NULL
) {
946 IoMmuUnmap (MapData
);
949 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
950 AhciWriteReg (AhciBar
, Offset
, OldRfisLo
);
951 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
952 AhciWriteReg (AhciBar
, Offset
, OldRfisHi
);
954 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
955 AhciWriteReg (AhciBar
, Offset
, OldCmdListLo
);
956 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
957 AhciWriteReg (AhciBar
, Offset
, OldCmdListHi
);
963 Start a non data transfer on specific port.
965 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
966 @param[in] Port The number of port.
967 @param[in] PortMultiplier The number of port multiplier.
968 @param[in] FisIndex The offset index of the FIS base address.
969 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
970 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
971 @param[in] Timeout The timeout value of non data transfer, uses
974 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
975 @retval EFI_TIMEOUT The operation is time out.
976 @retval EFI_UNSUPPORTED The device is not ready for transfer.
977 @retval EFI_SUCCESS The non data transfer executes successfully.
981 AhciNonDataTransfer (
982 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
984 IN UINT8 PortMultiplier
,
986 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
987 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
993 EFI_AHCI_REGISTERS
*AhciRegisters
;
997 EFI_AHCI_COMMAND_FIS CFis
;
998 EFI_AHCI_COMMAND_LIST CmdList
;
1000 AhciBar
= Private
->MmioBase
;
1001 AhciRegisters
= &Private
->AhciRegisters
;
1004 // Package read needed
1006 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1008 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1010 CmdList
.AhciCmdCfl
= AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1024 Status
= AhciStartCommand (
1030 if (EFI_ERROR (Status
)) {
1035 // Wait device sends the Response Fis
1037 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
1038 Offset
= FisBaseAddr
+ AHCI_D2H_FIS_OFFSET
;
1039 Status
= AhciWaitMemSet (
1042 AHCI_FIS_REGISTER_D2H
,
1046 if (EFI_ERROR (Status
)) {
1050 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
1051 PortTfd
= AhciReadReg (AhciBar
, (UINT32
) Offset
);
1052 if ((PortTfd
& AHCI_PORT_TFD_ERR
) != 0) {
1053 Status
= EFI_DEVICE_ERROR
;
1063 AhciDisableFisReceive (
1075 @param[in] AhciBar AHCI bar address.
1076 @param[in] Timeout The timeout, in 100ns units, to reset.
1078 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1079 @retval EFI_TIMEOUT The reset operation is time out.
1080 @retval EFI_SUCCESS AHCI controller is reset successfully.
1094 // Collect AHCI controller information
1096 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1099 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1101 if ((Capability
& AHCI_CAP_SAM
) == 0) {
1102 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_ENABLE
);
1105 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_RESET
);
1107 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1110 Value
= AhciReadReg(AhciBar
, AHCI_GHC_OFFSET
);
1111 if ((Value
& AHCI_GHC_RESET
) == 0) {
1116 // Stall for 100 microseconds.
1118 MicroSecondDelay(100);
1121 } while (Delay
> 0);
1127 Send Identify Drive command to a specific device.
1129 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
1130 @param[in] Port The number of port.
1131 @param[in] PortMultiplier The port multiplier port number.
1132 @param[in] FisIndex The offset index of the FIS base address.
1133 @param[in] Buffer The data buffer to store IDENTIFY PACKET data.
1135 @retval EFI_SUCCESS The cmd executes successfully.
1136 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1137 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1138 @retval EFI_TIMEOUT The operation is time out.
1139 @retval EFI_UNSUPPORTED The device is not ready for executing.
1144 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
1146 IN UINT8 PortMultiplier
,
1148 IN ATA_IDENTIFY_DATA
*Buffer
1152 EFI_ATA_COMMAND_BLOCK Acb
;
1153 EFI_ATA_STATUS_BLOCK Asb
;
1155 if (Buffer
== NULL
) {
1156 return EFI_INVALID_PARAMETER
;
1159 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1160 ZeroMem (&Asb
, sizeof (EFI_ATA_STATUS_BLOCK
));
1162 Acb
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1163 Acb
.AtaSectorCount
= 1;
1165 Status
= AhciPioTransfer (
1174 sizeof (ATA_IDENTIFY_DATA
),
1183 Collect the number of bits set within a port bitmap.
1185 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1187 @retval The number of bits set in the bitmap.
1191 AhciGetNumberOfPortsFromMap (
1192 IN UINT32 PortBitMap
1195 UINT8 NumberOfPorts
;
1199 while (PortBitMap
!= 0) {
1200 if ((PortBitMap
& ((UINT32
)BIT0
)) != 0) {
1203 PortBitMap
= PortBitMap
>> 1;
1206 return NumberOfPorts
;
1210 Get the specified port number from a port bitmap.
1212 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1213 @param[in] PortIndex The specified port index.
1214 @param[out] Port The port number of the port specified by PortIndex.
1216 @retval EFI_SUCCESS The specified port is found and its port number is
1218 @retval EFI_NOT_FOUND Cannot find the specified port within the port bitmap.
1222 AhciGetPortFromMap (
1223 IN UINT32 PortBitMap
,
1228 if (PortIndex
== 0) {
1229 return EFI_NOT_FOUND
;
1234 while (PortBitMap
!= 0) {
1235 if ((PortBitMap
& ((UINT32
)BIT0
)) != 0) {
1239 // Found the port specified by PortIndex.
1241 if (PortIndex
== 0) {
1245 PortBitMap
= PortBitMap
>> 1;
1249 return EFI_NOT_FOUND
;
1253 Allocate transfer-related data struct which is used at AHCI mode.
1255 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1257 @retval EFI_SUCCESS Data structures are allocated successfully.
1258 @retval Others Data structures are not allocated successfully.
1262 AhciCreateTransferDescriptor (
1263 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1268 EFI_AHCI_REGISTERS
*AhciRegisters
;
1269 EFI_PHYSICAL_ADDRESS DeviceAddress
;
1273 UINT32 PortImplementBitMap
;
1274 UINT8 MaxPortNumber
;
1275 UINT8 MaxCommandSlotNumber
;
1277 UINTN MaxCmdListSize
;
1278 UINTN MaxCmdTableSize
;
1280 AhciBar
= Private
->MmioBase
;
1281 AhciRegisters
= &Private
->AhciRegisters
;
1284 // Collect AHCI controller information
1286 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1289 // Get the number of command slots per port supported by this HBA.
1291 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1292 ASSERT (MaxCommandSlotNumber
> 0);
1293 if (MaxCommandSlotNumber
== 0) {
1294 return EFI_DEVICE_ERROR
;
1298 // Get the highest bit of implemented ports which decides how many bytes are
1299 // allocated for recived FIS.
1301 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1302 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
1303 if (MaxPortNumber
== 0) {
1304 return EFI_DEVICE_ERROR
;
1307 // Get the number of ports that actually needed to be initialized.
1309 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1312 // Allocate memory for received FIS.
1314 MaxRFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1315 Status
= IoMmuAllocateBuffer (
1316 EFI_SIZE_TO_PAGES (MaxRFisSize
),
1321 if (EFI_ERROR (Status
)) {
1322 return EFI_OUT_OF_RESOURCES
;
1324 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1325 AhciRegisters
->AhciRFis
= Base
;
1326 AhciRegisters
->AhciRFisMap
= Mapping
;
1327 AhciRegisters
->MaxRFisSize
= MaxRFisSize
;
1328 ZeroMem (AhciRegisters
->AhciRFis
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxRFisSize
));
1331 // Allocate memory for command list.
1332 // Note that the implemenation is a single task model which only use a command
1333 // list for each port.
1335 MaxCmdListSize
= 1 * sizeof (EFI_AHCI_COMMAND_LIST
);
1336 Status
= IoMmuAllocateBuffer (
1337 EFI_SIZE_TO_PAGES (MaxCmdListSize
),
1342 if (EFI_ERROR (Status
)) {
1343 Status
= EFI_OUT_OF_RESOURCES
;
1346 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1347 AhciRegisters
->AhciCmdList
= Base
;
1348 AhciRegisters
->AhciCmdListMap
= Mapping
;
1349 AhciRegisters
->MaxCmdListSize
= MaxCmdListSize
;
1350 ZeroMem (AhciRegisters
->AhciCmdList
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdListSize
));
1353 // Allocate memory for command table
1354 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1356 MaxCmdTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
1357 Status
= IoMmuAllocateBuffer (
1358 EFI_SIZE_TO_PAGES (MaxCmdTableSize
),
1363 if (EFI_ERROR (Status
)) {
1364 Status
= EFI_OUT_OF_RESOURCES
;
1367 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
) (UINTN
) Base
));
1368 AhciRegisters
->AhciCmdTable
= Base
;
1369 AhciRegisters
->AhciCmdTableMap
= Mapping
;
1370 AhciRegisters
->MaxCmdTableSize
= MaxCmdTableSize
;
1371 ZeroMem (AhciRegisters
->AhciCmdTable
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdTableSize
));
1376 if (AhciRegisters
->AhciRFisMap
!= NULL
) {
1378 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxRFisSize
),
1379 AhciRegisters
->AhciRFis
,
1380 AhciRegisters
->AhciRFisMap
1382 AhciRegisters
->AhciRFis
= NULL
;
1385 if (AhciRegisters
->AhciCmdListMap
!= NULL
) {
1387 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxCmdListSize
),
1388 AhciRegisters
->AhciCmdList
,
1389 AhciRegisters
->AhciCmdListMap
1391 AhciRegisters
->AhciCmdList
= NULL
;
1398 Gets ATA device Capacity according to ATA 6.
1400 This function returns the capacity of the ATA device if it follows
1401 ATA 6 to support 48 bit addressing.
1403 @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure.
1405 @return The capacity of the ATA device or 0 if the device does not support
1406 48-bit addressing defined in ATA 6.
1411 IN ATA_IDENTIFY_DATA
*IdentifyData
1418 if ((IdentifyData
->command_set_supported_83
& BIT10
) == 0) {
1420 // The device doesn't support 48 bit addressing
1426 // 48 bit address feature set is supported, get maximum capacity
1429 for (Index
= 0; Index
< 4; Index
++) {
1431 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
1433 TmpLba
= IdentifyData
->maximum_lba_for_48bit_addressing
[Index
];
1434 Capacity
|= LShiftU64 (TmpLba
, 16 * Index
);
1441 Identifies ATA device via the Identify data.
1443 This function identifies the ATA device and initializes the media information.
1445 @attention This is boundary function that may receive untrusted input.
1446 @attention The input is from peripheral hardware device.
1448 The Identify Drive command response data from an ATA device is the peripheral
1449 hardware input, so this routine will do basic validation for the Identify Drive
1450 command response data.
1452 @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1454 @retval EFI_SUCCESS The device is successfully identified and media
1455 information is correctly initialized.
1456 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
1461 IN OUT PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
1464 ATA_IDENTIFY_DATA
*IdentifyData
;
1465 EFI_PEI_BLOCK_IO2_MEDIA
*Media
;
1467 UINT32 MaxSectorCount
;
1468 UINT16 PhyLogicSectorSupport
;
1470 IdentifyData
= DeviceData
->IdentifyData
;
1471 Media
= &DeviceData
->Media
;
1473 if ((IdentifyData
->config
& BIT15
) != 0) {
1475 DEBUG_ERROR
, "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n",
1476 __FUNCTION__
, DeviceData
->Port
, DeviceData
->PortMultiplier
1478 return EFI_UNSUPPORTED
;
1482 DEBUG_INFO
, "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n",
1483 __FUNCTION__
, DeviceData
->Port
, DeviceData
->PortMultiplier
1487 // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the
1488 // driver only support PIO data transfer for now.
1492 // Get the capacity information of the device.
1494 Capacity
= GetAtapi6Capacity (IdentifyData
);
1495 if (Capacity
> MAX_28BIT_ADDRESSING_CAPACITY
) {
1497 // Capacity exceeds 120GB. 48-bit addressing is really needed
1499 DeviceData
->Lba48Bit
= TRUE
;
1502 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
1504 Capacity
= ((UINT32
)IdentifyData
->user_addressable_sectors_hi
<< 16) |
1505 IdentifyData
->user_addressable_sectors_lo
;
1506 DeviceData
->Lba48Bit
= FALSE
;
1509 if (Capacity
== 0) {
1510 DEBUG ((DEBUG_ERROR
, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__
));
1511 return EFI_UNSUPPORTED
;
1513 Media
->LastBlock
= (EFI_PEI_LBA
) (Capacity
- 1);
1515 Media
->BlockSize
= 0x200;
1517 // Check whether Long Physical Sector Feature is supported
1519 PhyLogicSectorSupport
= IdentifyData
->phy_logic_sector_support
;
1521 DEBUG_INFO
, "%a: PhyLogicSectorSupport = 0x%x\n",
1522 __FUNCTION__
, PhyLogicSectorSupport
1524 if ((PhyLogicSectorSupport
& (BIT14
| BIT15
)) == BIT14
) {
1526 // Check logical block size
1528 if ((PhyLogicSectorSupport
& BIT12
) != 0) {
1529 Media
->BlockSize
= (UINT32
) (((IdentifyData
->logic_sector_size_hi
<< 16) |
1530 IdentifyData
->logic_sector_size_lo
) * sizeof (UINT16
));
1535 // Check BlockSize validity
1537 MaxSectorCount
= mMaxTransferBlockNumber
[DeviceData
->Lba48Bit
];
1538 if ((Media
->BlockSize
== 0) || (Media
->BlockSize
> MAX_UINT32
/ MaxSectorCount
)) {
1539 DEBUG ((DEBUG_ERROR
, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__
, Media
->BlockSize
));
1540 return EFI_UNSUPPORTED
;
1544 DEBUG_INFO
, "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n",
1545 __FUNCTION__
, Media
->BlockSize
, Media
->LastBlock
1548 if ((IdentifyData
->trusted_computing_support
& BIT0
) != 0) {
1549 DEBUG ((DEBUG_INFO
, "%a: Found Trust Computing feature support.\n", __FUNCTION__
));
1550 DeviceData
->TrustComputing
= TRUE
;
1553 Media
->InterfaceType
= MSG_SATA_DP
;
1554 Media
->RemovableMedia
= FALSE
;
1555 Media
->MediaPresent
= TRUE
;
1556 Media
->ReadOnly
= FALSE
;
1562 Allocate device information data structure to contain device information.
1563 And insert the data structure to the tail of device list for tracing.
1565 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
1567 @param[in] DeviceIndex The device index.
1568 @param[in] Port The port number of the ATA device to send
1570 @param[in] PortMultiplierPort The port multiplier port number of the ATA
1571 device to send the command.
1572 If there is no port multiplier, then specify
1574 @param[in] FisIndex The index of the FIS of the ATA device to
1576 @param[in] IdentifyData The data buffer to store the output of the
1579 @retval EFI_SUCCESS Successfully insert the ATA device to the
1580 tail of device list.
1581 @retval EFI_OUT_OF_RESOURCES Not enough resource.
1586 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
1587 IN UINTN DeviceIndex
,
1589 IN UINT16 PortMultiplier
,
1591 IN ATA_IDENTIFY_DATA
*IdentifyData
1594 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
1597 DeviceData
= AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA
));
1598 if (DeviceData
== NULL
) {
1599 return EFI_OUT_OF_RESOURCES
;
1602 if (IdentifyData
!= NULL
) {
1603 DeviceData
->IdentifyData
= AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA
), IdentifyData
);
1604 if (DeviceData
->IdentifyData
== NULL
) {
1605 return EFI_OUT_OF_RESOURCES
;
1609 DeviceData
->Signature
= AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE
;
1610 DeviceData
->Port
= Port
;
1611 DeviceData
->PortMultiplier
= PortMultiplier
;
1612 DeviceData
->FisIndex
= FisIndex
;
1613 DeviceData
->DeviceIndex
= DeviceIndex
;
1614 DeviceData
->Private
= Private
;
1616 Status
= IdentifyAtaDevice (DeviceData
);
1617 if (EFI_ERROR (Status
)) {
1621 if (DeviceData
->TrustComputing
) {
1622 Private
->TrustComputingDevices
++;
1623 DeviceData
->TrustComputingDeviceIndex
= Private
->TrustComputingDevices
;
1625 Private
->ActiveDevices
++;
1626 InsertTailList (&Private
->DeviceList
, &DeviceData
->Link
);
1632 Initialize ATA host controller at AHCI mode.
1634 The function is designed to initialize ATA host controller.
1636 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1638 @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully.
1639 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing
1641 @retval Others A device error occurred while initializing the
1646 AhciModeInitialization (
1647 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1654 UINT8 MaxPortNumber
;
1655 UINT32 PortImplementBitMap
;
1656 UINT32 PortInitializeBitMap
;
1657 EFI_AHCI_REGISTERS
*AhciRegisters
;
1663 UINT32 PhyDetectDelay
;
1665 ATA_IDENTIFY_DATA IdentifyData
;
1667 AhciBar
= Private
->MmioBase
;
1669 Status
= AhciReset (AhciBar
, AHCI_PEI_RESET_TIMEOUT
);
1670 if (EFI_ERROR (Status
)) {
1671 DEBUG ((DEBUG_ERROR
, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__
, Status
));
1672 return EFI_DEVICE_ERROR
;
1676 // Collect AHCI controller information
1678 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1681 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1683 Value
= AhciReadReg (AhciBar
, AHCI_GHC_OFFSET
);
1684 if ((Value
& AHCI_GHC_ENABLE
) == 0) {
1685 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_ENABLE
);
1688 Status
= AhciCreateTransferDescriptor (Private
);
1689 if (EFI_ERROR (Status
)) {
1692 "%a: Transfer-related data allocation failed with %r.\n",
1693 __FUNCTION__
, Status
1695 return EFI_OUT_OF_RESOURCES
;
1699 // Get the number of command slots per port supported by this HBA.
1701 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1704 // Get the bit map of those ports exposed by this HBA.
1705 // It indicates which ports that the HBA supports are available for software
1708 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1711 // Get the number of ports that actually needed to be initialized.
1713 MaxPortNumber
= MIN (MaxPortNumber
, (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1));
1714 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1716 PortInitializeBitMap
= Private
->PortBitMap
;
1717 AhciRegisters
= &Private
->AhciRegisters
;
1720 // Enumerate ATA ports
1722 for (PortIndex
= 1; PortIndex
<= MaxPortNumber
; PortIndex
++) {
1723 Status
= AhciGetPortFromMap (PortInitializeBitMap
, PortIndex
, &Port
);
1724 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
1726 // Initialize FIS Base Address Register and Command List Base Address
1727 // Register for use.
1729 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) +
1730 sizeof (EFI_AHCI_RECEIVED_FIS
) * (PortIndex
- 1);
1731 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
1732 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1733 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
1734 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1736 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdList
);
1737 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
1738 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1739 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
1740 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1742 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1743 Data
= AhciReadReg (AhciBar
, Offset
);
1744 if ((Data
& AHCI_PORT_CMD_CPD
) != 0) {
1745 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_POD
);
1748 if ((Capability
& AHCI_CAP_SSS
) != 0) {
1749 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_SUD
);
1753 // Disable aggressive power management.
1755 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SCTL
;
1756 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_SCTL_IPM_INIT
);
1758 // Disable the reporting of the corresponding interrupt to system software.
1760 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IE
;
1761 AhciAndReg (AhciBar
, Offset
, 0);
1764 // Enable FIS Receive DMA engine for the first D2H FIS.
1766 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1767 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
1770 // Wait no longer than 15 ms to wait the Phy to detect the presence of a device.
1772 PhyDetectDelay
= AHCI_BUS_PHY_DETECT_TIMEOUT
;
1773 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SSTS
;
1775 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_SSTS_DET_MASK
;
1776 if ((Data
== AHCI_PORT_SSTS_DET_PCE
) || (Data
== AHCI_PORT_SSTS_DET
)) {
1780 MicroSecondDelay (1000);
1782 } while (PhyDetectDelay
> 0);
1784 if (PhyDetectDelay
== 0) {
1786 // No device detected at this port.
1787 // Clear PxCMD.SUD for those ports at which there are no device present.
1789 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1790 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_SUD
));
1791 DEBUG ((DEBUG_ERROR
, "%a: No device detected at Port %d.\n", __FUNCTION__
, Port
));
1796 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
1797 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
1799 PhyDetectDelay
= 16 * 1000;
1801 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
1802 if (AhciReadReg(AhciBar
, Offset
) != 0) {
1803 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
1805 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
1807 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_TFD_MASK
;
1812 MicroSecondDelay (1000);
1814 } while (PhyDetectDelay
> 0);
1816 if (PhyDetectDelay
== 0) {
1819 "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n",
1820 __FUNCTION__
, Port
, Data
1826 // When the first D2H register FIS is received, the content of PxSIG register is updated.
1828 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SIG
;
1829 Status
= AhciWaitMmioSet (
1836 if (EFI_ERROR (Status
)) {
1839 "%a: Error occured when waiting for the first D2H register FIS - %r\n",
1840 __FUNCTION__
, Status
1845 Data
= AhciReadReg (AhciBar
, Offset
);
1846 if ((Data
& AHCI_ATAPI_SIG_MASK
) == AHCI_ATA_DEVICE_SIG
) {
1847 Status
= AhciIdentify (Private
, Port
, 0, PortIndex
- 1, &IdentifyData
);
1848 if (EFI_ERROR (Status
)) {
1849 DEBUG ((DEBUG_ERROR
, "%a: AhciIdentify() failed with %r\n", __FUNCTION__
, Status
));
1852 DEBUG ((DEBUG_INFO
, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__
, Port
));
1858 // Found an ATA hard disk device, add it into the device list.
1876 Trust transfer data from/to ATA device.
1878 This function performs one ATA pass through transaction to do a trust transfer
1879 from/to ATA device. It chooses the appropriate ATA command and protocol to invoke
1880 PassThru interface of ATA pass through.
1882 @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1883 @param[in,out] Buffer The pointer to the current transaction buffer.
1884 @param[in] SecurityProtocolId
1885 The value of the "Security Protocol" parameter
1886 of the security protocol command to be sent.
1887 @param[in] SecurityProtocolSpecificData
1888 The value of the "Security Protocol Specific"
1889 parameter of the security protocol command to
1891 @param[in] TransferLength The block number or sector count of the transfer.
1892 @param[in] IsTrustSend Indicates whether it is a trust send operation
1894 @param[in] Timeout The timeout, in 100ns units, to use for the execution
1895 of the security protocol command. A Timeout value
1896 of 0 means that this function will wait indefinitely
1897 for the security protocol command to execute. If
1898 Timeout is greater than zero, then this function
1899 will return EFI_TIMEOUT if the time required to
1900 execute the receive data command is greater than
1902 @param[out] TransferLengthOut
1903 A pointer to a buffer to store the size in bytes
1904 of the data written to the buffer. Ignore it when
1905 IsTrustSend is TRUE.
1907 @retval EFI_SUCCESS The data transfer is complete successfully.
1908 @return others Some error occurs when transferring data.
1912 TrustTransferAtaDevice (
1913 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
1914 IN OUT VOID
*Buffer
,
1915 IN UINT8 SecurityProtocolId
,
1916 IN UINT16 SecurityProtocolSpecificData
,
1917 IN UINTN TransferLength
,
1918 IN BOOLEAN IsTrustSend
,
1920 OUT UINTN
*TransferLengthOut
1923 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
1924 EDKII_PEI_ATA_PASS_THRU_PPI
*AtaPassThru
;
1925 EFI_ATA_COMMAND_BLOCK Acb
;
1926 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1930 Private
= DeviceData
->Private
;
1931 AtaPassThru
= &Private
->AtaPassThruPpi
;
1934 // Ensure IsTrustSend are valid boolean values
1936 ASSERT ((UINTN
) IsTrustSend
< 2);
1937 if ((UINTN
) IsTrustSend
>= 2) {
1938 return EFI_INVALID_PARAMETER
;
1942 // Prepare for ATA command block.
1944 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1945 if (TransferLength
== 0) {
1946 Acb
.AtaCommand
= ATA_CMD_TRUST_NON_DATA
;
1948 Acb
.AtaCommand
= mAtaTrustCommands
[IsTrustSend
];
1950 Acb
.AtaFeatures
= SecurityProtocolId
;
1951 Acb
.AtaSectorCount
= (UINT8
) (TransferLength
/ 512);
1952 Acb
.AtaSectorNumber
= (UINT8
) ((TransferLength
/ 512) >> 8);
1954 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
1955 // Here use big endian for Cylinder register.
1957 Acb
.AtaCylinderHigh
= (UINT8
) SecurityProtocolSpecificData
;
1958 Acb
.AtaCylinderLow
= (UINT8
) (SecurityProtocolSpecificData
>> 8);
1959 Acb
.AtaDeviceHead
= (UINT8
) (BIT7
| BIT6
| BIT5
|
1960 (DeviceData
->PortMultiplier
== 0xFFFF ?
1961 0 : (DeviceData
->PortMultiplier
<< 4)));
1964 // Prepare for ATA pass through packet.
1966 ZeroMem (&Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
1967 if (TransferLength
== 0) {
1968 Packet
.InTransferLength
= 0;
1969 Packet
.OutTransferLength
= 0;
1970 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
1971 } else if (IsTrustSend
) {
1973 // Check the alignment of the incoming buffer prior to invoking underlying
1974 // ATA PassThru PPI.
1976 if ((AtaPassThru
->Mode
->IoAlign
> 1) &&
1977 !IS_ALIGNED (Buffer
, AtaPassThru
->Mode
->IoAlign
)) {
1978 NewBuffer
= AllocateAlignedPages (
1979 EFI_SIZE_TO_PAGES (TransferLength
),
1980 AtaPassThru
->Mode
->IoAlign
1982 if (NewBuffer
== NULL
) {
1983 return EFI_OUT_OF_RESOURCES
;
1986 CopyMem (NewBuffer
, Buffer
, TransferLength
);
1989 Packet
.OutDataBuffer
= Buffer
;
1990 Packet
.OutTransferLength
= (UINT32
) TransferLength
;
1991 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
1993 Packet
.InDataBuffer
= Buffer
;
1994 Packet
.InTransferLength
= (UINT32
) TransferLength
;
1995 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
1999 Packet
.Timeout
= Timeout
;
2000 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
2002 Status
= AtaPassThru
->PassThru (
2005 DeviceData
->PortMultiplier
,
2008 if (TransferLengthOut
!= NULL
) {
2010 *TransferLengthOut
= Packet
.InTransferLength
;