1 /** @file
2   The file for AHCI mode of ATA host controller.
3 
4   Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "AtaAtapiPassThru.h"
11 
12 /**
13   Read AHCI Operation register.
14 
15   @param  PciIo        The PCI IO protocol instance.
16   @param  Offset       The operation register offset.
17 
18   @return The register content read.
19 
20 **/
21 UINT32
22 EFIAPI
AhciReadReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset)23 AhciReadReg (
24   IN EFI_PCI_IO_PROTOCOL  *PciIo,
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 
46 /**
47   Write AHCI Operation register.
48 
49   @param  PciIo        The PCI IO protocol instance.
50   @param  Offset       The operation register offset.
51   @param  Data         The data used to write down.
52 
53 **/
54 VOID
55 EFIAPI
AhciWriteReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset,IN UINT32 Data)56 AhciWriteReg (
57   IN EFI_PCI_IO_PROTOCOL  *PciIo,
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 
76 /**
77   Do AND operation with the value of AHCI Operation register.
78 
79   @param  PciIo        The PCI IO protocol instance.
80   @param  Offset       The operation register offset.
81   @param  AndData      The data used to do AND operation.
82 
83 **/
84 VOID
85 EFIAPI
AhciAndReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset,IN UINT32 AndData)86 AhciAndReg (
87   IN EFI_PCI_IO_PROTOCOL  *PciIo,
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 
103 /**
104   Do OR operation with the value of AHCI Operation register.
105 
106   @param  PciIo        The PCI IO protocol instance.
107   @param  Offset       The operation register offset.
108   @param  OrData       The data used to do OR operation.
109 
110 **/
111 VOID
112 EFIAPI
AhciOrReg(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT32 Offset,IN UINT32 OrData)113 AhciOrReg (
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 
130 /**
131   Wait for the value of the specified MMIO register set to the test value.
132 
133   @param  PciIo             The PCI IO protocol instance.
134   @param  Offset            The MMIO address to test.
135   @param  MaskValue         The mask value of memory.
136   @param  TestValue         The test value of memory.
137   @param  Timeout           The time out value for wait memory set, uses 100ns as a unit.
138 
139   @retval EFI_TIMEOUT       The MMIO setting is time out.
140   @retval EFI_SUCCESS       The MMIO is correct set.
141 
142 **/
143 EFI_STATUS
144 EFIAPI
AhciWaitMmioSet(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINTN Offset,IN UINT32 MaskValue,IN UINT32 TestValue,IN UINT64 Timeout)145 AhciWaitMmioSet (
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 
182   } while (InfiniteWait || (Delay > 0));
183 
184   return EFI_TIMEOUT;
185 }
186 
187 /**
188   Wait for the value of the specified system memory set to the test value.
189 
190   @param  Address           The system memory address to test.
191   @param  MaskValue         The mask value of memory.
192   @param  TestValue         The test value of memory.
193   @param  Timeout           The time out value for wait memory set, uses 100ns as a unit.
194 
195   @retval EFI_TIMEOUT       The system memory setting is time out.
196   @retval EFI_SUCCESS       The system memory is correct set.
197 
198 **/
199 EFI_STATUS
200 EFIAPI
AhciWaitMemSet(IN EFI_PHYSICAL_ADDRESS Address,IN UINT32 MaskValue,IN UINT32 TestValue,IN UINT64 Timeout)201 AhciWaitMemSet (
202   IN  EFI_PHYSICAL_ADDRESS      Address,
203   IN  UINT32                    MaskValue,
204   IN  UINT32                    TestValue,
205   IN  UINT64                    Timeout
206   )
207 {
208   UINT32     Value;
209   UINT64     Delay;
210   BOOLEAN    InfiniteWait;
211 
212   if (Timeout == 0) {
213     InfiniteWait = TRUE;
214   } else {
215     InfiniteWait = FALSE;
216   }
217 
218   Delay =  DivU64x32 (Timeout, 1000) + 1;
219 
220   do {
221     //
222     // Access sytem memory to see if the value is the tested one.
223     //
224     // The system memory pointed by Address will be updated by the
225     // SATA Host Controller, "volatile" is introduced to prevent
226     // compiler from optimizing the access to the memory address
227     // to only read once.
228     //
229     Value  = *(volatile UINT32 *) (UINTN) Address;
230     Value &= MaskValue;
231 
232     if (Value == TestValue) {
233       return EFI_SUCCESS;
234     }
235 
236     //
237     // Stall for 100 microseconds.
238     //
239     MicroSecondDelay (100);
240 
241     Delay--;
242 
243   } while (InfiniteWait || (Delay > 0));
244 
245   return EFI_TIMEOUT;
246 }
247 
248 /**
249   Check the memory status to the test value.
250 
251   @param[in]       Address           The memory address to test.
252   @param[in]       MaskValue         The mask value of memory.
253   @param[in]       TestValue         The test value of memory.
254   @param[in, out]  Task              Optional. Pointer to the ATA_NONBLOCK_TASK used by
255                                      non-blocking mode. If NULL, then just try once.
256 
257   @retval EFI_NOTREADY      The memory is not set.
258   @retval EFI_TIMEOUT       The memory setting retry times out.
259   @retval EFI_SUCCESS       The memory is correct set.
260 
261 **/
262 EFI_STATUS
263 EFIAPI
AhciCheckMemSet(IN UINTN Address,IN UINT32 MaskValue,IN UINT32 TestValue,IN OUT ATA_NONBLOCK_TASK * Task)264 AhciCheckMemSet (
265   IN     UINTN                     Address,
266   IN     UINT32                    MaskValue,
267   IN     UINT32                    TestValue,
268   IN OUT ATA_NONBLOCK_TASK         *Task
269   )
270 {
271   UINT32     Value;
272 
273   if (Task != NULL) {
274     Task->RetryTimes--;
275   }
276 
277   Value  = *(volatile UINT32 *) Address;
278   Value &= MaskValue;
279 
280   if (Value == TestValue) {
281     return EFI_SUCCESS;
282   }
283 
284   if ((Task != NULL) && !Task->InfiniteWait && (Task->RetryTimes == 0)) {
285     return EFI_TIMEOUT;
286   } else {
287     return EFI_NOT_READY;
288   }
289 }
290 
291 
292 /**
293 
294   Clear the port interrupt and error status. It will also clear
295   HBA interrupt status.
296 
297   @param      PciIo          The PCI IO protocol instance.
298   @param      Port           The number of port.
299 
300 **/
301 VOID
302 EFIAPI
AhciClearPortStatus(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Port)303 AhciClearPortStatus (
304   IN  EFI_PCI_IO_PROTOCOL    *PciIo,
305   IN  UINT8                  Port
306   )
307 {
308   UINT32 Offset;
309 
310   //
311   // Clear any error status
312   //
313   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
314   AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
315 
316   //
317   // Clear any port interrupt status
318   //
319   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
320   AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
321 
322   //
323   // Clear any HBA interrupt status
324   //
325   AhciWriteReg (PciIo, EFI_AHCI_IS_OFFSET, AhciReadReg (PciIo, EFI_AHCI_IS_OFFSET));
326 }
327 
328 /**
329   This function is used to dump the Status Registers and if there is ERR bit set
330   in the Status Register, the Error Register's value is also be dumped.
331 
332   @param  PciIo            The PCI IO protocol instance.
333   @param  AhciRegisters    The pointer to the EFI_AHCI_REGISTERS.
334   @param  Port             The number of port.
335   @param  AtaStatusBlock   A pointer to EFI_ATA_STATUS_BLOCK data structure.
336 
337 **/
338 VOID
339 EFIAPI
AhciDumpPortStatus(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_AHCI_REGISTERS * AhciRegisters,IN UINT8 Port,IN OUT EFI_ATA_STATUS_BLOCK * AtaStatusBlock)340 AhciDumpPortStatus (
341   IN     EFI_PCI_IO_PROTOCOL        *PciIo,
342   IN     EFI_AHCI_REGISTERS         *AhciRegisters,
343   IN     UINT8                      Port,
344   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock
345   )
346 {
347   UINTN                Offset;
348   UINT32               Data;
349   UINTN                FisBaseAddr;
350   EFI_STATUS           Status;
351 
352   ASSERT (PciIo != NULL);
353 
354   if (AtaStatusBlock != NULL) {
355     ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
356 
357     FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
358     Offset      = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
359 
360     Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
361     if (!EFI_ERROR (Status)) {
362       //
363       // If D2H FIS is received, update StatusBlock with its content.
364       //
365       CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK));
366     } else {
367       //
368       // If D2H FIS is not received, only update Status & Error field through PxTFD
369       // as there is no other way to get the content of the Shadow Register Block.
370       //
371       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
372       Data   = AhciReadReg (PciIo, (UINT32)Offset);
373 
374       AtaStatusBlock->AtaStatus  = (UINT8)Data;
375       if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {
376         AtaStatusBlock->AtaError = (UINT8)(Data >> 8);
377       }
378     }
379   }
380 }
381 
382 
383 /**
384   Enable the FIS running for giving port.
385 
386   @param      PciIo          The PCI IO protocol instance.
387   @param      Port           The number of port.
388   @param      Timeout        The timeout value of enabling FIS, uses 100ns as a unit.
389 
390   @retval EFI_DEVICE_ERROR   The FIS enable setting fails.
391   @retval EFI_TIMEOUT        The FIS enable setting is time out.
392   @retval EFI_SUCCESS        The FIS enable successfully.
393 
394 **/
395 EFI_STATUS
396 EFIAPI
AhciEnableFisReceive(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Port,IN UINT64 Timeout)397 AhciEnableFisReceive (
398   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
399   IN  UINT8                     Port,
400   IN  UINT64                    Timeout
401   )
402 {
403   UINT32 Offset;
404 
405   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
406   AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
407 
408   return EFI_SUCCESS;
409 }
410 
411 /**
412   Disable the FIS running for giving port.
413 
414   @param      PciIo          The PCI IO protocol instance.
415   @param      Port           The number of port.
416   @param      Timeout        The timeout value of disabling FIS, uses 100ns as a unit.
417 
418   @retval EFI_DEVICE_ERROR   The FIS disable setting fails.
419   @retval EFI_TIMEOUT        The FIS disable setting is time out.
420   @retval EFI_UNSUPPORTED    The port is in running state.
421   @retval EFI_SUCCESS        The FIS disable successfully.
422 
423 **/
424 EFI_STATUS
425 EFIAPI
AhciDisableFisReceive(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Port,IN UINT64 Timeout)426 AhciDisableFisReceive (
427   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
428   IN  UINT8                     Port,
429   IN  UINT64                    Timeout
430   )
431 {
432   UINT32 Offset;
433   UINT32 Data;
434 
435   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
436   Data   = AhciReadReg (PciIo, Offset);
437 
438   //
439   // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
440   //
441   if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
442     return EFI_UNSUPPORTED;
443   }
444 
445   //
446   // Check if the Fis receive DMA engine for the port is running.
447   //
448   if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
449     return EFI_SUCCESS;
450   }
451 
452   AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
453 
454   return AhciWaitMmioSet (
455            PciIo,
456            Offset,
457            EFI_AHCI_PORT_CMD_FR,
458            0,
459            Timeout
460            );
461 }
462 
463 
464 
465 /**
466   Build the command list, command table and prepare the fis receiver.
467 
468   @param    PciIo                 The PCI IO protocol instance.
469   @param    AhciRegisters         The pointer to the EFI_AHCI_REGISTERS.
470   @param    Port                  The number of port.
471   @param    PortMultiplier        The timeout value of stop.
472   @param    CommandFis            The control fis will be used for the transfer.
473   @param    CommandList           The command list will be used for the transfer.
474   @param    AtapiCommand          The atapi command will be used for the transfer.
475   @param    AtapiCommandLength    The length of the atapi command.
476   @param    CommandSlotNumber     The command slot will be used for the transfer.
477   @param    DataPhysicalAddr      The pointer to the data buffer pci bus master address.
478   @param    DataLength            The data count to be transferred.
479 
480 **/
481 VOID
482 EFIAPI
AhciBuildCommand(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_AHCI_REGISTERS * AhciRegisters,IN UINT8 Port,IN UINT8 PortMultiplier,IN EFI_AHCI_COMMAND_FIS * CommandFis,IN EFI_AHCI_COMMAND_LIST * CommandList,IN EFI_AHCI_ATAPI_COMMAND * AtapiCommand OPTIONAL,IN UINT8 AtapiCommandLength,IN UINT8 CommandSlotNumber,IN OUT VOID * DataPhysicalAddr,IN UINT32 DataLength)483 AhciBuildCommand (
484   IN     EFI_PCI_IO_PROTOCOL        *PciIo,
485   IN     EFI_AHCI_REGISTERS         *AhciRegisters,
486   IN     UINT8                      Port,
487   IN     UINT8                      PortMultiplier,
488   IN     EFI_AHCI_COMMAND_FIS       *CommandFis,
489   IN     EFI_AHCI_COMMAND_LIST      *CommandList,
490   IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
491   IN     UINT8                      AtapiCommandLength,
492   IN     UINT8                      CommandSlotNumber,
493   IN OUT VOID                       *DataPhysicalAddr,
494   IN     UINT32                     DataLength
495   )
496 {
497   UINT64     BaseAddr;
498   UINT32     PrdtNumber;
499   UINT32     PrdtIndex;
500   UINTN      RemainedData;
501   UINTN      MemAddr;
502   DATA_64    Data64;
503   UINT32     Offset;
504 
505   //
506   // Filling the PRDT
507   //
508   PrdtNumber = (UINT32)DivU64x32 (((UINT64)DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1), EFI_AHCI_MAX_DATA_PER_PRDT);
509 
510   //
511   // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
512   // It also limits that the maximum amount of the PRDT entry in the command table
513   // is 65535.
514   //
515   ASSERT (PrdtNumber <= 65535);
516 
517   Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
518 
519   BaseAddr = Data64.Uint64;
520 
521   ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
522 
523   ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
524 
525   CommandFis->AhciCFisPmNum = PortMultiplier;
526 
527   CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
528 
529   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
530   if (AtapiCommand != NULL) {
531     CopyMem (
532       &AhciRegisters->AhciCommandTable->AtapiCmd,
533       AtapiCommand,
534       AtapiCommandLength
535       );
536 
537     CommandList->AhciCmdA = 1;
538     CommandList->AhciCmdP = 1;
539 
540     AhciOrReg (PciIo, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
541   } else {
542     AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
543   }
544 
545   RemainedData = (UINTN) DataLength;
546   MemAddr      = (UINTN) DataPhysicalAddr;
547   CommandList->AhciCmdPrdtl = PrdtNumber;
548 
549   for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
550     if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
551       AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
552     } else {
553       AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;
554     }
555 
556     Data64.Uint64 = (UINT64)MemAddr;
557     AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba  = Data64.Uint32.Lower32;
558     AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
559     RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
560     MemAddr      += EFI_AHCI_MAX_DATA_PER_PRDT;
561   }
562 
563   //
564   // Set the last PRDT to Interrupt On Complete
565   //
566   if (PrdtNumber > 0) {
567     AhciRegisters->AhciCommandTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
568   }
569 
570   CopyMem (
571     (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
572     CommandList,
573     sizeof (EFI_AHCI_COMMAND_LIST)
574     );
575 
576   Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTablePciAddr;
577   AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  = Data64.Uint32.Lower32;
578   AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
579   AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   = PortMultiplier;
580 
581 }
582 
583 /**
584   Buid a command FIS.
585 
586   @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS data structure.
587   @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis data structure.
588 
589 **/
590 VOID
591 EFIAPI
AhciBuildCommandFis(IN OUT EFI_AHCI_COMMAND_FIS * CmdFis,IN EFI_ATA_COMMAND_BLOCK * AtaCommandBlock)592 AhciBuildCommandFis (
593   IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,
594   IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock
595   )
596 {
597   ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
598 
599   CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
600   //
601   // Indicator it's a command
602   //
603   CmdFis->AhciCFisCmdInd      = 0x1;
604   CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;
605 
606   CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;
607   CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;
608 
609   CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;
610   CmdFis->AhciCFisSecNumExp   = AtaCommandBlock->AtaSectorNumberExp;
611 
612   CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;
613   CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;
614 
615   CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;
616   CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;
617 
618   CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;
619   CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
620 
621   CmdFis->AhciCFisDevHead     = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
622 }
623 
624 /**
625   Start a PIO data transfer on specific port.
626 
627   @param[in]       PciIo               The PCI IO protocol instance.
628   @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
629   @param[in]       Port                The number of port.
630   @param[in]       PortMultiplier      The timeout value of stop.
631   @param[in]       AtapiCommand        The atapi command will be used for the
632                                        transfer.
633   @param[in]       AtapiCommandLength  The length of the atapi command.
634   @param[in]       Read                The transfer direction.
635   @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
636   @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
637   @param[in, out]  MemoryAddr          The pointer to the data buffer.
638   @param[in]       DataCount           The data count to be transferred.
639   @param[in]       Timeout             The timeout value of non data transfer, uses 100ns as a unit.
640   @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
641                                        used by non-blocking mode.
642 
643   @retval EFI_DEVICE_ERROR    The PIO data transfer abort with error occurs.
644   @retval EFI_TIMEOUT         The operation is time out.
645   @retval EFI_UNSUPPORTED     The device is not ready for transfer.
646   @retval EFI_SUCCESS         The PIO data transfer executes successfully.
647 
648 **/
649 EFI_STATUS
650 EFIAPI
AhciPioTransfer(IN EFI_PCI_IO_PROTOCOL * PciIo,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)651 AhciPioTransfer (
652   IN     EFI_PCI_IO_PROTOCOL        *PciIo,
653   IN     EFI_AHCI_REGISTERS         *AhciRegisters,
654   IN     UINT8                      Port,
655   IN     UINT8                      PortMultiplier,
656   IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
657   IN     UINT8                      AtapiCommandLength,
658   IN     BOOLEAN                    Read,
659   IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
660   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
661   IN OUT VOID                       *MemoryAddr,
662   IN     UINT32                     DataCount,
663   IN     UINT64                     Timeout,
664   IN     ATA_NONBLOCK_TASK          *Task
665   )
666 {
667   EFI_STATUS                    Status;
668   UINTN                         FisBaseAddr;
669   UINTN                         Offset;
670   EFI_PHYSICAL_ADDRESS          PhyAddr;
671   VOID                          *Map;
672   UINTN                         MapLength;
673   EFI_PCI_IO_PROTOCOL_OPERATION Flag;
674   UINT64                        Delay;
675   EFI_AHCI_COMMAND_FIS          CFis;
676   EFI_AHCI_COMMAND_LIST         CmdList;
677   UINT32                        PortTfd;
678   UINT32                        PrdCount;
679   BOOLEAN                       InfiniteWait;
680   BOOLEAN                       PioFisReceived;
681   BOOLEAN                       D2hFisReceived;
682 
683   if (Timeout == 0) {
684     InfiniteWait = TRUE;
685   } else {
686     InfiniteWait = FALSE;
687   }
688 
689   if (Read) {
690     Flag = EfiPciIoOperationBusMasterWrite;
691   } else {
692     Flag = EfiPciIoOperationBusMasterRead;
693   }
694 
695   //
696   // construct command list and command table with pci bus address
697   //
698   MapLength = DataCount;
699   Status = PciIo->Map (
700                     PciIo,
701                     Flag,
702                     MemoryAddr,
703                     &MapLength,
704                     &PhyAddr,
705                     &Map
706                     );
707 
708   if (EFI_ERROR (Status) || (DataCount != MapLength)) {
709     return EFI_BAD_BUFFER_SIZE;
710   }
711 
712   //
713   // Package read needed
714   //
715   AhciBuildCommandFis (&CFis, AtaCommandBlock);
716 
717   ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
718 
719   CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
720   CmdList.AhciCmdW   = Read ? 0 : 1;
721 
722   AhciBuildCommand (
723     PciIo,
724     AhciRegisters,
725     Port,
726     PortMultiplier,
727     &CFis,
728     &CmdList,
729     AtapiCommand,
730     AtapiCommandLength,
731     0,
732     (VOID *)(UINTN)PhyAddr,
733     DataCount
734     );
735 
736   Status = AhciStartCommand (
737              PciIo,
738              Port,
739              0,
740              Timeout
741              );
742   if (EFI_ERROR (Status)) {
743     goto Exit;
744   }
745 
746   //
747   // Check the status and wait the driver sending data
748   //
749   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
750 
751   if (Read && (AtapiCommand == 0)) {
752     //
753     // Wait device sends the PIO setup fis before data transfer
754     //
755     Status = EFI_TIMEOUT;
756     Delay  = DivU64x32 (Timeout, 1000) + 1;
757     do {
758       PioFisReceived = FALSE;
759       D2hFisReceived = FALSE;
760       Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
761       Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);
762       if (!EFI_ERROR (Status)) {
763         PioFisReceived = TRUE;
764       }
765       //
766       // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
767       // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
768       // after the transaction is finished successfully.
769       // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
770       // By this way, we can know if there is a real error happened.
771       //
772       Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
773       Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
774       if (!EFI_ERROR (Status)) {
775         D2hFisReceived = TRUE;
776       }
777 
778       if (PioFisReceived || D2hFisReceived) {
779         Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
780         PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
781         //
782         // PxTFD will be updated if there is a D2H or SetupFIS received.
783         //
784         if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
785           Status = EFI_DEVICE_ERROR;
786           break;
787         }
788 
789         PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
790         if (PrdCount == DataCount) {
791           Status = EFI_SUCCESS;
792           break;
793         }
794       }
795 
796       //
797       // Stall for 100 microseconds.
798       //
799       MicroSecondDelay(100);
800 
801       Delay--;
802       if (Delay == 0) {
803         Status = EFI_TIMEOUT;
804       }
805     } while (InfiniteWait || (Delay > 0));
806   } else {
807     //
808     // Wait for D2H Fis is received
809     //
810     Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
811     Status = AhciWaitMemSet (
812                Offset,
813                EFI_AHCI_FIS_TYPE_MASK,
814                EFI_AHCI_FIS_REGISTER_D2H,
815                Timeout
816                );
817 
818     if (EFI_ERROR (Status)) {
819       goto Exit;
820     }
821 
822     Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
823     PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
824     if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
825       Status = EFI_DEVICE_ERROR;
826     }
827   }
828 
829 Exit:
830   AhciStopCommand (
831     PciIo,
832     Port,
833     Timeout
834     );
835 
836   AhciDisableFisReceive (
837     PciIo,
838     Port,
839     Timeout
840     );
841 
842   PciIo->Unmap (
843     PciIo,
844     Map
845     );
846 
847   AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
848 
849   return Status;
850 }
851 
852 /**
853   Start a DMA data transfer on specific port
854 
855   @param[in]       Instance            The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
856   @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
857   @param[in]       Port                The number of port.
858   @param[in]       PortMultiplier      The timeout value of stop.
859   @param[in]       AtapiCommand        The atapi command will be used for the
860                                        transfer.
861   @param[in]       AtapiCommandLength  The length of the atapi command.
862   @param[in]       Read                The transfer direction.
863   @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
864   @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
865   @param[in, out]  MemoryAddr          The pointer to the data buffer.
866   @param[in]       DataCount           The data count to be transferred.
867   @param[in]       Timeout             The timeout value of non data transfer, uses 100ns as a unit.
868   @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
869                                        used by non-blocking mode.
870 
871   @retval EFI_DEVICE_ERROR    The DMA data transfer abort with error occurs.
872   @retval EFI_TIMEOUT         The operation is time out.
873   @retval EFI_UNSUPPORTED     The device is not ready for transfer.
874   @retval EFI_SUCCESS         The DMA data transfer executes successfully.
875 
876 **/
877 EFI_STATUS
878 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)879 AhciDmaTransfer (
880   IN     ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
881   IN     EFI_AHCI_REGISTERS         *AhciRegisters,
882   IN     UINT8                      Port,
883   IN     UINT8                      PortMultiplier,
884   IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,
885   IN     UINT8                      AtapiCommandLength,
886   IN     BOOLEAN                    Read,
887   IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,
888   IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,
889   IN OUT VOID                       *MemoryAddr,
890   IN     UINT32                     DataCount,
891   IN     UINT64                     Timeout,
892   IN     ATA_NONBLOCK_TASK          *Task
893   )
894 {
895   EFI_STATUS                    Status;
896   UINTN                         Offset;
897   EFI_PHYSICAL_ADDRESS          PhyAddr;
898   VOID                          *Map;
899   UINTN                         MapLength;
900   EFI_PCI_IO_PROTOCOL_OPERATION Flag;
901   EFI_AHCI_COMMAND_FIS          CFis;
902   EFI_AHCI_COMMAND_LIST         CmdList;
903   UINTN                         FisBaseAddr;
904   UINT32                        PortTfd;
905 
906   EFI_PCI_IO_PROTOCOL           *PciIo;
907   EFI_TPL                       OldTpl;
908 
909   Map   = NULL;
910   PciIo = Instance->PciIo;
911 
912   if (PciIo == NULL) {
913     return EFI_INVALID_PARAMETER;
914   }
915 
916   //
917   // Before starting the Blocking BlockIO operation, push to finish all non-blocking
918   // BlockIO tasks.
919   // Delay 100us to simulate the blocking time out checking.
920   //
921   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
922   while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
923     AsyncNonBlockingTransferRoutine (NULL, Instance);
924     //
925     // Stall for 100us.
926     //
927     MicroSecondDelay (100);
928   }
929   gBS->RestoreTPL (OldTpl);
930 
931   if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {
932     //
933     // Mark the Task to indicate that it has been started.
934     //
935     if (Task != NULL) {
936       Task->IsStart      = TRUE;
937     }
938     if (Read) {
939       Flag = EfiPciIoOperationBusMasterWrite;
940     } else {
941       Flag = EfiPciIoOperationBusMasterRead;
942     }
943 
944     //
945     // Construct command list and command table with pci bus address.
946     //
947     MapLength = DataCount;
948     Status = PciIo->Map (
949                       PciIo,
950                       Flag,
951                       MemoryAddr,
952                       &MapLength,
953                       &PhyAddr,
954                       &Map
955                       );
956 
957     if (EFI_ERROR (Status) || (DataCount != MapLength)) {
958       return EFI_BAD_BUFFER_SIZE;
959     }
960 
961     if (Task != NULL) {
962       Task->Map = Map;
963     }
964     //
965     // Package read needed
966     //
967     AhciBuildCommandFis (&CFis, AtaCommandBlock);
968 
969     ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
970 
971     CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
972     CmdList.AhciCmdW   = Read ? 0 : 1;
973 
974     AhciBuildCommand (
975       PciIo,
976       AhciRegisters,
977       Port,
978       PortMultiplier,
979       &CFis,
980       &CmdList,
981       AtapiCommand,
982       AtapiCommandLength,
983       0,
984       (VOID *)(UINTN)PhyAddr,
985       DataCount
986       );
987 
988     Status = AhciStartCommand (
989                PciIo,
990                Port,
991                0,
992                Timeout
993                );
994     if (EFI_ERROR (Status)) {
995       goto Exit;
996     }
997   }
998 
999   //
1000   // Wait for command compelte
1001   //
1002   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
1003   Offset      = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
1004   if (Task != NULL) {
1005     //
1006     // For Non-blocking
1007     //
1008     Status = AhciCheckMemSet (
1009                Offset,
1010                EFI_AHCI_FIS_TYPE_MASK,
1011                EFI_AHCI_FIS_REGISTER_D2H,
1012                Task
1013                );
1014   } else {
1015     Status = AhciWaitMemSet (
1016                Offset,
1017                EFI_AHCI_FIS_TYPE_MASK,
1018                EFI_AHCI_FIS_REGISTER_D2H,
1019                Timeout
1020                );
1021   }
1022 
1023   if (EFI_ERROR (Status)) {
1024     goto Exit;
1025   }
1026 
1027   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
1028   PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
1029   if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
1030     Status = EFI_DEVICE_ERROR;
1031   }
1032 
1033 Exit:
1034   //
1035   // For Blocking mode, the command should be stopped, the Fis should be disabled
1036   // and the PciIo should be unmapped.
1037   // For non-blocking mode, only when a error is happened (if the return status is
1038   // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
1039   // context cleanup, then set the packet's Asb status.
1040   //
1041   if (Task == NULL ||
1042       ((Task != NULL) && (Status != EFI_NOT_READY))
1043      ) {
1044     AhciStopCommand (
1045       PciIo,
1046       Port,
1047       Timeout
1048       );
1049 
1050     AhciDisableFisReceive (
1051       PciIo,
1052       Port,
1053       Timeout
1054       );
1055 
1056     PciIo->Unmap (
1057              PciIo,
1058              (Task != NULL) ? Task->Map : Map
1059              );
1060 
1061     if (Task != NULL) {
1062       Task->Packet->Asb->AtaStatus = 0x01;
1063     }
1064   }
1065 
1066   AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
1067   return Status;
1068 }
1069 
1070 /**
1071   Start a non data transfer on specific port.
1072 
1073   @param[in]       PciIo               The PCI IO protocol instance.
1074   @param[in]       AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1075   @param[in]       Port                The number of port.
1076   @param[in]       PortMultiplier      The timeout value of stop.
1077   @param[in]       AtapiCommand        The atapi command will be used for the
1078                                        transfer.
1079   @param[in]       AtapiCommandLength  The length of the atapi command.
1080   @param[in]       AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK data.
1081   @param[in, out]  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK data.
1082   @param[in]       Timeout             The timeout value of non data transfer, uses 100ns as a unit.
1083   @param[in]       Task                Optional. Pointer to the ATA_NONBLOCK_TASK
1084                                        used by non-blocking mode.
1085 
1086   @retval EFI_DEVICE_ERROR    The non data transfer abort with error occurs.
1087   @retval EFI_TIMEOUT         The operation is time out.
1088   @retval EFI_UNSUPPORTED     The device is not ready for transfer.
1089   @retval EFI_SUCCESS         The non data transfer executes successfully.
1090 
1091 **/
1092 EFI_STATUS
1093 EFIAPI
AhciNonDataTransfer(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_AHCI_REGISTERS * AhciRegisters,IN UINT8 Port,IN UINT8 PortMultiplier,IN EFI_AHCI_ATAPI_COMMAND * AtapiCommand OPTIONAL,IN UINT8 AtapiCommandLength,IN EFI_ATA_COMMAND_BLOCK * AtaCommandBlock,IN OUT EFI_ATA_STATUS_BLOCK * AtaStatusBlock,IN UINT64 Timeout,IN ATA_NONBLOCK_TASK * Task)1094 AhciNonDataTransfer (
1095   IN     EFI_PCI_IO_PROTOCOL           *PciIo,
1096   IN     EFI_AHCI_REGISTERS            *AhciRegisters,
1097   IN     UINT8                         Port,
1098   IN     UINT8                         PortMultiplier,
1099   IN     EFI_AHCI_ATAPI_COMMAND        *AtapiCommand OPTIONAL,
1100   IN     UINT8                         AtapiCommandLength,
1101   IN     EFI_ATA_COMMAND_BLOCK         *AtaCommandBlock,
1102   IN OUT EFI_ATA_STATUS_BLOCK          *AtaStatusBlock,
1103   IN     UINT64                        Timeout,
1104   IN     ATA_NONBLOCK_TASK             *Task
1105   )
1106 {
1107   EFI_STATUS                   Status;
1108   UINTN                        FisBaseAddr;
1109   UINTN                        Offset;
1110   UINT32                       PortTfd;
1111   EFI_AHCI_COMMAND_FIS         CFis;
1112   EFI_AHCI_COMMAND_LIST        CmdList;
1113 
1114   //
1115   // Package read needed
1116   //
1117   AhciBuildCommandFis (&CFis, AtaCommandBlock);
1118 
1119   ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
1120 
1121   CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
1122 
1123   AhciBuildCommand (
1124     PciIo,
1125     AhciRegisters,
1126     Port,
1127     PortMultiplier,
1128     &CFis,
1129     &CmdList,
1130     AtapiCommand,
1131     AtapiCommandLength,
1132     0,
1133     NULL,
1134     0
1135     );
1136 
1137   Status = AhciStartCommand (
1138              PciIo,
1139              Port,
1140              0,
1141              Timeout
1142              );
1143   if (EFI_ERROR (Status)) {
1144     goto Exit;
1145   }
1146 
1147   //
1148   // Wait device sends the Response Fis
1149   //
1150   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
1151   Offset      = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
1152   Status      = AhciWaitMemSet (
1153                   Offset,
1154                   EFI_AHCI_FIS_TYPE_MASK,
1155                   EFI_AHCI_FIS_REGISTER_D2H,
1156                   Timeout
1157                   );
1158 
1159   if (EFI_ERROR (Status)) {
1160     goto Exit;
1161   }
1162 
1163   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
1164   PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
1165   if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
1166     Status = EFI_DEVICE_ERROR;
1167   }
1168 
1169 Exit:
1170   AhciStopCommand (
1171     PciIo,
1172     Port,
1173     Timeout
1174     );
1175 
1176   AhciDisableFisReceive (
1177     PciIo,
1178     Port,
1179     Timeout
1180     );
1181 
1182   AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
1183 
1184   return Status;
1185 }
1186 
1187 /**
1188   Stop command running for giving port
1189 
1190   @param  PciIo              The PCI IO protocol instance.
1191   @param  Port               The number of port.
1192   @param  Timeout            The timeout value of stop, uses 100ns as a unit.
1193 
1194   @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.
1195   @retval EFI_TIMEOUT        The operation is time out.
1196   @retval EFI_SUCCESS        The command stop successfully.
1197 
1198 **/
1199 EFI_STATUS
1200 EFIAPI
AhciStopCommand(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Port,IN UINT64 Timeout)1201 AhciStopCommand (
1202   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
1203   IN  UINT8                     Port,
1204   IN  UINT64                    Timeout
1205   )
1206 {
1207   UINT32 Offset;
1208   UINT32 Data;
1209 
1210   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1211   Data   = AhciReadReg (PciIo, Offset);
1212 
1213   if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {
1214     return EFI_SUCCESS;
1215   }
1216 
1217   if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
1218     AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
1219   }
1220 
1221   return AhciWaitMmioSet (
1222            PciIo,
1223            Offset,
1224            EFI_AHCI_PORT_CMD_CR,
1225            0,
1226            Timeout
1227            );
1228 }
1229 
1230 /**
1231   Start command for give slot on specific port.
1232 
1233   @param  PciIo              The PCI IO protocol instance.
1234   @param  Port               The number of port.
1235   @param  CommandSlot        The number of Command Slot.
1236   @param  Timeout            The timeout value of start, uses 100ns as a unit.
1237 
1238   @retval EFI_DEVICE_ERROR   The command start unsuccessfully.
1239   @retval EFI_TIMEOUT        The operation is time out.
1240   @retval EFI_SUCCESS        The command start successfully.
1241 
1242 **/
1243 EFI_STATUS
1244 EFIAPI
AhciStartCommand(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT8 Port,IN UINT8 CommandSlot,IN UINT64 Timeout)1245 AhciStartCommand (
1246   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
1247   IN  UINT8                     Port,
1248   IN  UINT8                     CommandSlot,
1249   IN  UINT64                    Timeout
1250   )
1251 {
1252   UINT32     CmdSlotBit;
1253   EFI_STATUS Status;
1254   UINT32     PortStatus;
1255   UINT32     StartCmd;
1256   UINT32     PortTfd;
1257   UINT32     Offset;
1258   UINT32     Capability;
1259 
1260   //
1261   // Collect AHCI controller information
1262   //
1263   Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1264 
1265   CmdSlotBit = (UINT32) (1 << CommandSlot);
1266 
1267   AhciClearPortStatus (
1268     PciIo,
1269     Port
1270     );
1271 
1272   Status = AhciEnableFisReceive (
1273              PciIo,
1274              Port,
1275              Timeout
1276              );
1277 
1278   if (EFI_ERROR (Status)) {
1279     return Status;
1280   }
1281 
1282   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1283   PortStatus = AhciReadReg (PciIo, Offset);
1284 
1285   StartCmd = 0;
1286   if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
1287     StartCmd = AhciReadReg (PciIo, Offset);
1288     StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
1289     StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
1290   }
1291 
1292   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
1293   PortTfd = AhciReadReg (PciIo, Offset);
1294 
1295   if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
1296     if ((Capability & BIT24) != 0) {
1297       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1298       AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);
1299 
1300       AhciWaitMmioSet (
1301         PciIo,
1302         Offset,
1303         EFI_AHCI_PORT_CMD_CLO,
1304         0,
1305         Timeout
1306         );
1307     }
1308   }
1309 
1310   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1311   AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
1312 
1313   //
1314   // Setting the command
1315   //
1316   Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
1317   AhciAndReg (PciIo, Offset, 0);
1318   AhciOrReg (PciIo, Offset, CmdSlotBit);
1319 
1320   return EFI_SUCCESS;
1321 }
1322 
1323 
1324 /**
1325   Do AHCI HBA reset.
1326 
1327   @param  PciIo              The PCI IO protocol instance.
1328   @param  Timeout            The timeout value of reset, uses 100ns as a unit.
1329 
1330   @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete hardware reset.
1331   @retval EFI_TIMEOUT        The reset operation is time out.
1332   @retval EFI_SUCCESS        AHCI controller is reset successfully.
1333 
1334 **/
1335 EFI_STATUS
1336 EFIAPI
AhciReset(IN EFI_PCI_IO_PROTOCOL * PciIo,IN UINT64 Timeout)1337 AhciReset (
1338   IN  EFI_PCI_IO_PROTOCOL       *PciIo,
1339   IN  UINT64                    Timeout
1340   )
1341 {
1342   UINT64                 Delay;
1343   UINT32                 Value;
1344 
1345   //
1346   // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1347   //
1348   Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
1349 
1350   if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
1351     AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
1352   }
1353 
1354   AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
1355 
1356   Delay = DivU64x32(Timeout, 1000) + 1;
1357 
1358   do {
1359     Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
1360 
1361     if ((Value & EFI_AHCI_GHC_RESET) == 0) {
1362       break;
1363     }
1364 
1365     //
1366     // Stall for 100 microseconds.
1367     //
1368     MicroSecondDelay(100);
1369 
1370     Delay--;
1371   } while (Delay > 0);
1372 
1373   if (Delay == 0) {
1374     return EFI_TIMEOUT;
1375   }
1376 
1377   return EFI_SUCCESS;
1378 }
1379 
1380 /**
1381   Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1382 
1383   @param  PciIo               The PCI IO protocol instance.
1384   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1385   @param  Port                The number of port.
1386   @param  PortMultiplier      The port multiplier port number.
1387   @param  AtaStatusBlock      A pointer to EFI_ATA_STATUS_BLOCK data structure.
1388 
1389   @retval EFI_SUCCESS     Successfully get the return status of S.M.A.R.T command execution.
1390   @retval Others          Fail to get return status data.
1391 
1392 **/
1393 EFI_STATUS
1394 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)1395 AhciAtaSmartReturnStatusCheck (
1396   IN EFI_PCI_IO_PROTOCOL         *PciIo,
1397   IN EFI_AHCI_REGISTERS          *AhciRegisters,
1398   IN UINT8                       Port,
1399   IN UINT8                       PortMultiplier,
1400   IN OUT EFI_ATA_STATUS_BLOCK    *AtaStatusBlock
1401   )
1402 {
1403   EFI_STATUS              Status;
1404   EFI_ATA_COMMAND_BLOCK   AtaCommandBlock;
1405   UINT8                   LBAMid;
1406   UINT8                   LBAHigh;
1407   UINTN                   FisBaseAddr;
1408   UINT32                  Value;
1409 
1410   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1411 
1412   AtaCommandBlock.AtaCommand      = ATA_CMD_SMART;
1413   AtaCommandBlock.AtaFeatures     = ATA_SMART_RETURN_STATUS;
1414   AtaCommandBlock.AtaCylinderLow  = ATA_CONSTANT_4F;
1415   AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1416 
1417   //
1418   // Send S.M.A.R.T Read Return Status command to device
1419   //
1420   Status = AhciNonDataTransfer (
1421              PciIo,
1422              AhciRegisters,
1423              (UINT8)Port,
1424              (UINT8)PortMultiplier,
1425              NULL,
1426              0,
1427              &AtaCommandBlock,
1428              AtaStatusBlock,
1429              ATA_ATAPI_TIMEOUT,
1430              NULL
1431              );
1432 
1433   if (EFI_ERROR (Status)) {
1434     REPORT_STATUS_CODE (
1435       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1436       (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
1437       );
1438     return EFI_DEVICE_ERROR;
1439   }
1440 
1441   REPORT_STATUS_CODE (
1442     EFI_PROGRESS_CODE,
1443     (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
1444     );
1445 
1446   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
1447 
1448   Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
1449 
1450   if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {
1451     LBAMid  = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[5];
1452     LBAHigh = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[6];
1453 
1454     if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
1455       //
1456       // The threshold exceeded condition is not detected by the device
1457       //
1458       DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1459       REPORT_STATUS_CODE (
1460             EFI_PROGRESS_CODE,
1461             (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
1462             );
1463     } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
1464       //
1465       // The threshold exceeded condition is detected by the device
1466       //
1467       DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1468       REPORT_STATUS_CODE (
1469            EFI_PROGRESS_CODE,
1470            (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
1471            );
1472     }
1473   }
1474 
1475   return EFI_SUCCESS;
1476 }
1477 
1478 /**
1479   Enable SMART command of the disk if supported.
1480 
1481   @param  PciIo               The PCI IO protocol instance.
1482   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1483   @param  Port                The number of port.
1484   @param  PortMultiplier      The port multiplier port number.
1485   @param  IdentifyData        A pointer to data buffer which is used to contain IDENTIFY data.
1486   @param  AtaStatusBlock      A pointer to EFI_ATA_STATUS_BLOCK data structure.
1487 
1488 **/
1489 VOID
1490 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)1491 AhciAtaSmartSupport (
1492   IN EFI_PCI_IO_PROTOCOL           *PciIo,
1493   IN EFI_AHCI_REGISTERS            *AhciRegisters,
1494   IN UINT8                         Port,
1495   IN UINT8                         PortMultiplier,
1496   IN EFI_IDENTIFY_DATA             *IdentifyData,
1497   IN OUT EFI_ATA_STATUS_BLOCK      *AtaStatusBlock
1498   )
1499 {
1500   EFI_STATUS               Status;
1501   EFI_ATA_COMMAND_BLOCK    AtaCommandBlock;
1502 
1503   //
1504   // Detect if the device supports S.M.A.R.T.
1505   //
1506   if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
1507     //
1508     // S.M.A.R.T is not supported by the device
1509     //
1510     DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1511             Port, PortMultiplier));
1512     REPORT_STATUS_CODE (
1513       EFI_ERROR_CODE | EFI_ERROR_MINOR,
1514       (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
1515       );
1516   } else {
1517     //
1518     // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1519     //
1520     if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
1521 
1522       REPORT_STATUS_CODE (
1523         EFI_PROGRESS_CODE,
1524         (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)
1525         );
1526 
1527       ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1528 
1529       AtaCommandBlock.AtaCommand      = ATA_CMD_SMART;
1530       AtaCommandBlock.AtaFeatures     = ATA_SMART_ENABLE_OPERATION;
1531       AtaCommandBlock.AtaCylinderLow  = ATA_CONSTANT_4F;
1532       AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1533 
1534       //
1535       // Send S.M.A.R.T Enable command to device
1536       //
1537       Status = AhciNonDataTransfer (
1538                  PciIo,
1539                  AhciRegisters,
1540                  (UINT8)Port,
1541                  (UINT8)PortMultiplier,
1542                  NULL,
1543                  0,
1544                  &AtaCommandBlock,
1545                  AtaStatusBlock,
1546                  ATA_ATAPI_TIMEOUT,
1547                  NULL
1548                  );
1549 
1550 
1551       if (!EFI_ERROR (Status)) {
1552         //
1553         // Send S.M.A.R.T AutoSave command to device
1554         //
1555         ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1556 
1557         AtaCommandBlock.AtaCommand      = ATA_CMD_SMART;
1558         AtaCommandBlock.AtaFeatures     = 0xD2;
1559         AtaCommandBlock.AtaSectorCount  = 0xF1;
1560         AtaCommandBlock.AtaCylinderLow  = ATA_CONSTANT_4F;
1561         AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1562 
1563         Status = AhciNonDataTransfer (
1564                    PciIo,
1565                    AhciRegisters,
1566                    (UINT8)Port,
1567                    (UINT8)PortMultiplier,
1568                    NULL,
1569                    0,
1570                    &AtaCommandBlock,
1571                    AtaStatusBlock,
1572                    ATA_ATAPI_TIMEOUT,
1573                    NULL
1574                    );
1575 
1576         if (!EFI_ERROR (Status)) {
1577           Status = AhciAtaSmartReturnStatusCheck (
1578                      PciIo,
1579                      AhciRegisters,
1580                      (UINT8)Port,
1581                      (UINT8)PortMultiplier,
1582                      AtaStatusBlock
1583                      );
1584         }
1585       }
1586     }
1587     DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1588             Port, PortMultiplier));
1589   }
1590 
1591   return ;
1592 }
1593 
1594 /**
1595   Send Buffer cmd to specific device.
1596 
1597   @param  PciIo               The PCI IO protocol instance.
1598   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1599   @param  Port                The number of port.
1600   @param  PortMultiplier      The port multiplier port number.
1601   @param  Buffer              The data buffer to store IDENTIFY PACKET data.
1602 
1603   @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
1604   @retval EFI_TIMEOUT         The operation is time out.
1605   @retval EFI_UNSUPPORTED     The device is not ready for executing.
1606   @retval EFI_SUCCESS         The cmd executes successfully.
1607 
1608 **/
1609 EFI_STATUS
1610 EFIAPI
AhciIdentify(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_AHCI_REGISTERS * AhciRegisters,IN UINT8 Port,IN UINT8 PortMultiplier,IN OUT EFI_IDENTIFY_DATA * Buffer)1611 AhciIdentify (
1612   IN EFI_PCI_IO_PROTOCOL      *PciIo,
1613   IN EFI_AHCI_REGISTERS       *AhciRegisters,
1614   IN UINT8                    Port,
1615   IN UINT8                    PortMultiplier,
1616   IN OUT EFI_IDENTIFY_DATA    *Buffer
1617   )
1618 {
1619   EFI_STATUS                   Status;
1620   EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
1621   EFI_ATA_STATUS_BLOCK         AtaStatusBlock;
1622 
1623   if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
1624     return EFI_INVALID_PARAMETER;
1625   }
1626 
1627   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1628   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1629 
1630   AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DRIVE;
1631   AtaCommandBlock.AtaSectorCount = 1;
1632 
1633   Status = AhciPioTransfer (
1634              PciIo,
1635              AhciRegisters,
1636              Port,
1637              PortMultiplier,
1638              NULL,
1639              0,
1640              TRUE,
1641              &AtaCommandBlock,
1642              &AtaStatusBlock,
1643              Buffer,
1644              sizeof (EFI_IDENTIFY_DATA),
1645              ATA_ATAPI_TIMEOUT,
1646              NULL
1647              );
1648 
1649   return Status;
1650 }
1651 
1652 /**
1653   Send Buffer cmd to specific device.
1654 
1655   @param  PciIo               The PCI IO protocol instance.
1656   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1657   @param  Port                The number of port.
1658   @param  PortMultiplier      The port multiplier port number.
1659   @param  Buffer              The data buffer to store IDENTIFY PACKET data.
1660 
1661   @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
1662   @retval EFI_TIMEOUT         The operation is time out.
1663   @retval EFI_UNSUPPORTED     The device is not ready for executing.
1664   @retval EFI_SUCCESS         The cmd executes successfully.
1665 
1666 **/
1667 EFI_STATUS
1668 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)1669 AhciIdentifyPacket (
1670   IN EFI_PCI_IO_PROTOCOL      *PciIo,
1671   IN EFI_AHCI_REGISTERS       *AhciRegisters,
1672   IN UINT8                    Port,
1673   IN UINT8                    PortMultiplier,
1674   IN OUT EFI_IDENTIFY_DATA    *Buffer
1675   )
1676 {
1677   EFI_STATUS                   Status;
1678   EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
1679   EFI_ATA_STATUS_BLOCK         AtaStatusBlock;
1680 
1681   if (PciIo == NULL || AhciRegisters == NULL) {
1682     return EFI_INVALID_PARAMETER;
1683   }
1684 
1685   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1686   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1687 
1688   AtaCommandBlock.AtaCommand     = ATA_CMD_IDENTIFY_DEVICE;
1689   AtaCommandBlock.AtaSectorCount = 1;
1690 
1691   Status = AhciPioTransfer (
1692              PciIo,
1693              AhciRegisters,
1694              Port,
1695              PortMultiplier,
1696              NULL,
1697              0,
1698              TRUE,
1699              &AtaCommandBlock,
1700              &AtaStatusBlock,
1701              Buffer,
1702              sizeof (EFI_IDENTIFY_DATA),
1703              ATA_ATAPI_TIMEOUT,
1704              NULL
1705              );
1706 
1707   return Status;
1708 }
1709 
1710 /**
1711   Send SET FEATURE cmd on specific device.
1712 
1713   @param  PciIo               The PCI IO protocol instance.
1714   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
1715   @param  Port                The number of port.
1716   @param  PortMultiplier      The port multiplier port number.
1717   @param  Feature             The data to send Feature register.
1718   @param  FeatureSpecificData The specific data for SET FEATURE cmd.
1719   @param  Timeout             The timeout value of SET FEATURE cmd, uses 100ns as a unit.
1720 
1721   @retval EFI_DEVICE_ERROR    The cmd abort with error occurs.
1722   @retval EFI_TIMEOUT         The operation is time out.
1723   @retval EFI_UNSUPPORTED     The device is not ready for executing.
1724   @retval EFI_SUCCESS         The cmd executes successfully.
1725 
1726 **/
1727 EFI_STATUS
1728 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)1729 AhciDeviceSetFeature (
1730   IN EFI_PCI_IO_PROTOCOL    *PciIo,
1731   IN EFI_AHCI_REGISTERS     *AhciRegisters,
1732   IN UINT8                  Port,
1733   IN UINT8                  PortMultiplier,
1734   IN UINT16                 Feature,
1735   IN UINT32                 FeatureSpecificData,
1736   IN UINT64                 Timeout
1737   )
1738 {
1739   EFI_STATUS               Status;
1740   EFI_ATA_COMMAND_BLOCK    AtaCommandBlock;
1741   EFI_ATA_STATUS_BLOCK     AtaStatusBlock;
1742 
1743   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1744   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1745 
1746   AtaCommandBlock.AtaCommand      = ATA_CMD_SET_FEATURES;
1747   AtaCommandBlock.AtaFeatures     = (UINT8) Feature;
1748   AtaCommandBlock.AtaFeaturesExp  = (UINT8) (Feature >> 8);
1749   AtaCommandBlock.AtaSectorCount  = (UINT8) FeatureSpecificData;
1750   AtaCommandBlock.AtaSectorNumber = (UINT8) (FeatureSpecificData >> 8);
1751   AtaCommandBlock.AtaCylinderLow  = (UINT8) (FeatureSpecificData >> 16);
1752   AtaCommandBlock.AtaCylinderHigh = (UINT8) (FeatureSpecificData >> 24);
1753 
1754   Status = AhciNonDataTransfer (
1755              PciIo,
1756              AhciRegisters,
1757              (UINT8)Port,
1758              (UINT8)PortMultiplier,
1759              NULL,
1760              0,
1761              &AtaCommandBlock,
1762              &AtaStatusBlock,
1763              Timeout,
1764              NULL
1765              );
1766 
1767   return Status;
1768 }
1769 
1770 /**
1771   This function is used to send out ATAPI commands conforms to the Packet Command
1772   with PIO Protocol.
1773 
1774   @param PciIo              The PCI IO protocol instance.
1775   @param AhciRegisters      The pointer to the EFI_AHCI_REGISTERS.
1776   @param Port               The number of port.
1777   @param PortMultiplier     The number of port multiplier.
1778   @param Packet             A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1779 
1780   @retval EFI_SUCCESS       send out the ATAPI packet command successfully
1781                             and device sends data successfully.
1782   @retval EFI_DEVICE_ERROR  the device failed to send data.
1783 
1784 **/
1785 EFI_STATUS
1786 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)1787 AhciPacketCommandExecute (
1788   IN  EFI_PCI_IO_PROTOCOL                           *PciIo,
1789   IN  EFI_AHCI_REGISTERS                            *AhciRegisters,
1790   IN  UINT8                                         Port,
1791   IN  UINT8                                         PortMultiplier,
1792   IN  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet
1793   )
1794 {
1795   EFI_STATUS                   Status;
1796   VOID                         *Buffer;
1797   UINT32                       Length;
1798   EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
1799   EFI_ATA_STATUS_BLOCK         AtaStatusBlock;
1800   BOOLEAN                      Read;
1801 
1802   if (Packet == NULL || Packet->Cdb == NULL) {
1803     return EFI_INVALID_PARAMETER;
1804   }
1805 
1806   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1807   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1808   AtaCommandBlock.AtaCommand      = ATA_CMD_PACKET;
1809   //
1810   // No OVL; No DMA
1811   //
1812   AtaCommandBlock.AtaFeatures     = 0x00;
1813   //
1814   // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1815   // determine how many data should be transferred.
1816   //
1817   AtaCommandBlock.AtaCylinderLow  = (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff);
1818   AtaCommandBlock.AtaCylinderHigh = (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8);
1819 
1820   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1821     Buffer = Packet->InDataBuffer;
1822     Length = Packet->InTransferLength;
1823     Read = TRUE;
1824   } else {
1825     Buffer = Packet->OutDataBuffer;
1826     Length = Packet->OutTransferLength;
1827     Read = FALSE;
1828   }
1829 
1830   if (Length == 0) {
1831     Status = AhciNonDataTransfer (
1832                PciIo,
1833                AhciRegisters,
1834                Port,
1835                PortMultiplier,
1836                Packet->Cdb,
1837                Packet->CdbLength,
1838                &AtaCommandBlock,
1839                &AtaStatusBlock,
1840                Packet->Timeout,
1841                NULL
1842                );
1843   } else {
1844     Status = AhciPioTransfer (
1845                PciIo,
1846                AhciRegisters,
1847                Port,
1848                PortMultiplier,
1849                Packet->Cdb,
1850                Packet->CdbLength,
1851                Read,
1852                &AtaCommandBlock,
1853                &AtaStatusBlock,
1854                Buffer,
1855                Length,
1856                Packet->Timeout,
1857                NULL
1858                );
1859   }
1860   return Status;
1861 }
1862 
1863 /**
1864   Allocate transfer-related data struct which is used at AHCI mode.
1865 
1866   @param  PciIo                 The PCI IO protocol instance.
1867   @param  AhciRegisters         The pointer to the EFI_AHCI_REGISTERS.
1868 
1869 **/
1870 EFI_STATUS
1871 EFIAPI
AhciCreateTransferDescriptor(IN EFI_PCI_IO_PROTOCOL * PciIo,IN OUT EFI_AHCI_REGISTERS * AhciRegisters)1872 AhciCreateTransferDescriptor (
1873   IN     EFI_PCI_IO_PROTOCOL    *PciIo,
1874   IN OUT EFI_AHCI_REGISTERS     *AhciRegisters
1875   )
1876 {
1877   EFI_STATUS            Status;
1878   UINTN                 Bytes;
1879   VOID                  *Buffer;
1880 
1881   UINT32                Capability;
1882   UINT32                PortImplementBitMap;
1883   UINT8                 MaxPortNumber;
1884   UINT8                 MaxCommandSlotNumber;
1885   BOOLEAN               Support64Bit;
1886   UINT64                MaxReceiveFisSize;
1887   UINT64                MaxCommandListSize;
1888   UINT64                MaxCommandTableSize;
1889   EFI_PHYSICAL_ADDRESS  AhciRFisPciAddr;
1890   EFI_PHYSICAL_ADDRESS  AhciCmdListPciAddr;
1891   EFI_PHYSICAL_ADDRESS  AhciCommandTablePciAddr;
1892 
1893   Buffer = NULL;
1894   //
1895   // Collect AHCI controller information
1896   //
1897   Capability           = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1898   //
1899   // Get the number of command slots per port supported by this HBA.
1900   //
1901   MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
1902   Support64Bit         = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
1903 
1904   PortImplementBitMap  = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
1905   //
1906   // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
1907   //
1908   MaxPortNumber        = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1);
1909   if (MaxPortNumber == 0) {
1910     return EFI_DEVICE_ERROR;
1911   }
1912 
1913   MaxReceiveFisSize    = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
1914   Status = PciIo->AllocateBuffer (
1915                     PciIo,
1916                     AllocateAnyPages,
1917                     EfiBootServicesData,
1918                     EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
1919                     &Buffer,
1920                     0
1921                     );
1922 
1923   if (EFI_ERROR (Status)) {
1924     return EFI_OUT_OF_RESOURCES;
1925   }
1926 
1927   ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);
1928 
1929   AhciRegisters->AhciRFis          = Buffer;
1930   AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;
1931   Bytes  = (UINTN)MaxReceiveFisSize;
1932 
1933   Status = PciIo->Map (
1934                     PciIo,
1935                     EfiPciIoOperationBusMasterCommonBuffer,
1936                     Buffer,
1937                     &Bytes,
1938                     &AhciRFisPciAddr,
1939                     &AhciRegisters->MapRFis
1940                     );
1941 
1942   if (EFI_ERROR (Status) || (Bytes != MaxReceiveFisSize)) {
1943     //
1944     // Map error or unable to map the whole RFis buffer into a contiguous region.
1945     //
1946     Status = EFI_OUT_OF_RESOURCES;
1947     goto Error6;
1948   }
1949 
1950   if ((!Support64Bit) && (AhciRFisPciAddr > 0x100000000ULL)) {
1951     //
1952     // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1953     //
1954     Status = EFI_DEVICE_ERROR;
1955     goto Error5;
1956   }
1957   AhciRegisters->AhciRFisPciAddr = (EFI_AHCI_RECEIVED_FIS *)(UINTN)AhciRFisPciAddr;
1958 
1959   //
1960   // Allocate memory for command list
1961   // Note that the implemenation is a single task model which only use a command list for all ports.
1962   //
1963   Buffer = NULL;
1964   MaxCommandListSize = MaxCommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST);
1965   Status = PciIo->AllocateBuffer (
1966                     PciIo,
1967                     AllocateAnyPages,
1968                     EfiBootServicesData,
1969                     EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
1970                     &Buffer,
1971                     0
1972                     );
1973 
1974   if (EFI_ERROR (Status)) {
1975     //
1976     // Free mapped resource.
1977     //
1978     Status = EFI_OUT_OF_RESOURCES;
1979     goto Error5;
1980   }
1981 
1982   ZeroMem (Buffer, (UINTN)MaxCommandListSize);
1983 
1984   AhciRegisters->AhciCmdList        = Buffer;
1985   AhciRegisters->MaxCommandListSize = MaxCommandListSize;
1986   Bytes  = (UINTN)MaxCommandListSize;
1987 
1988   Status = PciIo->Map (
1989                     PciIo,
1990                     EfiPciIoOperationBusMasterCommonBuffer,
1991                     Buffer,
1992                     &Bytes,
1993                     &AhciCmdListPciAddr,
1994                     &AhciRegisters->MapCmdList
1995                     );
1996 
1997   if (EFI_ERROR (Status) || (Bytes != MaxCommandListSize)) {
1998     //
1999     // Map error or unable to map the whole cmd list buffer into a contiguous region.
2000     //
2001     Status = EFI_OUT_OF_RESOURCES;
2002     goto Error4;
2003   }
2004 
2005   if ((!Support64Bit) && (AhciCmdListPciAddr > 0x100000000ULL)) {
2006     //
2007     // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2008     //
2009     Status = EFI_DEVICE_ERROR;
2010     goto Error3;
2011   }
2012   AhciRegisters->AhciCmdListPciAddr = (EFI_AHCI_COMMAND_LIST *)(UINTN)AhciCmdListPciAddr;
2013 
2014   //
2015   // Allocate memory for command table
2016   // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2017   //
2018   Buffer = NULL;
2019   MaxCommandTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
2020 
2021   Status = PciIo->AllocateBuffer (
2022                     PciIo,
2023                     AllocateAnyPages,
2024                     EfiBootServicesData,
2025                     EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
2026                     &Buffer,
2027                     0
2028                     );
2029 
2030   if (EFI_ERROR (Status)) {
2031     //
2032     // Free mapped resource.
2033     //
2034     Status = EFI_OUT_OF_RESOURCES;
2035     goto Error3;
2036   }
2037 
2038   ZeroMem (Buffer, (UINTN)MaxCommandTableSize);
2039 
2040   AhciRegisters->AhciCommandTable    = Buffer;
2041   AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;
2042   Bytes  = (UINTN)MaxCommandTableSize;
2043 
2044   Status = PciIo->Map (
2045                     PciIo,
2046                     EfiPciIoOperationBusMasterCommonBuffer,
2047                     Buffer,
2048                     &Bytes,
2049                     &AhciCommandTablePciAddr,
2050                     &AhciRegisters->MapCommandTable
2051                     );
2052 
2053   if (EFI_ERROR (Status) || (Bytes != MaxCommandTableSize)) {
2054     //
2055     // Map error or unable to map the whole cmd list buffer into a contiguous region.
2056     //
2057     Status = EFI_OUT_OF_RESOURCES;
2058     goto Error2;
2059   }
2060 
2061   if ((!Support64Bit) && (AhciCommandTablePciAddr > 0x100000000ULL)) {
2062     //
2063     // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2064     //
2065     Status = EFI_DEVICE_ERROR;
2066     goto Error1;
2067   }
2068   AhciRegisters->AhciCommandTablePciAddr = (EFI_AHCI_COMMAND_TABLE *)(UINTN)AhciCommandTablePciAddr;
2069 
2070   return EFI_SUCCESS;
2071   //
2072   // Map error or unable to map the whole CmdList buffer into a contiguous region.
2073   //
2074 Error1:
2075   PciIo->Unmap (
2076            PciIo,
2077            AhciRegisters->MapCommandTable
2078            );
2079 Error2:
2080   PciIo->FreeBuffer (
2081            PciIo,
2082            EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
2083            AhciRegisters->AhciCommandTable
2084            );
2085 Error3:
2086   PciIo->Unmap (
2087            PciIo,
2088            AhciRegisters->MapCmdList
2089            );
2090 Error4:
2091   PciIo->FreeBuffer (
2092            PciIo,
2093            EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
2094            AhciRegisters->AhciCmdList
2095            );
2096 Error5:
2097   PciIo->Unmap (
2098            PciIo,
2099            AhciRegisters->MapRFis
2100            );
2101 Error6:
2102   PciIo->FreeBuffer (
2103            PciIo,
2104            EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
2105            AhciRegisters->AhciRFis
2106            );
2107 
2108   return Status;
2109 }
2110 
2111 /**
2112   Read logs from SATA device.
2113 
2114   @param  PciIo               The PCI IO protocol instance.
2115   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
2116   @param  Port                The number of port.
2117   @param  PortMultiplier      The multiplier of port.
2118   @param  Buffer              The data buffer to store SATA logs.
2119   @param  LogNumber           The address of the log.
2120   @param  PageNumber          The page number of the log.
2121 
2122   @retval EFI_INVALID_PARAMETER  PciIo, AhciRegisters or Buffer is NULL.
2123   @retval others                 Return status of AhciPioTransfer().
2124 **/
2125 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)2126 AhciReadLogExt (
2127   IN EFI_PCI_IO_PROTOCOL       *PciIo,
2128   IN EFI_AHCI_REGISTERS        *AhciRegisters,
2129   IN UINT8                     Port,
2130   IN UINT8                     PortMultiplier,
2131   IN OUT UINT8                 *Buffer,
2132   IN UINT8                     LogNumber,
2133   IN UINT8                     PageNumber
2134   )
2135 {
2136   EFI_ATA_COMMAND_BLOCK        AtaCommandBlock;
2137   EFI_ATA_STATUS_BLOCK         AtaStatusBlock;
2138 
2139   if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
2140     return EFI_INVALID_PARAMETER;
2141   }
2142 
2143   ///
2144   /// Read log from device
2145   ///
2146   ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2147   ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2148   ZeroMem (Buffer, 512);
2149 
2150   AtaCommandBlock.AtaCommand      = ATA_CMD_READ_LOG_EXT;
2151   AtaCommandBlock.AtaSectorCount  = 1;
2152   AtaCommandBlock.AtaSectorNumber = LogNumber;
2153   AtaCommandBlock.AtaCylinderLow  = PageNumber;
2154 
2155   return AhciPioTransfer (
2156            PciIo,
2157            AhciRegisters,
2158            Port,
2159            PortMultiplier,
2160            NULL,
2161            0,
2162            TRUE,
2163            &AtaCommandBlock,
2164            &AtaStatusBlock,
2165            Buffer,
2166            512,
2167            ATA_ATAPI_TIMEOUT,
2168            NULL
2169            );
2170 }
2171 
2172 /**
2173   Enable DEVSLP of the disk if supported.
2174 
2175   @param  PciIo               The PCI IO protocol instance.
2176   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
2177   @param  Port                The number of port.
2178   @param  PortMultiplier      The multiplier of port.
2179   @param  IdentifyData        A pointer to data buffer which is used to contain IDENTIFY data.
2180 
2181   @retval EFI_SUCCESS         The DEVSLP is enabled per policy successfully.
2182   @retval EFI_UNSUPPORTED     The DEVSLP isn't supported by the controller/device and policy requires to enable it.
2183 **/
2184 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)2185 AhciEnableDevSlp (
2186   IN EFI_PCI_IO_PROTOCOL           *PciIo,
2187   IN EFI_AHCI_REGISTERS            *AhciRegisters,
2188   IN UINT8                         Port,
2189   IN UINT8                         PortMultiplier,
2190   IN EFI_IDENTIFY_DATA             *IdentifyData
2191   )
2192 {
2193   EFI_STATUS               Status;
2194   UINT32                   Offset;
2195   UINT32                   Capability2;
2196   UINT8                    LogData[512];
2197   DEVSLP_TIMING_VARIABLES  DevSlpTiming;
2198   UINT32                   PortCmd;
2199   UINT32                   PortDevSlp;
2200 
2201   if (mAtaAtapiPolicy->DeviceSleepEnable != 1) {
2202     return EFI_SUCCESS;
2203   }
2204 
2205   //
2206   // Do not enable DevSlp if DevSlp is not supported.
2207   //
2208   Capability2 = AhciReadReg (PciIo, AHCI_CAPABILITY2_OFFSET);
2209   DEBUG ((DEBUG_INFO, "AHCI CAPABILITY2 = %08x\n", Capability2));
2210   if ((Capability2 & AHCI_CAP2_SDS) == 0) {
2211     return EFI_UNSUPPORTED;
2212   }
2213 
2214   //
2215   // Do not enable DevSlp if DevSlp is not present
2216   // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
2217   //
2218   Offset     = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH;
2219   PortCmd    = AhciReadReg (PciIo, Offset + EFI_AHCI_PORT_CMD);
2220   PortDevSlp = AhciReadReg (PciIo, Offset + AHCI_PORT_DEVSLP);
2221   DEBUG ((DEBUG_INFO, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd, PortDevSlp));
2222   if (((PortDevSlp & AHCI_PORT_DEVSLP_DSP) == 0) ||
2223       ((PortCmd & (EFI_AHCI_PORT_CMD_HPCP | EFI_AHCI_PORT_CMD_MPSP)) != 0)
2224      ) {
2225     return EFI_UNSUPPORTED;
2226   }
2227 
2228   //
2229   // Do not enable DevSlp if the device doesn't support DevSlp
2230   //
2231   DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
2232           IdentifyData->AtaData.reserved_77,
2233           IdentifyData->AtaData.serial_ata_features_supported, IdentifyData->AtaData.serial_ata_features_enabled));
2234   if ((IdentifyData->AtaData.serial_ata_features_supported & BIT8) == 0) {
2235     DEBUG ((DEBUG_INFO, "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
2236             Port, PortMultiplier));
2237     return EFI_UNSUPPORTED;
2238   }
2239 
2240   //
2241   // Enable DevSlp when it is not enabled.
2242   //
2243   if ((IdentifyData->AtaData.serial_ata_features_enabled & BIT8) != 0) {
2244     Status = AhciDeviceSetFeature (
2245       PciIo, AhciRegisters, Port, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE, 0x09, ATA_ATAPI_TIMEOUT
2246     );
2247     DEBUG ((DEBUG_INFO, "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
2248             Port, PortMultiplier, Status));
2249     if (EFI_ERROR (Status)) {
2250       return Status;
2251     }
2252   }
2253 
2254   Status = AhciReadLogExt(PciIo, AhciRegisters, Port, PortMultiplier, LogData, 0x30, 0x08);
2255 
2256   //
2257   // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
2258   //
2259   AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd & ~EFI_AHCI_PORT_CMD_ST);
2260   PortDevSlp &= ~AHCI_PORT_DEVSLP_ADSE;
2261   AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2262 
2263   //
2264   // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
2265   //
2266   PortDevSlp &= ~AHCI_PORT_DEVSLP_DETO_MASK;
2267   PortDevSlp &= ~AHCI_PORT_DEVSLP_MDAT_MASK;
2268   AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2269   DEBUG ((DEBUG_INFO, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port, PortMultiplier, Status));
2270   if (EFI_ERROR (Status)) {
2271     //
2272     // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
2273     //
2274     ZeroMem (&DevSlpTiming, sizeof (DevSlpTiming));
2275   } else {
2276     CopyMem (&DevSlpTiming, &LogData[48], sizeof (DevSlpTiming));
2277     DEBUG ((DEBUG_INFO, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
2278             DevSlpTiming.Supported, DevSlpTiming.Deto, DevSlpTiming.Madt));
2279   }
2280 
2281   //
2282   // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
2283   //
2284   if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Deto == 0)) {
2285     DevSlpTiming.Deto = 20;
2286   }
2287 
2288   //
2289   // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
2290   //
2291   if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Madt == 0)) {
2292     DevSlpTiming.Madt = 10;
2293   }
2294 
2295   PortDevSlp |= DevSlpTiming.Deto << 2;
2296   PortDevSlp |= DevSlpTiming.Madt << 10;
2297   AhciOrReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2298 
2299   if (mAtaAtapiPolicy->AggressiveDeviceSleepEnable == 1) {
2300     if ((Capability2 & AHCI_CAP2_SADM) != 0) {
2301       PortDevSlp &= ~AHCI_PORT_DEVSLP_DITO_MASK;
2302       PortDevSlp |= (625 << 15);
2303       AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2304 
2305       PortDevSlp |= AHCI_PORT_DEVSLP_ADSE;
2306       AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
2307     }
2308   }
2309 
2310 
2311   AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd);
2312 
2313   DEBUG ((DEBUG_INFO, "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
2314           Port, PortMultiplier, PortCmd, PortDevSlp));
2315 
2316   return EFI_SUCCESS;
2317 }
2318 
2319 /**
2320   Spin-up disk if IDD was incomplete or PUIS feature is enabled
2321 
2322   @param  PciIo               The PCI IO protocol instance.
2323   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
2324   @param  Port                The number of port.
2325   @param  PortMultiplier      The multiplier of port.
2326   @param  IdentifyData        A pointer to data buffer which is used to contain IDENTIFY data.
2327 
2328 **/
2329 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)2330 AhciSpinUpDisk (
2331   IN EFI_PCI_IO_PROTOCOL           *PciIo,
2332   IN EFI_AHCI_REGISTERS            *AhciRegisters,
2333   IN UINT8                         Port,
2334   IN UINT8                         PortMultiplier,
2335   IN OUT EFI_IDENTIFY_DATA         *IdentifyData
2336   )
2337 {
2338   EFI_STATUS               Status;
2339   EFI_ATA_COMMAND_BLOCK    AtaCommandBlock;
2340   EFI_ATA_STATUS_BLOCK     AtaStatusBlock;
2341   UINT8                    Buffer[512];
2342 
2343   if (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE) {
2344     //
2345     // Use SET_FEATURE subcommand to spin up the device.
2346     //
2347     Status = AhciDeviceSetFeature (
2348                PciIo, AhciRegisters, Port, PortMultiplier,
2349                ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP, 0x00, ATA_SPINUP_TIMEOUT
2350                );
2351     DEBUG ((DEBUG_INFO, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
2352             Port, PortMultiplier, Status));
2353     if (EFI_ERROR (Status)) {
2354       return Status;
2355     }
2356   } else {
2357     ASSERT (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE);
2358 
2359     //
2360     // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
2361     //
2362     ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
2363     ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
2364     //
2365     // Perform READ SECTORS PIO Data-In command to Read LBA 0
2366     //
2367     AtaCommandBlock.AtaCommand      = ATA_CMD_READ_SECTORS;
2368     AtaCommandBlock.AtaSectorCount  = 0x1;
2369 
2370     Status = AhciPioTransfer (
2371                PciIo,
2372                AhciRegisters,
2373                Port,
2374                PortMultiplier,
2375                NULL,
2376                0,
2377                TRUE,
2378                &AtaCommandBlock,
2379                &AtaStatusBlock,
2380                &Buffer,
2381                sizeof (Buffer),
2382                ATA_SPINUP_TIMEOUT,
2383                NULL
2384                );
2385     DEBUG ((DEBUG_INFO, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
2386             Port, PortMultiplier, Status));
2387     if (EFI_ERROR (Status)) {
2388       return Status;
2389     }
2390   }
2391 
2392   //
2393   // Read the complete IDENTIFY DEVICE data.
2394   //
2395   ZeroMem (IdentifyData, sizeof (*IdentifyData));
2396   Status = AhciIdentify (PciIo, AhciRegisters, Port, PortMultiplier, IdentifyData);
2397   if (EFI_ERROR (Status)) {
2398     DEBUG ((DEBUG_ERROR, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
2399             Port, PortMultiplier, Status));
2400     return Status;
2401   }
2402 
2403   DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2404           IdentifyData->AtaData.config, IdentifyData->AtaData.specific_config,
2405           IdentifyData->AtaData.command_set_supported_83, IdentifyData->AtaData.command_set_feature_enb_86));
2406   //
2407   // Check if IDD is incomplete
2408   //
2409   if ((IdentifyData->AtaData.config & BIT2) != 0) {
2410     return EFI_DEVICE_ERROR;
2411   }
2412 
2413   return EFI_SUCCESS;
2414 }
2415 
2416 /**
2417   Enable/disable/skip PUIS of the disk according to policy.
2418 
2419   @param  PciIo               The PCI IO protocol instance.
2420   @param  AhciRegisters       The pointer to the EFI_AHCI_REGISTERS.
2421   @param  Port                The number of port.
2422   @param  PortMultiplier      The multiplier of port.
2423 
2424 **/
2425 EFI_STATUS
AhciPuisEnable(IN EFI_PCI_IO_PROTOCOL * PciIo,IN EFI_AHCI_REGISTERS * AhciRegisters,IN UINT8 Port,IN UINT8 PortMultiplier)2426 AhciPuisEnable (
2427   IN EFI_PCI_IO_PROTOCOL           *PciIo,
2428   IN EFI_AHCI_REGISTERS            *AhciRegisters,
2429   IN UINT8                         Port,
2430   IN UINT8                         PortMultiplier
2431   )
2432 {
2433   EFI_STATUS                       Status;
2434 
2435   Status = EFI_SUCCESS;
2436   if (mAtaAtapiPolicy->PuisEnable == 0) {
2437     Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_DISABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
2438   } else if (mAtaAtapiPolicy->PuisEnable == 1) {
2439     Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_ENABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
2440   }
2441   DEBUG ((DEBUG_INFO, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
2442     (mAtaAtapiPolicy->PuisEnable == 0) ? "Disable" : (
2443     (mAtaAtapiPolicy->PuisEnable == 1) ? "Enable" : "Skip"
2444       ), Port, PortMultiplier, Status));
2445   return Status;
2446 }
2447 
2448 /**
2449   Initialize ATA host controller at AHCI mode.
2450 
2451   The function is designed to initialize ATA host controller.
2452 
2453   @param[in]  Instance          A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2454 
2455 **/
2456 EFI_STATUS
2457 EFIAPI
AhciModeInitialization(IN ATA_ATAPI_PASS_THRU_INSTANCE * Instance)2458 AhciModeInitialization (
2459   IN  ATA_ATAPI_PASS_THRU_INSTANCE    *Instance
2460   )
2461 {
2462   EFI_STATUS                       Status;
2463   EFI_PCI_IO_PROTOCOL              *PciIo;
2464   EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
2465   UINT32                           Capability;
2466   UINT8                            MaxPortNumber;
2467   UINT32                           PortImplementBitMap;
2468 
2469   EFI_AHCI_REGISTERS               *AhciRegisters;
2470 
2471   UINT8                            Port;
2472   DATA_64                          Data64;
2473   UINT32                           Offset;
2474   UINT32                           Data;
2475   EFI_IDENTIFY_DATA                Buffer;
2476   EFI_ATA_DEVICE_TYPE              DeviceType;
2477   EFI_ATA_COLLECTIVE_MODE          *SupportedModes;
2478   EFI_ATA_TRANSFER_MODE            TransferMode;
2479   UINT32                           PhyDetectDelay;
2480   UINT32                           Value;
2481 
2482   if (Instance == NULL) {
2483     return EFI_INVALID_PARAMETER;
2484   }
2485 
2486   PciIo   = Instance->PciIo;
2487   IdeInit = Instance->IdeControllerInit;
2488 
2489   Status = AhciReset (PciIo, EFI_AHCI_BUS_RESET_TIMEOUT);
2490 
2491   if (EFI_ERROR (Status)) {
2492     return EFI_DEVICE_ERROR;
2493   }
2494 
2495   //
2496   // Collect AHCI controller information
2497   //
2498   Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);
2499 
2500   //
2501   // Make sure that GHC.AE bit is set before accessing any AHCI registers.
2502   //
2503   Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
2504 
2505   if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
2506     AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
2507   }
2508 
2509   //
2510   // Enable 64-bit DMA support in the PCI layer if this controller
2511   // supports it.
2512   //
2513   if ((Capability & EFI_AHCI_CAP_S64A) != 0) {
2514     Status = PciIo->Attributes (
2515                       PciIo,
2516                       EfiPciIoAttributeOperationEnable,
2517                       EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
2518                       NULL
2519                       );
2520     if (EFI_ERROR (Status)) {
2521       DEBUG ((EFI_D_WARN,
2522         "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
2523         Status));
2524     }
2525   }
2526 
2527   //
2528   // Get the number of command slots per port supported by this HBA.
2529   //
2530   MaxPortNumber        = (UINT8) ((Capability & 0x1F) + 1);
2531 
2532   //
2533   // Get the bit map of those ports exposed by this HBA.
2534   // It indicates which ports that the HBA supports are available for software to use.
2535   //
2536   PortImplementBitMap  = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
2537 
2538   AhciRegisters = &Instance->AhciRegisters;
2539   Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
2540 
2541   if (EFI_ERROR (Status)) {
2542     return EFI_OUT_OF_RESOURCES;
2543   }
2544 
2545   for (Port = 0; Port < EFI_AHCI_MAX_PORTS; Port ++) {
2546     if ((PortImplementBitMap & (((UINT32)BIT0) << Port)) != 0) {
2547       //
2548       // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
2549       //
2550       if ((MaxPortNumber--) == 0) {
2551         //
2552         // Should never be here.
2553         //
2554         ASSERT (FALSE);
2555         return EFI_SUCCESS;
2556       }
2557 
2558       IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
2559 
2560       //
2561       // Initialize FIS Base Address Register and Command List Base Address Register for use.
2562       //
2563       Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
2564       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
2565       AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2566       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
2567       AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2568 
2569       Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
2570       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
2571       AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2572       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
2573       AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2574 
2575       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
2576       Data = AhciReadReg (PciIo, Offset);
2577       if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
2578         AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
2579       }
2580 
2581       if ((Capability & EFI_AHCI_CAP_SSS) != 0) {
2582         AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
2583       }
2584 
2585       //
2586       // Disable aggressive power management.
2587       //
2588       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
2589       AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
2590       //
2591       // Disable the reporting of the corresponding interrupt to system software.
2592       //
2593       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
2594       AhciAndReg (PciIo, Offset, 0);
2595 
2596       //
2597       // Now inform the IDE Controller Init Module.
2598       //
2599       IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
2600 
2601       //
2602       // Enable FIS Receive DMA engine for the first D2H FIS.
2603       //
2604       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
2605       AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
2606 
2607       //
2608       // Wait for the Phy to detect the presence of a device.
2609       //
2610       PhyDetectDelay = EFI_AHCI_BUS_PHY_DETECT_TIMEOUT;
2611       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
2612       do {
2613         Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
2614         if ((Data == EFI_AHCI_PORT_SSTS_DET_PCE) || (Data == EFI_AHCI_PORT_SSTS_DET)) {
2615           break;
2616         }
2617 
2618         MicroSecondDelay (1000);
2619         PhyDetectDelay--;
2620       } while (PhyDetectDelay > 0);
2621 
2622       if (PhyDetectDelay == 0) {
2623         //
2624         // No device detected at this port.
2625         // Clear PxCMD.SUD for those ports at which there are no device present.
2626         //
2627         Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
2628         AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_SUD));
2629         continue;
2630       }
2631 
2632       //
2633       // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
2634       // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
2635       //
2636       PhyDetectDelay = 16 * 1000;
2637       do {
2638         Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
2639         if (AhciReadReg(PciIo, Offset) != 0) {
2640           AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));
2641         }
2642         Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
2643 
2644         Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
2645         if (Data == 0) {
2646           break;
2647         }
2648 
2649         MicroSecondDelay (1000);
2650         PhyDetectDelay--;
2651       } while (PhyDetectDelay > 0);
2652 
2653       if (PhyDetectDelay == 0) {
2654         DEBUG ((EFI_D_ERROR, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port, Data));
2655         continue;
2656       }
2657 
2658       //
2659       // When the first D2H register FIS is received, the content of PxSIG register is updated.
2660       //
2661       Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
2662       Status = AhciWaitMmioSet (
2663                  PciIo,
2664                  Offset,
2665                  0x0000FFFF,
2666                  0x00000101,
2667                  EFI_TIMER_PERIOD_SECONDS(16)
2668                  );
2669       if (EFI_ERROR (Status)) {
2670         continue;
2671       }
2672 
2673       Data = AhciReadReg (PciIo, Offset);
2674       if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
2675         Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
2676 
2677         if (EFI_ERROR (Status)) {
2678           continue;
2679         }
2680 
2681         DeviceType = EfiIdeCdrom;
2682       } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
2683         Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
2684 
2685         if (EFI_ERROR (Status)) {
2686           REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));
2687           continue;
2688         }
2689 
2690         DEBUG ((
2691           DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
2692           Buffer.AtaData.config, Buffer.AtaData.specific_config,
2693           Buffer.AtaData.command_set_supported_83, Buffer.AtaData.command_set_feature_enb_86
2694           ));
2695         if ((Buffer.AtaData.config & BIT2) != 0) {
2696           //
2697           // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
2698           //
2699           Status = AhciSpinUpDisk (
2700                      PciIo,
2701                      AhciRegisters,
2702                      Port,
2703                      0,
2704                      &Buffer
2705                      );
2706           if (EFI_ERROR (Status)) {
2707             DEBUG ((DEBUG_ERROR, "Spin up standby device failed - %r\n", Status));
2708             continue;
2709           }
2710         }
2711 
2712         DeviceType = EfiIdeHarddisk;
2713       } else {
2714         continue;
2715       }
2716       DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
2717               Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
2718 
2719       //
2720       // If the device is a hard disk, then try to enable S.M.A.R.T feature
2721       //
2722       if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {
2723         AhciAtaSmartSupport (
2724           PciIo,
2725           AhciRegisters,
2726           Port,
2727           0,
2728           &Buffer,
2729           NULL
2730           );
2731       }
2732 
2733       //
2734       // Submit identify data to IDE controller init driver
2735       //
2736       IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
2737 
2738       //
2739       // Now start to config ide device parameter and transfer mode.
2740       //
2741       Status = IdeInit->CalculateMode (
2742                           IdeInit,
2743                           Port,
2744                           0,
2745                           &SupportedModes
2746                           );
2747       if (EFI_ERROR (Status)) {
2748         DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
2749         continue;
2750       }
2751 
2752       //
2753       // Set best supported PIO mode on this IDE device
2754       //
2755       if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
2756         TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
2757       } else {
2758         TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
2759       }
2760 
2761       TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
2762 
2763       //
2764       // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2765       // be set together. Only one DMA mode can be set to a device. If setting
2766       // DMA mode operation fails, we can continue moving on because we only use
2767       // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2768       //
2769       if (SupportedModes->UdmaMode.Valid) {
2770         TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
2771         TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
2772       } else if (SupportedModes->MultiWordDmaMode.Valid) {
2773         TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
2774         TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
2775       }
2776 
2777       Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode), ATA_ATAPI_TIMEOUT);
2778       if (EFI_ERROR (Status)) {
2779         DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
2780         continue;
2781       }
2782 
2783       //
2784       // Found a ATA or ATAPI device, add it into the device list.
2785       //
2786       CreateNewDeviceInfo (Instance, Port, 0xFFFF, DeviceType, &Buffer);
2787       if (DeviceType == EfiIdeHarddisk) {
2788         REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
2789         AhciEnableDevSlp (
2790           PciIo,
2791           AhciRegisters,
2792           Port,
2793           0,
2794           &Buffer
2795           );
2796       }
2797 
2798       //
2799       // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
2800       //
2801       if ((Buffer.AtaData.command_set_supported_83 & BIT5) != 0) {
2802         Status = AhciPuisEnable (
2803                    PciIo,
2804                    AhciRegisters,
2805                    Port,
2806                    0
2807                    );
2808         if (EFI_ERROR (Status)) {
2809           DEBUG ((DEBUG_ERROR, "PUIS enable/disable failed, Status = %r\n", Status));
2810           continue;
2811         }
2812       }
2813     }
2814   }
2815 
2816   return EFI_SUCCESS;
2817 }
2818 
2819