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
,
1395 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1397 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1399 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1402 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1404 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1409 // Stall for 100 microseconds.
1411 MicroSecondDelay(100);
1414 } while (Delay
> 0);
1424 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1426 @param PciIo The PCI IO protocol instance.
1427 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1428 @param Port The number of port.
1429 @param PortMultiplier The timeout value of stop.
1430 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1432 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1433 @retval Others Fail to get return status data.
1438 AhciAtaSmartReturnStatusCheck (
1439 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1440 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1442 IN UINT8 PortMultiplier
,
1443 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1447 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1453 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1455 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1456 AtaCommandBlock
.AtaFeatures
= ATA_SMART_RETURN_STATUS
;
1457 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1458 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1461 // Send S.M.A.R.T Read Return Status command to device
1463 Status
= AhciNonDataTransfer (
1467 (UINT8
)PortMultiplier
,
1476 if (EFI_ERROR (Status
)) {
1477 return EFI_DEVICE_ERROR
;
1480 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1482 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
1484 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
1485 LBAMid
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[5];
1486 LBAHigh
= ((UINT8
*)(UINTN
)(FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
))[6];
1488 if ((LBAMid
== 0x4f) && (LBAHigh
== 0xc2)) {
1490 // The threshold exceeded condition is not detected by the device
1492 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1494 } else if ((LBAMid
== 0xf4) && (LBAHigh
== 0x2c)) {
1496 // The threshold exceeded condition is detected by the device
1498 DEBUG ((EFI_D_INFO
, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1506 Enable SMART command of the disk if supported.
1508 @param PciIo The PCI IO protocol instance.
1509 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1510 @param Port The number of port.
1511 @param PortMultiplier The timeout value of stop.
1512 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1513 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1518 AhciAtaSmartSupport (
1519 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1520 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1522 IN UINT8 PortMultiplier
,
1523 IN EFI_IDENTIFY_DATA
*IdentifyData
,
1524 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
1528 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1531 // Detect if the device supports S.M.A.R.T.
1533 if ((IdentifyData
->AtaData
.command_set_supported_82
& 0x0001) != 0x0001) {
1535 // S.M.A.R.T is not supported by the device
1537 DEBUG ((EFI_D_INFO
, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1538 Port
, PortMultiplier
));
1541 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1543 if ((IdentifyData
->AtaData
.command_set_feature_enb_85
& 0x0001) != 0x0001) {
1544 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1546 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1547 AtaCommandBlock
.AtaFeatures
= ATA_SMART_ENABLE_OPERATION
;
1548 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1549 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1552 // Send S.M.A.R.T Enable command to device
1554 Status
= AhciNonDataTransfer (
1558 (UINT8
)PortMultiplier
,
1568 if (!EFI_ERROR (Status
)) {
1570 // Send S.M.A.R.T AutoSave command to device
1572 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1574 AtaCommandBlock
.AtaCommand
= ATA_CMD_SMART
;
1575 AtaCommandBlock
.AtaFeatures
= 0xD2;
1576 AtaCommandBlock
.AtaSectorCount
= 0xF1;
1577 AtaCommandBlock
.AtaCylinderLow
= ATA_CONSTANT_4F
;
1578 AtaCommandBlock
.AtaCylinderHigh
= ATA_CONSTANT_C2
;
1580 Status
= AhciNonDataTransfer (
1584 (UINT8
)PortMultiplier
,
1593 if (!EFI_ERROR (Status
)) {
1594 Status
= AhciAtaSmartReturnStatusCheck (
1598 (UINT8
)PortMultiplier
,
1604 DEBUG ((EFI_D_INFO
, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1605 Port
, PortMultiplier
));
1612 Send Buffer cmd to specific device.
1614 @param PciIo The PCI IO protocol instance.
1615 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1616 @param Port The number of port.
1617 @param PortMultiplier The timeout value of stop.
1618 @param Buffer The data buffer to store IDENTIFY PACKET data.
1620 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1621 @retval EFI_TIMEOUT The operation is time out.
1622 @retval EFI_UNSUPPORTED The device is not ready for executing.
1623 @retval EFI_SUCCESS The cmd executes successfully.
1629 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1630 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1632 IN UINT8 PortMultiplier
,
1633 IN OUT EFI_IDENTIFY_DATA
*Buffer
1637 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1638 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1640 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1641 return EFI_INVALID_PARAMETER
;
1644 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1645 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1647 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1648 AtaCommandBlock
.AtaSectorCount
= 1;
1650 Status
= AhciPioTransfer (
1661 sizeof (EFI_IDENTIFY_DATA
),
1670 Send Buffer cmd to specific device.
1672 @param PciIo The PCI IO protocol instance.
1673 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1674 @param Port The number of port.
1675 @param PortMultiplier The timeout value of stop.
1676 @param Buffer The data buffer to store IDENTIFY PACKET data.
1678 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1679 @retval EFI_TIMEOUT The operation is time out.
1680 @retval EFI_UNSUPPORTED The device is not ready for executing.
1681 @retval EFI_SUCCESS The cmd executes successfully.
1686 AhciIdentifyPacket (
1687 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1688 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1690 IN UINT8 PortMultiplier
,
1691 IN OUT EFI_IDENTIFY_DATA
*Buffer
1695 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1696 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1698 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1699 return EFI_INVALID_PARAMETER
;
1702 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1703 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1705 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1706 AtaCommandBlock
.AtaSectorCount
= 1;
1708 Status
= AhciPioTransfer (
1719 sizeof (EFI_IDENTIFY_DATA
),
1728 Send SET FEATURE cmd on specific device.
1730 @param PciIo The PCI IO protocol instance.
1731 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1732 @param Port The number of port.
1733 @param PortMultiplier The timeout value of stop.
1734 @param Feature The data to send Feature register.
1735 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1737 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1738 @retval EFI_TIMEOUT The operation is time out.
1739 @retval EFI_UNSUPPORTED The device is not ready for executing.
1740 @retval EFI_SUCCESS The cmd executes successfully.
1745 AhciDeviceSetFeature (
1746 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1747 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1749 IN UINT8 PortMultiplier
,
1751 IN UINT32 FeatureSpecificData
1755 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1756 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1758 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1759 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1761 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1762 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1763 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1764 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1765 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1766 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1767 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1769 Status
= AhciNonDataTransfer (
1773 (UINT8
)PortMultiplier
,
1786 This function is used to send out ATAPI commands conforms to the Packet Command
1789 @param PciIo The PCI IO protocol instance.
1790 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1791 @param Port The number of port.
1792 @param PortMultiplier The number of port multiplier.
1793 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1795 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1796 and device sends data successfully.
1797 @retval EFI_DEVICE_ERROR the device failed to send data.
1802 AhciPacketCommandExecute (
1803 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1804 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1806 IN UINT8 PortMultiplier
,
1807 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1813 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1814 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1817 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1818 return EFI_INVALID_PARAMETER
;
1821 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1822 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1823 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1827 AtaCommandBlock
.AtaFeatures
= 0x00;
1829 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1830 // determine how many data should be transferred.
1832 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1833 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1835 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1836 Buffer
= Packet
->InDataBuffer
;
1837 Length
= Packet
->InTransferLength
;
1840 Buffer
= Packet
->OutDataBuffer
;
1841 Length
= Packet
->OutTransferLength
;
1846 Status
= AhciNonDataTransfer (
1859 Status
= AhciPioTransfer (
1879 Allocate transfer-related data struct which is used at AHCI mode.
1881 @param PciIo The PCI IO protocol instance.
1882 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1887 AhciCreateTransferDescriptor (
1888 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1889 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1897 UINT8 MaxPortNumber
;
1898 UINT8 MaxCommandSlotNumber
;
1899 BOOLEAN Support64Bit
;
1900 UINT64 MaxReceiveFisSize
;
1901 UINT64 MaxCommandListSize
;
1902 UINT64 MaxCommandTableSize
;
1903 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr
;
1904 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr
;
1905 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr
;
1909 // Collect AHCI controller information
1911 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1912 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1914 // Get the number of command slots per port supported by this HBA.
1916 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1917 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1919 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1920 Status
= PciIo
->AllocateBuffer (
1923 EfiBootServicesData
,
1924 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
1929 if (EFI_ERROR (Status
)) {
1930 return EFI_OUT_OF_RESOURCES
;
1933 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1935 AhciRegisters
->AhciRFis
= Buffer
;
1936 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1937 Bytes
= (UINTN
)MaxReceiveFisSize
;
1939 Status
= PciIo
->Map (
1941 EfiPciIoOperationBusMasterCommonBuffer
,
1945 &AhciRegisters
->MapRFis
1948 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1950 // Map error or unable to map the whole RFis buffer into a contiguous region.
1952 Status
= EFI_OUT_OF_RESOURCES
;
1956 if ((!Support64Bit
) && (AhciRFisPciAddr
> 0x100000000ULL
)) {
1958 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1960 Status
= EFI_DEVICE_ERROR
;
1963 AhciRegisters
->AhciRFisPciAddr
= (EFI_AHCI_RECEIVED_FIS
*)(UINTN
)AhciRFisPciAddr
;
1966 // Allocate memory for command list
1967 // Note that the implemenation is a single task model which only use a command list for all ports.
1970 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1971 Status
= PciIo
->AllocateBuffer (
1974 EfiBootServicesData
,
1975 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
1980 if (EFI_ERROR (Status
)) {
1982 // Free mapped resource.
1984 Status
= EFI_OUT_OF_RESOURCES
;
1988 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
1990 AhciRegisters
->AhciCmdList
= Buffer
;
1991 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
1992 Bytes
= (UINTN
)MaxCommandListSize
;
1994 Status
= PciIo
->Map (
1996 EfiPciIoOperationBusMasterCommonBuffer
,
1999 &AhciCmdListPciAddr
,
2000 &AhciRegisters
->MapCmdList
2003 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
2005 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2007 Status
= EFI_OUT_OF_RESOURCES
;
2011 if ((!Support64Bit
) && (AhciCmdListPciAddr
> 0x100000000ULL
)) {
2013 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2015 Status
= EFI_DEVICE_ERROR
;
2018 AhciRegisters
->AhciCmdListPciAddr
= (EFI_AHCI_COMMAND_LIST
*)(UINTN
)AhciCmdListPciAddr
;
2021 // Allocate memory for command table
2022 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2025 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
2027 Status
= PciIo
->AllocateBuffer (
2030 EfiBootServicesData
,
2031 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2036 if (EFI_ERROR (Status
)) {
2038 // Free mapped resource.
2040 Status
= EFI_OUT_OF_RESOURCES
;
2044 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
2046 AhciRegisters
->AhciCommandTable
= Buffer
;
2047 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
2048 Bytes
= (UINTN
)MaxCommandTableSize
;
2050 Status
= PciIo
->Map (
2052 EfiPciIoOperationBusMasterCommonBuffer
,
2055 &AhciCommandTablePciAddr
,
2056 &AhciRegisters
->MapCommandTable
2059 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
2061 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2063 Status
= EFI_OUT_OF_RESOURCES
;
2067 if ((!Support64Bit
) && (AhciCommandTablePciAddr
> 0x100000000ULL
)) {
2069 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2071 Status
= EFI_DEVICE_ERROR
;
2074 AhciRegisters
->AhciCommandTablePciAddr
= (EFI_AHCI_COMMAND_TABLE
*)(UINTN
)AhciCommandTablePciAddr
;
2078 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2083 AhciRegisters
->MapCommandTable
2088 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandTableSize
),
2089 AhciRegisters
->AhciCommandTable
2094 AhciRegisters
->MapCmdList
2099 EFI_SIZE_TO_PAGES ((UINTN
) MaxCommandListSize
),
2100 AhciRegisters
->AhciCmdList
2105 AhciRegisters
->MapRFis
2110 EFI_SIZE_TO_PAGES ((UINTN
) MaxReceiveFisSize
),
2111 AhciRegisters
->AhciRFis
2118 Initialize ATA host controller at AHCI mode.
2120 The function is designed to initialize ATA host controller.
2122 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2127 AhciModeInitialization (
2128 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
2132 EFI_PCI_IO_PROTOCOL
*PciIo
;
2133 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
2135 UINT8 MaxPortNumber
;
2136 UINT32 PortImplementBitMap
;
2138 EFI_AHCI_REGISTERS
*AhciRegisters
;
2144 EFI_IDENTIFY_DATA Buffer
;
2145 EFI_ATA_DEVICE_TYPE DeviceType
;
2146 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
2147 EFI_ATA_TRANSFER_MODE TransferMode
;
2148 UINT32 PhyDetectDelay
;
2150 if (Instance
== NULL
) {
2151 return EFI_INVALID_PARAMETER
;
2154 PciIo
= Instance
->PciIo
;
2155 IdeInit
= Instance
->IdeControllerInit
;
2157 Status
= AhciReset (PciIo
, EFI_AHCI_BUS_RESET_TIMEOUT
);
2159 if (EFI_ERROR (Status
)) {
2160 return EFI_DEVICE_ERROR
;
2164 // Enable AE before accessing any AHCI registers
2166 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
2169 // Collect AHCI controller information
2171 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
2174 // Get the number of command slots per port supported by this HBA.
2176 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
2179 // Get the bit map of those ports exposed by this HBA.
2180 // It indicates which ports that the HBA supports are available for software to use.
2182 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
2184 AhciRegisters
= &Instance
->AhciRegisters
;
2185 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
2187 if (EFI_ERROR (Status
)) {
2188 return EFI_OUT_OF_RESOURCES
;
2191 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
2192 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
2193 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
2196 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2198 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
2199 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
2200 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2201 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
2202 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2204 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
2205 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
2206 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
2207 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
2208 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
2210 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2211 Data
= AhciReadReg (PciIo
, Offset
);
2212 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
2213 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
2216 if ((Capability
& EFI_AHCI_CAP_SSS
) != 0) {
2217 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
2221 // Disable aggressive power management.
2223 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
2224 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_INIT
);
2226 // Disable the reporting of the corresponding interrupt to system software.
2228 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
2229 AhciAndReg (PciIo
, Offset
, 0);
2232 // Now inform the IDE Controller Init Module.
2234 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
2237 // Enable FIS Receive DMA engine for the first D2H FIS.
2239 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
2240 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
2241 Status
= AhciWaitMemSet (
2244 EFI_AHCI_PORT_CMD_FR
,
2245 EFI_AHCI_PORT_CMD_FR
,
2246 EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT
2248 if (EFI_ERROR (Status
)) {
2253 // Wait no longer than 10 ms to wait the Phy to detect the presence of a device.
2254 // It's the requirment from SATA1.0a spec section 5.2.
2256 PhyDetectDelay
= EFI_AHCI_BUS_PHY_DETECT_TIMEOUT
;
2257 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
2259 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
2260 if ((Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) || (Data
== EFI_AHCI_PORT_SSTS_DET
)) {
2264 MicroSecondDelay (1000);
2266 } while (PhyDetectDelay
> 0);
2268 if (PhyDetectDelay
== 0) {
2270 // No device detected at this port.
2276 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2277 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2279 PhyDetectDelay
= 16 * 1000;
2281 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
2282 if (AhciReadReg(PciIo
, Offset
) != 0) {
2283 AhciWriteReg (PciIo
, Offset
, AhciReadReg(PciIo
, Offset
));
2285 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
2287 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_TFD_MASK
;
2292 MicroSecondDelay (1000);
2294 } while (PhyDetectDelay
> 0);
2296 if (PhyDetectDelay
== 0) {
2301 // When the first D2H register FIS is received, the content of PxSIG register is updated.
2303 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
2304 Status
= AhciWaitMemSet (
2309 EFI_TIMER_PERIOD_SECONDS(16)
2311 if (EFI_ERROR (Status
)) {
2315 Data
= AhciReadReg (PciIo
, Offset
);
2316 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
2317 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2319 if (EFI_ERROR (Status
)) {
2323 DeviceType
= EfiIdeCdrom
;
2324 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
2325 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
2327 if (EFI_ERROR (Status
)) {
2328 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_EC_NOT_DETECTED
));
2332 DeviceType
= EfiIdeHarddisk
;
2336 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
2337 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
2340 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2342 if (DeviceType
== EfiIdeHarddisk
) {
2343 AhciAtaSmartSupport (
2354 // Submit identify data to IDE controller init driver
2356 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
2359 // Now start to config ide device parameter and transfer mode.
2361 Status
= IdeInit
->CalculateMode (
2367 if (EFI_ERROR (Status
)) {
2368 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
2373 // Set best supported PIO mode on this IDE device
2375 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
2376 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
2378 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
2381 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
2384 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2385 // be set together. Only one DMA mode can be set to a device. If setting
2386 // DMA mode operation fails, we can continue moving on because we only use
2387 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2389 if (SupportedModes
->UdmaMode
.Valid
) {
2390 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
2391 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
2392 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
2393 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
2394 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
2397 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
2398 if (EFI_ERROR (Status
)) {
2399 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2404 // Found a ATA or ATAPI device, add it into the device list.
2406 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);
2407 if (DeviceType
== EfiIdeHarddisk
) {
2408 REPORT_STATUS_CODE (EFI_PROGRESS_CODE
, (EFI_PERIPHERAL_FIXED_MEDIA
| EFI_P_PC_ENABLE
));