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