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