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