Home | History | Annotate | Download | only in AtaAtapiPassThru
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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