2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "AtaAtapiPassThru.h"
18 Read AHCI Operation register.
20 @param PciIo The PCI IO protocol instance.
21 @param Offset The operation register offset.
23 @return The register content read.
29 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
35 ASSERT (PciIo
!= NULL
);
52 Write AHCI Operation register.
54 @param PciIo The PCI IO protocol instance.
55 @param Offset The operation register offset.
56 @param Data The data used to write down.
62 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
67 ASSERT (PciIo
!= NULL
);
82 Do AND operation with the value of AHCI Operation register.
84 @param PciIo The PCI IO protocol instance.
85 @param Offset The operation register offset.
86 @param AndData The data used to do AND operation.
92 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
99 ASSERT (PciIo
!= NULL
);
101 Data
= AhciReadReg (PciIo
, Offset
);
105 AhciWriteReg (PciIo
, Offset
, Data
);
109 Do OR operation with the value of AHCI Operation register.
111 @param PciIo The PCI IO protocol instance.
112 @param Offset The operation register offset.
113 @param OrData The data used to do OR operation.
119 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
126 ASSERT (PciIo
!= NULL
);
128 Data
= AhciReadReg (PciIo
, Offset
);
132 AhciWriteReg (PciIo
, Offset
, Data
);
136 Wait for the value of the specified MMIO register set to the test value.
138 @param PciIo The PCI IO protocol instance.
139 @param Offset The MMIO address to test.
140 @param MaskValue The mask value of memory.
141 @param TestValue The test value of memory.
142 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
144 @retval EFI_TIMEOUT The MMIO setting is time out.
145 @retval EFI_SUCCESS The MMIO is correct set.
151 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
160 BOOLEAN InfiniteWait
;
165 InfiniteWait
= FALSE
;
168 Delay
= DivU64x32 (Timeout
, 1000) + 1;
172 // Access PCI MMIO space to see if the value is the tested one.
174 Value
= AhciReadReg (PciIo
, (UINT32
) Offset
) & MaskValue
;
176 if (Value
== TestValue
) {
181 // Stall for 100 microseconds.
183 MicroSecondDelay (100);
187 } while (InfiniteWait
|| (Delay
> 0));
193 Wait for the value of the specified system memory set to the test value.
195 @param Address The system memory address to test.
196 @param MaskValue The mask value of memory.
197 @param TestValue The test value of memory.
198 @param Timeout The time out value for wait memory set, uses 100ns as a unit.
200 @retval EFI_TIMEOUT The system memory setting is time out.
201 @retval EFI_SUCCESS The system memory is correct set.
207 IN EFI_PHYSICAL_ADDRESS Address
,
215 BOOLEAN InfiniteWait
;
220 InfiniteWait
= FALSE
;
223 Delay
= DivU64x32 (Timeout
, 1000) + 1;
227 // Access sytem memory to see if the value is the tested one.
229 // The system memory pointed by Address will be updated by the
230 // SATA Host Controller, "volatile" is introduced to prevent
231 // compiler from optimizing the access to the memory address
232 // to only read once.
234 Value
= *(volatile UINT32
*) (UINTN
) Address
;
237 if (Value
== TestValue
) {
242 // Stall for 100 microseconds.
244 MicroSecondDelay (100);
248 } while (InfiniteWait
|| (Delay
> 0));
254 Check the memory status to the test value.
256 @param[in] Address The memory address to test.
257 @param[in] MaskValue The mask value of memory.
258 @param[in] TestValue The test value of memory.
259 @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
260 non-blocking mode. If NULL, then just try once.
262 @retval EFI_NOTREADY The memory is not set.
263 @retval EFI_TIMEOUT The memory setting retry times out.
264 @retval EFI_SUCCESS The memory is correct set.
273 IN OUT ATA_NONBLOCK_TASK
*Task
282 Value
= *(volatile UINT32
*) Address
;
285 if (Value
== TestValue
) {
289 if ((Task
!= NULL
) && !Task
->InfiniteWait
&& (Task
->RetryTimes
== 0)) {
292 return EFI_NOT_READY
;
297 Check if the device is still on port. It also checks if the AHCI controller
298 supports the address and data count will be transferred.
300 @param PciIo The PCI IO protocol instance.
301 @param Port The number of port.
303 @retval EFI_SUCCESS The device is attached to port and the transfer data is
304 supported by AHCI controller.
305 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
307 @retval EFI_NOT_READY The physical communication between AHCI controller and device
313 AhciCheckDeviceStatus (
314 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
321 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
323 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
325 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
329 return EFI_NOT_READY
;
334 Clear the port interrupt and error status. It will also clear
335 HBA interrupt status.
337 @param PciIo The PCI IO protocol instance.
338 @param Port The number of port.
343 AhciClearPortStatus (
344 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
351 // Clear any error status
353 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
354 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
357 // Clear any port interrupt status
359 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
360 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
363 // Clear any HBA interrupt status
365 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
369 This function is used to dump the Status Registers and if there is ERR bit set
370 in the Status Register, the Error Register's value is also be dumped.
372 @param PciIo The PCI IO protocol instance.
373 @param Port The number of port.
374 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
380 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
382 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
388 ASSERT (PciIo
!= NULL
);
390 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
391 Data
= AhciReadReg (PciIo
, Offset
);
393 if (AtaStatusBlock
!= NULL
) {
394 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
396 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
397 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
398 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
405 Enable the FIS running for giving port.
407 @param PciIo The PCI IO protocol instance.
408 @param Port The number of port.
409 @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
411 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
412 @retval EFI_TIMEOUT The FIS enable setting is time out.
413 @retval EFI_SUCCESS The FIS enable successfully.
418 AhciEnableFisReceive (
419 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
426 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
427 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
429 return AhciWaitMmioSet (
432 EFI_AHCI_PORT_CMD_FR
,
433 EFI_AHCI_PORT_CMD_FR
,
439 Disable the FIS running for giving port.
441 @param PciIo The PCI IO protocol instance.
442 @param Port The number of port.
443 @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
445 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
446 @retval EFI_TIMEOUT The FIS disable setting is time out.
447 @retval EFI_UNSUPPORTED The port is in running state.
448 @retval EFI_SUCCESS The FIS disable successfully.
453 AhciDisableFisReceive (
454 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
462 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
463 Data
= AhciReadReg (PciIo
, Offset
);
466 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
468 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
469 return EFI_UNSUPPORTED
;
473 // Check if the Fis receive DMA engine for the port is running.
475 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
479 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
481 return AhciWaitMmioSet (
484 EFI_AHCI_PORT_CMD_FR
,
493 Build the command list, command table and prepare the fis receiver.
495 @param PciIo The PCI IO protocol instance.
496 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
497 @param Port The number of port.
498 @param PortMultiplier The timeout value of stop.
499 @param CommandFis The control fis will be used for the transfer.
500 @param CommandList The command list will be used for the transfer.
501 @param AtapiCommand The atapi command will be used for the transfer.
502 @param AtapiCommandLength The length of the atapi command.
503 @param CommandSlotNumber The command slot will be used for the transfer.
504 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
505 @param DataLength The data count to be transferred.
511 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
512 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
514 IN UINT8 PortMultiplier
,
515 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
516 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
517 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
518 IN UINT8 AtapiCommandLength
,
519 IN UINT8 CommandSlotNumber
,
520 IN OUT VOID
*DataPhysicalAddr
,
535 PrdtNumber
= (UINT32
)DivU64x32 (((UINT64
)DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1), EFI_AHCI_MAX_DATA_PER_PRDT
);
538 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
539 // It also limits that the maximum amount of the PRDT entry in the command table
542 ASSERT (PrdtNumber
<= 65535);
544 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
546 BaseAddr
= Data64
.Uint64
;
548 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
550 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
552 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
554 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
556 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
557 if (AtapiCommand
!= NULL
) {
559 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
564 CommandList
->AhciCmdA
= 1;
565 CommandList
->AhciCmdP
= 1;
567 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
569 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
572 RemainedData
= (UINTN
) DataLength
;
573 MemAddr
= (UINTN
) DataPhysicalAddr
;
574 CommandList
->AhciCmdPrdtl
= PrdtNumber
;
576 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
577 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
578 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
580 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
583 Data64
.Uint64
= (UINT64
)MemAddr
;
584 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
585 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
586 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
587 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
591 // Set the last PRDT to Interrupt On Complete
593 if (PrdtNumber
> 0) {
594 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
598 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
600 sizeof (EFI_AHCI_COMMAND_LIST
)
603 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
604 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
605 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
606 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
613 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
614 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
619 AhciBuildCommandFis (
620 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
621 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
624 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
626 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
628 // Indicator it's a command
630 CmdFis
->AhciCFisCmdInd
= 0x1;
631 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
633 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
634 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
636 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
637 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
639 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
640 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
642 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
643 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
645 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
646 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
648 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
652 Start a PIO data transfer on specific port.
654 @param[in] PciIo The PCI IO protocol instance.
655 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
656 @param[in] Port The number of port.
657 @param[in] PortMultiplier The timeout value of stop.
658 @param[in] AtapiCommand The atapi command will be used for the
660 @param[in] AtapiCommandLength The length of the atapi command.
661 @param[in] Read The transfer direction.
662 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
663 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
664 @param[in, out] MemoryAddr The pointer to the data buffer.
665 @param[in] DataCount The data count to be transferred.
666 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
667 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
668 used by non-blocking mode.
670 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
671 @retval EFI_TIMEOUT The operation is time out.
672 @retval EFI_UNSUPPORTED The device is not ready for transfer.
673 @retval EFI_SUCCESS The PIO data transfer executes successfully.
679 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
680 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
682 IN UINT8 PortMultiplier
,
683 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
684 IN UINT8 AtapiCommandLength
,
686 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
687 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
688 IN OUT VOID
*MemoryAddr
,
691 IN ATA_NONBLOCK_TASK
*Task
697 EFI_PHYSICAL_ADDRESS PhyAddr
;
700 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
702 EFI_AHCI_COMMAND_FIS CFis
;
703 EFI_AHCI_COMMAND_LIST CmdList
;
706 BOOLEAN InfiniteWait
;
707 BOOLEAN PioFisReceived
;
708 BOOLEAN D2hFisReceived
;
713 InfiniteWait
= FALSE
;
717 Flag
= EfiPciIoOperationBusMasterWrite
;
719 Flag
= EfiPciIoOperationBusMasterRead
;
723 // construct command list and command table with pci bus address
725 MapLength
= DataCount
;
726 Status
= PciIo
->Map (
735 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
736 return EFI_BAD_BUFFER_SIZE
;
740 // Package read needed
742 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
744 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
746 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
747 CmdList
.AhciCmdW
= Read
? 0 : 1;
759 (VOID
*)(UINTN
)PhyAddr
,
763 Status
= AhciStartCommand (
769 if (EFI_ERROR (Status
)) {
774 // Check the status and wait the driver sending data
776 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
778 if (Read
&& (AtapiCommand
== 0)) {
780 // Wait device sends the PIO setup fis before data transfer
782 Status
= EFI_TIMEOUT
;
783 Delay
= DivU64x32 (Timeout
, 1000) + 1;
785 PioFisReceived
= FALSE
;
786 D2hFisReceived
= FALSE
;
787 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
788 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, NULL
);
789 if (!EFI_ERROR (Status
)) {
790 PioFisReceived
= TRUE
;
793 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
794 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
795 // after the transaction is finished successfully.
796 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
797 // By this way, we can know if there is a real error happened.
799 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
800 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
801 if (!EFI_ERROR (Status
)) {
802 D2hFisReceived
= TRUE
;
805 if (PioFisReceived
|| D2hFisReceived
) {
806 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
807 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
809 // PxTFD will be updated if there is a D2H or SetupFIS received.
811 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
812 Status
= EFI_DEVICE_ERROR
;
816 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
817 if (PrdCount
== DataCount
) {
818 Status
= EFI_SUCCESS
;
824 // Stall for 100 microseconds.
826 MicroSecondDelay(100);
830 Status
= EFI_TIMEOUT
;
832 } while (InfiniteWait
|| (Delay
> 0));
835 // Wait for D2H Fis is received
837 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
838 Status
= AhciWaitMemSet (
840 EFI_AHCI_FIS_TYPE_MASK
,
841 EFI_AHCI_FIS_REGISTER_D2H
,
845 if (EFI_ERROR (Status
)) {
849 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
850 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
851 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
852 Status
= EFI_DEVICE_ERROR
;
863 AhciDisableFisReceive (
874 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
880 Start a DMA data transfer on specific port
882 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
883 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
884 @param[in] Port The number of port.
885 @param[in] PortMultiplier The timeout value of stop.
886 @param[in] AtapiCommand The atapi command will be used for the
888 @param[in] AtapiCommandLength The length of the atapi command.
889 @param[in] Read The transfer direction.
890 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
891 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
892 @param[in, out] MemoryAddr The pointer to the data buffer.
893 @param[in] DataCount The data count to be transferred.
894 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
895 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
896 used by non-blocking mode.
898 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
899 @retval EFI_TIMEOUT The operation is time out.
900 @retval EFI_UNSUPPORTED The device is not ready for transfer.
901 @retval EFI_SUCCESS The DMA data transfer executes successfully.
907 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
908 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
910 IN UINT8 PortMultiplier
,
911 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
912 IN UINT8 AtapiCommandLength
,
914 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
915 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
916 IN OUT VOID
*MemoryAddr
,
919 IN ATA_NONBLOCK_TASK
*Task
924 EFI_PHYSICAL_ADDRESS PhyAddr
;
927 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
928 EFI_AHCI_COMMAND_FIS CFis
;
929 EFI_AHCI_COMMAND_LIST CmdList
;
933 EFI_PCI_IO_PROTOCOL
*PciIo
;
937 PciIo
= Instance
->PciIo
;
940 return EFI_INVALID_PARAMETER
;
944 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
946 // Delay 100us to simulate the blocking time out checking.
948 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
949 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
950 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
954 MicroSecondDelay (100);
956 gBS
->RestoreTPL (OldTpl
);
958 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
960 // Mark the Task to indicate that it has been started.
963 Task
->IsStart
= TRUE
;
966 Flag
= EfiPciIoOperationBusMasterWrite
;
968 Flag
= EfiPciIoOperationBusMasterRead
;
972 // Construct command list and command table with pci bus address.
974 MapLength
= DataCount
;
975 Status
= PciIo
->Map (
984 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
985 return EFI_BAD_BUFFER_SIZE
;
992 // Package read needed
994 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
996 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
998 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
999 CmdList
.AhciCmdW
= Read
? 0 : 1;
1011 (VOID
*)(UINTN
)PhyAddr
,
1015 Status
= AhciStartCommand (
1021 if (EFI_ERROR (Status
)) {
1027 // Wait for command compelte
1029 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1030 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1035 Status
= AhciCheckMemSet (
1037 EFI_AHCI_FIS_TYPE_MASK
,
1038 EFI_AHCI_FIS_REGISTER_D2H
,
1042 Status
= AhciWaitMemSet (
1044 EFI_AHCI_FIS_TYPE_MASK
,
1045 EFI_AHCI_FIS_REGISTER_D2H
,
1050 if (EFI_ERROR (Status
)) {
1054 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1055 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1056 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1057 Status
= EFI_DEVICE_ERROR
;
1062 // For Blocking mode, the command should be stopped, the Fis should be disabled
1063 // and the PciIo should be unmapped.
1064 // For non-blocking mode, only when a error is happened (if the return status is
1065 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1066 // context cleanup, then set the packet's Asb status.
1069 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1077 AhciDisableFisReceive (
1085 (Task
!= NULL
) ? Task
->Map
: Map
1089 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1093 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1098 Start a non data transfer on specific port.
1100 @param[in] PciIo The PCI IO protocol instance.
1101 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1102 @param[in] Port The number of port.
1103 @param[in] PortMultiplier The timeout value of stop.
1104 @param[in] AtapiCommand The atapi command will be used for the
1106 @param[in] AtapiCommandLength The length of the atapi command.
1107 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1108 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1109 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1110 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1111 used by non-blocking mode.
1113 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1114 @retval EFI_TIMEOUT The operation is time out.
1115 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1116 @retval EFI_SUCCESS The non data transfer executes successfully.
1121 AhciNonDataTransfer (
1122 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1123 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1125 IN UINT8 PortMultiplier
,
1126 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1127 IN UINT8 AtapiCommandLength
,
1128 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1129 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1131 IN ATA_NONBLOCK_TASK
*Task
1138 EFI_AHCI_COMMAND_FIS CFis
;
1139 EFI_AHCI_COMMAND_LIST CmdList
;
1142 // Package read needed
1144 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1146 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1148 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1164 Status
= AhciStartCommand (
1170 if (EFI_ERROR (Status
)) {
1175 // Wait device sends the Response Fis
1177 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1178 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1179 Status
= AhciWaitMemSet (
1181 EFI_AHCI_FIS_TYPE_MASK
,
1182 EFI_AHCI_FIS_REGISTER_D2H
,
1186 if (EFI_ERROR (Status
)) {
1190 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1191 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1192 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1193 Status
= EFI_DEVICE_ERROR
;
1203 AhciDisableFisReceive (
1209 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1215 Stop command running for giving port
1217 @param PciIo The PCI IO protocol instance.
1218 @param Port The number of port.
1219 @param Timeout The timeout value of stop, uses 100ns as a unit.
1221 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1222 @retval EFI_TIMEOUT The operation is time out.
1223 @retval EFI_SUCCESS The command stop successfully.
1229 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1237 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1238 Data
= AhciReadReg (PciIo
, Offset
);
1240 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1244 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1245 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1248 return AhciWaitMmioSet (
1251 EFI_AHCI_PORT_CMD_CR
,
1258 Start command for give slot on specific port.
1260 @param PciIo The PCI IO protocol instance.
1261 @param Port The number of port.
1262 @param CommandSlot The number of Command Slot.
1263 @param Timeout The timeout value of start, uses 100ns as a unit.
1265 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1266 @retval EFI_TIMEOUT The operation is time out.
1267 @retval EFI_SUCCESS The command start successfully.
1273 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1275 IN UINT8 CommandSlot
,
1288 // Collect AHCI controller information
1290 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1292 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1294 AhciClearPortStatus (
1299 Status
= AhciEnableFisReceive (
1305 if (EFI_ERROR (Status
)) {
1309 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1310 PortStatus
= AhciReadReg (PciIo
, Offset
);
1313 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1314 StartCmd
= AhciReadReg (PciIo
, Offset
);
1315 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1316 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1319 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1320 PortTfd
= AhciReadReg (PciIo
, Offset
);
1322 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1323 if ((Capability
& BIT24
) != 0) {
1324 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1325 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1330 EFI_AHCI_PORT_CMD_CLO
,
1337 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1338 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1341 // Setting the command
1343 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1344 AhciAndReg (PciIo
, Offset
, 0);
1345 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1347 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1348 AhciAndReg (PciIo
, Offset
, 0);
1349 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1357 @param PciIo The PCI IO protocol instance.
1358 @param Port The number of port.
1359 @param Timeout The timeout value of reset, uses 100ns as a unit.
1361 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1362 @retval EFI_TIMEOUT The reset operation is time out.
1363 @retval EFI_SUCCESS The port reset successfully.
1369 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1377 AhciClearPortStatus (PciIo
, Port
);
1379 AhciStopCommand (PciIo
, Port
, Timeout
);
1381 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1383 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1385 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1387 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1390 // wait 5 millisecond before de-assert DET
1392 MicroSecondDelay (5000);
1394 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1397 // wait 5 millisecond before de-assert DET
1399 MicroSecondDelay (5000);
1402 // Wait for communication to be re-established
1404 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1405 Status
= AhciWaitMmioSet (
1408 EFI_AHCI_PORT_SSTS_DET_MASK
,
1409 EFI_AHCI_PORT_SSTS_DET_PCE
,
1413 if (EFI_ERROR (Status
)) {
1417 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1418 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1426 @param PciIo The PCI IO protocol instance.
1427 @param Timeout The timeout value of reset, uses 100ns as a unit.
1429 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1430 @retval EFI_TIMEOUT The reset operation is time out.
1431 @retval EFI_SUCCESS AHCI controller is reset successfully.
1437 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1446 // Collect AHCI controller information
1448 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1451 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1453 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
1454 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1457 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1459 Delay
= DivU64x32(Timeout
, 1000) + 1;
1462 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1464 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1469 // Stall for 100 microseconds.
1471 MicroSecondDelay(100);
1474 } while (Delay
> 0);
1484 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1486 @param PciIo The PCI IO protocol instance.
1487 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1488 @param Port The number of port.
1489 @param PortMultiplier The timeout value of stop.
1490 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1492 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1493 @retval Others Fail to get return status data.
1498 AhciAtaSmartReturnStatusCheck (
1499 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1500 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1502 IN UINT8 PortMultiplier
,
1503 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1507 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1513 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1515 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1516 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1517 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1518 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1521 // Send S.M.A.R.T Read Return Status command to device
1523 Status
= AhciNonDataTransfer (
1527 (UINT8
)PortMultiplier
,
1536 if (EFI_ERROR (Status
)) {
1537 REPORT_STATUS_CODE (
1538 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1539 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1541 return EFI_DEVICE_ERROR
;
1544 REPORT_STATUS_CODE (
1546 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1549 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1551 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1553 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1554 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1555 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1557 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1559 // The threshold exceeded condition is not detected by the device
1561 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1562 REPORT_STATUS_CODE (
1564 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1566 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1568 // The threshold exceeded condition is detected by the device
1570 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1571 REPORT_STATUS_CODE (
1573 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1582 Enable SMART command of the disk if supported.
1584 @param PciIo The PCI IO protocol instance.
1585 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1586 @param Port The number of port.
1587 @param PortMultiplier The timeout value of stop.
1588 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1589 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1594 AhciAtaSmartSupport (
1595 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1596 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1598 IN UINT8 PortMultiplier
,
1599 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1600 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1604 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1607 // Detect if the device supports S.M.A.R.T.
1609 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1611 // S.M.A.R.T is not supported by the device
1613 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1614 Port
, PortMultiplier
));
1615 REPORT_STATUS_CODE (
1616 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1617 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1621 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1623 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1625 REPORT_STATUS_CODE (
1627 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1630 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1632 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1633 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1634 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1635 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1638 // Send S.M.A.R.T Enable command to device
1640 Status
= AhciNonDataTransfer (
1644 (UINT8
)PortMultiplier
,
1654 if (!EFI_ERROR (Status
)) {
1656 // Send S.M.A.R.T AutoSave command to device
1658 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1660 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1661 AtaCommandBlock
.AtaFeatures
= 0xD2;
1662 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1663 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1664 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1666 Status
= AhciNonDataTransfer (
1670 (UINT8
)PortMultiplier
,
1679 if (!EFI_ERROR (Status
)) {
1680 Status
= AhciAtaSmartReturnStatusCheck (
1684 (UINT8
)PortMultiplier
,
1690 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1691 Port
, PortMultiplier
));
1698 Send Buffer cmd to specific device.
1700 @param PciIo The PCI IO protocol instance.
1701 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1702 @param Port The number of port.
1703 @param PortMultiplier The timeout value of stop.
1704 @param Buffer The data buffer to store IDENTIFY PACKET data.
1706 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1707 @retval EFI_TIMEOUT The operation is time out.
1708 @retval EFI_UNSUPPORTED The device is not ready for executing.
1709 @retval EFI_SUCCESS The cmd executes successfully.
1715 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1716 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1718 IN UINT8 PortMultiplier
,
1719 IN OUT EFI_IDENTIFY_DATA
*Buffer
1723 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1724 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1726 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1727 return EFI_INVALID_PARAMETER
;
1730 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1731 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1733 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1734 AtaCommandBlock
.AtaSectorCount
= 1;
1736 Status
= AhciPioTransfer (
1747 sizeof (EFI_IDENTIFY_DATA
),
1756 Send Buffer cmd to specific device.
1758 @param PciIo The PCI IO protocol instance.
1759 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1760 @param Port The number of port.
1761 @param PortMultiplier The timeout value of stop.
1762 @param Buffer The data buffer to store IDENTIFY PACKET data.
1764 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1765 @retval EFI_TIMEOUT The operation is time out.
1766 @retval EFI_UNSUPPORTED The device is not ready for executing.
1767 @retval EFI_SUCCESS The cmd executes successfully.
1772 AhciIdentifyPacket (
1773 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1774 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1776 IN UINT8 PortMultiplier
,
1777 IN OUT EFI_IDENTIFY_DATA
*Buffer
1781 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1782 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1784 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1785 return EFI_INVALID_PARAMETER
;
1788 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1789 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1791 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1792 AtaCommandBlock
.AtaSectorCount
= 1;
1794 Status
= AhciPioTransfer (
1805 sizeof (EFI_IDENTIFY_DATA
),
1814 Send SET FEATURE cmd on specific device.
1816 @param PciIo The PCI IO protocol instance.
1817 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1818 @param Port The number of port.
1819 @param PortMultiplier The timeout value of stop.
1820 @param Feature The data to send Feature register.
1821 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1823 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1824 @retval EFI_TIMEOUT The operation is time out.
1825 @retval EFI_UNSUPPORTED The device is not ready for executing.
1826 @retval EFI_SUCCESS The cmd executes successfully.
1831 AhciDeviceSetFeature (
1832 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1833 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1835 IN UINT8 PortMultiplier
,
1837 IN UINT32 FeatureSpecificData
1841 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1842 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1844 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1845 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1847 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1848 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1849 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1850 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1851 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1852 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1853 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1855 Status
= AhciNonDataTransfer (
1859 (UINT8
)PortMultiplier
,
1872 This function is used to send out ATAPI commands conforms to the Packet Command
1875 @param PciIo The PCI IO protocol instance.
1876 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1877 @param Port The number of port.
1878 @param PortMultiplier The number of port multiplier.
1879 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1881 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1882 and device sends data successfully.
1883 @retval EFI_DEVICE_ERROR the device failed to send data.
1888 AhciPacketCommandExecute (
1889 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1890 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1892 IN UINT8 PortMultiplier
,
1893 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1899 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1900 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1903 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1904 return EFI_INVALID_PARAMETER
;
1907 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1908 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1909 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1913 AtaCommandBlock
.AtaFeatures
= 0x00;
1915 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1916 // determine how many data should be transferred.
1918 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1919 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1921 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1922 Buffer
= Packet
->InDataBuffer
;
1923 Length
= Packet
->InTransferLength
;
1926 Buffer
= Packet
->OutDataBuffer
;
1927 Length
= Packet
->OutTransferLength
;
1932 Status
= AhciNonDataTransfer (
1945 Status
= AhciPioTransfer (
1965 Allocate transfer-related data struct which is used at AHCI mode.
1967 @param PciIo The PCI IO protocol instance.
1968 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1973 AhciCreateTransferDescriptor (
1974 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1975 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1983 UINT32 PortImplementBitMap
;
1984 UINT8 MaxPortNumber
;
1985 UINT8 MaxCommandSlotNumber
;
1986 BOOLEAN Support64Bit
;
1987 UINT64 MaxReceiveFisSize
;
1988 UINT64 MaxCommandListSize
;
1989 UINT64 MaxCommandTableSize
;
1990 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1991 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1992 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1996 // Collect AHCI controller information
1998 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2000 // Get the number of command slots per port supported by this HBA.
2002 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2003 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2005 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2007 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
2009 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
2010 if (MaxPortNumber
== 0) {
2011 return EFI_DEVICE_ERROR
;
2014 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
2015 Status
= PciIo
->AllocateBuffer (
2018 EfiBootServicesData
,
2019 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2024 if (EFI_ERROR (Status
)) {
2025 return EFI_OUT_OF_RESOURCES
;
2028 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2030 AhciRegisters
->AhciRFis
= Buffer
;
2031 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2032 Bytes
= (UINTN
)MaxReceiveFisSize
;
2034 Status
= PciIo
->Map (
2036 EfiPciIoOperationBusMasterCommonBuffer
,
2040 &AhciRegisters
->MapRFis
2043 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2045 // Map error or unable to map the whole RFis buffer into a contiguous region.
2047 Status
= EFI_OUT_OF_RESOURCES
;
2051 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2053 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2055 Status
= EFI_DEVICE_ERROR
;
2058 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2061 // Allocate memory for command list
2062 // Note that the implemenation is a single task model which only use a command list for all ports.
2065 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2066 Status
= PciIo
->AllocateBuffer (
2069 EfiBootServicesData
,
2070 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2075 if (EFI_ERROR (Status
)) {
2077 // Free mapped resource.
2079 Status
= EFI_OUT_OF_RESOURCES
;
2083 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2085 AhciRegisters
->AhciCmdList
= Buffer
;
2086 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2087 Bytes
= (UINTN
)MaxCommandListSize
;
2089 Status
= PciIo
->Map (
2091 EfiPciIoOperationBusMasterCommonBuffer
,
2094 &AhciCmdListPciAddr
,
2095 &AhciRegisters
->MapCmdList
2098 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2100 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2102 Status
= EFI_OUT_OF_RESOURCES
;
2106 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2108 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2110 Status
= EFI_DEVICE_ERROR
;
2113 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2116 // Allocate memory for command table
2117 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2120 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2122 Status
= PciIo
->AllocateBuffer (
2125 EfiBootServicesData
,
2126 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2131 if (EFI_ERROR (Status
)) {
2133 // Free mapped resource.
2135 Status
= EFI_OUT_OF_RESOURCES
;
2139 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2141 AhciRegisters
->AhciCommandTable
= Buffer
;
2142 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2143 Bytes
= (UINTN
)MaxCommandTableSize
;
2145 Status
= PciIo
->Map (
2147 EfiPciIoOperationBusMasterCommonBuffer
,
2150 &AhciCommandTablePciAddr
,
2151 &AhciRegisters
->MapCommandTable
2154 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2156 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2158 Status
= EFI_OUT_OF_RESOURCES
;
2162 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2164 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2166 Status
= EFI_DEVICE_ERROR
;
2169 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2173 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2178 AhciRegisters
->MapCommandTable
2183 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2184 AhciRegisters
->AhciCommandTable
2189 AhciRegisters
->MapCmdList
2194 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2195 AhciRegisters
->AhciCmdList
2200 AhciRegisters
->MapRFis
2205 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2206 AhciRegisters
->AhciRFis
2213 Initialize ATA host controller at AHCI mode.
2215 The function is designed to initialize ATA host controller.
2217 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2222 AhciModeInitialization (
2223 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2227 EFI_PCI_IO_PROTOCOL
*PciIo
;
2228 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2230 UINT8 MaxPortNumber
;
2231 UINT32 PortImplementBitMap
;
2233 EFI_AHCI_REGISTERS
*AhciRegisters
;
2239 EFI_IDENTIFY_DATA Buffer
;
2240 EFI_ATA_DEVICE_TYPE DeviceType
;
2241 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2242 EFI_ATA_TRANSFER_MODE TransferMode
;
2243 UINT32 PhyDetectDelay
;
2245 if (Instance
== NULL
) {
2246 return EFI_INVALID_PARAMETER
;
2249 PciIo
= Instance
->PciIo
;
2250 IdeInit
= Instance
->IdeControllerInit
;
2252 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2254 if (EFI_ERROR (Status
)) {
2255 return EFI_DEVICE_ERROR
;
2259 // Collect AHCI controller information
2261 Capability
= AhciReadReg (PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2264 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
2266 if ((Capability
& EFI_AHCI_CAP_SAM
) == 0) {
2267 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2271 // Get the number of command slots per port supported by this HBA.
2273 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2276 // Get the bit map of those ports exposed by this HBA.
2277 // It indicates which ports that the HBA supports are available for software to use.
2279 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2281 AhciRegisters
= &Instance
->AhciRegisters
;
2282 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2284 if (EFI_ERROR (Status
)) {
2285 return EFI_OUT_OF_RESOURCES
;
2288 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2289 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2291 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2293 if ((MaxPortNumber
--) == 0) {
2295 // Should never be here.
2301 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2304 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2306 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2307 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2308 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2309 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2310 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2312 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2313 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2314 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2315 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2316 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2318 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2319 Data
= AhciReadReg (PciIo
, Offset
);
2320 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2321 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2324 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2325 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2329 // Disable aggressive power management.
2331 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2332 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2334 // Disable the reporting of the corresponding interrupt to system software.
2336 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2337 AhciAndReg (PciIo
, Offset
, 0);
2340 // Now inform the IDE Controller Init Module.
2342 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2345 // Enable FIS Receive DMA engine for the first D2H FIS.
2347 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2348 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2349 Status
= AhciWaitMmioSet (
2352 EFI_AHCI_PORT_CMD_FR
,
2353 EFI_AHCI_PORT_CMD_FR
,
2354 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2356 if (EFI_ERROR (Status
)) {
2361 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2362 // It's the requirment from SATA1.0a spec section 5.2.
2364 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2365 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2367 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2368 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2372 MicroSecondDelay (1000);
2374 } while (PhyDetectDelay
> 0);
2376 if (PhyDetectDelay
== 0) {
2378 // No device detected at this port.
2379 // Clear PxCMD.SUD for those ports at which there are no device present.
2381 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2382 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2387 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2388 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2390 PhyDetectDelay
= 16 * 1000;
2392 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2393 if (AhciReadReg(PciIo
, Offset
) != 0) {
2394 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2396 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2398 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2403 MicroSecondDelay (1000);
2405 } while (PhyDetectDelay
> 0);
2407 if (PhyDetectDelay
== 0) {
2412 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2414 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2415 Status
= AhciWaitMmioSet (
2420 EFI_TIMER_PERIOD_SECONDS(16)
2422 if (EFI_ERROR (Status
)) {
2426 Data
= AhciReadReg (PciIo
, Offset
);
2427 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2428 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2430 if (EFI_ERROR (Status
)) {
2434 DeviceType
= EfiIdeCdrom
;
2435 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2436 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2438 if (EFI_ERROR (Status
)) {
2439 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2443 DeviceType
= EfiIdeHarddisk
;
2447 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2448 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2451 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2453 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2454 AhciAtaSmartSupport (
2465 // Submit identify data to IDE controller init driver
2467 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2470 // Now start to config ide device parameter and transfer mode.
2472 Status
= IdeInit
->CalculateMode (
2478 if (EFI_ERROR (Status
)) {
2479 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2484 // Set best supported PIO mode on this IDE device
2486 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2487 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2489 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2492 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2495 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2496 // be set together. Only one DMA mode can be set to a device. If setting
2497 // DMA mode operation fails, we can continue moving on because we only use
2498 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2500 if (SupportedModes
->UdmaMode
.Valid
) {
2501 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2502 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2503 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2504 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2505 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2508 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2509 if (EFI_ERROR (Status
)) {
2510 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2515 // Found a ATA or ATAPI device, add it into the device list.
2517 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2518 if (DeviceType
== EfiIdeHarddisk
) {
2519 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));