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
;
711 InfiniteWait
= FALSE
;
715 Flag
= EfiPciIoOperationBusMasterWrite
;
717 Flag
= EfiPciIoOperationBusMasterRead
;
721 // construct command list and command table with pci bus address
723 MapLength
= DataCount
;
724 Status
= PciIo
->Map (
733 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
734 return EFI_BAD_BUFFER_SIZE
;
738 // Package read needed
740 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
742 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
744 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
745 CmdList
.AhciCmdW
= Read
? 0 : 1;
757 (VOID
*)(UINTN
)PhyAddr
,
761 Status
= AhciStartCommand (
767 if (EFI_ERROR (Status
)) {
772 // Check the status and wait the driver sending data
774 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
776 if (Read
&& (AtapiCommand
== 0)) {
778 // Wait device sends the PIO setup fis before data transfer
780 Status
= EFI_TIMEOUT
;
781 Delay
= DivU64x32 (Timeout
, 1000) + 1;
783 Offset
= FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
;
785 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_PIO_SETUP
, NULL
);
786 if (!EFI_ERROR (Status
)) {
787 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
788 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
790 // PxTFD will be updated if there is a D2H or SetupFIS received.
791 // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
793 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
794 Status
= EFI_DEVICE_ERROR
;
798 PrdCount
= *(volatile UINT32
*) (&(AhciRegisters
->AhciCmdList
[0].AhciCmdPrdbc
));
799 if (PrdCount
== DataCount
) {
804 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
805 Status
= AhciCheckMemSet (Offset
, EFI_AHCI_FIS_TYPE_MASK
, EFI_AHCI_FIS_REGISTER_D2H
, NULL
);
806 if (!EFI_ERROR (Status
)) {
807 Status
= EFI_DEVICE_ERROR
;
812 // Stall for 100 microseconds.
814 MicroSecondDelay(100);
817 } while (InfiniteWait
|| (Delay
> 0));
820 // Wait for D2H Fis is received
822 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
823 Status
= AhciWaitMemSet (
825 EFI_AHCI_FIS_TYPE_MASK
,
826 EFI_AHCI_FIS_REGISTER_D2H
,
830 if (EFI_ERROR (Status
)) {
834 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
835 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
836 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
837 Status
= EFI_DEVICE_ERROR
;
848 AhciDisableFisReceive (
859 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
865 Start a DMA data transfer on specific port
867 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
868 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
869 @param[in] Port The number of port.
870 @param[in] PortMultiplier The timeout value of stop.
871 @param[in] AtapiCommand The atapi command will be used for the
873 @param[in] AtapiCommandLength The length of the atapi command.
874 @param[in] Read The transfer direction.
875 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
876 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
877 @param[in, out] MemoryAddr The pointer to the data buffer.
878 @param[in] DataCount The data count to be transferred.
879 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
880 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
881 used by non-blocking mode.
883 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
884 @retval EFI_TIMEOUT The operation is time out.
885 @retval EFI_UNSUPPORTED The device is not ready for transfer.
886 @retval EFI_SUCCESS The DMA data transfer executes successfully.
892 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
893 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
895 IN UINT8 PortMultiplier
,
896 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
897 IN UINT8 AtapiCommandLength
,
899 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
900 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
901 IN OUT VOID
*MemoryAddr
,
904 IN ATA_NONBLOCK_TASK
*Task
909 EFI_PHYSICAL_ADDRESS PhyAddr
;
912 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
913 EFI_AHCI_COMMAND_FIS CFis
;
914 EFI_AHCI_COMMAND_LIST CmdList
;
918 EFI_PCI_IO_PROTOCOL
*PciIo
;
922 PciIo
= Instance
->PciIo
;
925 return EFI_INVALID_PARAMETER
;
929 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
931 // Delay 100us to simulate the blocking time out checking.
933 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
934 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
935 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
939 MicroSecondDelay (100);
941 gBS
->RestoreTPL (OldTpl
);
943 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
945 // Mark the Task to indicate that it has been started.
948 Task
->IsStart
= TRUE
;
951 Flag
= EfiPciIoOperationBusMasterWrite
;
953 Flag
= EfiPciIoOperationBusMasterRead
;
957 // Construct command list and command table with pci bus address.
959 MapLength
= DataCount
;
960 Status
= PciIo
->Map (
969 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
970 return EFI_BAD_BUFFER_SIZE
;
977 // Package read needed
979 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
981 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
983 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
984 CmdList
.AhciCmdW
= Read
? 0 : 1;
996 (VOID
*)(UINTN
)PhyAddr
,
1000 Status
= AhciStartCommand (
1006 if (EFI_ERROR (Status
)) {
1012 // Wait for command compelte
1014 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1015 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1020 Status
= AhciCheckMemSet (
1022 EFI_AHCI_FIS_TYPE_MASK
,
1023 EFI_AHCI_FIS_REGISTER_D2H
,
1027 Status
= AhciWaitMemSet (
1029 EFI_AHCI_FIS_TYPE_MASK
,
1030 EFI_AHCI_FIS_REGISTER_D2H
,
1035 if (EFI_ERROR (Status
)) {
1039 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1040 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1041 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1042 Status
= EFI_DEVICE_ERROR
;
1047 // For Blocking mode, the command should be stopped, the Fis should be disabled
1048 // and the PciIo should be unmapped.
1049 // For non-blocking mode, only when a error is happened (if the return status is
1050 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1051 // context cleanup, then set the packet's Asb status.
1054 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1062 AhciDisableFisReceive (
1070 (Task
!= NULL
) ? Task
->Map
: Map
1074 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1078 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1083 Start a non data transfer on specific port.
1085 @param[in] PciIo The PCI IO protocol instance.
1086 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1087 @param[in] Port The number of port.
1088 @param[in] PortMultiplier The timeout value of stop.
1089 @param[in] AtapiCommand The atapi command will be used for the
1091 @param[in] AtapiCommandLength The length of the atapi command.
1092 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1093 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1094 @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
1095 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1096 used by non-blocking mode.
1098 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1099 @retval EFI_TIMEOUT The operation is time out.
1100 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1101 @retval EFI_SUCCESS The non data transfer executes successfully.
1106 AhciNonDataTransfer (
1107 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1108 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1110 IN UINT8 PortMultiplier
,
1111 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1112 IN UINT8 AtapiCommandLength
,
1113 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1114 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1116 IN ATA_NONBLOCK_TASK
*Task
1123 EFI_AHCI_COMMAND_FIS CFis
;
1124 EFI_AHCI_COMMAND_LIST CmdList
;
1127 // Package read needed
1129 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1131 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1133 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1149 Status
= AhciStartCommand (
1155 if (EFI_ERROR (Status
)) {
1160 // Wait device sends the Response Fis
1162 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1163 Offset
= FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
;
1164 Status
= AhciWaitMemSet (
1166 EFI_AHCI_FIS_TYPE_MASK
,
1167 EFI_AHCI_FIS_REGISTER_D2H
,
1171 if (EFI_ERROR (Status
)) {
1175 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1176 PortTfd
= AhciReadReg (PciIo
, (UINT32
) Offset
);
1177 if ((PortTfd
& EFI_AHCI_PORT_TFD_ERR
) != 0) {
1178 Status
= EFI_DEVICE_ERROR
;
1188 AhciDisableFisReceive (
1194 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1200 Stop command running for giving port
1202 @param PciIo The PCI IO protocol instance.
1203 @param Port The number of port.
1204 @param Timeout The timeout value of stop, uses 100ns as a unit.
1206 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1207 @retval EFI_TIMEOUT The operation is time out.
1208 @retval EFI_SUCCESS The command stop successfully.
1214 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1222 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1223 Data
= AhciReadReg (PciIo
, Offset
);
1225 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1229 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1230 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1233 return AhciWaitMmioSet (
1236 EFI_AHCI_PORT_CMD_CR
,
1243 Start command for give slot on specific port.
1245 @param PciIo The PCI IO protocol instance.
1246 @param Port The number of port.
1247 @param CommandSlot The number of Command Slot.
1248 @param Timeout The timeout value of start, uses 100ns as a unit.
1250 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1251 @retval EFI_TIMEOUT The operation is time out.
1252 @retval EFI_SUCCESS The command start successfully.
1258 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1260 IN UINT8 CommandSlot
,
1273 // Collect AHCI controller information
1275 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1277 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1279 AhciClearPortStatus (
1284 Status
= AhciEnableFisReceive (
1290 if (EFI_ERROR (Status
)) {
1294 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1295 PortStatus
= AhciReadReg (PciIo
, Offset
);
1298 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1299 StartCmd
= AhciReadReg (PciIo
, Offset
);
1300 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1301 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1304 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1305 PortTfd
= AhciReadReg (PciIo
, Offset
);
1307 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1308 if ((Capability
& BIT24
) != 0) {
1309 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1310 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_CLO
);
1315 EFI_AHCI_PORT_CMD_CLO
,
1322 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1323 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1326 // Setting the command
1328 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1329 AhciAndReg (PciIo
, Offset
, 0);
1330 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1332 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1333 AhciAndReg (PciIo
, Offset
, 0);
1334 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1342 @param PciIo The PCI IO protocol instance.
1343 @param Port The number of port.
1344 @param Timeout The timeout value of reset, uses 100ns as a unit.
1346 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1347 @retval EFI_TIMEOUT The reset operation is time out.
1348 @retval EFI_SUCCESS The port reset successfully.
1354 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1362 AhciClearPortStatus (PciIo
, Port
);
1364 AhciStopCommand (PciIo
, Port
, Timeout
);
1366 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1368 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1370 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1372 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1375 // wait 5 millisecond before de-assert DET
1377 MicroSecondDelay (5000);
1379 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1382 // wait 5 millisecond before de-assert DET
1384 MicroSecondDelay (5000);
1387 // Wait for communication to be re-established
1389 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1390 Status
= AhciWaitMmioSet (
1393 EFI_AHCI_PORT_SSTS_DET_MASK
,
1394 EFI_AHCI_PORT_SSTS_DET_PCE
,
1398 if (EFI_ERROR (Status
)) {
1402 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1403 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1411 @param PciIo The PCI IO protocol instance.
1412 @param Timeout The timeout value of reset, uses 100ns as a unit.
1414 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1415 @retval EFI_TIMEOUT The reset operation is time out.
1416 @retval EFI_SUCCESS AHCI controller is reset successfully.
1422 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1429 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1431 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1433 Delay
= DivU64x32(Timeout
, 1000) + 1;
1436 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1438 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1443 // Stall for 100 microseconds.
1445 MicroSecondDelay(100);
1448 } while (Delay
> 0);
1458 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1460 @param PciIo The PCI IO protocol instance.
1461 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1462 @param Port The number of port.
1463 @param PortMultiplier The timeout value of stop.
1464 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1466 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1467 @retval Others Fail to get return status data.
1472 AhciAtaSmartReturnStatusCheck (
1473 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1474 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1476 IN UINT8 PortMultiplier
,
1477 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1481 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1487 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1489 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1490 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1491 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1492 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1495 // Send S.M.A.R.T Read Return Status command to device
1497 Status
= AhciNonDataTransfer (
1501 (UINT8
)PortMultiplier
,
1510 if (EFI_ERROR (Status
)) {
1511 REPORT_STATUS_CODE (
1512 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1513 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLED
)
1515 return EFI_DEVICE_ERROR
;
1518 REPORT_STATUS_CODE (
1520 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_ENABLE
)
1523 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1525 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1527 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1528 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1529 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1531 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1533 // The threshold exceeded condition is not detected by the device
1535 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1536 REPORT_STATUS_CODE (
1538 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD
)
1540 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1542 // The threshold exceeded condition is detected by the device
1544 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1545 REPORT_STATUS_CODE (
1547 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD
)
1556 Enable SMART command of the disk if supported.
1558 @param PciIo The PCI IO protocol instance.
1559 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1560 @param Port The number of port.
1561 @param PortMultiplier The timeout value of stop.
1562 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1563 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1568 AhciAtaSmartSupport (
1569 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1570 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1572 IN UINT8 PortMultiplier
,
1573 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1574 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1578 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1581 // Detect if the device supports S.M.A.R.T.
1583 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1585 // S.M.A.R.T is not supported by the device
1587 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1588 Port
, PortMultiplier
));
1589 REPORT_STATUS_CODE (
1590 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1591 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED
)
1595 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1597 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1599 REPORT_STATUS_CODE (
1601 (EFI_IO_BUS_ATA_ATAPI
| EFI_IOB_ATA_BUS_SMART_DISABLE
)
1604 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1606 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1607 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1608 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1609 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1612 // Send S.M.A.R.T Enable command to device
1614 Status
= AhciNonDataTransfer (
1618 (UINT8
)PortMultiplier
,
1628 if (!EFI_ERROR (Status
)) {
1630 // Send S.M.A.R.T AutoSave command to device
1632 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1634 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1635 AtaCommandBlock
.AtaFeatures
= 0xD2;
1636 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1637 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1638 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1640 Status
= AhciNonDataTransfer (
1644 (UINT8
)PortMultiplier
,
1653 if (!EFI_ERROR (Status
)) {
1654 Status
= AhciAtaSmartReturnStatusCheck (
1658 (UINT8
)PortMultiplier
,
1664 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1665 Port
, PortMultiplier
));
1672 Send Buffer cmd to specific device.
1674 @param PciIo The PCI IO protocol instance.
1675 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1676 @param Port The number of port.
1677 @param PortMultiplier The timeout value of stop.
1678 @param Buffer The data buffer to store IDENTIFY PACKET data.
1680 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1681 @retval EFI_TIMEOUT The operation is time out.
1682 @retval EFI_UNSUPPORTED The device is not ready for executing.
1683 @retval EFI_SUCCESS The cmd executes successfully.
1689 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1690 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1692 IN UINT8 PortMultiplier
,
1693 IN OUT EFI_IDENTIFY_DATA
*Buffer
1697 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1698 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1700 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1701 return EFI_INVALID_PARAMETER
;
1704 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1705 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1707 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1708 AtaCommandBlock
.AtaSectorCount
= 1;
1710 Status
= AhciPioTransfer (
1721 sizeof (EFI_IDENTIFY_DATA
),
1730 Send Buffer cmd to specific device.
1732 @param PciIo The PCI IO protocol instance.
1733 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1734 @param Port The number of port.
1735 @param PortMultiplier The timeout value of stop.
1736 @param Buffer The data buffer to store IDENTIFY PACKET data.
1738 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1739 @retval EFI_TIMEOUT The operation is time out.
1740 @retval EFI_UNSUPPORTED The device is not ready for executing.
1741 @retval EFI_SUCCESS The cmd executes successfully.
1746 AhciIdentifyPacket (
1747 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1748 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1750 IN UINT8 PortMultiplier
,
1751 IN OUT EFI_IDENTIFY_DATA
*Buffer
1755 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1756 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1758 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1759 return EFI_INVALID_PARAMETER
;
1762 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1763 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1765 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1766 AtaCommandBlock
.AtaSectorCount
= 1;
1768 Status
= AhciPioTransfer (
1779 sizeof (EFI_IDENTIFY_DATA
),
1788 Send SET FEATURE cmd on specific device.
1790 @param PciIo The PCI IO protocol instance.
1791 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1792 @param Port The number of port.
1793 @param PortMultiplier The timeout value of stop.
1794 @param Feature The data to send Feature register.
1795 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1797 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1798 @retval EFI_TIMEOUT The operation is time out.
1799 @retval EFI_UNSUPPORTED The device is not ready for executing.
1800 @retval EFI_SUCCESS The cmd executes successfully.
1805 AhciDeviceSetFeature (
1806 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1807 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1809 IN UINT8 PortMultiplier
,
1811 IN UINT32 FeatureSpecificData
1815 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1816 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1818 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1819 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1821 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1822 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1823 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1824 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1825 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1826 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1827 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1829 Status
= AhciNonDataTransfer (
1833 (UINT8
)PortMultiplier
,
1846 This function is used to send out ATAPI commands conforms to the Packet Command
1849 @param PciIo The PCI IO protocol instance.
1850 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1851 @param Port The number of port.
1852 @param PortMultiplier The number of port multiplier.
1853 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1855 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1856 and device sends data successfully.
1857 @retval EFI_DEVICE_ERROR the device failed to send data.
1862 AhciPacketCommandExecute (
1863 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1864 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1866 IN UINT8 PortMultiplier
,
1867 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1873 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1874 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1877 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1878 return EFI_INVALID_PARAMETER
;
1881 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1882 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1883 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1887 AtaCommandBlock
.AtaFeatures
= 0x00;
1889 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1890 // determine how many data should be transferred.
1892 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1893 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1895 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1896 Buffer
= Packet
->InDataBuffer
;
1897 Length
= Packet
->InTransferLength
;
1900 Buffer
= Packet
->OutDataBuffer
;
1901 Length
= Packet
->OutTransferLength
;
1906 Status
= AhciNonDataTransfer (
1919 Status
= AhciPioTransfer (
1939 Allocate transfer-related data struct which is used at AHCI mode.
1941 @param PciIo The PCI IO protocol instance.
1942 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1947 AhciCreateTransferDescriptor (
1948 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1949 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1957 UINT32 PortImplementBitMap
;
1958 UINT8 MaxPortNumber
;
1959 UINT8 MaxCommandSlotNumber
;
1960 BOOLEAN Support64Bit
;
1961 UINT64 MaxReceiveFisSize
;
1962 UINT64 MaxCommandListSize
;
1963 UINT64 MaxCommandTableSize
;
1964 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1965 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1966 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1970 // Collect AHCI controller information
1972 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1974 // Get the number of command slots per port supported by this HBA.
1976 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1977 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1979 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
1981 // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
1983 MaxPortNumber
= (UINT8
)(UINTN
)(HighBitSet32(PortImplementBitMap
) + 1);
1984 if (MaxPortNumber
== 0) {
1985 return EFI_DEVICE_ERROR
;
1988 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1989 Status
= PciIo
->AllocateBuffer (
1992 EfiBootServicesData
,
1993 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1998 if (EFI_ERROR (Status
)) {
1999 return EFI_OUT_OF_RESOURCES
;
2002 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
2004 AhciRegisters
->AhciRFis
= Buffer
;
2005 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
2006 Bytes
= (UINTN
)MaxReceiveFisSize
;
2008 Status
= PciIo
->Map (
2010 EfiPciIoOperationBusMasterCommonBuffer
,
2014 &AhciRegisters
->MapRFis
2017 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
2019 // Map error or unable to map the whole RFis buffer into a contiguous region.
2021 Status
= EFI_OUT_OF_RESOURCES
;
2025 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
2027 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2029 Status
= EFI_DEVICE_ERROR
;
2032 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
2035 // Allocate memory for command list
2036 // Note that the implemenation is a single task model which only use a command list for all ports.
2039 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
2040 Status
= PciIo
->AllocateBuffer (
2043 EfiBootServicesData
,
2044 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2049 if (EFI_ERROR (Status
)) {
2051 // Free mapped resource.
2053 Status
= EFI_OUT_OF_RESOURCES
;
2057 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2059 AhciRegisters
->AhciCmdList
= Buffer
;
2060 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2061 Bytes
= (UINTN
)MaxCommandListSize
;
2063 Status
= PciIo
->Map (
2065 EfiPciIoOperationBusMasterCommonBuffer
,
2068 &AhciCmdListPciAddr
,
2069 &AhciRegisters
->MapCmdList
2072 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2074 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2076 Status
= EFI_OUT_OF_RESOURCES
;
2080 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2082 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2084 Status
= EFI_DEVICE_ERROR
;
2087 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2090 // Allocate memory for command table
2091 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2094 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2096 Status
= PciIo
->AllocateBuffer (
2099 EfiBootServicesData
,
2100 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2105 if (EFI_ERROR (Status
)) {
2107 // Free mapped resource.
2109 Status
= EFI_OUT_OF_RESOURCES
;
2113 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2115 AhciRegisters
->AhciCommandTable
= Buffer
;
2116 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2117 Bytes
= (UINTN
)MaxCommandTableSize
;
2119 Status
= PciIo
->Map (
2121 EfiPciIoOperationBusMasterCommonBuffer
,
2124 &AhciCommandTablePciAddr
,
2125 &AhciRegisters
->MapCommandTable
2128 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2130 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2132 Status
= EFI_OUT_OF_RESOURCES
;
2136 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2138 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2140 Status
= EFI_DEVICE_ERROR
;
2143 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2147 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2152 AhciRegisters
->MapCommandTable
2157 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2158 AhciRegisters
->AhciCommandTable
2163 AhciRegisters
->MapCmdList
2168 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2169 AhciRegisters
->AhciCmdList
2174 AhciRegisters
->MapRFis
2179 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2180 AhciRegisters
->AhciRFis
2187 Initialize ATA host controller at AHCI mode.
2189 The function is designed to initialize ATA host controller.
2191 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2196 AhciModeInitialization (
2197 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2201 EFI_PCI_IO_PROTOCOL
*PciIo
;
2202 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2204 UINT8 MaxPortNumber
;
2205 UINT32 PortImplementBitMap
;
2207 EFI_AHCI_REGISTERS
*AhciRegisters
;
2213 EFI_IDENTIFY_DATA Buffer
;
2214 EFI_ATA_DEVICE_TYPE DeviceType
;
2215 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2216 EFI_ATA_TRANSFER_MODE TransferMode
;
2217 UINT32 PhyDetectDelay
;
2219 if (Instance
== NULL
) {
2220 return EFI_INVALID_PARAMETER
;
2223 PciIo
= Instance
->PciIo
;
2224 IdeInit
= Instance
->IdeControllerInit
;
2226 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2228 if (EFI_ERROR (Status
)) {
2229 return EFI_DEVICE_ERROR
;
2233 // Enable AE before accessing any AHCI registers
2235 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2238 // Collect AHCI controller information
2240 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2243 // Get the number of command slots per port supported by this HBA.
2245 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2248 // Get the bit map of those ports exposed by this HBA.
2249 // It indicates which ports that the HBA supports are available for software to use.
2251 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2253 AhciRegisters
= &Instance
->AhciRegisters
;
2254 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2256 if (EFI_ERROR (Status
)) {
2257 return EFI_OUT_OF_RESOURCES
;
2260 for (Port
= 0; Port
< EFI_AHCI_MAX_PORTS
; Port
++) {
2261 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2263 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2265 if ((MaxPortNumber
--) == 0) {
2267 // Should never be here.
2273 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2276 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2278 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2279 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2280 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2281 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2282 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2284 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2285 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2286 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2287 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2288 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2290 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2291 Data
= AhciReadReg (PciIo
, Offset
);
2292 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2293 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2296 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2297 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2301 // Disable aggressive power management.
2303 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2304 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2306 // Disable the reporting of the corresponding interrupt to system software.
2308 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2309 AhciAndReg (PciIo
, Offset
, 0);
2312 // Now inform the IDE Controller Init Module.
2314 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2317 // Enable FIS Receive DMA engine for the first D2H FIS.
2319 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2320 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2321 Status
= AhciWaitMmioSet (
2324 EFI_AHCI_PORT_CMD_FR
,
2325 EFI_AHCI_PORT_CMD_FR
,
2326 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2328 if (EFI_ERROR (Status
)) {
2333 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2334 // It's the requirment from SATA1.0a spec section 5.2.
2336 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2337 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2339 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2340 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2344 MicroSecondDelay (1000);
2346 } while (PhyDetectDelay
> 0);
2348 if (PhyDetectDelay
== 0) {
2350 // No device detected at this port.
2351 // Clear PxCMD.SUD for those ports at which there are no device present.
2353 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2354 AhciAndReg (PciIo
, Offset
, (UINT32
) ~(EFI_AHCI_PORT_CMD_SUD
));
2359 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2360 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2362 PhyDetectDelay
= 16 * 1000;
2364 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2365 if (AhciReadReg(PciIo
, Offset
) != 0) {
2366 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2368 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2370 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2375 MicroSecondDelay (1000);
2377 } while (PhyDetectDelay
> 0);
2379 if (PhyDetectDelay
== 0) {
2384 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2386 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2387 Status
= AhciWaitMmioSet (
2392 EFI_TIMER_PERIOD_SECONDS(16)
2394 if (EFI_ERROR (Status
)) {
2398 Data
= AhciReadReg (PciIo
, Offset
);
2399 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2400 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2402 if (EFI_ERROR (Status
)) {
2406 DeviceType
= EfiIdeCdrom
;
2407 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2408 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2410 if (EFI_ERROR (Status
)) {
2411 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2415 DeviceType
= EfiIdeHarddisk
;
2419 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2420 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2423 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2425 if ((DeviceType
== EfiIdeHarddisk
) && PcdGetBool (PcdAtaSmartEnable
)) {
2426 AhciAtaSmartSupport (
2437 // Submit identify data to IDE controller init driver
2439 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2442 // Now start to config ide device parameter and transfer mode.
2444 Status
= IdeInit
->CalculateMode (
2450 if (EFI_ERROR (Status
)) {
2451 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2456 // Set best supported PIO mode on this IDE device
2458 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2459 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2461 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2464 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2467 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2468 // be set together. Only one DMA mode can be set to a device. If setting
2469 // DMA mode operation fails, we can continue moving on because we only use
2470 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2472 if (SupportedModes
->UdmaMode
.Valid
) {
2473 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2474 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2475 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2476 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2477 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2480 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2481 if (EFI_ERROR (Status
)) {
2482 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2487 // Found a ATA or ATAPI device, add it into the device list.
2489 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2490 if (DeviceType
== EfiIdeHarddisk
) {
2491 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));