TianoCore EDK2 master
Loading...
Searching...
No Matches
AhciMode.c
Go to the documentation of this file.
1
10#include "AtaAtapiPassThru.h"
11
21UINT32
22EFIAPI
25 IN UINT32 Offset
26 )
27{
28 UINT32 Data;
29
30 ASSERT (PciIo != NULL);
31
32 Data = 0;
33
34 PciIo->Mem.Read (
35 PciIo,
36 EfiPciIoWidthUint32,
37 EFI_AHCI_BAR_INDEX,
38 (UINT64)Offset,
39 1,
40 &Data
41 );
42
43 return Data;
44}
45
54VOID
55EFIAPI
58 IN UINT32 Offset,
59 IN UINT32 Data
60 )
61{
62 ASSERT (PciIo != NULL);
63
64 PciIo->Mem.Write (
65 PciIo,
66 EfiPciIoWidthUint32,
67 EFI_AHCI_BAR_INDEX,
68 (UINT64)Offset,
69 1,
70 &Data
71 );
72
73 return;
74}
75
84VOID
85EFIAPI
88 IN UINT32 Offset,
89 IN UINT32 AndData
90 )
91{
92 UINT32 Data;
93
94 ASSERT (PciIo != NULL);
95
96 Data = AhciReadReg (PciIo, Offset);
97
98 Data &= AndData;
99
100 AhciWriteReg (PciIo, Offset, Data);
101}
102
111VOID
112EFIAPI
114 IN EFI_PCI_IO_PROTOCOL *PciIo,
115 IN UINT32 Offset,
116 IN UINT32 OrData
117 )
118{
119 UINT32 Data;
120
121 ASSERT (PciIo != NULL);
122
123 Data = AhciReadReg (PciIo, Offset);
124
125 Data |= OrData;
126
127 AhciWriteReg (PciIo, Offset, Data);
128}
129
144EFIAPI
146 IN EFI_PCI_IO_PROTOCOL *PciIo,
147 IN UINTN Offset,
148 IN UINT32 MaskValue,
149 IN UINT32 TestValue,
150 IN UINT64 Timeout
151 )
152{
153 UINT32 Value;
154 UINT64 Delay;
155 BOOLEAN InfiniteWait;
156
157 if (Timeout == 0) {
158 InfiniteWait = TRUE;
159 } else {
160 InfiniteWait = FALSE;
161 }
162
163 Delay = DivU64x32 (Timeout, 1000) + 1;
164
165 do {
166 //
167 // Access PCI MMIO space to see if the value is the tested one.
168 //
169 Value = AhciReadReg (PciIo, (UINT32)Offset) & MaskValue;
170
171 if (Value == TestValue) {
172 return EFI_SUCCESS;
173 }
174
175 //
176 // Stall for 100 microseconds.
177 //
178 MicroSecondDelay (100);
179
180 Delay--;
181 } while (InfiniteWait || (Delay > 0));
182
183 return EFI_TIMEOUT;
184}
185
199EFIAPI
201 IN EFI_PHYSICAL_ADDRESS Address,
202 IN UINT32 MaskValue,
203 IN UINT32 TestValue,
204 IN UINT64 Timeout
205 )
206{
207 UINT32 Value;
208 UINT64 Delay;
209 BOOLEAN InfiniteWait;
210
211 if (Timeout == 0) {
212 InfiniteWait = TRUE;
213 } else {
214 InfiniteWait = FALSE;
215 }
216
217 Delay = DivU64x32 (Timeout, 1000) + 1;
218
219 do {
220 //
221 // Access system memory to see if the value is the tested one.
222 //
223 // The system memory pointed by Address will be updated by the
224 // SATA Host Controller, "volatile" is introduced to prevent
225 // compiler from optimizing the access to the memory address
226 // to only read once.
227 //
228 Value = *(volatile UINT32 *)(UINTN)Address;
229 Value &= MaskValue;
230
231 if (Value == TestValue) {
232 return EFI_SUCCESS;
233 }
234
235 //
236 // Stall for 100 microseconds.
237 //
238 MicroSecondDelay (100);
239
240 Delay--;
241 } while (InfiniteWait || (Delay > 0));
242
243 return EFI_TIMEOUT;
244}
245
257EFIAPI
259 IN UINTN Address,
260 IN UINT32 MaskValue,
261 IN UINT32 TestValue
262 )
263{
264 UINT32 Value;
265
266 Value = *(volatile UINT32 *)Address;
267 Value &= MaskValue;
268
269 if (Value == TestValue) {
270 return EFI_SUCCESS;
271 }
272
273 return EFI_NOT_READY;
274}
275
285VOID
286EFIAPI
288 IN EFI_PCI_IO_PROTOCOL *PciIo,
289 IN UINT8 Port
290 )
291{
292 UINT32 Offset;
293
294 //
295 // Clear any error status
296 //
297 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
298 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
299
300 //
301 // Clear any port interrupt status
302 //
303 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
304 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
305
306 //
307 // Clear any HBA interrupt status
308 //
309 AhciWriteReg (PciIo, EFI_AHCI_IS_OFFSET, AhciReadReg (PciIo, EFI_AHCI_IS_OFFSET));
310}
311
322VOID
323EFIAPI
325 IN EFI_PCI_IO_PROTOCOL *PciIo,
326 IN EFI_AHCI_REGISTERS *AhciRegisters,
327 IN UINT8 Port,
328 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
329 )
330{
331 UINTN Offset;
332 UINT32 Data;
333 UINTN FisBaseAddr;
334 EFI_STATUS Status;
335
336 ASSERT (PciIo != NULL);
337
338 if (AtaStatusBlock != NULL) {
339 ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
340
341 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
342 Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
343
344 Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H);
345 if (!EFI_ERROR (Status)) {
346 //
347 // If D2H FIS is received, update StatusBlock with its content.
348 //
349 CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK));
350 } else {
351 //
352 // If D2H FIS is not received, only update Status & Error field through PxTFD
353 // as there is no other way to get the content of the Shadow Register Block.
354 //
355 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
356 Data = AhciReadReg (PciIo, (UINT32)Offset);
357
358 AtaStatusBlock->AtaStatus = (UINT8)Data;
359 if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {
360 AtaStatusBlock->AtaError = (UINT8)(Data >> 8);
361 }
362 }
363 }
364}
365
379EFIAPI
381 IN EFI_PCI_IO_PROTOCOL *PciIo,
382 IN UINT8 Port,
383 IN UINT64 Timeout
384 )
385{
386 UINT32 Offset;
387
388 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
389 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
390
391 return EFI_SUCCESS;
392}
393
408EFIAPI
410 IN EFI_PCI_IO_PROTOCOL *PciIo,
411 IN UINT8 Port,
412 IN UINT64 Timeout
413 )
414{
415 UINT32 Offset;
416 UINT32 Data;
417
418 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
419 Data = AhciReadReg (PciIo, Offset);
420
421 //
422 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
423 //
424 if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
425 return EFI_UNSUPPORTED;
426 }
427
428 //
429 // Check if the Fis receive DMA engine for the port is running.
430 //
431 if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
432 return EFI_SUCCESS;
433 }
434
435 AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_FRE));
436
437 return AhciWaitMmioSet (
438 PciIo,
439 Offset,
440 EFI_AHCI_PORT_CMD_FR,
441 0,
442 Timeout
443 );
444}
445
462VOID
463EFIAPI
465 IN EFI_PCI_IO_PROTOCOL *PciIo,
466 IN EFI_AHCI_REGISTERS *AhciRegisters,
467 IN UINT8 Port,
468 IN UINT8 PortMultiplier,
469 IN EFI_AHCI_COMMAND_FIS *CommandFis,
470 IN EFI_AHCI_COMMAND_LIST *CommandList,
471 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
472 IN UINT8 AtapiCommandLength,
473 IN UINT8 CommandSlotNumber,
474 IN OUT VOID *DataPhysicalAddr,
475 IN UINT32 DataLength
476 )
477{
478 UINT64 BaseAddr;
479 UINT32 PrdtNumber;
480 UINT32 PrdtIndex;
481 UINTN RemainedData;
482 UINTN MemAddr;
483 DATA_64 Data64;
484 UINT32 Offset;
485
486 //
487 // Filling the PRDT
488 //
489 PrdtNumber = (UINT32)DivU64x32 (((UINT64)DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1), EFI_AHCI_MAX_DATA_PER_PRDT);
490
491 //
492 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
493 // It also limits that the maximum amount of the PRDT entry in the command table
494 // is 65535.
495 //
496 ASSERT (PrdtNumber <= 65535);
497
498 Data64.Uint64 = (UINTN)(AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
499
500 BaseAddr = Data64.Uint64;
501
502 ZeroMem ((VOID *)((UINTN)BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
503
504 ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
505
506 CommandFis->AhciCFisPmNum = PortMultiplier;
507
508 CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
509
510 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
511 if (AtapiCommand != NULL) {
512 CopyMem (
513 &AhciRegisters->AhciCommandTable->AtapiCmd,
514 AtapiCommand,
515 AtapiCommandLength
516 );
517
518 CommandList->AhciCmdA = 1;
519 CommandList->AhciCmdP = 1;
520
521 AhciOrReg (PciIo, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
522 } else {
523 AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
524 }
525
526 RemainedData = (UINTN)DataLength;
527 MemAddr = (UINTN)DataPhysicalAddr;
528 CommandList->AhciCmdPrdtl = PrdtNumber;
529
530 for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
531 if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
532 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
533 } else {
534 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;
535 }
536
537 Data64.Uint64 = (UINT64)MemAddr;
538 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
539 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
540 RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
541 MemAddr += EFI_AHCI_MAX_DATA_PER_PRDT;
542 }
543
544 //
545 // Set the last PRDT to Interrupt On Complete
546 //
547 if (PrdtNumber > 0) {
548 AhciRegisters->AhciCommandTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
549 }
550
551 CopyMem (
552 (VOID *)((UINTN)AhciRegisters->AhciCmdList + (UINTN)CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
553 CommandList,
554 sizeof (EFI_AHCI_COMMAND_LIST)
555 );
556
557 Data64.Uint64 = (UINT64)(UINTN)AhciRegisters->AhciCommandTablePciAddr;
558 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32;
559 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
560 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier;
561}
562
570VOID
571EFIAPI
574 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
575 )
576{
577 ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
578
579 CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
580 //
581 // Indicator it's a command
582 //
583 CmdFis->AhciCFisCmdInd = 0x1;
584 CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
585
586 CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
587 CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
588
589 CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
590 CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp;
591
592 CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
593 CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
594
595 CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
596 CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
597
598 CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
599 CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
600
601 CmdFis->AhciCFisDevHead = (UINT8)(AtaCommandBlock->AtaDeviceHead | 0xE0);
602}
603
615 IN EFI_PCI_IO_PROTOCOL *PciIo,
616 IN UINT8 Port
617 )
618{
619 UINT32 PhyDetectDelay;
620 UINT32 Data;
621 UINT32 Offset;
622
623 //
624 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
625 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
626 //
627 PhyDetectDelay = 16 * 1000;
628 do {
629 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
630 if (AhciReadReg (PciIo, Offset) != 0) {
631 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
632 }
633
634 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
635
636 Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
637 if (Data == 0) {
638 break;
639 }
640
641 MicroSecondDelay (1000);
642 PhyDetectDelay--;
643 } while (PhyDetectDelay > 0);
644
645 if (PhyDetectDelay == 0) {
646 DEBUG ((DEBUG_ERROR, "Port %d Device not ready (TFD=0x%X)\n", Port, Data));
647 return EFI_TIMEOUT;
648 } else {
649 return EFI_SUCCESS;
650 }
651}
652
664 IN EFI_PCI_IO_PROTOCOL *PciIo,
665 IN UINT8 Port
666 )
667{
668 UINT32 Offset;
669 EFI_STATUS Status;
670
671 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
672 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);
673 //
674 // SW is required to keep DET set to 0x1 at least for 1 milisecond to ensure that
675 // at least one COMRESET signal is sent.
676 //
677 MicroSecondDelay (1000);
678 AhciAndReg (PciIo, Offset, ~(UINT32)EFI_AHCI_PORT_SSTS_DET_MASK);
679
680 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
681 Status = AhciWaitMmioSet (PciIo, Offset, EFI_AHCI_PORT_SSTS_DET_MASK, EFI_AHCI_PORT_SSTS_DET_PCE, ATA_ATAPI_TIMEOUT);
682 if (EFI_ERROR (Status)) {
683 return Status;
684 }
685
686 return AhciWaitDeviceReady (PciIo, Port);
687}
688
702 IN EFI_PCI_IO_PROTOCOL *PciIo,
703 IN UINT8 Port
704 )
705{
706 UINT32 Offset;
707 UINT32 PortInterrupt;
708 UINT32 PortTfd;
709 EFI_STATUS Status;
710
711 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
712 PortInterrupt = AhciReadReg (PciIo, Offset);
713 if ((PortInterrupt & EFI_AHCI_PORT_IS_FATAL_ERROR_MASK) == 0) {
714 //
715 // No fatal error detected. Exit with success as port should still be operational.
716 // No need to clear IS as it will be cleared when the next command starts.
717 //
718 return EFI_SUCCESS;
719 }
720
721 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
722 AhciAndReg (PciIo, Offset, ~(UINT32)EFI_AHCI_PORT_CMD_ST);
723
724 Status = AhciWaitMmioSet (PciIo, Offset, EFI_AHCI_PORT_CMD_CR, 0, ATA_ATAPI_TIMEOUT);
725 if (EFI_ERROR (Status)) {
726 DEBUG ((DEBUG_ERROR, "Ahci port %d is in hung state, aborting recovery\n", Port));
727 return Status;
728 }
729
730 //
731 // If TFD.BSY or TFD.DRQ is still set it means that drive is hung and software has
732 // to reset it before sending any additional commands.
733 //
734 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
735 PortTfd = AhciReadReg (PciIo, Offset);
736 if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
737 Status = AhciResetPort (PciIo, Port);
738 if (EFI_ERROR (Status)) {
739 DEBUG ((DEBUG_ERROR, "Failed to reset the port %d\n", Port));
740 return EFI_DEVICE_ERROR;
741 }
742 }
743
744 return EFI_SUCCESS;
745}
746
757BOOLEAN
759 IN EFI_PCI_IO_PROTOCOL *PciIo,
760 IN UINT8 Port
761 )
762{
763 UINT32 Offset;
764 UINT32 PortInterrupt;
765 UINT32 Serr;
766 UINT32 Tfd;
767
768 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
769 PortInterrupt = AhciReadReg (PciIo, Offset);
770 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
771 Serr = AhciReadReg (PciIo, Offset);
772 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
773 Tfd = AhciReadReg (PciIo, Offset);
774
775 //
776 // This can occur if there was a CRC error on a path from system memory to
777 // host controller.
778 //
779 if (PortInterrupt & EFI_AHCI_PORT_IS_HBDS) {
780 return TRUE;
781 //
782 // This can occur if there was a CRC error detected by host during communication
783 // with the device
784 //
785 } else if ((PortInterrupt & (EFI_AHCI_PORT_IS_IFS | EFI_AHCI_PORT_IS_INFS)) &&
786 (Serr & EFI_AHCI_PORT_SERR_CRCE))
787 {
788 return TRUE;
789 //
790 // This can occur if there was a CRC error detected by device during communication
791 // with the host. Device returns error status to host with D2H FIS.
792 //
793 } else if ((PortInterrupt & EFI_AHCI_PORT_IS_TFES) &&
794 (Tfd & EFI_AHCI_PORT_TFD_ERR_INT_CRC))
795 {
796 return TRUE;
797 }
798
799 return FALSE;
800}
801
815 IN EFI_PCI_IO_PROTOCOL *PciIo,
816 IN UINT8 Port,
817 IN SATA_FIS_TYPE FisType
818 )
819{
820 UINT32 Offset;
821 UINT32 PortInterrupt;
822 UINT32 PortTfd;
823
824 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
825 PortInterrupt = AhciReadReg (PciIo, Offset);
826 if ((PortInterrupt & EFI_AHCI_PORT_IS_ERROR_MASK) != 0) {
827 DEBUG ((DEBUG_ERROR, "AHCI: Error interrupt reported PxIS: %X\n", PortInterrupt));
828 return EFI_DEVICE_ERROR;
829 }
830
831 //
832 // For PIO setup FIS - According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
833 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
834 // after the transaction is finished successfully.
835 // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
836 // By this way, we can know if there is a real error happened.
837 //
838 if (((FisType == SataFisD2H) && ((PortInterrupt & EFI_AHCI_PORT_IS_DHRS) != 0)) ||
839 ((FisType == SataFisPioSetup) && ((PortInterrupt & (EFI_AHCI_PORT_IS_PSS | EFI_AHCI_PORT_IS_DHRS)) != 0)) ||
840 ((FisType == SataFisDmaSetup) && ((PortInterrupt & (EFI_AHCI_PORT_IS_DSS | EFI_AHCI_PORT_IS_DHRS)) != 0)))
841 {
842 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
843 PortTfd = AhciReadReg (PciIo, (UINT32)Offset);
844 if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
845 return EFI_DEVICE_ERROR;
846 } else {
847 return EFI_SUCCESS;
848 }
849 }
850
851 return EFI_NOT_READY;
852}
853
868 IN EFI_PCI_IO_PROTOCOL *PciIo,
869 IN UINT8 Port,
870 IN UINT64 Timeout,
871 IN SATA_FIS_TYPE FisType
872 )
873{
874 EFI_STATUS Status;
875 BOOLEAN InfiniteWait;
876 UINT64 Delay;
877
878 Delay = DivU64x32 (Timeout, 1000) + 1;
879 if (Timeout == 0) {
880 InfiniteWait = TRUE;
881 } else {
882 InfiniteWait = FALSE;
883 }
884
885 do {
886 Status = AhciCheckFisReceived (PciIo, Port, FisType);
887 if (Status != EFI_NOT_READY) {
888 return Status;
889 }
890
891 //
892 // Stall for 100 microseconds.
893 //
894 MicroSecondDelay (100);
895 Delay--;
896 } while (InfiniteWait || (Delay > 0));
897
898 return EFI_TIMEOUT;
899}
900
907VOID
909 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
910 IN UINT32 DebugLevel
911 )
912{
913 DEBUG ((DebugLevel, "ATA COMMAND BLOCK:\n"));
914 DEBUG ((DebugLevel, "AtaCommand: %d\n", AtaCommandBlock->AtaCommand));
915 DEBUG ((DebugLevel, "AtaFeatures: %X\n", AtaCommandBlock->AtaFeatures));
916 DEBUG ((DebugLevel, "AtaSectorNumber: %d\n", AtaCommandBlock->AtaSectorNumber));
917 DEBUG ((DebugLevel, "AtaCylinderLow: %X\n", AtaCommandBlock->AtaCylinderHigh));
918 DEBUG ((DebugLevel, "AtaCylinderHigh: %X\n", AtaCommandBlock->AtaCylinderHigh));
919 DEBUG ((DebugLevel, "AtaDeviceHead: %d\n", AtaCommandBlock->AtaDeviceHead));
920 DEBUG ((DebugLevel, "AtaSectorNumberExp: %d\n", AtaCommandBlock->AtaSectorNumberExp));
921 DEBUG ((DebugLevel, "AtaCylinderLowExp: %X\n", AtaCommandBlock->AtaCylinderLowExp));
922 DEBUG ((DebugLevel, "AtaCylinderHighExp: %X\n", AtaCommandBlock->AtaCylinderHighExp));
923 DEBUG ((DebugLevel, "AtaFeaturesExp: %X\n", AtaCommandBlock->AtaFeaturesExp));
924 DEBUG ((DebugLevel, "AtaSectorCount: %d\n", AtaCommandBlock->AtaSectorCount));
925 DEBUG ((DebugLevel, "AtaSectorCountExp: %d\n", AtaCommandBlock->AtaSectorCountExp));
926}
927
934VOID
936 IN EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
937 IN UINT32 DebugLevel
938 )
939{
940 //
941 // Skip NULL pointer
942 //
943 if (AtaStatusBlock == NULL) {
944 return;
945 }
946
947 //
948 // Only print status and error since we have all of the rest printed as
949 // a part of command block print.
950 //
951 DEBUG ((DebugLevel, "ATA STATUS BLOCK:\n"));
952 DEBUG ((DebugLevel, "AtaStatus: %d\n", AtaStatusBlock->AtaStatus));
953 DEBUG ((DebugLevel, "AtaError: %d\n", AtaStatusBlock->AtaError));
954}
955
982EFIAPI
984 IN EFI_PCI_IO_PROTOCOL *PciIo,
985 IN EFI_AHCI_REGISTERS *AhciRegisters,
986 IN UINT8 Port,
987 IN UINT8 PortMultiplier,
988 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
989 IN UINT8 AtapiCommandLength,
990 IN BOOLEAN Read,
991 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
992 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
993 IN OUT VOID *MemoryAddr,
994 IN UINT32 DataCount,
995 IN UINT64 Timeout,
997 )
998{
999 EFI_STATUS Status;
1000 EFI_PHYSICAL_ADDRESS PhyAddr;
1001 VOID *Map;
1002 UINTN MapLength;
1005 EFI_AHCI_COMMAND_LIST CmdList;
1006 UINT32 PrdCount;
1007 UINT32 Retry;
1008 EFI_STATUS RecoveryStatus;
1009 BOOLEAN DoRetry;
1010
1011 if (Read) {
1013 } else {
1015 }
1016
1017 //
1018 // construct command list and command table with pci bus address
1019 //
1020 MapLength = DataCount;
1021 Status = PciIo->Map (
1022 PciIo,
1023 Flag,
1024 MemoryAddr,
1025 &MapLength,
1026 &PhyAddr,
1027 &Map
1028 );
1029
1030 if (EFI_ERROR (Status) || (DataCount != MapLength)) {
1031 return EFI_BAD_BUFFER_SIZE;
1032 }
1033
1034 //
1035 // Package read needed
1036 //
1037 AhciBuildCommandFis (&CFis, AtaCommandBlock);
1038
1039 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
1040
1041 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
1042 CmdList.AhciCmdW = Read ? 0 : 1;
1043
1044 for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
1046 PciIo,
1047 AhciRegisters,
1048 Port,
1049 PortMultiplier,
1050 &CFis,
1051 &CmdList,
1052 AtapiCommand,
1053 AtapiCommandLength,
1054 0,
1055 (VOID *)(UINTN)PhyAddr,
1056 DataCount
1057 );
1058
1059 DEBUG ((DEBUG_VERBOSE, "Starting command for PIO transfer:\n"));
1060 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
1061 Status = AhciStartCommand (
1062 PciIo,
1063 Port,
1064 0,
1065 Timeout
1066 );
1067 if (EFI_ERROR (Status)) {
1068 break;
1069 }
1070
1071 if (Read && (AtapiCommand == 0)) {
1072 Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisPioSetup);
1073 if (Status == EFI_SUCCESS) {
1074 PrdCount = *(volatile UINT32 *)(&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
1075 if (PrdCount == DataCount) {
1076 Status = EFI_SUCCESS;
1077 } else {
1078 Status = EFI_DEVICE_ERROR;
1079 }
1080 }
1081 } else {
1082 Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
1083 }
1084
1085 if (Status == EFI_DEVICE_ERROR) {
1086 DEBUG ((DEBUG_ERROR, "PIO command failed at retry %d\n", Retry));
1087 DoRetry = AhciShouldCmdBeRetried (PciIo, Port); // needs to be called before error recovery
1088 RecoveryStatus = AhciRecoverPortError (PciIo, Port);
1089 if (!DoRetry || EFI_ERROR (RecoveryStatus)) {
1090 break;
1091 }
1092 } else {
1093 break;
1094 }
1095 }
1096
1098 PciIo,
1099 Port,
1100 Timeout
1101 );
1102
1104 PciIo,
1105 Port,
1106 Timeout
1107 );
1108
1109 PciIo->Unmap (
1110 PciIo,
1111 Map
1112 );
1113
1114 AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
1115
1116 if (Status == EFI_DEVICE_ERROR) {
1117 DEBUG ((DEBUG_ERROR, "Failed to execute command for PIO transfer:\n"));
1118 //
1119 // Repeat command block here to make sure it is printed on
1120 // device error debug level.
1121 //
1122 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
1123 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
1124 } else {
1125 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
1126 }
1127
1128 return Status;
1129}
1130
1157EFIAPI
1160 IN EFI_AHCI_REGISTERS *AhciRegisters,
1161 IN UINT8 Port,
1162 IN UINT8 PortMultiplier,
1163 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
1164 IN UINT8 AtapiCommandLength,
1165 IN BOOLEAN Read,
1166 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
1167 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
1168 IN OUT VOID *MemoryAddr,
1169 IN UINT32 DataCount,
1170 IN UINT64 Timeout,
1171 IN ATA_NONBLOCK_TASK *Task
1172 )
1173{
1174 EFI_STATUS Status;
1175 EFI_PHYSICAL_ADDRESS PhyAddr;
1176 VOID *Map;
1177 UINTN MapLength;
1180 EFI_AHCI_COMMAND_LIST CmdList;
1181 EFI_PCI_IO_PROTOCOL *PciIo;
1182 EFI_TPL OldTpl;
1183 UINT32 Retry;
1184 EFI_STATUS RecoveryStatus;
1185 BOOLEAN DoRetry;
1186
1187 Map = NULL;
1188 PciIo = Instance->PciIo;
1189
1190 if (PciIo == NULL) {
1191 return EFI_INVALID_PARAMETER;
1192 }
1193
1194 //
1195 // Set Status to suppress incorrect compiler/analyzer warnings
1196 //
1197 Status = EFI_SUCCESS;
1198
1199 //
1200 // DMA buffer allocation. Needs to be done only once for both sync and async
1201 // DMA transfers irrespective of number of retries.
1202 //
1203 if ((Task == NULL) || ((Task != NULL) && (Task->Map == NULL))) {
1204 if (Read) {
1206 } else {
1208 }
1209
1210 MapLength = DataCount;
1211 Status = PciIo->Map (
1212 PciIo,
1213 Flag,
1214 MemoryAddr,
1215 &MapLength,
1216 &PhyAddr,
1217 &Map
1218 );
1219
1220 if (EFI_ERROR (Status) || (DataCount != MapLength)) {
1221 return EFI_BAD_BUFFER_SIZE;
1222 }
1223
1224 if (Task != NULL) {
1225 Task->Map = Map;
1226 }
1227 }
1228
1229 if ((Task == NULL) || ((Task != NULL) && !Task->IsStart)) {
1230 AhciBuildCommandFis (&CFis, AtaCommandBlock);
1231
1232 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
1233
1234 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
1235 CmdList.AhciCmdW = Read ? 0 : 1;
1236 }
1237
1238 if (Task == NULL) {
1239 //
1240 // Before starting the Blocking BlockIO operation, push to finish all non-blocking
1241 // BlockIO tasks.
1242 // Delay 100us to simulate the blocking time out checking.
1243 //
1244 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1245 while (!IsListEmpty (&Instance->NonBlockingTaskList)) {
1247 //
1248 // Stall for 100us.
1249 //
1250 MicroSecondDelay (100);
1251 }
1252
1253 gBS->RestoreTPL (OldTpl);
1254 for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
1256 PciIo,
1257 AhciRegisters,
1258 Port,
1259 PortMultiplier,
1260 &CFis,
1261 &CmdList,
1262 AtapiCommand,
1263 AtapiCommandLength,
1264 0,
1265 (VOID *)(UINTN)PhyAddr,
1266 DataCount
1267 );
1268
1269 DEBUG ((DEBUG_VERBOSE, "Starting command for sync DMA transfer:\n"));
1270 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
1271 Status = AhciStartCommand (
1272 PciIo,
1273 Port,
1274 0,
1275 Timeout
1276 );
1277 if (EFI_ERROR (Status)) {
1278 break;
1279 }
1280
1281 Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
1282 if (Status == EFI_DEVICE_ERROR) {
1283 DEBUG ((DEBUG_ERROR, "DMA command failed at retry: %d\n", Retry));
1284 DoRetry = AhciShouldCmdBeRetried (PciIo, Port); // needs to be called before error recovery
1285 RecoveryStatus = AhciRecoverPortError (PciIo, Port);
1286 if (!DoRetry || EFI_ERROR (RecoveryStatus)) {
1287 break;
1288 }
1289 } else {
1290 break;
1291 }
1292 }
1293 } else {
1294 if (!Task->IsStart) {
1296 PciIo,
1297 AhciRegisters,
1298 Port,
1299 PortMultiplier,
1300 &CFis,
1301 &CmdList,
1302 AtapiCommand,
1303 AtapiCommandLength,
1304 0,
1305 (VOID *)(UINTN)PhyAddr,
1306 DataCount
1307 );
1308
1309 DEBUG ((DEBUG_VERBOSE, "Starting command for async DMA transfer:\n"));
1310 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
1311 Status = AhciStartCommand (
1312 PciIo,
1313 Port,
1314 0,
1315 Timeout
1316 );
1317 if (!EFI_ERROR (Status)) {
1318 Task->IsStart = TRUE;
1319 }
1320 }
1321
1322 if (Task->IsStart) {
1323 Status = AhciCheckFisReceived (PciIo, Port, SataFisD2H);
1324 if (Status == EFI_DEVICE_ERROR) {
1325 DEBUG ((DEBUG_ERROR, "DMA command failed at retry: %d\n", Task->RetryTimes));
1326 DoRetry = AhciShouldCmdBeRetried (PciIo, Port); // call this before error recovery
1327 RecoveryStatus = AhciRecoverPortError (PciIo, Port);
1328 //
1329 // If recovery passed mark the Task as not started and change the status
1330 // to EFI_NOT_READY. This will make the higher level call this function again
1331 // and on next call the command will be re-issued due to IsStart being FALSE.
1332 // This also makes the next condition decrement the RetryTimes.
1333 //
1334 if (DoRetry && (RecoveryStatus == EFI_SUCCESS)) {
1335 Task->IsStart = FALSE;
1336 Status = EFI_NOT_READY;
1337 }
1338 }
1339
1340 if (Status == EFI_NOT_READY) {
1341 if (!Task->InfiniteWait && (Task->RetryTimes == 0)) {
1342 Status = EFI_TIMEOUT;
1343 } else {
1344 Task->RetryTimes--;
1345 }
1346 }
1347 }
1348 }
1349
1350 //
1351 // For Blocking mode, the command should be stopped, the Fis should be disabled
1352 // and the PciIo should be unmapped.
1353 // For non-blocking mode, only when a error is happened (if the return status is
1354 // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1355 // context cleanup, then set the packet's Asb status.
1356 //
1357 if ((Task == NULL) ||
1358 ((Task != NULL) && (Status != EFI_NOT_READY))
1359 )
1360 {
1362 PciIo,
1363 Port,
1364 Timeout
1365 );
1366
1368 PciIo,
1369 Port,
1370 Timeout
1371 );
1372
1373 PciIo->Unmap (
1374 PciIo,
1375 (Task != NULL) ? Task->Map : Map
1376 );
1377
1378 if (Task != NULL) {
1379 Task->Packet->Asb->AtaStatus = 0x01;
1380 }
1381 }
1382
1383 AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
1384
1385 if (Status == EFI_DEVICE_ERROR) {
1386 DEBUG ((DEBUG_ERROR, "Failed to execute command for DMA transfer:\n"));
1387 //
1388 // Repeat command block here to make sure it is printed on
1389 // device error debug level.
1390 //
1391 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
1392 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
1393 } else {
1394 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
1395 }
1396
1397 return Status;
1398}
1399
1423EFIAPI
1425 IN EFI_PCI_IO_PROTOCOL *PciIo,
1426 IN EFI_AHCI_REGISTERS *AhciRegisters,
1427 IN UINT8 Port,
1428 IN UINT8 PortMultiplier,
1429 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
1430 IN UINT8 AtapiCommandLength,
1431 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
1432 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
1433 IN UINT64 Timeout,
1434 IN ATA_NONBLOCK_TASK *Task
1435 )
1436{
1437 EFI_STATUS Status;
1439 EFI_AHCI_COMMAND_LIST CmdList;
1440 UINT32 Retry;
1441 EFI_STATUS RecoveryStatus;
1442 BOOLEAN DoRetry;
1443
1444 //
1445 // Package read needed
1446 //
1447 AhciBuildCommandFis (&CFis, AtaCommandBlock);
1448
1449 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
1450
1451 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
1452
1453 for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
1455 PciIo,
1456 AhciRegisters,
1457 Port,
1458 PortMultiplier,
1459 &CFis,
1460 &CmdList,
1461 AtapiCommand,
1462 AtapiCommandLength,
1463 0,
1464 NULL,
1465 0
1466 );
1467
1468 DEBUG ((DEBUG_VERBOSE, "Starting command for non data transfer:\n"));
1469 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
1470 Status = AhciStartCommand (
1471 PciIo,
1472 Port,
1473 0,
1474 Timeout
1475 );
1476 if (EFI_ERROR (Status)) {
1477 break;
1478 }
1479
1480 Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
1481 if (Status == EFI_DEVICE_ERROR) {
1482 DEBUG ((DEBUG_ERROR, "Non data transfer failed at retry %d\n", Retry));
1483 DoRetry = AhciShouldCmdBeRetried (PciIo, Port); // call this before error recovery
1484 RecoveryStatus = AhciRecoverPortError (PciIo, Port);
1485 if (!DoRetry || EFI_ERROR (RecoveryStatus)) {
1486 break;
1487 }
1488 } else {
1489 break;
1490 }
1491 }
1492
1494 PciIo,
1495 Port,
1496 Timeout
1497 );
1498
1500 PciIo,
1501 Port,
1502 Timeout
1503 );
1504
1505 AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
1506
1507 if (Status == EFI_DEVICE_ERROR) {
1508 DEBUG ((DEBUG_ERROR, "Failed to execute command for non data transfer:\n"));
1509 //
1510 // Repeat command block here to make sure it is printed on
1511 // device error debug level.
1512 //
1513 AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
1514 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
1515 } else {
1516 AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
1517 }
1518
1519 return Status;
1520}
1521
1535EFIAPI
1537 IN EFI_PCI_IO_PROTOCOL *PciIo,
1538 IN UINT8 Port,
1539 IN UINT64 Timeout
1540 )
1541{
1542 UINT32 Offset;
1543 UINT32 Data;
1544
1545 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1546 Data = AhciReadReg (PciIo, Offset);
1547
1548 if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {
1549 return EFI_SUCCESS;
1550 }
1551
1552 if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
1553 AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_ST));
1554 }
1555
1556 return AhciWaitMmioSet (
1557 PciIo,
1558 Offset,
1559 EFI_AHCI_PORT_CMD_CR,
1560 0,
1561 Timeout
1562 );
1563}
1564
1579EFIAPI
1581 IN EFI_PCI_IO_PROTOCOL *PciIo,
1582 IN UINT8 Port,
1583 IN UINT8 CommandSlot,
1584 IN UINT64 Timeout
1585 )
1586{
1587 UINT32 CmdSlotBit;
1588 EFI_STATUS Status;
1589 UINT32 PortStatus;
1590 UINT32 StartCmd;
1591 UINT32 PortTfd;
1592 UINT32 Offset;
1593 UINT32 Capability;
1594
1595 //
1596 // Collect AHCI controller information
1597 //
1598 Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1599
1600 CmdSlotBit = (UINT32)(1 << CommandSlot);
1601
1603 PciIo,
1604 Port
1605 );
1606
1607 Status = AhciEnableFisReceive (
1608 PciIo,
1609 Port,
1610 Timeout
1611 );
1612
1613 if (EFI_ERROR (Status)) {
1614 return Status;
1615 }
1616
1617 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1618 PortStatus = AhciReadReg (PciIo, Offset);
1619
1620 StartCmd = 0;
1621 if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
1622 StartCmd = AhciReadReg (PciIo, Offset);
1623 StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
1624 StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
1625 }
1626
1627 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
1628 PortTfd = AhciReadReg (PciIo, Offset);
1629
1630 if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
1631 if ((Capability & BIT24) != 0) {
1632 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1633 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);
1634
1636 PciIo,
1637 Offset,
1638 EFI_AHCI_PORT_CMD_CLO,
1639 0,
1640 Timeout
1641 );
1642 }
1643 }
1644
1645 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1646 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
1647
1648 //
1649 // Setting the command
1650 //
1651 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
1652 AhciAndReg (PciIo, Offset, 0);
1653 AhciOrReg (PciIo, Offset, CmdSlotBit);
1654
1655 return EFI_SUCCESS;
1656}
1657
1670EFIAPI
1672 IN EFI_PCI_IO_PROTOCOL *PciIo,
1673 IN UINT64 Timeout
1674 )
1675{
1676 UINT64 Delay;
1677 UINT32 Value;
1678
1679 //
1680 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1681 //
1682 Value = AhciReadReg (PciIo, EFI_AHCI_GHC_OFFSET);
1683
1684 if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
1685 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
1686 }
1687
1688 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
1689
1690 Delay = DivU64x32 (Timeout, 1000) + 1;
1691
1692 do {
1693 Value = AhciReadReg (PciIo, EFI_AHCI_GHC_OFFSET);
1694
1695 if ((Value & EFI_AHCI_GHC_RESET) == 0) {
1696 break;
1697 }
1698
1699 //
1700 // Stall for 100 microseconds.
1701 //
1702 MicroSecondDelay (100);
1703
1704 Delay--;
1705 } while (Delay > 0);
1706
1707 if (Delay == 0) {
1708 return EFI_TIMEOUT;
1709 }
1710
1711 return EFI_SUCCESS;
1712}
1713
1728EFIAPI
1730 IN EFI_PCI_IO_PROTOCOL *PciIo,
1731 IN EFI_AHCI_REGISTERS *AhciRegisters,
1732 IN UINT8 Port,
1733 IN UINT8 PortMultiplier,
1734 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
1735 )
1736{
1737 EFI_STATUS Status;
1738 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1739 UINT8 LBAMid;
1740 UINT8 LBAHigh;
1741 UINTN FisBaseAddr;
1742 UINT32 Value;
1743
1744 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1745
1746 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1747 AtaCommandBlock.AtaFeatures = ATA_SMART_RETURN_STATUS;
1748 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1749 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1750
1751 //
1752 // Send S.M.A.R.T Read Return Status command to device
1753 //
1754 Status = AhciNonDataTransfer (
1755 PciIo,
1756 AhciRegisters,
1757 (UINT8)Port,
1758 (UINT8)PortMultiplier,
1759 NULL,
1760 0,
1761 &AtaCommandBlock,
1762 AtaStatusBlock,
1763 ATA_ATAPI_TIMEOUT,
1764 NULL
1765 );
1766
1767 if (EFI_ERROR (Status)) {
1769 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1770 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
1771 );
1772 return EFI_DEVICE_ERROR;
1773 }
1774
1777 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
1778 );
1779
1780 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
1781
1782 Value = *(UINT32 *)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
1783
1784 if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {
1785 LBAMid = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[5];
1786 LBAHigh = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[6];
1787
1788 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
1789 //
1790 // The threshold exceeded condition is not detected by the device
1791 //
1792 DEBUG ((DEBUG_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1795 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
1796 );
1797 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
1798 //
1799 // The threshold exceeded condition is detected by the device
1800 //
1801 DEBUG ((DEBUG_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1804 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
1805 );
1806 }
1807 }
1808
1809 return EFI_SUCCESS;
1810}
1811
1823VOID
1824EFIAPI
1826 IN EFI_PCI_IO_PROTOCOL *PciIo,
1827 IN EFI_AHCI_REGISTERS *AhciRegisters,
1828 IN UINT8 Port,
1829 IN UINT8 PortMultiplier,
1830 IN EFI_IDENTIFY_DATA *IdentifyData,
1831 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
1832 )
1833{
1834 EFI_STATUS Status;
1835 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1836
1837 //
1838 // Detect if the device supports S.M.A.R.T.
1839 //
1840 if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
1841 //
1842 // S.M.A.R.T is not supported by the device
1843 //
1844 DEBUG ((
1845 DEBUG_INFO,
1846 "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1847 Port,
1848 PortMultiplier
1849 ));
1851 EFI_ERROR_CODE | EFI_ERROR_MINOR,
1852 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
1853 );
1854 } else {
1855 //
1856 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1857 //
1858 if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
1861 (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)
1862 );
1863
1864 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1865
1866 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1867 AtaCommandBlock.AtaFeatures = ATA_SMART_ENABLE_OPERATION;
1868 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1869 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1870
1871 //
1872 // Send S.M.A.R.T Enable command to device
1873 //
1874 Status = AhciNonDataTransfer (
1875 PciIo,
1876 AhciRegisters,
1877 (UINT8)Port,
1878 (UINT8)PortMultiplier,
1879 NULL,
1880 0,
1881 &AtaCommandBlock,
1882 AtaStatusBlock,
1883 ATA_ATAPI_TIMEOUT,
1884 NULL
1885 );
1886
1887 if (!EFI_ERROR (Status)) {
1888 //
1889 // Send S.M.A.R.T AutoSave command to device
1890 //
1891 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1892
1893 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1894 AtaCommandBlock.AtaFeatures = 0xD2;
1895 AtaCommandBlock.AtaSectorCount = 0xF1;
1896 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1897 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1898
1899 Status = AhciNonDataTransfer (
1900 PciIo,
1901 AhciRegisters,
1902 (UINT8)Port,
1903 (UINT8)PortMultiplier,
1904 NULL,
1905 0,
1906 &AtaCommandBlock,
1907 AtaStatusBlock,
1908 ATA_ATAPI_TIMEOUT,
1909 NULL
1910 );
1911 }
1912 }
1913
1915 PciIo,
1916 AhciRegisters,
1917 (UINT8)Port,
1918 (UINT8)PortMultiplier,
1919 AtaStatusBlock
1920 );
1921
1922 DEBUG ((
1923 DEBUG_INFO,
1924 "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1925 Port,
1926 PortMultiplier
1927 ));
1928 }
1929
1930 return;
1931}
1932
1949EFIAPI
1951 IN EFI_PCI_IO_PROTOCOL *PciIo,
1952 IN EFI_AHCI_REGISTERS *AhciRegisters,
1953 IN UINT8 Port,
1954 IN UINT8 PortMultiplier,
1955 IN OUT EFI_IDENTIFY_DATA *Buffer
1956 )
1957{
1958 EFI_STATUS Status;
1959 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1960 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1961
1962 if ((PciIo == NULL) || (AhciRegisters == NULL) || (Buffer == NULL)) {
1963 return EFI_INVALID_PARAMETER;
1964 }
1965
1966 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1967 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1968
1969 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
1970 AtaCommandBlock.AtaSectorCount = 1;
1971
1972 Status = AhciPioTransfer (
1973 PciIo,
1974 AhciRegisters,
1975 Port,
1976 PortMultiplier,
1977 NULL,
1978 0,
1979 TRUE,
1980 &AtaCommandBlock,
1981 &AtaStatusBlock,
1982 Buffer,
1983 sizeof (EFI_IDENTIFY_DATA),
1984 ATA_ATAPI_TIMEOUT,
1985 NULL
1986 );
1987
1988 return Status;
1989}
1990
2007EFIAPI
2009 IN EFI_PCI_IO_PROTOCOL *PciIo,
2010 IN EFI_AHCI_REGISTERS *AhciRegisters,
2011 IN UINT8 Port,
2012 IN UINT8 PortMultiplier,
2013 IN OUT EFI_IDENTIFY_DATA *Buffer
2014 )
2015{
2016 EFI_STATUS Status;
2017 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
2018 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
2019
2020 if ((PciIo == NULL) || (AhciRegisters == NULL)) {
2021 return EFI_INVALID_PARAMETER;
2022 }
2023
2024 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2025 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2026
2027 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;
2028 AtaCommandBlock.AtaSectorCount = 1;
2029
2030 Status = AhciPioTransfer (
2031 PciIo,
2032 AhciRegisters,
2033 Port,
2034 PortMultiplier,
2035 NULL,
2036 0,
2037 TRUE,
2038 &AtaCommandBlock,
2039 &AtaStatusBlock,
2040 Buffer,
2041 sizeof (EFI_IDENTIFY_DATA),
2042 ATA_ATAPI_TIMEOUT,
2043 NULL
2044 );
2045
2046 return Status;
2047}
2048
2067EFIAPI
2069 IN EFI_PCI_IO_PROTOCOL *PciIo,
2070 IN EFI_AHCI_REGISTERS *AhciRegisters,
2071 IN UINT8 Port,
2072 IN UINT8 PortMultiplier,
2073 IN UINT16 Feature,
2074 IN UINT32 FeatureSpecificData,
2075 IN UINT64 Timeout
2076 )
2077{
2078 EFI_STATUS Status;
2079 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
2080 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
2081
2082 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2083 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2084
2085 AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;
2086 AtaCommandBlock.AtaFeatures = (UINT8)Feature;
2087 AtaCommandBlock.AtaFeaturesExp = (UINT8)(Feature >> 8);
2088 AtaCommandBlock.AtaSectorCount = (UINT8)FeatureSpecificData;
2089 AtaCommandBlock.AtaSectorNumber = (UINT8)(FeatureSpecificData >> 8);
2090 AtaCommandBlock.AtaCylinderLow = (UINT8)(FeatureSpecificData >> 16);
2091 AtaCommandBlock.AtaCylinderHigh = (UINT8)(FeatureSpecificData >> 24);
2092
2093 Status = AhciNonDataTransfer (
2094 PciIo,
2095 AhciRegisters,
2096 (UINT8)Port,
2097 (UINT8)PortMultiplier,
2098 NULL,
2099 0,
2100 &AtaCommandBlock,
2101 &AtaStatusBlock,
2102 Timeout,
2103 NULL
2104 );
2105
2106 return Status;
2107}
2108
2125EFIAPI
2127 IN EFI_PCI_IO_PROTOCOL *PciIo,
2128 IN EFI_AHCI_REGISTERS *AhciRegisters,
2129 IN UINT8 Port,
2130 IN UINT8 PortMultiplier,
2132 )
2133{
2134 EFI_STATUS Status;
2135 VOID *Buffer;
2136 UINT32 Length;
2137 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
2138 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
2139 BOOLEAN Read;
2140
2141 if ((Packet == NULL) || (Packet->Cdb == NULL)) {
2142 return EFI_INVALID_PARAMETER;
2143 }
2144
2145 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2146 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2147 AtaCommandBlock.AtaCommand = ATA_CMD_PACKET;
2148 //
2149 // No OVL; No DMA
2150 //
2151 AtaCommandBlock.AtaFeatures = 0x00;
2152 //
2153 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
2154 // determine how many data should be transferred.
2155 //
2156 AtaCommandBlock.AtaCylinderLow = (UINT8)(ATAPI_MAX_BYTE_COUNT & 0x00ff);
2157 AtaCommandBlock.AtaCylinderHigh = (UINT8)(ATAPI_MAX_BYTE_COUNT >> 8);
2158
2159 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
2160 Buffer = Packet->InDataBuffer;
2161 Length = Packet->InTransferLength;
2162 Read = TRUE;
2163 } else {
2164 Buffer = Packet->OutDataBuffer;
2165 Length = Packet->OutTransferLength;
2166 Read = FALSE;
2167 }
2168
2169 if (Length == 0) {
2170 Status = AhciNonDataTransfer (
2171 PciIo,
2172 AhciRegisters,
2173 Port,
2174 PortMultiplier,
2175 Packet->Cdb,
2176 Packet->CdbLength,
2177 &AtaCommandBlock,
2178 &AtaStatusBlock,
2179 Packet->Timeout,
2180 NULL
2181 );
2182 } else {
2183 Status = AhciPioTransfer (
2184 PciIo,
2185 AhciRegisters,
2186 Port,
2187 PortMultiplier,
2188 Packet->Cdb,
2189 Packet->CdbLength,
2190 Read,
2191 &AtaCommandBlock,
2192 &AtaStatusBlock,
2193 Buffer,
2194 Length,
2195 Packet->Timeout,
2196 NULL
2197 );
2198 }
2199
2200 return Status;
2201}
2202
2211EFIAPI
2213 IN EFI_PCI_IO_PROTOCOL *PciIo,
2214 IN OUT EFI_AHCI_REGISTERS *AhciRegisters
2215 )
2216{
2217 EFI_STATUS Status;
2218 UINTN Bytes;
2219 VOID *Buffer;
2220
2221 UINT32 Capability;
2222 UINT32 PortImplementBitMap;
2223 UINT8 MaxPortNumber;
2224 UINT8 MaxCommandSlotNumber;
2225 BOOLEAN Support64Bit;
2226 UINT64 MaxReceiveFisSize;
2227 UINT64 MaxCommandListSize;
2228 UINT64 MaxCommandTableSize;
2229 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr;
2230 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr;
2231 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr;
2232
2233 Buffer = NULL;
2234 //
2235 // Collect AHCI controller information
2236 //
2237 Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);
2238 //
2239 // Get the number of command slots per port supported by this HBA.
2240 //
2241 MaxCommandSlotNumber = (UINT8)(((Capability & 0x1F00) >> 8) + 1);
2242 Support64Bit = (BOOLEAN)(((Capability & BIT31) != 0) ? TRUE : FALSE);
2243
2244 PortImplementBitMap = AhciReadReg (PciIo, EFI_AHCI_PI_OFFSET);
2245 //
2246 // Get the highest bit of implemented ports which decides how many bytes are allocated for received FIS.
2247 //
2248 MaxPortNumber = (UINT8)(UINTN)(HighBitSet32 (PortImplementBitMap) + 1);
2249 if (MaxPortNumber == 0) {
2250 return EFI_DEVICE_ERROR;
2251 }
2252
2253 MaxReceiveFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
2254 Status = PciIo->AllocateBuffer (
2255 PciIo,
2258 EFI_SIZE_TO_PAGES ((UINTN)MaxReceiveFisSize),
2259 &Buffer,
2260 0
2261 );
2262
2263 if (EFI_ERROR (Status)) {
2264 return EFI_OUT_OF_RESOURCES;
2265 }
2266
2267 ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);
2268
2269 AhciRegisters->AhciRFis = Buffer;
2270 AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;
2271 Bytes = (UINTN)MaxReceiveFisSize;
2272
2273 Status = PciIo->Map (
2274 PciIo,
2276 Buffer,
2277 &Bytes,
2278 &AhciRFisPciAddr,
2279 &AhciRegisters->MapRFis
2280 );
2281
2282 if (EFI_ERROR (Status) || (Bytes != MaxReceiveFisSize)) {
2283 //
2284 // Map error or unable to map the whole RFis buffer into a contiguous region.
2285 //
2286 Status = EFI_OUT_OF_RESOURCES;
2287 goto Error6;
2288 }
2289
2290 if ((!Support64Bit) && (AhciRFisPciAddr > 0x100000000ULL)) {
2291 //
2292 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2293 //
2294 Status = EFI_DEVICE_ERROR;
2295 goto Error5;
2296 }
2297
2298 AhciRegisters->AhciRFisPciAddr = (EFI_AHCI_RECEIVED_FIS *)(UINTN)AhciRFisPciAddr;
2299
2300 //
2301 // Allocate memory for command list
2302 // Note that the implementation is a single task model which only use a command list for all ports.
2303 //
2304 Buffer = NULL;
2305 MaxCommandListSize = MaxCommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST);
2306 Status = PciIo->AllocateBuffer (
2307 PciIo,
2310 EFI_SIZE_TO_PAGES ((UINTN)MaxCommandListSize),
2311 &Buffer,
2312 0
2313 );
2314
2315 if (EFI_ERROR (Status)) {
2316 //
2317 // Free mapped resource.
2318 //
2319 Status = EFI_OUT_OF_RESOURCES;
2320 goto Error5;
2321 }
2322
2323 ZeroMem (Buffer, (UINTN)MaxCommandListSize);
2324
2325 AhciRegisters->AhciCmdList = Buffer;
2326 AhciRegisters->MaxCommandListSize = MaxCommandListSize;
2327 Bytes = (UINTN)MaxCommandListSize;
2328
2329 Status = PciIo->Map (
2330 PciIo,
2332 Buffer,
2333 &Bytes,
2334 &AhciCmdListPciAddr,
2335 &AhciRegisters->MapCmdList
2336 );
2337
2338 if (EFI_ERROR (Status) || (Bytes != MaxCommandListSize)) {
2339 //
2340 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2341 //
2342 Status = EFI_OUT_OF_RESOURCES;
2343 goto Error4;
2344 }
2345
2346 if ((!Support64Bit) && (AhciCmdListPciAddr > 0x100000000ULL)) {
2347 //
2348 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2349 //
2350 Status = EFI_DEVICE_ERROR;
2351 goto Error3;
2352 }
2353
2354 AhciRegisters->AhciCmdListPciAddr = (EFI_AHCI_COMMAND_LIST *)(UINTN)AhciCmdListPciAddr;
2355
2356 //
2357 // Allocate memory for command table
2358 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2359 //
2360 Buffer = NULL;
2361 MaxCommandTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
2362
2363 Status = PciIo->AllocateBuffer (
2364 PciIo,
2367 EFI_SIZE_TO_PAGES ((UINTN)MaxCommandTableSize),
2368 &Buffer,
2369 0
2370 );
2371
2372 if (EFI_ERROR (Status)) {
2373 //
2374 // Free mapped resource.
2375 //
2376 Status = EFI_OUT_OF_RESOURCES;
2377 goto Error3;
2378 }
2379
2380 ZeroMem (Buffer, (UINTN)MaxCommandTableSize);
2381
2382 AhciRegisters->AhciCommandTable = Buffer;
2383 AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;
2384 Bytes = (UINTN)MaxCommandTableSize;
2385
2386 Status = PciIo->Map (
2387 PciIo,
2389 Buffer,
2390 &Bytes,
2391 &AhciCommandTablePciAddr,
2392 &AhciRegisters->MapCommandTable
2393 );
2394
2395 if (EFI_ERROR (Status) || (Bytes != MaxCommandTableSize)) {
2396 //
2397 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2398 //
2399 Status = EFI_OUT_OF_RESOURCES;
2400 goto Error2;
2401 }
2402
2403 if ((!Support64Bit) && (AhciCommandTablePciAddr > 0x100000000ULL)) {
2404 //
2405 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2406 //
2407 Status = EFI_DEVICE_ERROR;
2408 goto Error1;
2409 }
2410
2411 AhciRegisters->AhciCommandTablePciAddr = (EFI_AHCI_COMMAND_TABLE *)(UINTN)AhciCommandTablePciAddr;
2412
2413 return EFI_SUCCESS;
2414 //
2415 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2416 //
2417Error1:
2418 PciIo->Unmap (
2419 PciIo,
2420 AhciRegisters->MapCommandTable
2421 );
2422Error2:
2423 PciIo->FreeBuffer (
2424 PciIo,
2425 EFI_SIZE_TO_PAGES ((UINTN)MaxCommandTableSize),
2426 AhciRegisters->AhciCommandTable
2427 );
2428Error3:
2429 PciIo->Unmap (
2430 PciIo,
2431 AhciRegisters->MapCmdList
2432 );
2433Error4:
2434 PciIo->FreeBuffer (
2435 PciIo,
2436 EFI_SIZE_TO_PAGES ((UINTN)MaxCommandListSize),
2437 AhciRegisters->AhciCmdList
2438 );
2439Error5:
2440 PciIo->Unmap (
2441 PciIo,
2442 AhciRegisters->MapRFis
2443 );
2444Error6:
2445 PciIo->FreeBuffer (
2446 PciIo,
2447 EFI_SIZE_TO_PAGES ((UINTN)MaxReceiveFisSize),
2448 AhciRegisters->AhciRFis
2449 );
2450
2451 return Status;
2452}
2453
2470 IN EFI_PCI_IO_PROTOCOL *PciIo,
2471 IN EFI_AHCI_REGISTERS *AhciRegisters,
2472 IN UINT8 Port,
2473 IN UINT8 PortMultiplier,
2474 IN OUT UINT8 *Buffer,
2475 IN UINT8 LogNumber,
2476 IN UINT8 PageNumber
2477 )
2478{
2479 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
2480 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
2481
2482 if ((PciIo == NULL) || (AhciRegisters == NULL) || (Buffer == NULL)) {
2483 return EFI_INVALID_PARAMETER;
2484 }
2485
2489 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2490 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2491 ZeroMem (Buffer, 512);
2492
2493 AtaCommandBlock.AtaCommand = ATA_CMD_READ_LOG_EXT;
2494 AtaCommandBlock.AtaSectorCount = 1;
2495 AtaCommandBlock.AtaSectorNumber = LogNumber;
2496 AtaCommandBlock.AtaCylinderLow = PageNumber;
2497
2498 return AhciPioTransfer (
2499 PciIo,
2500 AhciRegisters,
2501 Port,
2502 PortMultiplier,
2503 NULL,
2504 0,
2505 TRUE,
2506 &AtaCommandBlock,
2507 &AtaStatusBlock,
2508 Buffer,
2509 512,
2510 ATA_ATAPI_TIMEOUT,
2511 NULL
2512 );
2513}
2514
2529 IN EFI_PCI_IO_PROTOCOL *PciIo,
2530 IN EFI_AHCI_REGISTERS *AhciRegisters,
2531 IN UINT8 Port,
2532 IN UINT8 PortMultiplier,
2533 IN EFI_IDENTIFY_DATA *IdentifyData
2534 )
2535{
2536 EFI_STATUS Status;
2537 UINT32 Offset;
2538 UINT32 Capability2;
2539 UINT8 LogData[512];
2540 DEVSLP_TIMING_VARIABLES DevSlpTiming;
2541 UINT32 PortCmd;
2542 UINT32 PortDevSlp;
2543
2544 if (mAtaAtapiPolicy->DeviceSleepEnable != 1) {
2545 return EFI_SUCCESS;
2546 }
2547
2548 //
2549 // Do not enable DevSlp if DevSlp is not supported.
2550 //
2551 Capability2 = AhciReadReg (PciIo, AHCI_CAPABILITY2_OFFSET);
2552 DEBUG ((DEBUG_INFO, "AHCI CAPABILITY2 = %08x\n", Capability2));
2553 if ((Capability2 & AHCI_CAP2_SDS) == 0) {
2554 return EFI_UNSUPPORTED;
2555 }
2556
2557 //
2558 // Do not enable DevSlp if DevSlp is not present
2559 // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2560 //
2561 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH;
2562 PortCmd = AhciReadReg (PciIo, Offset + EFI_AHCI_PORT_CMD);
2563 PortDevSlp = AhciReadReg (PciIo, Offset + AHCI_PORT_DEVSLP);
2564 DEBUG ((DEBUG_INFO, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd, PortDevSlp));
2565 if (((PortDevSlp & AHCI_PORT_DEVSLP_DSP) == 0) ||
2566 ((PortCmd & (EFI_AHCI_PORT_CMD_HPCP | EFI_AHCI_PORT_CMD_MPSP)) != 0)
2567 )
2568 {
2569 return EFI_UNSUPPORTED;
2570 }
2571
2572 //
2573 // Do not enable DevSlp if the device doesn't support DevSlp
2574 //
2575 DEBUG ((
2576 DEBUG_INFO,
2577 "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2578 IdentifyData->AtaData.reserved_77,
2579 IdentifyData->AtaData.serial_ata_features_supported,
2580 IdentifyData->AtaData.serial_ata_features_enabled
2581 ));
2582 if ((IdentifyData->AtaData.serial_ata_features_supported & BIT8) == 0) {
2583 DEBUG ((
2584 DEBUG_INFO,
2585 "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2586 Port,
2587 PortMultiplier
2588 ));
2589 return EFI_UNSUPPORTED;
2590 }
2591
2592 //
2593 // Enable DevSlp when it is not enabled.
2594 //
2595 if ((IdentifyData->AtaData.serial_ata_features_enabled & BIT8) != 0) {
2596 Status = AhciDeviceSetFeature (
2597 PciIo,
2598 AhciRegisters,
2599 Port,
2600 0,
2602 0x09,
2603 ATA_ATAPI_TIMEOUT
2604 );
2605 DEBUG ((
2606 DEBUG_INFO,
2607 "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2608 Port,
2609 PortMultiplier,
2610 Status
2611 ));
2612 if (EFI_ERROR (Status)) {
2613 return Status;
2614 }
2615 }
2616
2617 Status = AhciReadLogExt (PciIo, AhciRegisters, Port, PortMultiplier, LogData, 0x30, 0x08);
2618
2619 //
2620 // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2621 //
2622 AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd & ~EFI_AHCI_PORT_CMD_ST);
2623 PortDevSlp &= ~AHCI_PORT_DEVSLP_ADSE;
2624 AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2625
2626 //
2627 // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2628 //
2629 PortDevSlp &= ~AHCI_PORT_DEVSLP_DETO_MASK;
2630 PortDevSlp &= ~AHCI_PORT_DEVSLP_MDAT_MASK;
2631 AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2632 DEBUG ((DEBUG_INFO, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port, PortMultiplier, Status));
2633 if (EFI_ERROR (Status)) {
2634 //
2635 // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2636 //
2637 ZeroMem (&DevSlpTiming, sizeof (DevSlpTiming));
2638 } else {
2639 CopyMem (&DevSlpTiming, &LogData[48], sizeof (DevSlpTiming));
2640 DEBUG ((
2641 DEBUG_INFO,
2642 "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2643 DevSlpTiming.Supported,
2644 DevSlpTiming.Deto,
2645 DevSlpTiming.Madt
2646 ));
2647 }
2648
2649 //
2650 // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2651 //
2652 if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Deto == 0)) {
2653 DevSlpTiming.Deto = 20;
2654 }
2655
2656 //
2657 // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2658 //
2659 if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Madt == 0)) {
2660 DevSlpTiming.Madt = 10;
2661 }
2662
2663 PortDevSlp |= DevSlpTiming.Deto << 2;
2664 PortDevSlp |= DevSlpTiming.Madt << 10;
2665 AhciOrReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2666
2667 if (mAtaAtapiPolicy->AggressiveDeviceSleepEnable == 1) {
2668 if ((Capability2 & AHCI_CAP2_SADM) != 0) {
2669 PortDevSlp &= ~AHCI_PORT_DEVSLP_DITO_MASK;
2670 PortDevSlp |= (625 << 15);
2671 AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2672
2673 PortDevSlp |= AHCI_PORT_DEVSLP_ADSE;
2674 AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2675 }
2676 }
2677
2678 AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd);
2679
2680 DEBUG ((
2681 DEBUG_INFO,
2682 "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2683 Port,
2684 PortMultiplier,
2685 PortCmd,
2686 PortDevSlp
2687 ));
2688
2689 return EFI_SUCCESS;
2690}
2691
2704 IN EFI_PCI_IO_PROTOCOL *PciIo,
2705 IN EFI_AHCI_REGISTERS *AhciRegisters,
2706 IN UINT8 Port,
2707 IN UINT8 PortMultiplier,
2708 IN OUT EFI_IDENTIFY_DATA *IdentifyData
2709 )
2710{
2711 EFI_STATUS Status;
2712 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
2713 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
2714 UINT8 Buffer[512];
2715
2716 if (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE) {
2717 //
2718 // Use SET_FEATURE subcommand to spin up the device.
2719 //
2720 Status = AhciDeviceSetFeature (
2721 PciIo,
2722 AhciRegisters,
2723 Port,
2724 PortMultiplier,
2726 0x00,
2727 ATA_SPINUP_TIMEOUT
2728 );
2729 DEBUG ((
2730 DEBUG_INFO,
2731 "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2732 Port,
2733 PortMultiplier,
2734 Status
2735 ));
2736 if (EFI_ERROR (Status)) {
2737 return Status;
2738 }
2739 } else {
2740 ASSERT (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE);
2741
2742 //
2743 // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2744 //
2745 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2746 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2747 //
2748 // Perform READ SECTORS PIO Data-In command to Read LBA 0
2749 //
2750 AtaCommandBlock.AtaCommand = ATA_CMD_READ_SECTORS;
2751 AtaCommandBlock.AtaSectorCount = 0x1;
2752
2753 Status = AhciPioTransfer (
2754 PciIo,
2755 AhciRegisters,
2756 Port,
2757 PortMultiplier,
2758 NULL,
2759 0,
2760 TRUE,
2761 &AtaCommandBlock,
2762 &AtaStatusBlock,
2763 &Buffer,
2764 sizeof (Buffer),
2765 ATA_SPINUP_TIMEOUT,
2766 NULL
2767 );
2768 DEBUG ((
2769 DEBUG_INFO,
2770 "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2771 Port,
2772 PortMultiplier,
2773 Status
2774 ));
2775 if (EFI_ERROR (Status)) {
2776 return Status;
2777 }
2778 }
2779
2780 //
2781 // Read the complete IDENTIFY DEVICE data.
2782 //
2783 ZeroMem (IdentifyData, sizeof (*IdentifyData));
2784 Status = AhciIdentify (PciIo, AhciRegisters, Port, PortMultiplier, IdentifyData);
2785 if (EFI_ERROR (Status)) {
2786 DEBUG ((
2787 DEBUG_ERROR,
2788 "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2789 Port,
2790 PortMultiplier,
2791 Status
2792 ));
2793 return Status;
2794 }
2795
2796 DEBUG ((
2797 DEBUG_INFO,
2798 "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2799 IdentifyData->AtaData.config,
2800 IdentifyData->AtaData.specific_config,
2801 IdentifyData->AtaData.command_set_supported_83,
2802 IdentifyData->AtaData.command_set_feature_enb_86
2803 ));
2804 //
2805 // Check if IDD is incomplete
2806 //
2807 if ((IdentifyData->AtaData.config & BIT2) != 0) {
2808 return EFI_DEVICE_ERROR;
2809 }
2810
2811 return EFI_SUCCESS;
2812}
2813
2825 IN EFI_PCI_IO_PROTOCOL *PciIo,
2826 IN EFI_AHCI_REGISTERS *AhciRegisters,
2827 IN UINT8 Port,
2828 IN UINT8 PortMultiplier
2829 )
2830{
2831 EFI_STATUS Status;
2832
2833 Status = EFI_SUCCESS;
2834 if (mAtaAtapiPolicy->PuisEnable == 0) {
2835 Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_DISABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
2836 } else if (mAtaAtapiPolicy->PuisEnable == 1) {
2837 Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_ENABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
2838 }
2839
2840 DEBUG ((
2841 DEBUG_INFO,
2842 "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2843 (mAtaAtapiPolicy->PuisEnable == 0) ? "Disable" : (
2844 (mAtaAtapiPolicy->PuisEnable == 1) ? "Enable" : "Skip"
2845 ),
2846 Port,
2847 PortMultiplier,
2848 Status
2849 ));
2850 return Status;
2851}
2852
2862EFIAPI
2865 )
2866{
2867 EFI_STATUS Status;
2868 EFI_PCI_IO_PROTOCOL *PciIo;
2870 UINT32 Capability;
2871 UINT8 MaxPortNumber;
2872 UINT32 PortImplementBitMap;
2873
2874 EFI_AHCI_REGISTERS *AhciRegisters;
2875
2876 UINT8 Port;
2877 DATA_64 Data64;
2878 UINT32 Offset;
2879 UINT32 Data;
2880 EFI_IDENTIFY_DATA Buffer;
2881 EFI_ATA_DEVICE_TYPE DeviceType;
2882 EFI_ATA_COLLECTIVE_MODE *SupportedModes;
2883 EFI_ATA_TRANSFER_MODE TransferMode;
2884 UINT32 PhyDetectDelay;
2885 UINT32 Value;
2886
2887 if (Instance == NULL) {
2888 return EFI_INVALID_PARAMETER;
2889 }
2890
2891 PciIo = Instance->PciIo;
2892 IdeInit = Instance->IdeControllerInit;
2893
2894 Status = AhciReset (PciIo, EFI_AHCI_BUS_RESET_TIMEOUT);
2895
2896 if (EFI_ERROR (Status)) {
2897 return EFI_DEVICE_ERROR;
2898 }
2899
2900 //
2901 // Collect AHCI controller information
2902 //
2903 Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);
2904
2905 //
2906 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2907 //
2908 Value = AhciReadReg (PciIo, EFI_AHCI_GHC_OFFSET);
2909
2910 if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
2911 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
2912 }
2913
2914 //
2915 // Enable 64-bit DMA support in the PCI layer if this controller
2916 // supports it.
2917 //
2918 if ((Capability & EFI_AHCI_CAP_S64A) != 0) {
2919 Status = PciIo->Attributes (
2920 PciIo,
2923 NULL
2924 );
2925 if (EFI_ERROR (Status)) {
2926 DEBUG ((
2927 DEBUG_WARN,
2928 "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2929 Status
2930 ));
2931 }
2932 }
2933
2934 //
2935 // Get the number of command slots per port supported by this HBA.
2936 //
2937 MaxPortNumber = (UINT8)((Capability & 0x1F) + 1);
2938
2939 //
2940 // Get the bit map of those ports exposed by this HBA.
2941 // It indicates which ports that the HBA supports are available for software to use.
2942 //
2943 PortImplementBitMap = AhciReadReg (PciIo, EFI_AHCI_PI_OFFSET);
2944
2945 AhciRegisters = &Instance->AhciRegisters;
2946 Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
2947
2948 if (EFI_ERROR (Status)) {
2949 return EFI_OUT_OF_RESOURCES;
2950 }
2951
2952 for (Port = 0; Port < EFI_AHCI_MAX_PORTS; Port++) {
2953 if ((PortImplementBitMap & (((UINT32)BIT0) << Port)) != 0) {
2954 //
2955 // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2956 //
2957 if ((MaxPortNumber--) == 0) {
2958 //
2959 // Should never be here.
2960 //
2961 ASSERT (FALSE);
2962 return EFI_SUCCESS;
2963 }
2964
2965 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
2966
2967 //
2968 // Initialize FIS Base Address Register and Command List Base Address Register for use.
2969 //
2970 Data64.Uint64 = (UINTN)(AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
2971 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
2972 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2973 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
2974 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2975
2976 Data64.Uint64 = (UINTN)(AhciRegisters->AhciCmdListPciAddr);
2977 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
2978 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2979 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
2980 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2981
2982 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
2983 Data = AhciReadReg (PciIo, Offset);
2984 if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
2985 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
2986 }
2987
2988 if ((Capability & EFI_AHCI_CAP_SSS) != 0) {
2989 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
2990 }
2991
2992 //
2993 // Disable aggressive power management.
2994 //
2995 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
2996 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
2997 //
2998 // Disable the reporting of the corresponding interrupt to system software.
2999 //
3000 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
3001 AhciAndReg (PciIo, Offset, 0);
3002
3003 //
3004 // Now inform the IDE Controller Init Module.
3005 //
3006 IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
3007
3008 //
3009 // Enable FIS Receive DMA engine for the first D2H FIS.
3010 //
3011 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
3012 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
3013
3014 //
3015 // Wait for the Phy to detect the presence of a device.
3016 //
3017 PhyDetectDelay = EFI_AHCI_BUS_PHY_DETECT_TIMEOUT;
3018 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
3019 do {
3020 Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
3021 if ((Data == EFI_AHCI_PORT_SSTS_DET_PCE) || (Data == EFI_AHCI_PORT_SSTS_DET)) {
3022 break;
3023 }
3024
3025 MicroSecondDelay (1000);
3026 PhyDetectDelay--;
3027 } while (PhyDetectDelay > 0);
3028
3029 if (PhyDetectDelay == 0) {
3030 //
3031 // No device detected at this port.
3032 // Clear PxCMD.SUD for those ports at which there are no device present.
3033 //
3034 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
3035 AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_SUD));
3036 continue;
3037 }
3038
3039 Status = AhciWaitDeviceReady (PciIo, Port);
3040 if (EFI_ERROR (Status)) {
3041 continue;
3042 }
3043
3044 //
3045 // When the first D2H register FIS is received, the content of PxSIG register is updated.
3046 //
3047 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
3048 Status = AhciWaitMmioSet (
3049 PciIo,
3050 Offset,
3051 0x0000FFFF,
3052 0x00000101,
3054 );
3055 if (EFI_ERROR (Status)) {
3056 continue;
3057 }
3058
3059 Data = AhciReadReg (PciIo, Offset);
3060 if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
3061 Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
3062
3063 if (EFI_ERROR (Status)) {
3064 continue;
3065 }
3066
3067 DeviceType = EfiIdeCdrom;
3068 } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
3069 Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
3070
3071 if (EFI_ERROR (Status)) {
3072 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));
3073 continue;
3074 }
3075
3076 DEBUG ((
3077 DEBUG_INFO,
3078 "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
3079 Buffer.AtaData.config,
3080 Buffer.AtaData.specific_config,
3083 ));
3084 if ((Buffer.AtaData.config & BIT2) != 0) {
3085 //
3086 // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
3087 //
3088 Status = AhciSpinUpDisk (
3089 PciIo,
3090 AhciRegisters,
3091 Port,
3092 0,
3093 &Buffer
3094 );
3095 if (EFI_ERROR (Status)) {
3096 DEBUG ((DEBUG_ERROR, "Spin up standby device failed - %r\n", Status));
3097 continue;
3098 }
3099 }
3100
3101 DeviceType = EfiIdeHarddisk;
3102 } else {
3103 continue;
3104 }
3105
3106 DEBUG ((
3107 DEBUG_INFO,
3108 "port [%d] port multitplier [%d] has a [%a]\n",
3109 Port,
3110 0,
3111 DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"
3112 ));
3113
3114 //
3115 // If the device is a hard disk, then try to enable S.M.A.R.T feature
3116 //
3117 if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {
3119 PciIo,
3120 AhciRegisters,
3121 Port,
3122 0,
3123 &Buffer,
3124 NULL
3125 );
3126 }
3127
3128 //
3129 // Submit identify data to IDE controller init driver
3130 //
3131 IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
3132
3133 //
3134 // Now start to config ide device parameter and transfer mode.
3135 //
3136 Status = IdeInit->CalculateMode (
3137 IdeInit,
3138 Port,
3139 0,
3140 &SupportedModes
3141 );
3142 if (EFI_ERROR (Status)) {
3143 DEBUG ((DEBUG_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
3144 continue;
3145 }
3146
3147 //
3148 // Set best supported PIO mode on this IDE device
3149 //
3150 if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
3151 TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
3152 } else {
3153 TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
3154 }
3155
3156 TransferMode.ModeNumber = (UINT8)(SupportedModes->PioMode.Mode);
3157
3158 //
3159 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA can't
3160 // be set together. Only one DMA mode can be set to a device. If setting
3161 // DMA mode operation fails, we can continue moving on because we only use
3162 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
3163 //
3164 if (SupportedModes->UdmaMode.Valid) {
3165 TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
3166 TransferMode.ModeNumber = (UINT8)(SupportedModes->UdmaMode.Mode);
3167 } else if (SupportedModes->MultiWordDmaMode.Valid) {
3168 TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
3169 TransferMode.ModeNumber = (UINT8)SupportedModes->MultiWordDmaMode.Mode;
3170 }
3171
3172 Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode), ATA_ATAPI_TIMEOUT);
3173 if (EFI_ERROR (Status)) {
3174 DEBUG ((DEBUG_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
3175 continue;
3176 }
3177
3178 //
3179 // Found a ATA or ATAPI device, add it into the device list.
3180 //
3181 CreateNewDeviceInfo (Instance, Port, 0xFFFF, DeviceType, &Buffer);
3182 if (DeviceType == EfiIdeHarddisk) {
3183 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
3185 PciIo,
3186 AhciRegisters,
3187 Port,
3188 0,
3189 &Buffer
3190 );
3191 }
3192
3193 //
3194 // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
3195 //
3196 if ((Buffer.AtaData.command_set_supported_83 & BIT5) != 0) {
3197 Status = AhciPuisEnable (
3198 PciIo,
3199 AhciRegisters,
3200 Port,
3201 0
3202 );
3203 if (EFI_ERROR (Status)) {
3204 DEBUG ((DEBUG_ERROR, "PUIS enable/disable failed, Status = %r\n", Status));
3205 continue;
3206 }
3207 }
3208 }
3209 }
3210
3211 return EFI_SUCCESS;
3212}
UINT64 UINTN
VOID AhciClearPortStatus(IN UINTN AhciBar, IN UINT8 Port)
Definition: AhciMode.c:302
VOID AhciOrReg(IN UINTN AhciBar, IN UINT32 Offset, IN UINT32 OrData)
Definition: AhciMode.c:142
EFI_STATUS AhciModeInitialization(IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private)
Definition: AhciMode.c:1664
EFI_STATUS AhciNonDataTransfer(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN UINT64 Timeout)
Definition: AhciMode.c:981
VOID AhciBuildCommandFis(IN OUT EFI_AHCI_COMMAND_FIS *CmdFis, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock)
Definition: AhciMode.c:529
EFI_STATUS EFIAPI AhciWaitMmioSet(IN UINTN AhciBar, IN UINT32 Offset, IN UINT32 MaskValue, IN UINT32 TestValue, IN UINT64 Timeout)
Definition: AhciMode.c:172
VOID AhciAndReg(IN UINTN AhciBar, IN UINT32 Offset, IN UINT32 AndData)
Definition: AhciMode.c:119
EFI_STATUS AhciReset(IN UINTN AhciBar, IN UINT64 Timeout)
Definition: AhciMode.c:1084
VOID AhciWriteReg(IN UINTN AhciBar, IN UINT32 Offset, IN UINT32 Data)
Definition: AhciMode.c:101
EFI_STATUS AhciPioTransfer(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN BOOLEAN Read, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN OUT VOID *MemoryAddr, IN UINT32 DataCount, IN UINT64 Timeout)
Definition: AhciMode.c:717
EFI_STATUS AhciCheckMemSet(IN UINTN Address, IN UINT32 MaskValue, IN UINT32 TestValue)
Definition: AhciMode.c:215
EFI_STATUS AhciCreateTransferDescriptor(IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private)
Definition: AhciMode.c:1263
EFI_STATUS AhciDisableFisReceive(IN UINTN AhciBar, IN UINT8 Port, IN UINT64 Timeout)
Definition: AhciMode.c:368
EFI_STATUS AhciIdentify(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN ATA_IDENTIFY_DATA *Buffer)
Definition: AhciMode.c:1143
EFI_STATUS AhciStopCommand(IN UINTN AhciBar, IN UINT8 Port, IN UINT64 Timeout)
Definition: AhciMode.c:574
EFI_STATUS AhciStartCommand(IN UINTN AhciBar, IN UINT8 Port, IN UINT8 CommandSlot, IN UINT64 Timeout)
Definition: AhciMode.c:617
UINT32 AhciReadReg(IN UINTN AhciBar, IN UINT32 Offset)
Definition: AhciMode.c:79
EFI_STATUS AhciWaitMemSet(IN EFI_PHYSICAL_ADDRESS Address, IN UINT32 MaskValue, IN UINT32 TestValue, IN UINT64 Timeout)
Definition: AhciMode.c:246
EFI_STATUS AhciEnableFisReceive(IN UINTN AhciBar, IN UINT8 Port, IN UINT64 Timeout)
Definition: AhciMode.c:340
VOID AhciBuildCommand(IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT8 FisIndex, IN EFI_AHCI_COMMAND_FIS *CommandFis, IN EFI_AHCI_COMMAND_LIST *CommandList, IN UINT8 CommandSlotNumber, IN OUT VOID *DataPhysicalAddr, IN UINT32 DataLength)
Definition: AhciMode.c:422
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
EFI_STATUS EFIAPI AhciPacketCommandExecute(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet)
Definition: AhciMode.c:2126
VOID EFIAPI AhciAtaSmartSupport(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN EFI_IDENTIFY_DATA *IdentifyData, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock)
Definition: AhciMode.c:1825
VOID AhciPrintCommandBlock(IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN UINT32 DebugLevel)
Definition: AhciMode.c:908
EFI_STATUS EFIAPI AhciDeviceSetFeature(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN UINT16 Feature, IN UINT32 FeatureSpecificData, IN UINT64 Timeout)
Definition: AhciMode.c:2068
EFI_STATUS AhciPuisEnable(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier)
Definition: AhciMode.c:2824
EFI_STATUS AhciWaitDeviceReady(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port)
Definition: AhciMode.c:614
EFI_STATUS AhciEnableDevSlp(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN EFI_IDENTIFY_DATA *IdentifyData)
Definition: AhciMode.c:2528
VOID EFIAPI AhciDumpPortStatus(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock)
Definition: AhciMode.c:324
EFI_STATUS AhciRecoverPortError(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port)
Definition: AhciMode.c:701
EFI_STATUS EFIAPI AhciDmaTransfer(IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL, IN UINT8 AtapiCommandLength, IN BOOLEAN Read, IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN OUT VOID *MemoryAddr, IN UINT32 DataCount, IN UINT64 Timeout, IN ATA_NONBLOCK_TASK *Task)
Definition: AhciMode.c:1158
EFI_STATUS EFIAPI AhciAtaSmartReturnStatusCheck(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock)
Definition: AhciMode.c:1729
EFI_STATUS AhciReadLogExt(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN OUT UINT8 *Buffer, IN UINT8 LogNumber, IN UINT8 PageNumber)
Definition: AhciMode.c:2469
EFI_STATUS AhciSpinUpDisk(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN OUT EFI_IDENTIFY_DATA *IdentifyData)
Definition: AhciMode.c:2703
BOOLEAN AhciShouldCmdBeRetried(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port)
Definition: AhciMode.c:758
EFI_STATUS AhciWaitUntilFisReceived(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port, IN UINT64 Timeout, IN SATA_FIS_TYPE FisType)
Definition: AhciMode.c:867
VOID AhciPrintStatusBlock(IN EFI_ATA_STATUS_BLOCK *AtaStatusBlock, IN UINT32 DebugLevel)
Definition: AhciMode.c:935
EFI_STATUS AhciCheckFisReceived(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port, IN SATA_FIS_TYPE FisType)
Definition: AhciMode.c:814
EFI_STATUS AhciResetPort(IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port)
Definition: AhciMode.c:663
EFI_STATUS EFIAPI AhciIdentifyPacket(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN OUT EFI_IDENTIFY_DATA *Buffer)
Definition: AhciMode.c:2008
VOID EFIAPI AsyncNonBlockingTransferRoutine(EFI_EVENT Event, VOID *Context)
EFI_STATUS EFIAPI CreateNewDeviceInfo(IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance, IN UINT16 Port, IN UINT16 PortMultiplier, IN EFI_ATA_DEVICE_TYPE DeviceType, IN EFI_IDENTIFY_DATA *IdentifyData)
#define ATA_SUB_CMD_ENABLE_PUIS
defined in ACS-3
Definition: Atapi.h:604
#define ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE
defined in ACS-3
Definition: Atapi.h:479
#define ATA_CMD_READ_LOG_EXT
defined in ACS-3
Definition: Atapi.h:551
#define ATA_SMART_ENABLE_OPERATION
reserved
Definition: Atapi.h:655
#define ATA_CMD_SET_FEATURES
defined from ATA-1
Definition: Atapi.h:589
#define ATA_SMART_RETURN_STATUS
defined from ATA-3
Definition: Atapi.h:657
#define ATA_CONSTANT_C2
reserved
Definition: Atapi.h:632
#define ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE
defined in ACS-3
Definition: Atapi.h:477
#define ATA_CMD_SMART
defined from ATA-3
Definition: Atapi.h:631
#define ATA_CMD_READ_SECTORS
defined from ATA-1
Definition: Atapi.h:544
#define ATA_CMD_IDENTIFY_DRIVE
defined from ATA-3
Definition: Atapi.h:542
#define ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP
defined in ACS-3
Definition: Atapi.h:605
#define ATA_SUB_CMD_DISABLE_PUIS
defined in ACS-3
Definition: Atapi.h:618
#define ATA_CONSTANT_4F
reserved
Definition: Atapi.h:633
#define ATA_SUB_CMD_ENABLE_SATA_FEATURE
defined in ACS-3
Definition: Atapi.h:607
#define ATA_CMD_IDENTIFY_DEVICE
defined from ATA-3
Definition: Atapi.h:488
#define ATA_CMD_PACKET
defined from ATA-3
Definition: Atapi.h:487
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
INTN EFIAPI HighBitSet32(IN UINT32 Operand)
Definition: HighBitSet32.c:27
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
@ EfiIdeBeforeChannelEnumeration
@ EfiIdeBusBeforeDevicePresenceDetection
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE(Type, Value)
#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
Clear for PCI controllers that can not genrate a DAC.
Definition: PciIo.h:64
@ EfiPciIoAttributeOperationEnable
Definition: PciIo.h:111
EFI_PCI_IO_PROTOCOL_OPERATION
Definition: PciIo.h:77
@ EfiPciIoOperationBusMasterWrite
Definition: PciIo.h:85
@ EfiPciIoOperationBusMasterRead
Definition: PciIo.h:81
@ EfiPciIoOperationBusMasterCommonBuffer
Definition: PciIo.h:90
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define EFI_ERROR_MINOR
Definition: PiStatusCode.h:58
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
#define EFI_TIMER_PERIOD_SECONDS(Seconds)
Definition: UefiLib.h:98
@ EfiBootServicesData
@ AllocateAnyPages
Definition: UefiSpec.h:33
EFI_IDE_CONTROLLER_SUBMIT_DATA SubmitData
EFI_IDE_CONTROLLER_CALCULATE_MODE CalculateMode
EFI_IDE_CONTROLLER_NOTIFY_PHASE NotifyPhase
UINT16 specific_config
Specific Configuration.
Definition: Atapi.h:81
UINT16 config
General Configuration.
Definition: Atapi.h:79
UINT16 command_set_feature_enb_86
word 86
Definition: Atapi.h:123
UINT16 command_set_supported_83
word 83
Definition: Atapi.h:120
UINT32 Mode
The actual ATA mode. This field is not a bit map.
BOOLEAN Valid
TRUE if Mode is valid.
EFI_ATA_IDENTIFY_DATA AtaData