2 The file for AHCI mode of ATA host controller.
4 Copyright (c) 2010, 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 if the device is still on port. It also checks if the AHCI controller
189 supports the address and data count will be transfered.
191 @param PciIo The PCI IO protocol instance.
192 @param Port The number of port.
194 @retval EFI_SUCCESS The device is attached to port and the transfer data is
195 supported by AHCI controller.
196 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
198 @retval EFI_NOT_READY The physical communication between AHCI controller and device
204 AhciCheckDeviceStatus (
205 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
212 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
214 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
216 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
220 return EFI_NOT_READY
;
225 Clear the port interrupt and error status. It will also clear
226 HBA interrupt status.
228 @param PciIo The PCI IO protocol instance.
229 @param Port The number of port.
234 AhciClearPortStatus (
235 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
242 // Clear any error status
244 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
245 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
248 // Clear any port interrupt status
250 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
251 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
254 // Clear any HBA interrupt status
256 AhciWriteReg (PciIo
, EFI_AHCI_IS_OFFSET
, AhciReadReg (PciIo
, EFI_AHCI_IS_OFFSET
));
260 Enable the FIS running for giving port.
262 @param PciIo The PCI IO protocol instance.
263 @param Port The number of port.
264 @param Timeout The timeout value of enabling FIS.
266 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
267 @retval EFI_TIMEOUT The FIS enable setting is time out.
268 @retval EFI_SUCCESS The FIS enable successfully.
273 AhciEnableFisReceive (
274 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
281 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
282 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_FRE
);
284 return AhciWaitMemSet (
287 EFI_AHCI_PORT_CMD_FR
,
288 EFI_AHCI_PORT_CMD_FR
,
294 Disable the FIS running for giving port.
296 @param PciIo The PCI IO protocol instance.
297 @param Port The number of port.
298 @param Timeout The timeout value of disabling FIS.
300 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
301 @retval EFI_TIMEOUT The FIS disable setting is time out.
302 @retval EFI_UNSUPPORTED The port is in running state.
303 @retval EFI_SUCCESS The FIS disable successfully.
308 AhciDisableFisReceive (
309 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
317 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
318 Data
= AhciReadReg (PciIo
, Offset
);
321 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
323 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) != 0) {
324 return EFI_UNSUPPORTED
;
328 // Check if the Fis receive DMA engine for the port is running.
330 if ((Data
& EFI_AHCI_PORT_CMD_FR
) != EFI_AHCI_PORT_CMD_FR
) {
334 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
));
336 return AhciWaitMemSet (
339 EFI_AHCI_PORT_CMD_FR
,
348 Build the command list, command table and prepare the fis receiver.
350 @param PciIo The PCI IO protocol instance.
351 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
352 @param Port The number of port.
353 @param PortMultiplier The timeout value of stop.
354 @param CommandFis The control fis will be used for the transfer.
355 @param CommandList The command list will be used for the transfer.
356 @param AtapiCommand The atapi command will be used for the transfer.
357 @param AtapiCommandLength The length of the atapi command.
358 @param CommandSlotNumber The command slot will be used for the transfer.
359 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
360 @param DataLength The data count to be transferred.
366 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
367 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
369 IN UINT8 PortMultiplier
,
370 IN EFI_AHCI_COMMAND_FIS
*CommandFis
,
371 IN EFI_AHCI_COMMAND_LIST
*CommandList
,
372 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
373 IN UINT8 AtapiCommandLength
,
374 IN UINT8 CommandSlotNumber
,
375 IN OUT VOID
*DataPhysicalAddr
,
390 PrdtNumber
= (DataLength
+ EFI_AHCI_MAX_DATA_PER_PRDT
- 1) / EFI_AHCI_MAX_DATA_PER_PRDT
;
393 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
394 // It also limits that the maximum amount of the PRDT entry in the command table
397 ASSERT (PrdtNumber
<= 65535);
399 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFis
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
401 BaseAddr
= Data64
.Uint64
;
403 ZeroMem ((VOID
*)((UINTN
) BaseAddr
), sizeof (EFI_AHCI_RECEIVED_FIS
));
405 ZeroMem (AhciRegisters
->AhciCommandTable
, sizeof (EFI_AHCI_COMMAND_TABLE
));
407 CommandFis
->AhciCFisPmNum
= PortMultiplier
;
409 CopyMem (&AhciRegisters
->AhciCommandTable
->CommandFis
, CommandFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
411 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
412 if (AtapiCommand
!= NULL
) {
414 &AhciRegisters
->AhciCommandTable
->AtapiCmd
,
419 CommandList
->AhciCmdA
= 1;
420 CommandList
->AhciCmdP
= 1;
421 CommandList
->AhciCmdC
= (DataLength
== 0) ? 1 : 0;
423 AhciOrReg (PciIo
, Offset
, (EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
425 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_DLAE
| EFI_AHCI_PORT_CMD_ATAPI
));
428 RemainedData
= (UINTN
) DataLength
;
429 MemAddr
= (UINTN
) DataPhysicalAddr
;
430 CommandList
->AhciCmdPrdtl
= (UINT32
)PrdtNumber
;
432 for (PrdtIndex
= 0; PrdtIndex
< PrdtNumber
; PrdtIndex
++) {
433 if (RemainedData
< EFI_AHCI_MAX_DATA_PER_PRDT
) {
434 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= (UINT32
)RemainedData
- 1;
436 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbc
= EFI_AHCI_MAX_DATA_PER_PRDT
- 1;
439 Data64
.Uint64
= (UINT64
)MemAddr
;
440 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDba
= Data64
.Uint32
.Lower32
;
441 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtIndex
].AhciPrdtDbau
= Data64
.Uint32
.Upper32
;
442 RemainedData
-= EFI_AHCI_MAX_DATA_PER_PRDT
;
443 MemAddr
+= EFI_AHCI_MAX_DATA_PER_PRDT
;
447 // Set the last PRDT to Interrupt On Complete
449 if (PrdtNumber
> 0) {
450 AhciRegisters
->AhciCommandTable
->PrdtTable
[PrdtNumber
- 1].AhciPrdtIoc
= 1;
454 (VOID
*) ((UINTN
) AhciRegisters
->AhciCmdList
+ (UINTN
) CommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
)),
456 sizeof (EFI_AHCI_COMMAND_LIST
)
459 Data64
.Uint64
= (UINT64
)(UINTN
) AhciRegisters
->AhciCommandTablePciAddr
;
460 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtba
= Data64
.Uint32
.Lower32
;
461 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdCtbau
= Data64
.Uint32
.Upper32
;
462 AhciRegisters
->AhciCmdList
[CommandSlotNumber
].AhciCmdPmp
= PortMultiplier
;
469 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
470 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
475 AhciBuildCommandFis (
476 IN OUT EFI_AHCI_COMMAND_FIS
*CmdFis
,
477 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
480 ZeroMem (CmdFis
, sizeof (EFI_AHCI_COMMAND_FIS
));
482 CmdFis
->AhciCFisType
= EFI_AHCI_FIS_REGISTER_H2D
;
484 // Indicator it's a command
486 CmdFis
->AhciCFisCmdInd
= 0x1;
487 CmdFis
->AhciCFisCmd
= AtaCommandBlock
->AtaCommand
;
489 CmdFis
->AhciCFisFeature
= AtaCommandBlock
->AtaFeatures
;
490 CmdFis
->AhciCFisFeatureExp
= AtaCommandBlock
->AtaFeaturesExp
;
492 CmdFis
->AhciCFisSecNum
= AtaCommandBlock
->AtaSectorNumber
;
493 CmdFis
->AhciCFisSecNumExp
= AtaCommandBlock
->AtaSectorNumberExp
;
495 CmdFis
->AhciCFisClyLow
= AtaCommandBlock
->AtaCylinderLow
;
496 CmdFis
->AhciCFisClyLowExp
= AtaCommandBlock
->AtaCylinderLowExp
;
498 CmdFis
->AhciCFisClyHigh
= AtaCommandBlock
->AtaCylinderHigh
;
499 CmdFis
->AhciCFisClyHighExp
= AtaCommandBlock
->AtaCylinderHighExp
;
501 CmdFis
->AhciCFisSecCount
= AtaCommandBlock
->AtaSectorCount
;
502 CmdFis
->AhciCFisSecCountExp
= AtaCommandBlock
->AtaSectorCountExp
;
504 CmdFis
->AhciCFisDevHead
= (UINT8
) (AtaCommandBlock
->AtaDeviceHead
| 0xE0);
508 Start a PIO data transfer on specific port.
510 @param PciIo The PCI IO protocol instance.
511 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
512 @param Port The number of port.
513 @param PortMultiplier The timeout value of stop.
514 @param AtapiCommand The atapi command will be used for the transfer.
515 @param AtapiCommandLength The length of the atapi command.
516 @param Read The transfer direction.
517 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
518 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
519 @param MemoryAddr The pointer to the data buffer.
520 @param DataCount The data count to be transferred.
521 @param Timeout The timeout value of non data transfer.
523 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
524 @retval EFI_TIMEOUT The operation is time out.
525 @retval EFI_UNSUPPORTED The device is not ready for transfer.
526 @retval EFI_SUCCESS The PIO data transfer executes successfully.
532 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
533 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
535 IN UINT8 PortMultiplier
,
536 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
537 IN UINT8 AtapiCommandLength
,
539 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
540 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
541 IN OUT VOID
*MemoryAddr
,
550 EFI_PHYSICAL_ADDRESS PhyAddr
;
553 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
555 EFI_AHCI_COMMAND_FIS CFis
;
556 EFI_AHCI_COMMAND_LIST CmdList
;
559 Flag
= EfiPciIoOperationBusMasterWrite
;
561 Flag
= EfiPciIoOperationBusMasterRead
;
565 // construct command list and command table with pci bus address
567 MapLength
= DataCount
;
568 Status
= PciIo
->Map (
577 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
578 return EFI_OUT_OF_RESOURCES
;
582 // Package read needed
584 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
586 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
588 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
589 CmdList
.AhciCmdW
= Read
? 0 : 1;
601 (VOID
*)(UINTN
)PhyAddr
,
605 Status
= AhciStartCommand (
611 if (EFI_ERROR (Status
)) {
616 // Checking the status and wait the driver sending data
618 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
620 // Wait device sends the PIO setup fis before data transfer
622 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
624 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_PIO_FIS_OFFSET
);
626 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_PIO_SETUP
) {
631 // Stall for 100 microseconds.
633 MicroSecondDelay(100);
639 Status
= EFI_TIMEOUT
;
644 // Wait for command compelte
646 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
647 Status
= AhciWaitMemSet (
655 if (EFI_ERROR (Status
)) {
659 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
660 Status
= AhciWaitMemSet (
663 EFI_AHCI_PORT_IS_PSS
,
664 EFI_AHCI_PORT_IS_PSS
,
667 if (EFI_ERROR (Status
)) {
678 AhciDisableFisReceive (
693 Start a DMA data transfer on specific port
695 @param PciIo The PCI IO protocol instance.
696 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
697 @param Port The number of port.
698 @param PortMultiplier The timeout value of stop.
699 @param AtapiCommand The atapi command will be used for the transfer.
700 @param AtapiCommandLength The length of the atapi command.
701 @param Read The transfer direction.
702 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
703 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
704 @param MemoryAddr The pointer to the data buffer.
705 @param DataCount The data count to be transferred.
706 @param Timeout The timeout value of non data transfer.
708 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
709 @retval EFI_TIMEOUT The operation is time out.
710 @retval EFI_UNSUPPORTED The device is not ready for transfer.
711 @retval EFI_SUCCESS The DMA data transfer executes successfully.
717 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
718 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
720 IN UINT8 PortMultiplier
,
721 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
722 IN UINT8 AtapiCommandLength
,
724 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
725 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
726 IN OUT VOID
*MemoryAddr
,
733 EFI_PHYSICAL_ADDRESS PhyAddr
;
736 EFI_PCI_IO_PROTOCOL_OPERATION Flag
;
737 EFI_AHCI_COMMAND_FIS CFis
;
738 EFI_AHCI_COMMAND_LIST CmdList
;
741 Flag
= EfiPciIoOperationBusMasterWrite
;
743 Flag
= EfiPciIoOperationBusMasterRead
;
747 // construct command list and command table with pci bus address
749 MapLength
= DataCount
;
750 Status
= PciIo
->Map (
759 if (EFI_ERROR (Status
) || (DataCount
!= MapLength
)) {
760 return EFI_OUT_OF_RESOURCES
;
764 // Package read needed
766 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
768 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
770 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
771 CmdList
.AhciCmdW
= Read
? 0 : 1;
783 (VOID
*)(UINTN
)PhyAddr
,
787 Status
= AhciStartCommand (
793 if (EFI_ERROR (Status
)) {
798 // Wait device PRD processed
800 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
801 Status
= AhciWaitMemSet (
804 EFI_AHCI_PORT_IS_DPS
,
805 EFI_AHCI_PORT_IS_DPS
,
809 if (EFI_ERROR (Status
)) {
814 // Wait for command compelte
816 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
817 Status
= AhciWaitMemSet (
824 if (EFI_ERROR (Status
)) {
828 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IS
;
829 Status
= AhciWaitMemSet (
832 EFI_AHCI_PORT_IS_DHRS
,
833 EFI_AHCI_PORT_IS_DHRS
,
836 if (EFI_ERROR (Status
)) {
847 AhciDisableFisReceive (
862 Start a non data transfer on specific port.
864 @param PciIo The PCI IO protocol instance.
865 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
866 @param Port The number of port.
867 @param PortMultiplier The timeout value of stop.
868 @param AtapiCommand The atapi command will be used for the transfer.
869 @param AtapiCommandLength The length of the atapi command.
870 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
871 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
872 @param Timeout The timeout value of non data transfer.
874 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
875 @retval EFI_TIMEOUT The operation is time out.
876 @retval EFI_UNSUPPORTED The device is not ready for transfer.
877 @retval EFI_SUCCESS The non data transfer executes successfully.
882 AhciNonDataTransfer (
883 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
884 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
886 IN UINT8 PortMultiplier
,
887 IN EFI_AHCI_ATAPI_COMMAND
*AtapiCommand OPTIONAL
,
888 IN UINT8 AtapiCommandLength
,
889 IN EFI_ATA_COMMAND_BLOCK
*AtaCommandBlock
,
890 IN OUT EFI_ATA_STATUS_BLOCK
*AtaStatusBlock
,
900 EFI_AHCI_COMMAND_FIS CFis
;
901 EFI_AHCI_COMMAND_LIST CmdList
;
904 // Package read needed
906 AhciBuildCommandFis (&CFis
, AtaCommandBlock
);
908 ZeroMem (&CmdList
, sizeof (EFI_AHCI_COMMAND_LIST
));
910 CmdList
.AhciCmdCfl
= EFI_AHCI_FIS_REGISTER_H2D_LENGTH
/ 4;
926 Status
= AhciStartCommand (
932 if (EFI_ERROR (Status
)) {
937 // Wait device sends the Response Fis
939 FisBaseAddr
= (UINTN
)AhciRegisters
->AhciRFis
+ Port
* sizeof (EFI_AHCI_RECEIVED_FIS
);
941 // Wait device sends the PIO setup fis before data transfer
943 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
945 Value
= *(UINT32
*) (FisBaseAddr
+ EFI_AHCI_D2H_FIS_OFFSET
);
947 if ((Value
& EFI_AHCI_FIS_TYPE_MASK
) == EFI_AHCI_FIS_REGISTER_D2H
) {
952 // Stall for 100 microseconds.
954 MicroSecondDelay(100);
960 Status
= EFI_TIMEOUT
;
964 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
966 Status
= AhciWaitMemSet (
981 AhciDisableFisReceive (
991 Stop command running for giving port
993 @param PciIo The PCI IO protocol instance.
994 @param Port The number of port.
995 @param Timeout The timeout value of stop.
997 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
998 @retval EFI_TIMEOUT The operation is time out.
999 @retval EFI_SUCCESS The command stop successfully.
1005 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1013 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1014 Data
= AhciReadReg (PciIo
, Offset
);
1016 if ((Data
& (EFI_AHCI_PORT_CMD_ST
| EFI_AHCI_PORT_CMD_CR
)) == 0) {
1020 if ((Data
& EFI_AHCI_PORT_CMD_ST
) != 0) {
1021 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_ST
));
1024 return AhciWaitMemSet (
1027 EFI_AHCI_PORT_CMD_CR
,
1034 Start command for give slot on specific port.
1036 @param PciIo The PCI IO protocol instance.
1037 @param Port The number of port.
1038 @param CommandSlot The number of CommandSlot.
1039 @param Timeout The timeout value of start.
1041 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1042 @retval EFI_TIMEOUT The operation is time out.
1043 @retval EFI_SUCCESS The command start successfully.
1049 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1051 IN UINT8 CommandSlot
,
1064 // Collect AHCI controller information
1066 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1068 CmdSlotBit
= (UINT32
) (1 << CommandSlot
);
1070 AhciClearPortStatus (
1075 Status
= AhciEnableFisReceive (
1081 if (EFI_ERROR (Status
)) {
1086 // Setting the command
1088 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SACT
;
1089 AhciAndReg (PciIo
, Offset
, 0);
1090 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1092 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CI
;
1093 AhciAndReg (PciIo
, Offset
, 0);
1094 AhciOrReg (PciIo
, Offset
, CmdSlotBit
);
1096 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1097 PortStatus
= AhciReadReg (PciIo
, Offset
);
1100 if ((PortStatus
& EFI_AHCI_PORT_CMD_ALPE
) != 0) {
1101 StartCmd
= AhciReadReg (PciIo
, Offset
);
1102 StartCmd
&= ~EFI_AHCI_PORT_CMD_ICC_MASK
;
1103 StartCmd
|= EFI_AHCI_PORT_CMD_ACTIVE
;
1106 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_TFD
;
1107 PortTfd
= AhciReadReg (PciIo
, Offset
);
1109 if ((PortTfd
& (EFI_AHCI_PORT_TFD_BSY
| EFI_AHCI_PORT_TFD_DRQ
)) != 0) {
1110 if ((Capability
& BIT24
) != 0) {
1111 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1112 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_COL
);
1117 EFI_AHCI_PORT_CMD_COL
,
1124 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1125 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_ST
| StartCmd
);
1133 @param PciIo The PCI IO protocol instance.
1134 @param Port The number of port.
1135 @param Timeout The timeout value of reset.
1137 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1138 @retval EFI_TIMEOUT The reset operation is time out.
1139 @retval EFI_SUCCESS The port reset successfully.
1145 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1153 AhciClearPortStatus (PciIo
, Port
);
1155 AhciStopCommand (PciIo
, Port
, Timeout
);
1157 AhciDisableFisReceive (PciIo
, Port
, Timeout
);
1159 AhciEnableFisReceive (PciIo
, Port
, Timeout
);
1161 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1163 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_DET_INIT
);
1166 // wait 5 milliseceond before de-assert DET
1168 MicroSecondDelay (5000);
1170 AhciAndReg (PciIo
, Offset
, (UINT32
)EFI_AHCI_PORT_SCTL_MASK
);
1173 // wait 5 milliseceond before de-assert DET
1175 MicroSecondDelay (5000);
1178 // Wait for communication to be re-established
1180 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1181 Status
= AhciWaitMemSet (
1184 EFI_AHCI_PORT_SSTS_DET_MASK
,
1185 EFI_AHCI_PORT_SSTS_DET_PCE
,
1189 if (EFI_ERROR (Status
)) {
1193 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1194 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_ERR_CLEAR
);
1202 @param PciIo The PCI IO protocol instance.
1203 @param Timeout The timeout value of reset.
1206 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1207 @retval EFI_TIMEOUT The reset operation is time out.
1208 @retval EFI_SUCCESS AHCI controller is reset successfully.
1214 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1222 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1224 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_RESET
);
1226 Status
= EFI_TIMEOUT
;
1228 Delay
= (UINT32
) (DivU64x32(Timeout
, 1000) + 1);
1231 Value
= AhciReadReg(PciIo
, EFI_AHCI_GHC_OFFSET
);
1233 if ((Value
& EFI_AHCI_GHC_RESET
) == 0) {
1238 // Stall for 100 microseconds.
1240 MicroSecondDelay(100);
1243 } while (Delay
> 0);
1253 Send Buffer cmd to specific device.
1255 @param PciIo The PCI IO protocol instance.
1256 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1257 @param Port The number of port.
1258 @param PortMultiplier The timeout value of stop.
1259 @param Buffer The data buffer to store IDENTIFY PACKET data.
1261 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1262 @retval EFI_TIMEOUT The operation is time out.
1263 @retval EFI_UNSUPPORTED The device is not ready for executing.
1264 @retval EFI_SUCCESS The cmd executes successfully.
1270 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1271 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1273 IN UINT8 PortMultiplier
,
1274 IN OUT EFI_IDENTIFY_DATA
*Buffer
1278 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1279 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1281 if (PciIo
== NULL
|| AhciRegisters
== NULL
|| Buffer
== NULL
) {
1282 return EFI_INVALID_PARAMETER
;
1285 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1286 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1288 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DRIVE
;
1289 AtaCommandBlock
.AtaSectorCount
= 1;
1291 Status
= AhciPioTransfer (
1302 sizeof (EFI_IDENTIFY_DATA
),
1310 Send Buffer cmd to specific device.
1312 @param PciIo The PCI IO protocol instance.
1313 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1314 @param Port The number of port.
1315 @param PortMultiplier The timeout value of stop.
1316 @param Buffer The data buffer to store IDENTIFY PACKET data.
1318 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1319 @retval EFI_TIMEOUT The operation is time out.
1320 @retval EFI_UNSUPPORTED The device is not ready for executing.
1321 @retval EFI_SUCCESS The cmd executes successfully.
1326 AhciIdentifyPacket (
1327 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1328 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1330 IN UINT8 PortMultiplier
,
1331 IN OUT EFI_IDENTIFY_DATA
*Buffer
1335 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1336 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1338 if (PciIo
== NULL
|| AhciRegisters
== NULL
) {
1339 return EFI_INVALID_PARAMETER
;
1342 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1343 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1345 AtaCommandBlock
.AtaCommand
= ATA_CMD_IDENTIFY_DEVICE
;
1346 AtaCommandBlock
.AtaSectorCount
= 1;
1348 Status
= AhciPioTransfer (
1359 sizeof (EFI_IDENTIFY_DATA
),
1367 Send SET FEATURE cmd on specific device.
1369 @param PciIo The PCI IO protocol instance.
1370 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1371 @param Port The number of port.
1372 @param PortMultiplier The timeout value of stop.
1373 @param Feature The data to send Feature register.
1374 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1376 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1377 @retval EFI_TIMEOUT The operation is time out.
1378 @retval EFI_UNSUPPORTED The device is not ready for executing.
1379 @retval EFI_SUCCESS The cmd executes successfully.
1384 AhciDeviceSetFeature (
1385 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1386 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1388 IN UINT8 PortMultiplier
,
1390 IN UINT32 FeatureSpecificData
1394 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1395 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1397 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1398 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1400 AtaCommandBlock
.AtaCommand
= ATA_CMD_SET_FEATURES
;
1401 AtaCommandBlock
.AtaFeatures
= (UINT8
) Feature
;
1402 AtaCommandBlock
.AtaFeaturesExp
= (UINT8
) (Feature
>> 8);
1403 AtaCommandBlock
.AtaSectorCount
= (UINT8
) FeatureSpecificData
;
1404 AtaCommandBlock
.AtaSectorNumber
= (UINT8
) (FeatureSpecificData
>> 8);
1405 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (FeatureSpecificData
>> 16);
1406 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (FeatureSpecificData
>> 24);
1408 Status
= AhciNonDataTransfer (
1412 (UINT8
)PortMultiplier
,
1424 This function is used to send out ATAPI commands conforms to the Packet Command
1427 @param PciIo The PCI IO protocol instance.
1428 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1429 @param Port The number of port.
1430 @param PortMultiplier The number of port multiplier.
1431 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1433 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1434 and device sends data successfully.
1435 @retval EFI_DEVICE_ERROR the device failed to send data.
1440 AhciPacketCommandExecute (
1441 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1442 IN EFI_AHCI_REGISTERS
*AhciRegisters
,
1444 IN UINT8 PortMultiplier
,
1445 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
*Packet
1451 EFI_ATA_COMMAND_BLOCK AtaCommandBlock
;
1452 EFI_ATA_STATUS_BLOCK AtaStatusBlock
;
1456 if (Packet
== NULL
|| Packet
->Cdb
== NULL
) {
1457 return EFI_INVALID_PARAMETER
;
1460 ZeroMem (&AtaCommandBlock
, sizeof (EFI_ATA_COMMAND_BLOCK
));
1461 ZeroMem (&AtaStatusBlock
, sizeof (EFI_ATA_STATUS_BLOCK
));
1462 AtaCommandBlock
.AtaCommand
= ATA_CMD_PACKET
;
1466 AtaCommandBlock
.AtaFeatures
= 0x00;
1468 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1469 // determine how many data should be transferred.
1471 AtaCommandBlock
.AtaCylinderLow
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
& 0x00ff);
1472 AtaCommandBlock
.AtaCylinderHigh
= (UINT8
) (ATAPI_MAX_BYTE_COUNT
>> 8);
1474 if (Packet
->DataDirection
== EFI_EXT_SCSI_DATA_DIRECTION_READ
) {
1475 Buffer
= Packet
->InDataBuffer
;
1476 Length
= Packet
->InTransferLength
;
1479 Buffer
= Packet
->OutDataBuffer
;
1480 Length
= Packet
->OutTransferLength
;
1485 Status
= AhciNonDataTransfer (
1498 // READ_CAPACITY cmd may execute failure. Retry 5 times
1500 if (((UINT8
*)Packet
->Cdb
)[0] == ATA_CMD_READ_CAPACITY
) {
1506 Status
= AhciPioTransfer (
1520 if (!EFI_ERROR (Status
)) {
1524 } while (Retry
!= 0);
1530 Allocate transfer-related data struct which is used at AHCI mode.
1532 @param PciIo The PCI IO protocol instance.
1533 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1538 AhciCreateTransferDescriptor (
1539 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1540 IN OUT EFI_AHCI_REGISTERS
*AhciRegisters
1548 UINT8 MaxPortNumber
;
1549 UINT8 MaxCommandSlotNumber
;
1550 BOOLEAN Support64Bit
;
1551 UINT64 MaxReceiveFisSize
;
1552 UINT64 MaxCommandListSize
;
1553 UINT64 MaxCommandTableSize
;
1557 // Collect AHCI controller information
1559 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1560 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1562 // Get the number of command slots per port supported by this HBA.
1564 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1565 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1567 MaxReceiveFisSize
= MaxPortNumber
* sizeof (EFI_AHCI_RECEIVED_FIS
);
1568 Status
= PciIo
->AllocateBuffer (
1571 EfiBootServicesData
,
1572 (UINTN
)EFI_SIZE_TO_PAGES (MaxReceiveFisSize
),
1577 if (EFI_ERROR (Status
)) {
1578 return EFI_OUT_OF_RESOURCES
;
1581 ZeroMem (Buffer
, (UINTN
)MaxReceiveFisSize
);
1583 AhciRegisters
->AhciRFis
= Buffer
;
1584 AhciRegisters
->MaxReceiveFisSize
= MaxReceiveFisSize
;
1585 Bytes
= (UINTN
)MaxReceiveFisSize
;
1587 Status
= PciIo
->Map (
1589 EfiPciIoOperationBusMasterCommonBuffer
,
1592 (EFI_PHYSICAL_ADDRESS
*) &AhciRegisters
->AhciRFisPciAddr
,
1593 &AhciRegisters
->MapRFis
1596 if (EFI_ERROR (Status
) || (Bytes
!= MaxReceiveFisSize
)) {
1598 // Map error or unable to map the whole RFis buffer into a contiguous region.
1600 Status
= EFI_OUT_OF_RESOURCES
;
1604 if ((!Support64Bit
) && ((EFI_PHYSICAL_ADDRESS
)(UINTN
)AhciRegisters
->AhciRFisPciAddr
> 0x100000000ULL
)) {
1606 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1608 Status
= EFI_DEVICE_ERROR
;
1613 // Allocate memory for command list
1614 // Note that the implemenation is a single task model which only use a command list for all ports.
1617 MaxCommandListSize
= MaxCommandSlotNumber
* sizeof (EFI_AHCI_COMMAND_LIST
);
1618 Status
= PciIo
->AllocateBuffer (
1621 EfiBootServicesData
,
1622 (UINTN
)EFI_SIZE_TO_PAGES (MaxCommandListSize
),
1627 if (EFI_ERROR (Status
)) {
1629 // Free mapped resource.
1631 Status
= EFI_OUT_OF_RESOURCES
;
1635 ZeroMem (Buffer
, (UINTN
)MaxCommandListSize
);
1637 AhciRegisters
->AhciCmdList
= Buffer
;
1638 AhciRegisters
->MaxCommandListSize
= MaxCommandListSize
;
1639 Bytes
= (UINTN
)MaxCommandListSize
;
1641 Status
= PciIo
->Map (
1643 EfiPciIoOperationBusMasterCommonBuffer
,
1646 (EFI_PHYSICAL_ADDRESS
*)&AhciRegisters
->AhciCmdListPciAddr
,
1647 &AhciRegisters
->MapCmdList
1650 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandListSize
)) {
1652 // Map error or unable to map the whole cmd list buffer into a contiguous region.
1654 Status
= EFI_OUT_OF_RESOURCES
;
1658 if ((!Support64Bit
) && ((EFI_PHYSICAL_ADDRESS
)(UINTN
)AhciRegisters
->AhciCmdListPciAddr
> 0x100000000ULL
)) {
1660 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1662 Status
= EFI_DEVICE_ERROR
;
1667 // Allocate memory for command table
1668 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1671 MaxCommandTableSize
= sizeof (EFI_AHCI_COMMAND_TABLE
);
1673 Status
= PciIo
->AllocateBuffer (
1676 EfiBootServicesData
,
1677 (UINTN
)EFI_SIZE_TO_PAGES (MaxCommandTableSize
),
1682 if (EFI_ERROR (Status
)) {
1684 // Free mapped resource.
1686 Status
= EFI_OUT_OF_RESOURCES
;
1690 ZeroMem (Buffer
, (UINTN
)MaxCommandTableSize
);
1692 AhciRegisters
->AhciCommandTable
= Buffer
;
1693 AhciRegisters
->MaxCommandTableSize
= MaxCommandTableSize
;
1694 Bytes
= (UINTN
)MaxCommandTableSize
;
1696 Status
= PciIo
->Map (
1698 EfiPciIoOperationBusMasterCommonBuffer
,
1701 (EFI_PHYSICAL_ADDRESS
*)&AhciRegisters
->AhciCommandTablePciAddr
,
1702 &AhciRegisters
->MapCommandTable
1705 if (EFI_ERROR (Status
) || (Bytes
!= MaxCommandTableSize
)) {
1707 // Map error or unable to map the whole cmd list buffer into a contiguous region.
1709 Status
= EFI_OUT_OF_RESOURCES
;
1713 if ((!Support64Bit
) && ((EFI_PHYSICAL_ADDRESS
)(UINTN
)AhciRegisters
->AhciCommandTablePciAddr
> 0x100000000ULL
)) {
1715 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1717 Status
= EFI_DEVICE_ERROR
;
1723 // Map error or unable to map the whole CmdList buffer into a contiguous region.
1728 AhciRegisters
->MapCommandTable
1733 (UINTN
)EFI_SIZE_TO_PAGES (MaxCommandTableSize
),
1734 AhciRegisters
->AhciCommandTable
1739 AhciRegisters
->MapCmdList
1744 (UINTN
)EFI_SIZE_TO_PAGES (MaxCommandListSize
),
1745 AhciRegisters
->AhciCmdList
1750 AhciRegisters
->MapRFis
1755 (UINTN
)EFI_SIZE_TO_PAGES (MaxReceiveFisSize
),
1756 AhciRegisters
->AhciRFis
1763 Initialize ATA host controller at AHCI mode.
1765 The function is designed to initialize ATA host controller.
1767 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1772 AhciModeInitialization (
1773 IN ATA_ATAPI_PASS_THRU_INSTANCE
*Instance
1777 EFI_PCI_IO_PROTOCOL
*PciIo
;
1778 EFI_IDE_CONTROLLER_INIT_PROTOCOL
*IdeInit
;
1780 UINT8 MaxPortNumber
;
1781 UINT32 PortImplementBitMap
;
1782 UINT8 MaxCommandSlotNumber
;
1783 BOOLEAN Support64Bit
;
1785 EFI_AHCI_REGISTERS
*AhciRegisters
;
1791 EFI_IDENTIFY_DATA Buffer
;
1792 EFI_ATA_DEVICE_TYPE DeviceType
;
1793 EFI_ATA_COLLECTIVE_MODE
*SupportedModes
;
1794 EFI_ATA_TRANSFER_MODE TransferMode
;
1796 if (Instance
== NULL
) {
1797 return EFI_INVALID_PARAMETER
;
1800 PciIo
= Instance
->PciIo
;
1801 IdeInit
= Instance
->IdeControllerInit
;
1803 Status
= AhciReset (PciIo
, ATA_ATAPI_TIMEOUT
);
1805 if (EFI_ERROR (Status
)) {
1806 return EFI_DEVICE_ERROR
;
1810 // Enable AE before accessing any AHCI registers
1812 AhciOrReg (PciIo
, EFI_AHCI_GHC_OFFSET
, EFI_AHCI_GHC_ENABLE
);
1815 // Collect AHCI controller information
1817 Capability
= AhciReadReg(PciIo
, EFI_AHCI_CAPABILITY_OFFSET
);
1820 // Get the number of command slots per port supported by this HBA.
1822 MaxCommandSlotNumber
= (UINT8
) (((Capability
& 0x1F00) >> 8) + 1);
1823 Support64Bit
= (BOOLEAN
) (((Capability
& BIT31
) != 0) ? TRUE
: FALSE
);
1826 // Get the bit map of those ports exposed by this HBA.
1827 // It indicates which ports that the HBA supports are available for software to use.
1829 PortImplementBitMap
= AhciReadReg(PciIo
, EFI_AHCI_PI_OFFSET
);
1830 MaxPortNumber
= (UINT8
) ((Capability
& 0x1F) + 1);
1832 AhciRegisters
= &Instance
->AhciRegisters
;
1833 Status
= AhciCreateTransferDescriptor (PciIo
, AhciRegisters
);
1835 if (EFI_ERROR (Status
)) {
1836 return EFI_OUT_OF_RESOURCES
;
1839 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
1840 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciRFisPciAddr
) + sizeof (EFI_AHCI_RECEIVED_FIS
) * Port
;
1842 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FB
;
1843 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
1844 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_FBU
;
1845 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
1848 // Single task envrionment, we only use one command table for all port
1850 Data64
.Uint64
= (UINTN
) (AhciRegisters
->AhciCmdListPciAddr
);
1852 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLB
;
1853 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Lower32
);
1854 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CLBU
;
1855 AhciWriteReg (PciIo
, Offset
, Data64
.Uint32
.Upper32
);
1857 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
1858 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_CMD
;
1860 if ((Capability
& EFI_AHCI_PORT_CMD_ASP
) != 0) {
1861 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_SUD
);
1863 Data
= AhciReadReg (PciIo
, Offset
);
1864 if ((Data
& EFI_AHCI_PORT_CMD_CPD
) != 0) {
1865 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_CMD_POD
);
1868 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_CMD_FRE
|EFI_AHCI_PORT_CMD_COL
|EFI_AHCI_PORT_CMD_ST
));
1871 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SCTL
;
1872 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_SCTL_IPM_MASK
));
1874 AhciAndReg (PciIo
, Offset
,(UINT32
) ~(EFI_AHCI_PORT_SCTL_IPM_PSD
));
1875 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_PSD
);
1877 AhciAndReg (PciIo
, Offset
, (UINT32
)~(EFI_AHCI_PORT_SCTL_IPM_SSD
));
1878 AhciOrReg (PciIo
, Offset
, EFI_AHCI_PORT_SCTL_IPM_SSD
);
1880 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_IE
;
1881 AhciAndReg (PciIo
, Offset
, 0);
1883 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SERR
;
1884 AhciWriteReg (PciIo
, Offset
, AhciReadReg (PciIo
, Offset
));
1888 // Stall for 100 milliseconds.
1890 MicroSecondDelay(100000);
1892 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBeforeChannelEnumeration
, Port
);
1894 for (Port
= 0; Port
< MaxPortNumber
; Port
++) {
1895 if ((PortImplementBitMap
& (BIT0
<< Port
)) != 0) {
1897 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SSTS
;
1898 Data
= AhciReadReg (PciIo
, Offset
) & EFI_AHCI_PORT_SSTS_DET_MASK
;
1904 // Found device in the port
1906 if (Data
== EFI_AHCI_PORT_SSTS_DET_PCE
) {
1907 Offset
= EFI_AHCI_PORT_START
+ Port
* EFI_AHCI_PORT_REG_WIDTH
+ EFI_AHCI_PORT_SIG
;
1909 Status
= AhciWaitMemSet (
1916 if (EFI_ERROR (Status
)) {
1921 // Now inform the IDE Controller Init Module.
1923 IdeInit
->NotifyPhase (IdeInit
, EfiIdeBusBeforeDevicePresenceDetection
, Port
);
1925 Data
= AhciReadReg (PciIo
, Offset
);
1927 if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATAPI_DEVICE_SIG
) {
1928 Status
= AhciIdentifyPacket (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
1930 if (EFI_ERROR (Status
)) {
1934 DeviceType
= EfiIdeCdrom
;
1935 } else if ((Data
& EFI_AHCI_ATAPI_SIG_MASK
) == EFI_AHCI_ATA_DEVICE_SIG
) {
1936 Status
= AhciIdentify (PciIo
, AhciRegisters
, Port
, 0, &Buffer
);
1938 if (EFI_ERROR (Status
)) {
1942 DeviceType
= EfiIdeHarddisk
;
1947 DEBUG ((EFI_D_INFO
, "port [%d] port mulitplier [%d] has a [%a]\n",
1948 Port
, 0, DeviceType
== EfiIdeCdrom
? "cdrom" : "harddisk"));
1951 // Submit identify data to IDE controller init driver
1953 IdeInit
->SubmitData (IdeInit
, Port
, 0, &Buffer
);
1956 // Now start to config ide device parameter and transfer mode.
1958 Status
= IdeInit
->CalculateMode (
1964 if (EFI_ERROR (Status
)) {
1965 DEBUG ((EFI_D_ERROR
, "Calculate Mode Fail, Status = %r\n", Status
));
1970 // Set best supported PIO mode on this IDE device
1972 if (SupportedModes
->PioMode
.Mode
<= EfiAtaPioMode2
) {
1973 TransferMode
.ModeCategory
= EFI_ATA_MODE_DEFAULT_PIO
;
1975 TransferMode
.ModeCategory
= EFI_ATA_MODE_FLOW_PIO
;
1978 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->PioMode
.Mode
);
1981 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
1982 // be set together. Only one DMA mode can be set to a device. If setting
1983 // DMA mode operation fails, we can continue moving on because we only use
1984 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
1986 if (SupportedModes
->UdmaMode
.Valid
) {
1987 TransferMode
.ModeCategory
= EFI_ATA_MODE_UDMA
;
1988 TransferMode
.ModeNumber
= (UINT8
) (SupportedModes
->UdmaMode
.Mode
);
1989 } else if (SupportedModes
->MultiWordDmaMode
.Valid
) {
1990 TransferMode
.ModeCategory
= EFI_ATA_MODE_MDMA
;
1991 TransferMode
.ModeNumber
= (UINT8
) SupportedModes
->MultiWordDmaMode
.Mode
;
1994 Status
= AhciDeviceSetFeature (PciIo
, AhciRegisters
, Port
, 0, 0x03, (UINT32
)(*(UINT8
*)&TransferMode
));
1996 if (EFI_ERROR (Status
)) {
1997 DEBUG ((EFI_D_ERROR
, "Set transfer Mode Fail, Status = %r\n", Status
));
2001 // Found a ATA or ATAPI device, add it into the device list.
2003 CreateNewDeviceInfo (Instance
, Port
, 0, DeviceType
, &Buffer
);