2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010 - 2011, 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 memory set to the test value.
138 @param PciIo The PCI IO protocol instance.
139 @param Offset The memory 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.
144 @retval EFI_DEVICE_ERROR The memory is not set.
145 @retval EFI_TIMEOUT The memory setting is time out.
146 @retval EFI_SUCCESS The memory is correct set.
152 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
162 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
165 Value
= AhciReadReg (PciIo
, Offset
) & MaskValue
;
167 if (Value
== TestValue
) {
172 // Stall for 100 microseconds.
174 MicroSecondDelay (100);
184 return EFI_DEVICE_ERROR
;
188 Check the memory status to the test value.
190 @param[in] PciIo The PCI IO protocol instance.
191 @param[in] Offset The memory address to test.
192 @param[in] MaskValue The mask value of memory.
193 @param[in] TestValue The test value of memory.
194 @param[in, out] RetryTimes The retry times value for waitting memory set.
196 @retval EFI_NOTREADY The memory is not set.
197 @retval EFI_TIMEOUT The memory setting retry times out.
198 @retval EFI_SUCCESS The memory is correct set.
204 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
208 IN OUT UINTN
*RetryTimes
215 Value
= AhciReadReg (PciIo
, Offset
) & MaskValue
;
217 if (Value
== TestValue
) {
221 if ((*RetryTimes
) == 0) {
224 return EFI_NOT_READY
;
229 Check if the device is still on port. It also checks if the AHCI controller
230 supports the address and data count will be transferred.
232 @param PciIo The PCI IO protocol instance.
233 @param Port The number of port.
235 @retval EFI_SUCCESS The device is attached to port and the transfer data is
236 supported by AHCI controller.
237 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
239 @retval EFI_NOT_READY The physical communication between AHCI controller and device
245 AhciCheckDeviceStatus (
246 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
253 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
255 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
257 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
261 return EFI_NOT_READY
;
266 Clear the port interrupt and error status. It will also clear
267 HBA interrupt status.
269 @param PciIo The PCI IO protocol instance.
270 @param Port The number of port.
275 AhciClearPortStatus (
276 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
283 // Clear any error status
285 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
286 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
289 // Clear any port interrupt status
291 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
292 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
295 // Clear any HBA interrupt status
297 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
301 This function is used to dump the Status Registers and if there is ERR bit set
302 in the Status Register, the Error Register's value is also be dumped.
304 @param PciIo The PCI IO protocol instance.
305 @param Port The number of port.
306 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
312 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
314 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
320 ASSERT (PciIo
!= NULL
);
322 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
323 Data
= AhciReadReg (PciIo
, Offset
);
325 if (AtaStatusBlock
!= NULL
) {
326 ZeroMem (AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
328 AtaStatusBlock
->AtaStatus
= (UINT8
)Data
;
329 if ((AtaStatusBlock
->AtaStatus
& BIT0
) != 0) {
330 AtaStatusBlock
->AtaError
= (UINT8
)(Data
>> 8);
337 Enable the FIS running for giving port.
339 @param PciIo The PCI IO protocol instance.
340 @param Port The number of port.
341 @param Timeout The timeout value of enabling FIS.
343 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
344 @retval EFI_TIMEOUT The FIS enable setting is time out.
345 @retval EFI_SUCCESS The FIS enable successfully.
350 AhciEnableFisReceive (
351 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
358 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
359 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
361 return AhciWaitMemSet (
364 EFI_AHCI_PORT_CMD_FR
,
365 EFI_AHCI_PORT_CMD_FR
,
371 Disable the FIS running for giving port.
373 @param PciIo The PCI IO protocol instance.
374 @param Port The number of port.
375 @param Timeout The timeout value of disabling FIS.
377 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
378 @retval EFI_TIMEOUT The FIS disable setting is time out.
379 @retval EFI_UNSUPPORTED The port is in running state.
380 @retval EFI_SUCCESS The FIS disable successfully.
385 AhciDisableFisReceive (
386 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
394 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
395 Data
= AhciReadReg (PciIo
, Offset
);
398 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
400 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
401 return EFI_UNSUPPORTED
;
405 // Check if the Fis receive DMA engine for the port is running.
407 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
411 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
413 return AhciWaitMemSet (
416 EFI_AHCI_PORT_CMD_FR
,
425 Build the command list, command table and prepare the fis receiver.
427 @param PciIo The PCI IO protocol instance.
428 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
429 @param Port The number of port.
430 @param PortMultiplier The timeout value of stop.
431 @param CommandFis The control fis will be used for the transfer.
432 @param CommandList The command list will be used for the transfer.
433 @param AtapiCommand The atapi command will be used for the transfer.
434 @param AtapiCommandLength The length of the atapi command.
435 @param CommandSlotNumber The command slot will be used for the transfer.
436 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
437 @param DataLength The data count to be transferred.
443 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
444 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
446 IN UINT8 PortMultiplier
,
447 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
448 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
449 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
450 IN UINT8 AtapiCommandLength
,
451 IN UINT8 CommandSlotNumber
,
452 IN OUT VOID
*DataPhysicalAddr
,
467 PrdtNumber
= (DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1) / EFI_AHCI_MAX_DATA_PER_PRDT
;
470 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
471 // It also limits that the maximum amount of the PRDT entry in the command table
474 ASSERT (PrdtNumber
<= 65535);
476 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
478 BaseAddr
= Data64
.Uint64
;
480 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
482 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
484 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
486 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
488 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
489 if (AtapiCommand
!= NULL
) {
491 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
496 CommandList
->AhciCmdA
= 1;
497 CommandList
->AhciCmdP
= 1;
498 CommandList
->AhciCmdC
= (DataLength
== 0) ? 1 : 0;
500 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
502 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
505 RemainedData
= (UINTN
) DataLength
;
506 MemAddr
= (UINTN
) DataPhysicalAddr
;
507 CommandList
->AhciCmdPrdtl
= (UINT32
)PrdtNumber
;
509 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
510 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
511 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
513 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
516 Data64
.Uint64
= (UINT64
)MemAddr
;
517 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
518 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
519 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
520 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
524 // Set the last PRDT to Interrupt On Complete
526 if (PrdtNumber
> 0) {
527 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
531 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
533 sizeof (EFI_AHCI_COMMAND_LIST
)
536 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
537 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
538 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
539 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
546 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
547 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
552 AhciBuildCommandFis (
553 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
554 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
557 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
559 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
561 // Indicator it's a command
563 CmdFis
->AhciCFisCmdInd
= 0x1;
564 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
566 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
567 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
569 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
570 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
572 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
573 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
575 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
576 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
578 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
579 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
581 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
585 Start a PIO data transfer on specific port.
587 @param[in] PciIo The PCI IO protocol instance.
588 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
589 @param[in] Port The number of port.
590 @param[in] PortMultiplier The timeout value of stop.
591 @param[in] AtapiCommand The atapi command will be used for the
593 @param[in] AtapiCommandLength The length of the atapi command.
594 @param[in] Read The transfer direction.
595 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
596 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
597 @param[in, out] MemoryAddr The pointer to the data buffer.
598 @param[in] DataCount The data count to be transferred.
599 @param[in] Timeout The timeout value of non data transfer.
600 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
601 used by non-blocking mode.
603 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
604 @retval EFI_TIMEOUT The operation is time out.
605 @retval EFI_UNSUPPORTED The device is not ready for transfer.
606 @retval EFI_SUCCESS The PIO data transfer executes successfully.
612 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
613 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
615 IN UINT8 PortMultiplier
,
616 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
617 IN UINT8 AtapiCommandLength
,
619 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
620 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
621 IN OUT VOID
*MemoryAddr
,
624 IN ATA_NONBLOCK_TASK
*Task
631 EFI_PHYSICAL_ADDRESS PhyAddr
;
634 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
636 EFI_AHCI_COMMAND_FIS CFis
;
637 EFI_AHCI_COMMAND_LIST CmdList
;
640 Flag
= EfiPciIoOperationBusMasterWrite
;
642 Flag
= EfiPciIoOperationBusMasterRead
;
646 // construct command list and command table with pci bus address
648 MapLength
= DataCount
;
649 Status
= PciIo
->Map (
658 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
659 return EFI_OUT_OF_RESOURCES
;
663 // Package read needed
665 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
667 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
669 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
670 CmdList
.AhciCmdW
= Read
? 0 : 1;
682 (VOID
*)(UINTN
)PhyAddr
,
686 Status
= AhciStartCommand (
692 if (EFI_ERROR (Status
)) {
697 // Check the status and wait the driver sending data
699 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
701 // Wait device sends the PIO setup fis before data transfer
703 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
705 Value
= *(volatile UINT32
*) (FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
);
707 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_PIO_SETUP
) {
712 // Stall for 100 microseconds.
714 MicroSecondDelay(100);
720 Status
= EFI_TIMEOUT
;
725 // Wait for command compelte
727 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
728 Status
= AhciWaitMemSet (
736 if (EFI_ERROR (Status
)) {
740 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
741 Status
= AhciWaitMemSet (
744 EFI_AHCI_PORT_IS_PSS
,
745 EFI_AHCI_PORT_IS_PSS
,
748 if (EFI_ERROR (Status
)) {
759 AhciDisableFisReceive (
770 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
776 Start a DMA data transfer on specific port
778 @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
779 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
780 @param[in] Port The number of port.
781 @param[in] PortMultiplier The timeout value of stop.
782 @param[in] AtapiCommand The atapi command will be used for the
784 @param[in] AtapiCommandLength The length of the atapi command.
785 @param[in] Read The transfer direction.
786 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
787 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
788 @param[in, out] MemoryAddr The pointer to the data buffer.
789 @param[in] DataCount The data count to be transferred.
790 @param[in] Timeout The timeout value of non data transfer.
791 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
792 used by non-blocking mode.
794 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
795 @retval EFI_TIMEOUT The operation is time out.
796 @retval EFI_UNSUPPORTED The device is not ready for transfer.
797 @retval EFI_SUCCESS The DMA data transfer executes successfully.
803 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
,
804 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
806 IN UINT8 PortMultiplier
,
807 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
808 IN UINT8 AtapiCommandLength
,
810 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
811 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
812 IN OUT VOID
*MemoryAddr
,
815 IN ATA_NONBLOCK_TASK
*Task
820 EFI_PHYSICAL_ADDRESS PhyAddr
;
823 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
824 EFI_AHCI_COMMAND_FIS CFis
;
825 EFI_AHCI_COMMAND_LIST CmdList
;
827 EFI_PCI_IO_PROTOCOL
*PciIo
;
831 PciIo
= Instance
->PciIo
;
834 return EFI_INVALID_PARAMETER
;
838 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
840 // Delay 100us to simulate the blocking time out checking.
842 while ((Task
== NULL
) && (!IsListEmpty (&Instance
->NonBlockingTaskList
))) {
843 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
844 AsyncNonBlockingTransferRoutine (NULL
, Instance
);
845 gBS
->RestoreTPL (OldTpl
);
849 MicroSecondDelay (100);
852 if ((Task
== NULL
) || ((Task
!= NULL
) && (!Task
->IsStart
))) {
854 // Mark the Task to indicate that it has been started.
857 Task
->IsStart
= TRUE
;
858 Task
->RetryTimes
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
861 Flag
= EfiPciIoOperationBusMasterWrite
;
863 Flag
= EfiPciIoOperationBusMasterRead
;
867 // Construct command list and command table with pci bus address.
869 MapLength
= DataCount
;
870 Status
= PciIo
->Map (
879 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
880 return EFI_OUT_OF_RESOURCES
;
887 // Package read needed
889 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
891 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
893 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
894 CmdList
.AhciCmdW
= Read
? 0 : 1;
906 (VOID
*)(UINTN
)PhyAddr
,
910 Status
= AhciStartCommand (
916 if (EFI_ERROR (Status
)) {
921 // Wait device PRD processed
923 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
924 Status
= AhciWaitMemSet (
927 EFI_AHCI_PORT_IS_DPS
,
928 EFI_AHCI_PORT_IS_DPS
,
932 if (EFI_ERROR (Status
)) {
938 // Wait for command compelte
940 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
945 Status
= AhciCheckMemSet (
950 (UINTN
*) (&Task
->RetryTimes
)
953 Status
= AhciWaitMemSet (
962 if (EFI_ERROR (Status
)) {
966 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
972 Status
= AhciCheckMemSet (
975 EFI_AHCI_PORT_IS_DHRS
,
976 EFI_AHCI_PORT_IS_DHRS
,
977 (UINTN
*) (&Task
->RetryTimes
)
980 Status
= AhciWaitMemSet (
983 EFI_AHCI_PORT_IS_DHRS
,
984 EFI_AHCI_PORT_IS_DHRS
,
989 if (EFI_ERROR (Status
)) {
995 // For Blocking mode, the command should be stopped, the Fis should be disabled
996 // and the PciIo should be unmapped.
997 // For non-blocking mode, only when a error is happened (if the return status is
998 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
999 // context cleanup, then set the packet's Asb status.
1002 ((Task
!= NULL
) && (Status
!= EFI_NOT_READY
))
1010 AhciDisableFisReceive (
1018 (Task
!= NULL
) ? Task
->Map
: Map
1022 Task
->Packet
->Asb
->AtaStatus
= 0x01;
1026 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1031 Start a non data transfer on specific port.
1033 @param[in] PciIo The PCI IO protocol instance.
1034 @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1035 @param[in] Port The number of port.
1036 @param[in] PortMultiplier The timeout value of stop.
1037 @param[in] AtapiCommand The atapi command will be used for the
1039 @param[in] AtapiCommandLength The length of the atapi command.
1040 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
1041 @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
1042 @param[in] Timeout The timeout value of non data transfer.
1043 @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
1044 used by non-blocking mode.
1046 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
1047 @retval EFI_TIMEOUT The operation is time out.
1048 @retval EFI_UNSUPPORTED The device is not ready for transfer.
1049 @retval EFI_SUCCESS The non data transfer executes successfully.
1054 AhciNonDataTransfer (
1055 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1056 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1058 IN UINT8 PortMultiplier
,
1059 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
1060 IN UINT8 AtapiCommandLength
,
1061 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
1062 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
1064 IN ATA_NONBLOCK_TASK
*Task
1073 EFI_AHCI_COMMAND_FIS CFis
;
1074 EFI_AHCI_COMMAND_LIST CmdList
;
1077 // Package read needed
1079 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
1081 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
1083 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
1099 Status
= AhciStartCommand (
1105 if (EFI_ERROR (Status
)) {
1110 // Wait device sends the Response Fis
1112 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1114 // Wait device sends the PIO setup fis before data transfer
1116 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1118 Value
= *(volatile UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1120 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1125 // Stall for 100 microseconds.
1127 MicroSecondDelay(100);
1130 } while (Delay
> 0);
1133 Status
= EFI_TIMEOUT
;
1137 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1139 Status
= AhciWaitMemSet (
1154 AhciDisableFisReceive (
1160 AhciDumpPortStatus (PciIo
, Port
, AtaStatusBlock
);
1166 Stop command running for giving port
1168 @param PciIo The PCI IO protocol instance.
1169 @param Port The number of port.
1170 @param Timeout The timeout value of stop.
1172 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
1173 @retval EFI_TIMEOUT The operation is time out.
1174 @retval EFI_SUCCESS The command stop successfully.
1180 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1188 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1189 Data
= AhciReadReg (PciIo
, Offset
);
1191 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1195 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1196 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1199 return AhciWaitMemSet (
1202 EFI_AHCI_PORT_CMD_CR
,
1209 Start command for give slot on specific port.
1211 @param PciIo The PCI IO protocol instance.
1212 @param Port The number of port.
1213 @param CommandSlot The number of Command Slot.
1214 @param Timeout The timeout value of start.
1216 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1217 @retval EFI_TIMEOUT The operation is time out.
1218 @retval EFI_SUCCESS The command start successfully.
1224 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1226 IN UINT8 CommandSlot
,
1239 // Collect AHCI controller information
1241 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1243 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1245 AhciClearPortStatus (
1250 Status
= AhciEnableFisReceive (
1256 if (EFI_ERROR (Status
)) {
1260 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1261 PortStatus
= AhciReadReg (PciIo
, Offset
);
1264 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1265 StartCmd
= AhciReadReg (PciIo
, Offset
);
1266 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1267 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1270 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1271 PortTfd
= AhciReadReg (PciIo
, Offset
);
1273 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1274 if ((Capability
& BIT24
) != 0) {
1275 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1276 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_COL
);
1281 EFI_AHCI_PORT_CMD_COL
,
1288 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1289 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1292 // Setting the command
1294 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1295 AhciAndReg (PciIo
, Offset
, 0);
1296 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1298 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1299 AhciAndReg (PciIo
, Offset
, 0);
1300 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1308 @param PciIo The PCI IO protocol instance.
1309 @param Port The number of port.
1310 @param Timeout The timeout value of reset.
1312 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1313 @retval EFI_TIMEOUT The reset operation is time out.
1314 @retval EFI_SUCCESS The port reset successfully.
1320 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1328 AhciClearPortStatus (PciIo
, Port
);
1330 AhciStopCommand (PciIo
, Port
, Timeout
);
1332 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1334 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1336 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1338 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1341 // wait 5 millisecond before de-assert DET
1343 MicroSecondDelay (5000);
1345 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1348 // wait 5 millisecond before de-assert DET
1350 MicroSecondDelay (5000);
1353 // Wait for communication to be re-established
1355 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1356 Status
= AhciWaitMemSet (
1359 EFI_AHCI_PORT_SSTS_DET_MASK
,
1360 EFI_AHCI_PORT_SSTS_DET_PCE
,
1364 if (EFI_ERROR (Status
)) {
1368 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1369 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1377 @param PciIo The PCI IO protocol instance.
1378 @param Timeout The timeout value of reset.
1380 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1381 @retval EFI_TIMEOUT The reset operation is time out.
1382 @retval EFI_SUCCESS AHCI controller is reset successfully.
1388 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1396 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1398 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1400 Status
= EFI_TIMEOUT
;
1402 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1405 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1407 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1412 // Stall for 100 microseconds.
1414 MicroSecondDelay(100);
1417 } while (Delay
> 0);
1427 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1429 @param PciIo The PCI IO protocol instance.
1430 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1431 @param Port The number of port.
1432 @param PortMultiplier The timeout value of stop.
1433 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1435 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1436 @retval Others Fail to get return status data.
1441 AhciAtaSmartReturnStatusCheck (
1442 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1443 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1445 IN UINT8 PortMultiplier
,
1446 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1450 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1456 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1458 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1459 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1460 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1461 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1464 // Send S.M.A.R.T Read Return Status command to device
1466 Status
= AhciNonDataTransfer (
1470 (UINT8
)PortMultiplier
,
1479 if (EFI_ERROR (Status
)) {
1480 return EFI_DEVICE_ERROR
;
1483 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1485 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1487 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1488 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1489 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1491 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1493 // The threshold exceeded condition is not detected by the device
1495 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1497 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1499 // The threshold exceeded condition is detected by the device
1501 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1509 Enable SMART command of the disk if supported.
1511 @param PciIo The PCI IO protocol instance.
1512 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1513 @param Port The number of port.
1514 @param PortMultiplier The timeout value of stop.
1515 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1516 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1521 AhciAtaSmartSupport (
1522 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1523 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1525 IN UINT8 PortMultiplier
,
1526 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1527 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1531 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1534 // Detect if the device supports S.M.A.R.T.
1536 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1538 // S.M.A.R.T is not supported by the device
1540 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1541 Port
, PortMultiplier
));
1544 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1546 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1547 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1549 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1550 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1551 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1552 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1555 // Send S.M.A.R.T Enable command to device
1557 Status
= AhciNonDataTransfer (
1561 (UINT8
)PortMultiplier
,
1571 if (!EFI_ERROR (Status
)) {
1573 // Send S.M.A.R.T AutoSave command to device
1575 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1577 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1578 AtaCommandBlock
.AtaFeatures
= 0xD2;
1579 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1580 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1581 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1583 Status
= AhciNonDataTransfer (
1587 (UINT8
)PortMultiplier
,
1596 if (!EFI_ERROR (Status
)) {
1597 Status
= AhciAtaSmartReturnStatusCheck (
1601 (UINT8
)PortMultiplier
,
1607 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1608 Port
, PortMultiplier
));
1615 Send Buffer cmd to specific device.
1617 @param PciIo The PCI IO protocol instance.
1618 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1619 @param Port The number of port.
1620 @param PortMultiplier The timeout value of stop.
1621 @param Buffer The data buffer to store IDENTIFY PACKET data.
1623 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1624 @retval EFI_TIMEOUT The operation is time out.
1625 @retval EFI_UNSUPPORTED The device is not ready for executing.
1626 @retval EFI_SUCCESS The cmd executes successfully.
1632 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1633 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1635 IN UINT8 PortMultiplier
,
1636 IN OUT EFI_IDENTIFY_DATA
*Buffer
1640 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1641 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1643 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1644 return EFI_INVALID_PARAMETER
;
1647 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1648 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1650 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1651 AtaCommandBlock
.AtaSectorCount
= 1;
1653 Status
= AhciPioTransfer (
1664 sizeof (EFI_IDENTIFY_DATA
),
1673 Send Buffer cmd to specific device.
1675 @param PciIo The PCI IO protocol instance.
1676 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1677 @param Port The number of port.
1678 @param PortMultiplier The timeout value of stop.
1679 @param Buffer The data buffer to store IDENTIFY PACKET data.
1681 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1682 @retval EFI_TIMEOUT The operation is time out.
1683 @retval EFI_UNSUPPORTED The device is not ready for executing.
1684 @retval EFI_SUCCESS The cmd executes successfully.
1689 AhciIdentifyPacket (
1690 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1691 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1693 IN UINT8 PortMultiplier
,
1694 IN OUT EFI_IDENTIFY_DATA
*Buffer
1698 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1699 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1701 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1702 return EFI_INVALID_PARAMETER
;
1705 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1706 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1708 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1709 AtaCommandBlock
.AtaSectorCount
= 1;
1711 Status
= AhciPioTransfer (
1722 sizeof (EFI_IDENTIFY_DATA
),
1731 Send SET FEATURE cmd on specific device.
1733 @param PciIo The PCI IO protocol instance.
1734 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1735 @param Port The number of port.
1736 @param PortMultiplier The timeout value of stop.
1737 @param Feature The data to send Feature register.
1738 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1740 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1741 @retval EFI_TIMEOUT The operation is time out.
1742 @retval EFI_UNSUPPORTED The device is not ready for executing.
1743 @retval EFI_SUCCESS The cmd executes successfully.
1748 AhciDeviceSetFeature (
1749 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1750 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1752 IN UINT8 PortMultiplier
,
1754 IN UINT32 FeatureSpecificData
1758 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1759 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1761 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1762 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1764 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1765 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1766 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1767 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1768 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1769 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1770 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1772 Status
= AhciNonDataTransfer (
1776 (UINT8
)PortMultiplier
,
1789 This function is used to send out ATAPI commands conforms to the Packet Command
1792 @param PciIo The PCI IO protocol instance.
1793 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1794 @param Port The number of port.
1795 @param PortMultiplier The number of port multiplier.
1796 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1798 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1799 and device sends data successfully.
1800 @retval EFI_DEVICE_ERROR the device failed to send data.
1805 AhciPacketCommandExecute (
1806 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1807 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1809 IN UINT8 PortMultiplier
,
1810 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1816 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1817 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1821 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1822 return EFI_INVALID_PARAMETER
;
1825 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1826 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1827 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1831 AtaCommandBlock
.AtaFeatures
= 0x00;
1833 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1834 // determine how many data should be transferred.
1836 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1837 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1839 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1840 Buffer
= Packet
->InDataBuffer
;
1841 Length
= Packet
->InTransferLength
;
1844 Buffer
= Packet
->OutDataBuffer
;
1845 Length
= Packet
->OutTransferLength
;
1850 Status
= AhciNonDataTransfer (
1864 // READ_CAPACITY cmd may execute failure. Retry 5 times
1866 if (((UINT8
*)Packet
->Cdb
)[0] == ATA_CMD_READ_CAPACITY
) {
1872 Status
= AhciPioTransfer (
1887 if (!EFI_ERROR (Status
)) {
1891 } while (Retry
!= 0);
1897 Allocate transfer-related data struct which is used at AHCI mode.
1899 @param PciIo The PCI IO protocol instance.
1900 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1905 AhciCreateTransferDescriptor (
1906 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1907 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1915 UINT8 MaxPortNumber
;
1916 UINT8 MaxCommandSlotNumber
;
1917 BOOLEAN Support64Bit
;
1918 UINT64 MaxReceiveFisSize
;
1919 UINT64 MaxCommandListSize
;
1920 UINT64 MaxCommandTableSize
;
1921 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1922 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1923 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1927 // Collect AHCI controller information
1929 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1930 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1932 // Get the number of command slots per port supported by this HBA.
1934 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1935 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1937 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1938 Status
= PciIo
->AllocateBuffer (
1941 EfiBootServicesData
,
1942 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1947 if (EFI_ERROR (Status
)) {
1948 return EFI_OUT_OF_RESOURCES
;
1951 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1953 AhciRegisters
->AhciRFis
= Buffer
;
1954 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1955 Bytes
= (UINTN
)MaxReceiveFisSize
;
1957 Status
= PciIo
->Map (
1959 EfiPciIoOperationBusMasterCommonBuffer
,
1963 &AhciRegisters
->MapRFis
1966 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1968 // Map error or unable to map the whole RFis buffer into a contiguous region.
1970 Status
= EFI_OUT_OF_RESOURCES
;
1974 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1976 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1978 Status
= EFI_DEVICE_ERROR
;
1981 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1984 // Allocate memory for command list
1985 // Note that the implemenation is a single task model which only use a command list for all ports.
1988 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1989 Status
= PciIo
->AllocateBuffer (
1992 EfiBootServicesData
,
1993 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
1998 if (EFI_ERROR (Status
)) {
2000 // Free mapped resource.
2002 Status
= EFI_OUT_OF_RESOURCES
;
2006 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
2008 AhciRegisters
->AhciCmdList
= Buffer
;
2009 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
2010 Bytes
= (UINTN
)MaxCommandListSize
;
2012 Status
= PciIo
->Map (
2014 EfiPciIoOperationBusMasterCommonBuffer
,
2017 &AhciCmdListPciAddr
,
2018 &AhciRegisters
->MapCmdList
2021 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2023 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2025 Status
= EFI_OUT_OF_RESOURCES
;
2029 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2031 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2033 Status
= EFI_DEVICE_ERROR
;
2036 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2039 // Allocate memory for command table
2040 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2043 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2045 Status
= PciIo
->AllocateBuffer (
2048 EfiBootServicesData
,
2049 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2054 if (EFI_ERROR (Status
)) {
2056 // Free mapped resource.
2058 Status
= EFI_OUT_OF_RESOURCES
;
2062 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2064 AhciRegisters
->AhciCommandTable
= Buffer
;
2065 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2066 Bytes
= (UINTN
)MaxCommandTableSize
;
2068 Status
= PciIo
->Map (
2070 EfiPciIoOperationBusMasterCommonBuffer
,
2073 &AhciCommandTablePciAddr
,
2074 &AhciRegisters
->MapCommandTable
2077 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2079 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2081 Status
= EFI_OUT_OF_RESOURCES
;
2085 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2087 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2089 Status
= EFI_DEVICE_ERROR
;
2092 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2096 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2101 AhciRegisters
->MapCommandTable
2106 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2107 AhciRegisters
->AhciCommandTable
2112 AhciRegisters
->MapCmdList
2117 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2118 AhciRegisters
->AhciCmdList
2123 AhciRegisters
->MapRFis
2128 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2129 AhciRegisters
->AhciRFis
2136 Initialize ATA host controller at AHCI mode.
2138 The function is designed to initialize ATA host controller.
2140 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2145 AhciModeInitialization (
2146 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2150 EFI_PCI_IO_PROTOCOL
*PciIo
;
2151 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2153 UINT8 MaxPortNumber
;
2154 UINT32 PortImplementBitMap
;
2155 UINT8 MaxCommandSlotNumber
;
2156 BOOLEAN Support64Bit
;
2158 EFI_AHCI_REGISTERS
*AhciRegisters
;
2164 EFI_IDENTIFY_DATA Buffer
;
2165 EFI_ATA_DEVICE_TYPE DeviceType
;
2166 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2167 EFI_ATA_TRANSFER_MODE TransferMode
;
2169 if (Instance
== NULL
) {
2170 return EFI_INVALID_PARAMETER
;
2173 PciIo
= Instance
->PciIo
;
2174 IdeInit
= Instance
->IdeControllerInit
;
2176 Status
= AhciReset (PciIo
, ATA_ATAPI_TIMEOUT
);
2178 if (EFI_ERROR (Status
)) {
2179 return EFI_DEVICE_ERROR
;
2183 // Enable AE before accessing any AHCI registers
2185 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2188 // Collect AHCI controller information
2190 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2193 // Get the number of command slots per port supported by this HBA.
2195 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2196 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
2199 // Get the bit map of those ports exposed by this HBA.
2200 // It indicates which ports that the HBA supports are available for software to use.
2202 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2203 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2205 AhciRegisters
= &Instance
->AhciRegisters
;
2206 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2208 if (EFI_ERROR (Status
)) {
2209 return EFI_OUT_OF_RESOURCES
;
2212 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
2213 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2215 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2216 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2217 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2218 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2221 // Single task envrionment, we only use one command table for all port
2223 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2225 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2226 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2227 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2228 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2230 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2231 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2233 if ((Capability
& EFI_AHCI_PORT_CMD_ASP
) != 0) {
2234 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2236 Data
= AhciReadReg (PciIo
, Offset
);
2237 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2238 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2241 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
|EFI_AHCI_PORT_CMD_COL
|EFI_AHCI_PORT_CMD_ST
));
2244 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2245 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_SCTL_IPM_MASK
));
2247 AhciAndReg (PciIo
, Offset
,(UINT32
) ~(EFI_AHCI_PORT_SCTL_IPM_PSD
));
2248 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_PSD
);
2250 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_SCTL_IPM_SSD
));
2251 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_SSD
);
2253 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2254 AhciAndReg (PciIo
, Offset
, 0);
2256 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2257 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
2261 // Stall for 100 milliseconds.
2263 MicroSecondDelay(100000);
2265 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2267 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
2268 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2270 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2271 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2277 // Found device in the port
2279 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
2280 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2282 Status
= AhciWaitMemSet (
2289 if (EFI_ERROR (Status
)) {
2294 // Now inform the IDE Controller Init Module.
2296 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2298 Data
= AhciReadReg (PciIo
, Offset
);
2300 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2301 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2303 if (EFI_ERROR (Status
)) {
2307 DeviceType
= EfiIdeCdrom
;
2308 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2309 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2311 if (EFI_ERROR (Status
)) {
2315 DeviceType
= EfiIdeHarddisk
;
2320 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2321 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2324 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2326 if (DeviceType
== EfiIdeHarddisk
) {
2327 AhciAtaSmartSupport (
2338 // Submit identify data to IDE controller init driver
2340 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2343 // Now start to config ide device parameter and transfer mode.
2345 Status
= IdeInit
->CalculateMode (
2351 if (EFI_ERROR (Status
)) {
2352 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2357 // Set best supported PIO mode on this IDE device
2359 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2360 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2362 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2365 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2368 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2369 // be set together. Only one DMA mode can be set to a device. If setting
2370 // DMA mode operation fails, we can continue moving on because we only use
2371 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2373 if (SupportedModes
->UdmaMode
.Valid
) {
2374 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2375 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2376 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2377 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2378 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2381 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2383 if (EFI_ERROR (Status
)) {
2384 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2388 // Found a ATA or ATAPI device, add it into the device list.
2390 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);