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_BAD_BUFFER_SIZE
;
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_BAD_BUFFER_SIZE
;
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_CLO
);
1281 EFI_AHCI_PORT_CMD_CLO
,
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
;
1820 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1821 return EFI_INVALID_PARAMETER
;
1824 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1825 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1826 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1830 AtaCommandBlock
.AtaFeatures
= 0x00;
1832 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1833 // determine how many data should be transferred.
1835 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1836 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1838 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1839 Buffer
= Packet
->InDataBuffer
;
1840 Length
= Packet
->InTransferLength
;
1843 Buffer
= Packet
->OutDataBuffer
;
1844 Length
= Packet
->OutTransferLength
;
1849 Status
= AhciNonDataTransfer (
1862 Status
= AhciPioTransfer (
1882 Allocate transfer-related data struct which is used at AHCI mode.
1884 @param PciIo The PCI IO protocol instance.
1885 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1890 AhciCreateTransferDescriptor (
1891 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1892 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1900 UINT8 MaxPortNumber
;
1901 UINT8 MaxCommandSlotNumber
;
1902 BOOLEAN Support64Bit
;
1903 UINT64 MaxReceiveFisSize
;
1904 UINT64 MaxCommandListSize
;
1905 UINT64 MaxCommandTableSize
;
1906 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1907 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1908 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1912 // Collect AHCI controller information
1914 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1915 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1917 // Get the number of command slots per port supported by this HBA.
1919 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1920 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1922 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1923 Status
= PciIo
->AllocateBuffer (
1926 EfiBootServicesData
,
1927 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1932 if (EFI_ERROR (Status
)) {
1933 return EFI_OUT_OF_RESOURCES
;
1936 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1938 AhciRegisters
->AhciRFis
= Buffer
;
1939 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1940 Bytes
= (UINTN
)MaxReceiveFisSize
;
1942 Status
= PciIo
->Map (
1944 EfiPciIoOperationBusMasterCommonBuffer
,
1948 &AhciRegisters
->MapRFis
1951 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1953 // Map error or unable to map the whole RFis buffer into a contiguous region.
1955 Status
= EFI_OUT_OF_RESOURCES
;
1959 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1961 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1963 Status
= EFI_DEVICE_ERROR
;
1966 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1969 // Allocate memory for command list
1970 // Note that the implemenation is a single task model which only use a command list for all ports.
1973 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1974 Status
= PciIo
->AllocateBuffer (
1977 EfiBootServicesData
,
1978 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
1983 if (EFI_ERROR (Status
)) {
1985 // Free mapped resource.
1987 Status
= EFI_OUT_OF_RESOURCES
;
1991 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
1993 AhciRegisters
->AhciCmdList
= Buffer
;
1994 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
1995 Bytes
= (UINTN
)MaxCommandListSize
;
1997 Status
= PciIo
->Map (
1999 EfiPciIoOperationBusMasterCommonBuffer
,
2002 &AhciCmdListPciAddr
,
2003 &AhciRegisters
->MapCmdList
2006 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2008 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2010 Status
= EFI_OUT_OF_RESOURCES
;
2014 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2016 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2018 Status
= EFI_DEVICE_ERROR
;
2021 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2024 // Allocate memory for command table
2025 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2028 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2030 Status
= PciIo
->AllocateBuffer (
2033 EfiBootServicesData
,
2034 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2039 if (EFI_ERROR (Status
)) {
2041 // Free mapped resource.
2043 Status
= EFI_OUT_OF_RESOURCES
;
2047 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2049 AhciRegisters
->AhciCommandTable
= Buffer
;
2050 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2051 Bytes
= (UINTN
)MaxCommandTableSize
;
2053 Status
= PciIo
->Map (
2055 EfiPciIoOperationBusMasterCommonBuffer
,
2058 &AhciCommandTablePciAddr
,
2059 &AhciRegisters
->MapCommandTable
2062 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2064 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2066 Status
= EFI_OUT_OF_RESOURCES
;
2070 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2072 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2074 Status
= EFI_DEVICE_ERROR
;
2077 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2081 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2086 AhciRegisters
->MapCommandTable
2091 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2092 AhciRegisters
->AhciCommandTable
2097 AhciRegisters
->MapCmdList
2102 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2103 AhciRegisters
->AhciCmdList
2108 AhciRegisters
->MapRFis
2113 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2114 AhciRegisters
->AhciRFis
2121 Initialize ATA host controller at AHCI mode.
2123 The function is designed to initialize ATA host controller.
2125 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2130 AhciModeInitialization (
2131 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2135 EFI_PCI_IO_PROTOCOL
*PciIo
;
2136 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2138 UINT8 MaxPortNumber
;
2139 UINT32 PortImplementBitMap
;
2140 UINT8 MaxCommandSlotNumber
;
2141 BOOLEAN Support64Bit
;
2143 EFI_AHCI_REGISTERS
*AhciRegisters
;
2149 EFI_IDENTIFY_DATA Buffer
;
2150 EFI_ATA_DEVICE_TYPE DeviceType
;
2151 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2152 EFI_ATA_TRANSFER_MODE TransferMode
;
2153 UINT32 PhyDetectDelay
;
2155 if (Instance
== NULL
) {
2156 return EFI_INVALID_PARAMETER
;
2159 PciIo
= Instance
->PciIo
;
2160 IdeInit
= Instance
->IdeControllerInit
;
2162 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2164 if (EFI_ERROR (Status
)) {
2165 return EFI_DEVICE_ERROR
;
2169 // Enable AE before accessing any AHCI registers
2171 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2174 // Collect AHCI controller information
2176 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2179 // Get the number of command slots per port supported by this HBA.
2181 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
2182 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2183 Support64Bit
= (BOOLEAN
) (((Capability
& EFI_AHCI_CAP_S64A
) != 0) ? TRUE
: FALSE
);
2186 // Get the bit map of those ports exposed by this HBA.
2187 // It indicates which ports that the HBA supports are available for software to use.
2189 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2191 AhciRegisters
= &Instance
->AhciRegisters
;
2192 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2194 if (EFI_ERROR (Status
)) {
2195 return EFI_OUT_OF_RESOURCES
;
2198 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
2199 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2200 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2203 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2205 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2206 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2207 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2208 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2209 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2211 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2212 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2213 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2214 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2215 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2217 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2218 Data
= AhciReadReg (PciIo
, Offset
);
2219 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2220 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2223 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2224 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2228 // Disable aggressive power management.
2230 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2231 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2233 // Disable the reporting of the corresponding interrupt to system software.
2235 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2236 AhciAndReg (PciIo
, Offset
, 0);
2239 // Now inform the IDE Controller Init Module.
2241 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2244 // Enable FIS Receive DMA engine for the first D2H FIS.
2246 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2247 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2248 Status
= AhciWaitMemSet (
2251 EFI_AHCI_PORT_CMD_FR
,
2252 EFI_AHCI_PORT_CMD_FR
,
2253 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2255 if (EFI_ERROR (Status
)) {
2260 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2261 // It's the requirment from SATA1.0a spec section 5.2.
2263 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2264 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2266 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2267 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2271 MicroSecondDelay (1000);
2273 } while (PhyDetectDelay
> 0);
2275 if (PhyDetectDelay
== 0) {
2277 // No device detected at this port.
2283 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2284 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2286 PhyDetectDelay
= 16 * 1000;
2288 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2289 if (AhciReadReg(PciIo
, Offset
) != 0) {
2290 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2292 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2294 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2299 MicroSecondDelay (1000);
2301 } while (PhyDetectDelay
> 0);
2303 if (PhyDetectDelay
== 0) {
2308 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2310 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2311 Status
= AhciWaitMemSet (
2316 EFI_TIMER_PERIOD_SECONDS(16)
2318 if (EFI_ERROR (Status
)) {
2322 Data
= AhciReadReg (PciIo
, Offset
);
2323 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2324 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2326 if (EFI_ERROR (Status
)) {
2330 DeviceType
= EfiIdeCdrom
;
2331 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2332 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2334 if (EFI_ERROR (Status
)) {
2335 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2339 DeviceType
= EfiIdeHarddisk
;
2343 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2344 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2347 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2349 if (DeviceType
== EfiIdeHarddisk
) {
2350 AhciAtaSmartSupport (
2361 // Submit identify data to IDE controller init driver
2363 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2366 // Now start to config ide device parameter and transfer mode.
2368 Status
= IdeInit
->CalculateMode (
2374 if (EFI_ERROR (Status
)) {
2375 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2380 // Set best supported PIO mode on this IDE device
2382 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2383 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2385 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2388 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2391 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2392 // be set together. Only one DMA mode can be set to a device. If setting
2393 // DMA mode operation fails, we can continue moving on because we only use
2394 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2396 if (SupportedModes
->UdmaMode
.Valid
) {
2397 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2398 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2399 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2400 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2401 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2404 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2405 if (EFI_ERROR (Status
)) {
2406 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2411 // Found a ATA or ATAPI device, add it into the device list.
2413 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2414 if (DeviceType
== EfiIdeHarddisk
) {
2415 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));