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
70 Read AHCI Operation register.
72 @param[in] AhciBar AHCI bar address.
73 @param[in] Offset The operation register offset.
75 @return The register content read.
87 Data
= MmioRead32 (AhciBar
+ Offset
);
93 Write AHCI Operation register.
95 @param[in] AhciBar AHCI bar address.
96 @param[in] Offset The operation register offset.
97 @param[in] Data The Data used to write down.
107 MmioWrite32 (AhciBar
+ Offset
, Data
);
111 Do AND operation with the value of AHCI Operation register.
113 @param[in] AhciBar AHCI bar address.
114 @param[in] Offset The operation register offset.
115 @param[in] AndData The data used to do AND operation.
127 Data
= AhciReadReg (AhciBar
, Offset
);
130 AhciWriteReg (AhciBar
, Offset
, Data
);
134 Do OR operation with the Value of AHCI Operation register.
136 @param[in] AhciBar AHCI bar address.
137 @param[in] Offset The operation register offset.
138 @param[in] OrData The Data used to do OR operation.
150 Data
= AhciReadReg (AhciBar
, Offset
);
153 AhciWriteReg (AhciBar
, Offset
, Data
);
157 Wait for memory set to the test Value.
159 @param[in] AhciBar AHCI bar address.
160 @param[in] Offset The memory offset to test.
161 @param[in] MaskValue The mask Value of memory.
162 @param[in] TestValue The test Value of memory.
163 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
165 @retval EFI_DEVICE_ERROR The memory is not set.
166 @retval EFI_TIMEOUT The memory setting is time out.
167 @retval EFI_SUCCESS The memory is correct set.
183 Delay
= (UINT32
)(DivU64x32 (Timeout
, 1000) + 1);
186 Value
= AhciReadReg (AhciBar
, Offset
) & MaskValue
;
188 if (Value
== TestValue
) {
193 // Stall for 100 microseconds.
195 MicroSecondDelay (100);
204 Check the memory status to the test value.
206 @param[in] Address The memory address to test.
207 @param[in] MaskValue The mask value of memory.
208 @param[in] TestValue The test value of memory.
210 @retval EFI_NOT_READY The memory is not set.
211 @retval EFI_SUCCESS The memory is correct set.
223 Value
= *(volatile UINT32
*)Address
;
226 if (Value
== TestValue
) {
229 return EFI_NOT_READY
;
234 Wait for the value of the specified system memory set to the test value.
236 @param[in] Address The system memory address to test.
237 @param[in] MaskValue The mask value of memory.
238 @param[in] TestValue The test value of memory.
239 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
241 @retval EFI_TIMEOUT The system memory setting is time out.
242 @retval EFI_SUCCESS The system memory is correct set.
247 IN EFI_PHYSICAL_ADDRESS Address
,
255 BOOLEAN InfiniteWait
;
260 InfiniteWait
= FALSE
;
263 Delay
= DivU64x32 (Timeout
, 1000) + 1;
267 // Access system memory to see if the value is the tested one.
269 // The system memory pointed by Address will be updated by the
270 // SATA Host Controller, "volatile" is introduced to prevent
271 // compiler from optimizing the access to the memory address
272 // to only read once.
274 Value
= *(volatile UINT32
*)(UINTN
)Address
;
277 if (Value
== TestValue
) {
282 // Stall for 100 microseconds.
284 MicroSecondDelay (100);
287 } while (InfiniteWait
|| (Delay
> 0));
294 Clear the port interrupt and error status. It will also clear HBA interrupt
297 @param[in] AhciBar AHCI bar address.
298 @param[in] Port The number of port.
302 AhciClearPortStatus (
310 // Clear any error status
312 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
313 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
316 // Clear any port interrupt status
318 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IS
;
319 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
322 // Clear any HBA interrupt status
324 AhciWriteReg (AhciBar
, AHCI_IS_OFFSET
, AhciReadReg (AhciBar
, AHCI_IS_OFFSET
));
328 Enable the FIS running for giving port.
330 @param[in] AhciBar AHCI bar address.
331 @param[in] Port The number of port.
332 @param[in] Timeout The timeout, in 100ns units, to enabling FIS.
334 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
335 @retval EFI_TIMEOUT The FIS enable setting is time out.
336 @retval EFI_SUCCESS The FIS enable successfully.
340 AhciEnableFisReceive (
348 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
349 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
355 Disable the FIS running for giving port.
357 @param[in] AhciBar AHCI bar address.
358 @param[in] Port The number of port.
359 @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit.
361 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
362 @retval EFI_TIMEOUT The FIS disable setting is time out.
363 @retval EFI_UNSUPPORTED The port is in running state.
364 @retval EFI_SUCCESS The FIS disable successfully.
368 AhciDisableFisReceive (
377 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
378 Data
= AhciReadReg (AhciBar
, Offset
);
381 // Before disabling Fis receive, the DMA engine of the port should NOT be in
384 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) != 0) {
385 return EFI_UNSUPPORTED
;
389 // Check if the Fis receive DMA engine for the port is running.
391 if ((Data
& AHCI_PORT_CMD_FR
) != AHCI_PORT_CMD_FR
) {
395 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_FRE
));
397 return AhciWaitMmioSet (
407 Build the command list, command table and prepare the fis receiver.
409 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
410 @param[in] Port The number of port.
411 @param[in] PortMultiplier The number of port multiplier.
412 @param[in] FisIndex The offset index of the FIS base address.
413 @param[in] CommandFis The control fis will be used for the transfer.
414 @param[in] CommandList The command list will be used for the transfer.
415 @param[in] CommandSlotNumber The command slot will be used for the transfer.
416 @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master
418 @param[in] DataLength The data count to be transferred.
423 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
425 IN UINT8 PortMultiplier
,
427 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
428 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
429 IN UINT8 CommandSlotNumber
,
430 IN OUT VOID
*DataPhysicalAddr
,
434 EFI_AHCI_REGISTERS
*AhciRegisters
;
444 AhciRegisters
= &Private
->AhciRegisters
;
445 AhciBar
= Private
->MmioBase
;
450 PrdtNumber
= (UINT32
)DivU64x32 (
451 (UINT64
)DataLength
+ AHCI_MAX_DATA_PER_PRDT
- 1,
452 AHCI_MAX_DATA_PER_PRDT
456 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
457 // It also limits that the maximum amount of the PRDT entry in the command table
459 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
462 ASSERT (PrdtNumber
<= AHCI_MAX_PRDT_NUMBER
);
463 if (PrdtNumber
> AHCI_MAX_PRDT_NUMBER
) {
467 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
469 BaseAddr
= Data64
.Uint64
;
471 ZeroMem ((VOID
*)((UINTN
)BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
473 ZeroMem (AhciRegisters
->AhciCmdTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
475 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
477 CopyMem (&AhciRegisters
->AhciCmdTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
479 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
480 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_DLAE
| AHCI_PORT_CMD_ATAPI
));
482 RemainedData
= (UINTN
)DataLength
;
483 MemAddr
= (UINTN
)DataPhysicalAddr
;
484 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
486 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
487 if (RemainedData
< AHCI_MAX_DATA_PER_PRDT
) {
488 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
490 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= AHCI_MAX_DATA_PER_PRDT
- 1;
493 Data64
.Uint64
= (UINT64
)MemAddr
;
494 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
495 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
496 RemainedData
-= AHCI_MAX_DATA_PER_PRDT
;
497 MemAddr
+= AHCI_MAX_DATA_PER_PRDT
;
501 // Set the last PRDT to Interrupt On Complete
503 if (PrdtNumber
> 0) {
504 AhciRegisters
->AhciCmdTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
508 (VOID
*)((UINTN
)AhciRegisters
->AhciCmdList
+ (UINTN
)CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
510 sizeof (EFI_AHCI_COMMAND_LIST
)
513 Data64
.Uint64
= (UINT64
)(UINTN
)AhciRegisters
->AhciCmdTable
;
514 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
515 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
516 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
522 @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data
524 @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data
529 AhciBuildCommandFis (
530 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
531 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
534 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
536 CmdFis
->AhciCFisType
= AHCI_FIS_REGISTER_H2D
;
538 // Indicator it's a command
540 CmdFis
->AhciCFisCmdInd
= 0x1;
541 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
543 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
544 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
546 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
547 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
549 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
550 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
552 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
553 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
555 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
556 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
558 CmdFis
->AhciCFisDevHead
= (UINT8
)(AtaCommandBlock
->AtaDeviceHead
| 0xE0);
562 Stop command running for giving port
564 @param[in] AhciBar AHCI bar address.
565 @param[in] Port The number of port.
566 @param[in] Timeout The timeout value, in 100ns units, to stop.
568 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
569 @retval EFI_TIMEOUT The operation is time out.
570 @retval EFI_SUCCESS The command stop successfully.
583 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
584 Data
= AhciReadReg (AhciBar
, Offset
);
586 if ((Data
& (AHCI_PORT_CMD_ST
| AHCI_PORT_CMD_CR
)) == 0) {
590 if ((Data
& AHCI_PORT_CMD_ST
) != 0) {
591 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_ST
));
594 return AhciWaitMmioSet (
604 Start command for give slot on specific port.
606 @param[in] AhciBar AHCI bar address.
607 @param[in] Port The number of port.
608 @param[in] CommandSlot The number of Command Slot.
609 @param[in] Timeout The timeout value, in 100ns units, to start.
611 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
612 @retval EFI_TIMEOUT The operation is time out.
613 @retval EFI_SUCCESS The command start successfully.
620 IN UINT8 CommandSlot
,
633 // Collect AHCI controller information
635 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
637 CmdSlotBit
= (UINT32
)(1 << CommandSlot
);
639 AhciClearPortStatus (
644 Status
= AhciEnableFisReceive (
649 if (EFI_ERROR (Status
)) {
653 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
654 PortStatus
= AhciReadReg (AhciBar
, Offset
);
657 if ((PortStatus
& AHCI_PORT_CMD_ALPE
) != 0) {
658 StartCmd
= AhciReadReg (AhciBar
, Offset
);
659 StartCmd
&= ~AHCI_PORT_CMD_ICC_MASK
;
660 StartCmd
|= AHCI_PORT_CMD_ACTIVE
;
663 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
664 PortTfd
= AhciReadReg (AhciBar
, Offset
);
666 if ((PortTfd
& (AHCI_PORT_TFD_BSY
| AHCI_PORT_TFD_DRQ
)) != 0) {
667 if ((Capability
& BIT24
) != 0) {
668 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
669 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_CLO
);
681 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
682 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_ST
| StartCmd
);
685 // Setting the command
687 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CI
;
688 AhciAndReg (AhciBar
, Offset
, 0);
689 AhciOrReg (AhciBar
, Offset
, CmdSlotBit
);
695 Start a PIO Data transfer on specific port.
697 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
698 @param[in] Port The number of port.
699 @param[in] PortMultiplier The number of port multiplier.
700 @param[in] FisIndex The offset index of the FIS base address.
701 @param[in] Read The transfer direction.
702 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
703 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
704 @param[in,out] MemoryAddr The pointer to the data buffer.
705 @param[in] DataCount The data count to be transferred.
706 @param[in] Timeout The timeout value of PIO data transfer, uses
709 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
710 @retval EFI_TIMEOUT The operation is time out.
711 @retval EFI_UNSUPPORTED The device is not ready for transfer.
712 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
713 @retval EFI_SUCCESS The PIO data transfer executes successfully.
718 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
720 IN UINT8 PortMultiplier
,
723 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
724 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
725 IN OUT VOID
*MemoryAddr
,
731 EDKII_IOMMU_OPERATION MapOp
;
733 EFI_PHYSICAL_ADDRESS PhyAddr
;
735 EFI_AHCI_REGISTERS
*AhciRegisters
;
737 BOOLEAN InfiniteWait
;
746 EFI_AHCI_COMMAND_FIS CFis
;
747 EFI_AHCI_COMMAND_LIST CmdList
;
750 BOOLEAN PioFisReceived
;
751 BOOLEAN D2hFisReceived
;
754 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
757 if (DataCount
/ (UINT32
)AHCI_MAX_PRDT_NUMBER
> AHCI_MAX_DATA_PER_PRDT
) {
760 "%a: Driver only support a maximum of 0x%x PRDT entries, "
761 "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n",
763 AHCI_MAX_PRDT_NUMBER
,
765 AHCI_MAX_PRDT_NUMBER
* AHCI_MAX_DATA_PER_PRDT
767 return EFI_UNSUPPORTED
;
770 MapOp
= Read
? EdkiiIoMmuOperationBusMasterWrite
:
771 EdkiiIoMmuOperationBusMasterRead
;
772 MapLength
= DataCount
;
780 if (EFI_ERROR (Status
) || (MapLength
!= DataCount
)) {
781 DEBUG ((DEBUG_ERROR
, "%a: Fail to map data buffer.\n", __FUNCTION__
));
782 return EFI_OUT_OF_RESOURCES
;
785 AhciRegisters
= &Private
->AhciRegisters
;
786 AhciBar
= Private
->MmioBase
;
787 InfiniteWait
= (Timeout
== 0) ? TRUE
: FALSE
;
790 // Fill FIS base address register
792 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
793 OldRfisLo
= AhciReadReg (AhciBar
, Offset
);
794 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
795 OldRfisHi
= AhciReadReg (AhciBar
, Offset
);
796 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
797 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
798 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
799 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
800 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
803 // Single task environment, we only use one command table for all port
805 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
806 OldCmdListLo
= AhciReadReg (AhciBar
, Offset
);
807 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
808 OldCmdListHi
= AhciReadReg (AhciBar
, Offset
);
809 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciCmdList
);
810 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
811 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
812 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
813 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
816 // Package read needed
818 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
820 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
822 CmdList
.AhciCmdCfl
= AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
823 CmdList
.AhciCmdW
= Read
? 0 : 1;
833 (VOID
*)(UINTN
)PhyAddr
,
837 Status
= AhciStartCommand (
843 if (EFI_ERROR (Status
)) {
848 // Checking the status and wait the driver sending Data
850 FisBaseAddr
= (UINT32
)(UINTN
)AhciRegisters
->AhciRFis
+ sizeof (EFI_AHCI_RECEIVED_FIS
) * FisIndex
;
853 // Wait device sends the PIO setup fis before data transfer
855 Status
= EFI_TIMEOUT
;
856 Delay
= (UINT32
)DivU64x32 (Timeout
, 1000) + 1;
858 PioFisReceived
= FALSE
;
859 D2hFisReceived
= FALSE
;
860 Offset
= FisBaseAddr
+ AHCI_PIO_FIS_OFFSET
;
861 Status
= AhciCheckMemSet (Offset
, AHCI_FIS_TYPE_MASK
, AHCI_FIS_PIO_SETUP
);
862 if (!EFI_ERROR (Status
)) {
863 DEBUG ((DEBUG_INFO
, "%a: PioFisReceived.\n", __FUNCTION__
));
864 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
),
1182 Collect the number of bits set within a port bitmap.
1184 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1186 @retval The number of bits set in the bitmap.
1190 AhciGetNumberOfPortsFromMap (
1191 IN UINT32 PortBitMap
1194 UINT8 NumberOfPorts
;
1198 while (PortBitMap
!= 0) {
1199 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) {
1246 PortBitMap
= PortBitMap
>> 1;
1250 return EFI_NOT_FOUND
;
1254 Allocate transfer-related data struct which is used at AHCI mode.
1256 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1258 @retval EFI_SUCCESS Data structures are allocated successfully.
1259 @retval Others Data structures are not allocated successfully.
1263 AhciCreateTransferDescriptor (
1264 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1269 EFI_AHCI_REGISTERS
*AhciRegisters
;
1270 EFI_PHYSICAL_ADDRESS DeviceAddress
;
1274 UINT32 PortImplementBitMap
;
1275 UINT8 MaxPortNumber
;
1276 UINT8 MaxCommandSlotNumber
;
1278 UINTN MaxCmdListSize
;
1279 UINTN MaxCmdTableSize
;
1281 AhciBar
= Private
->MmioBase
;
1282 AhciRegisters
= &Private
->AhciRegisters
;
1285 // Collect AHCI controller information
1287 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1290 // Get the number of command slots per port supported by this HBA.
1292 MaxCommandSlotNumber
= (UINT8
)(((Capability
& 0x1F00) >> 8) + 1);
1293 ASSERT (MaxCommandSlotNumber
> 0);
1294 if (MaxCommandSlotNumber
== 0) {
1295 return EFI_DEVICE_ERROR
;
1299 // Get the highest bit of implemented ports which decides how many bytes are
1300 // allocated for recived FIS.
1302 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1303 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32 (PortImplementBitMap
) + 1);
1304 if (MaxPortNumber
== 0) {
1305 return EFI_DEVICE_ERROR
;
1309 // Get the number of ports that actually needed to be initialized.
1311 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1314 // Allocate memory for received FIS.
1316 MaxRFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1317 Status
= IoMmuAllocateBuffer (
1318 EFI_SIZE_TO_PAGES (MaxRFisSize
),
1323 if (EFI_ERROR (Status
)) {
1324 return EFI_OUT_OF_RESOURCES
;
1327 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Base
));
1328 AhciRegisters
->AhciRFis
= Base
;
1329 AhciRegisters
->AhciRFisMap
= Mapping
;
1330 AhciRegisters
->MaxRFisSize
= MaxRFisSize
;
1331 ZeroMem (AhciRegisters
->AhciRFis
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxRFisSize
));
1334 // Allocate memory for command list.
1335 // Note that the implemenation is a single task model which only use a command
1336 // list for each port.
1338 MaxCmdListSize
= 1 * sizeof (EFI_AHCI_COMMAND_LIST
);
1339 Status
= IoMmuAllocateBuffer (
1340 EFI_SIZE_TO_PAGES (MaxCmdListSize
),
1345 if (EFI_ERROR (Status
)) {
1346 Status
= EFI_OUT_OF_RESOURCES
;
1350 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Base
));
1351 AhciRegisters
->AhciCmdList
= Base
;
1352 AhciRegisters
->AhciCmdListMap
= Mapping
;
1353 AhciRegisters
->MaxCmdListSize
= MaxCmdListSize
;
1354 ZeroMem (AhciRegisters
->AhciCmdList
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdListSize
));
1357 // Allocate memory for command table
1358 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1360 MaxCmdTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
1361 Status
= IoMmuAllocateBuffer (
1362 EFI_SIZE_TO_PAGES (MaxCmdTableSize
),
1367 if (EFI_ERROR (Status
)) {
1368 Status
= EFI_OUT_OF_RESOURCES
;
1372 ASSERT (DeviceAddress
== ((EFI_PHYSICAL_ADDRESS
)(UINTN
)Base
));
1373 AhciRegisters
->AhciCmdTable
= Base
;
1374 AhciRegisters
->AhciCmdTableMap
= Mapping
;
1375 AhciRegisters
->MaxCmdTableSize
= MaxCmdTableSize
;
1376 ZeroMem (AhciRegisters
->AhciCmdTable
, EFI_PAGE_SIZE
* EFI_SIZE_TO_PAGES (MaxCmdTableSize
));
1381 if (AhciRegisters
->AhciRFisMap
!= NULL
) {
1383 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxRFisSize
),
1384 AhciRegisters
->AhciRFis
,
1385 AhciRegisters
->AhciRFisMap
1387 AhciRegisters
->AhciRFis
= NULL
;
1390 if (AhciRegisters
->AhciCmdListMap
!= NULL
) {
1392 EFI_SIZE_TO_PAGES (AhciRegisters
->MaxCmdListSize
),
1393 AhciRegisters
->AhciCmdList
,
1394 AhciRegisters
->AhciCmdListMap
1396 AhciRegisters
->AhciCmdList
= NULL
;
1403 Gets ATA device Capacity according to ATA 6.
1405 This function returns the capacity of the ATA device if it follows
1406 ATA 6 to support 48 bit addressing.
1408 @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure.
1410 @return The capacity of the ATA device or 0 if the device does not support
1411 48-bit addressing defined in ATA 6.
1416 IN ATA_IDENTIFY_DATA
*IdentifyData
1423 if ((IdentifyData
->command_set_supported_83
& BIT10
) == 0) {
1425 // The device doesn't support 48 bit addressing
1431 // 48 bit address feature set is supported, get maximum capacity
1434 for (Index
= 0; Index
< 4; Index
++) {
1436 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
1438 TmpLba
= IdentifyData
->maximum_lba_for_48bit_addressing
[Index
];
1439 Capacity
|= LShiftU64 (TmpLba
, 16 * Index
);
1446 Identifies ATA device via the Identify data.
1448 This function identifies the ATA device and initializes the media information.
1450 @attention This is boundary function that may receive untrusted input.
1451 @attention The input is from peripheral hardware device.
1453 The Identify Drive command response data from an ATA device is the peripheral
1454 hardware input, so this routine will do basic validation for the Identify Drive
1455 command response data.
1457 @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1459 @retval EFI_SUCCESS The device is successfully identified and media
1460 information is correctly initialized.
1461 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
1466 IN OUT PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
1469 ATA_IDENTIFY_DATA
*IdentifyData
;
1470 EFI_PEI_BLOCK_IO2_MEDIA
*Media
;
1472 UINT32 MaxSectorCount
;
1473 UINT16 PhyLogicSectorSupport
;
1475 IdentifyData
= DeviceData
->IdentifyData
;
1476 Media
= &DeviceData
->Media
;
1478 if ((IdentifyData
->config
& BIT15
) != 0) {
1481 "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n",
1484 DeviceData
->PortMultiplier
1486 return EFI_UNSUPPORTED
;
1491 "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n",
1494 DeviceData
->PortMultiplier
1498 // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the
1499 // driver only support PIO data transfer for now.
1503 // Get the capacity information of the device.
1505 Capacity
= GetAtapi6Capacity (IdentifyData
);
1506 if (Capacity
> MAX_28BIT_ADDRESSING_CAPACITY
) {
1508 // Capacity exceeds 120GB. 48-bit addressing is really needed
1510 DeviceData
->Lba48Bit
= TRUE
;
1513 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
1515 Capacity
= ((UINT32
)IdentifyData
->user_addressable_sectors_hi
<< 16) |
1516 IdentifyData
->user_addressable_sectors_lo
;
1517 DeviceData
->Lba48Bit
= FALSE
;
1520 if (Capacity
== 0) {
1521 DEBUG ((DEBUG_ERROR
, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__
));
1522 return EFI_UNSUPPORTED
;
1525 Media
->LastBlock
= (EFI_PEI_LBA
)(Capacity
- 1);
1527 Media
->BlockSize
= 0x200;
1529 // Check whether Long Physical Sector Feature is supported
1531 PhyLogicSectorSupport
= IdentifyData
->phy_logic_sector_support
;
1534 "%a: PhyLogicSectorSupport = 0x%x\n",
1536 PhyLogicSectorSupport
1538 if ((PhyLogicSectorSupport
& (BIT14
| BIT15
)) == BIT14
) {
1540 // Check logical block size
1542 if ((PhyLogicSectorSupport
& BIT12
) != 0) {
1543 Media
->BlockSize
= (UINT32
)(((IdentifyData
->logic_sector_size_hi
<< 16) |
1544 IdentifyData
->logic_sector_size_lo
) * sizeof (UINT16
));
1549 // Check BlockSize validity
1551 MaxSectorCount
= mMaxTransferBlockNumber
[DeviceData
->Lba48Bit
];
1552 if ((Media
->BlockSize
== 0) || (Media
->BlockSize
> MAX_UINT32
/ MaxSectorCount
)) {
1553 DEBUG ((DEBUG_ERROR
, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__
, Media
->BlockSize
));
1554 return EFI_UNSUPPORTED
;
1559 "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n",
1565 if ((IdentifyData
->trusted_computing_support
& BIT0
) != 0) {
1566 DEBUG ((DEBUG_INFO
, "%a: Found Trust Computing feature support.\n", __FUNCTION__
));
1567 DeviceData
->TrustComputing
= TRUE
;
1570 Media
->InterfaceType
= MSG_SATA_DP
;
1571 Media
->RemovableMedia
= FALSE
;
1572 Media
->MediaPresent
= TRUE
;
1573 Media
->ReadOnly
= FALSE
;
1579 Allocate device information data structure to contain device information.
1580 And insert the data structure to the tail of device list for tracing.
1582 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
1584 @param[in] DeviceIndex The device index.
1585 @param[in] Port The port number of the ATA device to send
1587 @param[in] PortMultiplierPort The port multiplier port number of the ATA
1588 device to send the command.
1589 If there is no port multiplier, then specify
1591 @param[in] FisIndex The index of the FIS of the ATA device to
1593 @param[in] IdentifyData The data buffer to store the output of the
1596 @retval EFI_SUCCESS Successfully insert the ATA device to the
1597 tail of device list.
1598 @retval EFI_OUT_OF_RESOURCES Not enough resource.
1603 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
,
1604 IN UINTN DeviceIndex
,
1606 IN UINT16 PortMultiplier
,
1608 IN ATA_IDENTIFY_DATA
*IdentifyData
1611 PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
;
1614 DeviceData
= AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA
));
1615 if (DeviceData
== NULL
) {
1616 return EFI_OUT_OF_RESOURCES
;
1619 if (IdentifyData
!= NULL
) {
1620 DeviceData
->IdentifyData
= AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA
), IdentifyData
);
1621 if (DeviceData
->IdentifyData
== NULL
) {
1622 return EFI_OUT_OF_RESOURCES
;
1626 DeviceData
->Signature
= AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE
;
1627 DeviceData
->Port
= Port
;
1628 DeviceData
->PortMultiplier
= PortMultiplier
;
1629 DeviceData
->FisIndex
= FisIndex
;
1630 DeviceData
->DeviceIndex
= DeviceIndex
;
1631 DeviceData
->Private
= Private
;
1633 Status
= IdentifyAtaDevice (DeviceData
);
1634 if (EFI_ERROR (Status
)) {
1638 if (DeviceData
->TrustComputing
) {
1639 Private
->TrustComputingDevices
++;
1640 DeviceData
->TrustComputingDeviceIndex
= Private
->TrustComputingDevices
;
1643 Private
->ActiveDevices
++;
1644 InsertTailList (&Private
->DeviceList
, &DeviceData
->Link
);
1650 Initialize ATA host controller at AHCI mode.
1652 The function is designed to initialize ATA host controller.
1654 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1656 @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully.
1657 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing
1659 @retval Others A device error occurred while initializing the
1664 AhciModeInitialization (
1665 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
1672 UINT8 MaxPortNumber
;
1673 UINT32 PortImplementBitMap
;
1674 UINT32 PortInitializeBitMap
;
1675 EFI_AHCI_REGISTERS
*AhciRegisters
;
1681 UINT32 PhyDetectDelay
;
1683 ATA_IDENTIFY_DATA IdentifyData
;
1685 AhciBar
= Private
->MmioBase
;
1687 Status
= AhciReset (AhciBar
, AHCI_PEI_RESET_TIMEOUT
);
1688 if (EFI_ERROR (Status
)) {
1689 DEBUG ((DEBUG_ERROR
, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__
, Status
));
1690 return EFI_DEVICE_ERROR
;
1694 // Collect AHCI controller information
1696 Capability
= AhciReadReg (AhciBar
, AHCI_CAPABILITY_OFFSET
);
1699 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1701 Value
= AhciReadReg (AhciBar
, AHCI_GHC_OFFSET
);
1702 if ((Value
& AHCI_GHC_ENABLE
) == 0) {
1703 AhciOrReg (AhciBar
, AHCI_GHC_OFFSET
, AHCI_GHC_ENABLE
);
1706 Status
= AhciCreateTransferDescriptor (Private
);
1707 if (EFI_ERROR (Status
)) {
1710 "%a: Transfer-related data allocation failed with %r.\n",
1714 return EFI_OUT_OF_RESOURCES
;
1718 // Get the number of command slots per port supported by this HBA.
1720 MaxPortNumber
= (UINT8
)((Capability
& 0x1F) + 1);
1723 // Get the bit map of those ports exposed by this HBA.
1724 // It indicates which ports that the HBA supports are available for software
1727 PortImplementBitMap
= AhciReadReg (AhciBar
, AHCI_PI_OFFSET
);
1730 // Get the number of ports that actually needed to be initialized.
1732 MaxPortNumber
= MIN (MaxPortNumber
, (UINT8
)(UINTN
)(HighBitSet32 (PortImplementBitMap
) + 1));
1733 MaxPortNumber
= MIN (MaxPortNumber
, AhciGetNumberOfPortsFromMap (Private
->PortBitMap
));
1735 PortInitializeBitMap
= Private
->PortBitMap
& PortImplementBitMap
;
1736 AhciRegisters
= &Private
->AhciRegisters
;
1739 // Enumerate ATA ports
1741 for (PortIndex
= 1; PortIndex
<= MaxPortNumber
; PortIndex
++) {
1742 Status
= AhciGetPortFromMap (PortInitializeBitMap
, PortIndex
, &Port
);
1743 if (EFI_ERROR (Status
)) {
1745 // No more available port, just break out of the loop.
1750 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
1752 // Initialize FIS Base Address Register and Command List Base Address
1753 // Register for use.
1755 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciRFis
) +
1756 sizeof (EFI_AHCI_RECEIVED_FIS
) * (PortIndex
- 1);
1757 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FB
;
1758 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1759 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_FBU
;
1760 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1762 Data64
.Uint64
= (UINTN
)(AhciRegisters
->AhciCmdList
);
1763 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLB
;
1764 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Lower32
);
1765 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CLBU
;
1766 AhciWriteReg (AhciBar
, Offset
, Data64
.Uint32
.Upper32
);
1768 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1769 Data
= AhciReadReg (AhciBar
, Offset
);
1770 if ((Data
& AHCI_PORT_CMD_CPD
) != 0) {
1771 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_POD
);
1774 if ((Capability
& AHCI_CAP_SSS
) != 0) {
1775 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_SUD
);
1779 // Disable aggressive power management.
1781 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SCTL
;
1782 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_SCTL_IPM_INIT
);
1784 // Disable the reporting of the corresponding interrupt to system software.
1786 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_IE
;
1787 AhciAndReg (AhciBar
, Offset
, 0);
1790 // Enable FIS Receive DMA engine for the first D2H FIS.
1792 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1793 AhciOrReg (AhciBar
, Offset
, AHCI_PORT_CMD_FRE
);
1796 // Wait no longer than 15 ms to wait the Phy to detect the presence of a device.
1798 PhyDetectDelay
= AHCI_BUS_PHY_DETECT_TIMEOUT
;
1799 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SSTS
;
1801 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_SSTS_DET_MASK
;
1802 if ((Data
== AHCI_PORT_SSTS_DET_PCE
) || (Data
== AHCI_PORT_SSTS_DET
)) {
1806 MicroSecondDelay (1000);
1808 } while (PhyDetectDelay
> 0);
1810 if (PhyDetectDelay
== 0) {
1812 // No device detected at this port.
1813 // Clear PxCMD.SUD for those ports at which there are no device present.
1815 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_CMD
;
1816 AhciAndReg (AhciBar
, Offset
, (UINT32
) ~(AHCI_PORT_CMD_SUD
));
1817 DEBUG ((DEBUG_ERROR
, "%a: No device detected at Port %d.\n", __FUNCTION__
, Port
));
1822 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
1823 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
1825 PhyDetectDelay
= 16 * 1000;
1827 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SERR
;
1828 if (AhciReadReg (AhciBar
, Offset
) != 0) {
1829 AhciWriteReg (AhciBar
, Offset
, AhciReadReg (AhciBar
, Offset
));
1832 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_TFD
;
1834 Data
= AhciReadReg (AhciBar
, Offset
) & AHCI_PORT_TFD_MASK
;
1839 MicroSecondDelay (1000);
1841 } while (PhyDetectDelay
> 0);
1843 if (PhyDetectDelay
== 0) {
1846 "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n",
1855 // When the first D2H register FIS is received, the content of PxSIG register is updated.
1857 Offset
= AHCI_PORT_START
+ Port
* AHCI_PORT_REG_WIDTH
+ AHCI_PORT_SIG
;
1858 Status
= AhciWaitMmioSet (
1865 if (EFI_ERROR (Status
)) {
1868 "%a: Error occurred when waiting for the first D2H register FIS - %r\n",
1875 Data
= AhciReadReg (AhciBar
, Offset
);
1876 if ((Data
& AHCI_ATAPI_SIG_MASK
) == AHCI_ATA_DEVICE_SIG
) {
1877 Status
= AhciIdentify (Private
, Port
, 0, PortIndex
- 1, &IdentifyData
);
1878 if (EFI_ERROR (Status
)) {
1879 DEBUG ((DEBUG_ERROR
, "%a: AhciIdentify() failed with %r\n", __FUNCTION__
, Status
));
1883 DEBUG ((DEBUG_INFO
, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__
, Port
));
1889 // Found an ATA hard disk device, add it into the device list.
1907 Transfer data from ATA device.
1909 This function performs one ATA pass through transaction to transfer data from/to
1910 ATA device. It chooses the appropriate ATA command and protocol to invoke PassThru
1911 interface of ATA pass through.
1913 @param[in] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1914 @param[in,out] Buffer The pointer to the current transaction buffer.
1915 @param[in] StartLba The starting logical block address to be accessed.
1916 @param[in] TransferLength The block number or sector count of the transfer.
1917 @param[in] IsWrite Indicates whether it is a write operation.
1919 @retval EFI_SUCCESS The data transfer is complete successfully.
1920 @return others Some error occurs when transferring data.
1925 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
1926 IN OUT VOID
*Buffer
,
1927 IN EFI_LBA StartLba
,
1928 IN UINT32 TransferLength
,
1932 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
1933 EDKII_PEI_ATA_PASS_THRU_PPI
*AtaPassThru
;
1934 EFI_ATA_COMMAND_BLOCK Acb
;
1935 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
1937 Private
= DeviceData
->Private
;
1938 AtaPassThru
= &Private
->AtaPassThruPpi
;
1941 // Ensure Lba48Bit and IsWrite are valid boolean values
1943 ASSERT ((UINTN
)DeviceData
->Lba48Bit
< 2);
1944 ASSERT ((UINTN
)IsWrite
< 2);
1945 if (((UINTN
)DeviceData
->Lba48Bit
>= 2) ||
1946 ((UINTN
)IsWrite
>= 2))
1948 return EFI_INVALID_PARAMETER
;
1952 // Prepare for ATA command block.
1954 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1955 Acb
.AtaCommand
= mAtaCommands
[DeviceData
->Lba48Bit
][IsWrite
];
1956 Acb
.AtaSectorNumber
= (UINT8
)StartLba
;
1957 Acb
.AtaCylinderLow
= (UINT8
)RShiftU64 (StartLba
, 8);
1958 Acb
.AtaCylinderHigh
= (UINT8
)RShiftU64 (StartLba
, 16);
1959 Acb
.AtaDeviceHead
= (UINT8
)(BIT7
| BIT6
| BIT5
|
1960 (DeviceData
->PortMultiplier
== 0xFFFF ?
1961 0 : (DeviceData
->PortMultiplier
<< 4)));
1962 Acb
.AtaSectorCount
= (UINT8
)TransferLength
;
1963 if (DeviceData
->Lba48Bit
) {
1964 Acb
.AtaSectorNumberExp
= (UINT8
)RShiftU64 (StartLba
, 24);
1965 Acb
.AtaCylinderLowExp
= (UINT8
)RShiftU64 (StartLba
, 32);
1966 Acb
.AtaCylinderHighExp
= (UINT8
)RShiftU64 (StartLba
, 40);
1967 Acb
.AtaSectorCountExp
= (UINT8
)(TransferLength
>> 8);
1969 Acb
.AtaDeviceHead
= (UINT8
)(Acb
.AtaDeviceHead
| RShiftU64 (StartLba
, 24));
1973 // Prepare for ATA pass through packet.
1975 ZeroMem (&Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
1977 Packet
.OutDataBuffer
= Buffer
;
1978 Packet
.OutTransferLength
= TransferLength
;
1980 Packet
.InDataBuffer
= Buffer
;
1981 Packet
.InTransferLength
= TransferLength
;
1986 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsWrite
];
1987 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_SECTOR_COUNT
;
1989 // |------------------------|-----------------|
1990 // | ATA PIO Transfer Mode | Transfer Rate |
1991 // |------------------------|-----------------|
1992 // | PIO Mode 0 | 3.3Mbytes/sec |
1993 // |------------------------|-----------------|
1994 // | PIO Mode 1 | 5.2Mbytes/sec |
1995 // |------------------------|-----------------|
1996 // | PIO Mode 2 | 8.3Mbytes/sec |
1997 // |------------------------|-----------------|
1998 // | PIO Mode 3 | 11.1Mbytes/sec |
1999 // |------------------------|-----------------|
2000 // | PIO Mode 4 | 16.6Mbytes/sec |
2001 // |------------------------|-----------------|
2003 // As AtaBus is used to manage ATA devices, we have to use the lowest transfer
2004 // rate to calculate the possible maximum timeout value for each read/write
2005 // operation. The timout value is rounded up to nearest integar and here an
2006 // additional 30s is added to follow ATA spec in which it mentioned that the
2007 // device may take up to 30s to respond commands in the Standby/Idle mode.
2009 // Calculate the maximum timeout value for PIO read/write operation.
2011 Packet
.Timeout
= TIMER_PERIOD_SECONDS (
2013 MultU64x32 (TransferLength
, DeviceData
->Media
.BlockSize
),
2018 return AtaPassThru
->PassThru (
2021 DeviceData
->PortMultiplier
,
2027 Trust transfer data from/to ATA device.
2029 This function performs one ATA pass through transaction to do a trust transfer
2030 from/to ATA device. It chooses the appropriate ATA command and protocol to invoke
2031 PassThru interface of ATA pass through.
2033 @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
2034 @param[in,out] Buffer The pointer to the current transaction buffer.
2035 @param[in] SecurityProtocolId
2036 The value of the "Security Protocol" parameter
2037 of the security protocol command to be sent.
2038 @param[in] SecurityProtocolSpecificData
2039 The value of the "Security Protocol Specific"
2040 parameter of the security protocol command to
2042 @param[in] TransferLength The block number or sector count of the transfer.
2043 @param[in] IsTrustSend Indicates whether it is a trust send operation
2045 @param[in] Timeout The timeout, in 100ns units, to use for the execution
2046 of the security protocol command. A Timeout value
2047 of 0 means that this function will wait indefinitely
2048 for the security protocol command to execute. If
2049 Timeout is greater than zero, then this function
2050 will return EFI_TIMEOUT if the time required to
2051 execute the receive data command is greater than
2053 @param[out] TransferLengthOut
2054 A pointer to a buffer to store the size in bytes
2055 of the data written to the buffer. Ignore it when
2056 IsTrustSend is TRUE.
2058 @retval EFI_SUCCESS The data transfer is complete successfully.
2059 @return others Some error occurs when transferring data.
2063 TrustTransferAtaDevice (
2064 IN PEI_AHCI_ATA_DEVICE_DATA
*DeviceData
,
2065 IN OUT VOID
*Buffer
,
2066 IN UINT8 SecurityProtocolId
,
2067 IN UINT16 SecurityProtocolSpecificData
,
2068 IN UINTN TransferLength
,
2069 IN BOOLEAN IsTrustSend
,
2071 OUT UINTN
*TransferLengthOut
2074 PEI_AHCI_CONTROLLER_PRIVATE_DATA
*Private
;
2075 EDKII_PEI_ATA_PASS_THRU_PPI
*AtaPassThru
;
2076 EFI_ATA_COMMAND_BLOCK Acb
;
2077 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet
;
2081 Private
= DeviceData
->Private
;
2082 AtaPassThru
= &Private
->AtaPassThruPpi
;
2085 // Ensure IsTrustSend are valid boolean values
2087 ASSERT ((UINTN
)IsTrustSend
< 2);
2088 if ((UINTN
)IsTrustSend
>= 2) {
2089 return EFI_INVALID_PARAMETER
;
2093 // Prepare for ATA command block.
2095 ZeroMem (&Acb
, sizeof (EFI_ATA_COMMAND_BLOCK
));
2096 if (TransferLength
== 0) {
2097 Acb
.AtaCommand
= ATA_CMD_TRUST_NON_DATA
;
2099 Acb
.AtaCommand
= mAtaTrustCommands
[IsTrustSend
];
2102 Acb
.AtaFeatures
= SecurityProtocolId
;
2103 Acb
.AtaSectorCount
= (UINT8
)(TransferLength
/ 512);
2104 Acb
.AtaSectorNumber
= (UINT8
)((TransferLength
/ 512) >> 8);
2106 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
2107 // Here use big endian for Cylinder register.
2109 Acb
.AtaCylinderHigh
= (UINT8
)SecurityProtocolSpecificData
;
2110 Acb
.AtaCylinderLow
= (UINT8
)(SecurityProtocolSpecificData
>> 8);
2111 Acb
.AtaDeviceHead
= (UINT8
)(BIT7
| BIT6
| BIT5
|
2112 (DeviceData
->PortMultiplier
== 0xFFFF ?
2113 0 : (DeviceData
->PortMultiplier
<< 4)));
2116 // Prepare for ATA pass through packet.
2118 ZeroMem (&Packet
, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET
));
2119 if (TransferLength
== 0) {
2120 Packet
.InTransferLength
= 0;
2121 Packet
.OutTransferLength
= 0;
2122 Packet
.Protocol
= EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA
;
2123 } else if (IsTrustSend
) {
2125 // Check the alignment of the incoming buffer prior to invoking underlying
2126 // ATA PassThru PPI.
2128 if ((AtaPassThru
->Mode
->IoAlign
> 1) &&
2129 !IS_ALIGNED (Buffer
, AtaPassThru
->Mode
->IoAlign
))
2131 NewBuffer
= AllocateAlignedPages (
2132 EFI_SIZE_TO_PAGES (TransferLength
),
2133 AtaPassThru
->Mode
->IoAlign
2135 if (NewBuffer
== NULL
) {
2136 return EFI_OUT_OF_RESOURCES
;
2139 CopyMem (NewBuffer
, Buffer
, TransferLength
);
2143 Packet
.OutDataBuffer
= Buffer
;
2144 Packet
.OutTransferLength
= (UINT32
)TransferLength
;
2145 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
2147 Packet
.InDataBuffer
= Buffer
;
2148 Packet
.InTransferLength
= (UINT32
)TransferLength
;
2149 Packet
.Protocol
= mAtaPassThruCmdProtocols
[IsTrustSend
];
2154 Packet
.Timeout
= Timeout
;
2155 Packet
.Length
= EFI_ATA_PASS_THRU_LENGTH_BYTES
;
2157 Status
= AtaPassThru
->PassThru (
2160 DeviceData
->PortMultiplier
,
2163 if (TransferLengthOut
!= NULL
) {
2165 *TransferLengthOut
= Packet
.InTransferLength
;