]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPassword / OpalAhciMode.c
diff --git a/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c b/SecurityPkg/Tcg/Opal/OpalPassword/OpalAhciMode.c
deleted file mode 100644 (file)
index 0c4edd5..0000000
+++ /dev/null
@@ -1,1282 +0,0 @@
-/** @file\r
-  This driver is used for Opal Password Feature support at AHCI mode.\r
-\r
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-\r
-#include "OpalPasswordPei.h"\r
-\r
-/**\r
-  Start command for give slot on specific port.\r
-\r
-  @param  AhciBar            AHCI bar address.\r
-  @param  Port               The number of port.\r
-  @param  CommandSlot        The number of CommandSlot.\r
-  @param  Timeout            The timeout Value of start.\r
-\r
-  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.\r
-  @retval EFI_TIMEOUT        The operation is time out.\r
-  @retval EFI_SUCCESS        The command start successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciStartCommand (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT8                     CommandSlot,\r
-  IN  UINT64                    Timeout\r
-  );\r
-\r
-/**\r
-  Stop command running for giving port\r
-\r
-  @param  AhciBar            AHCI bar address.\r
-  @param  Port               The number of port.\r
-  @param  Timeout            The timeout Value of stop.\r
-\r
-  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.\r
-  @retval EFI_TIMEOUT        The operation is time out.\r
-  @retval EFI_SUCCESS        The command stop successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciStopCommand (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT64                    Timeout\r
-  );\r
-\r
-/**\r
-  Read AHCI Operation register.\r
-\r
-  @param  AhciBar      AHCI bar address.\r
-  @param  Offset       The operation register offset.\r
-\r
-  @return The register content read.\r
-\r
-**/\r
-UINT32\r
-EFIAPI\r
-AhciReadReg (\r
-  IN  UINT32              AhciBar,\r
-  IN  UINT32              Offset\r
-  )\r
-{\r
-  UINT32   Data;\r
-\r
-  Data = 0;\r
-\r
-  Data = MmioRead32 (AhciBar + Offset);\r
-\r
-  return Data;\r
-}\r
-\r
-/**\r
-  Write AHCI Operation register.\r
-\r
-  @param  AhciBar      AHCI bar address.\r
-  @param  Offset       The operation register offset.\r
-  @param  Data         The Data used to write down.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciWriteReg (\r
-  IN UINT32               AhciBar,\r
-  IN UINT32               Offset,\r
-  IN UINT32               Data\r
-  )\r
-{\r
-  MmioWrite32 (AhciBar + Offset, Data);\r
-\r
-  return ;\r
-}\r
-\r
-/**\r
-  Do AND operation with the Value of AHCI Operation register.\r
-\r
-  @param  AhciBar      AHCI bar address.\r
-  @param  Offset       The operation register offset.\r
-  @param  AndData      The Data used to do AND operation.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciAndReg (\r
-  IN UINT32               AhciBar,\r
-  IN UINT32               Offset,\r
-  IN UINT32               AndData\r
-  )\r
-{\r
-  UINT32 Data;\r
-\r
-  Data  = AhciReadReg (AhciBar, Offset);\r
-\r
-  Data &= AndData;\r
-\r
-  AhciWriteReg (AhciBar, Offset, Data);\r
-}\r
-\r
-/**\r
-  Do OR operation with the Value of AHCI Operation register.\r
-\r
-  @param  AhciBar      AHCI bar address.\r
-  @param  Offset       The operation register offset.\r
-  @param  OrData       The Data used to do OR operation.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciOrReg (\r
-  IN UINT32               AhciBar,\r
-  IN UINT32               Offset,\r
-  IN UINT32               OrData\r
-  )\r
-{\r
-  UINT32 Data;\r
-\r
-  Data  = AhciReadReg (AhciBar, Offset);\r
-\r
-  Data |= OrData;\r
-\r
-  AhciWriteReg (AhciBar, Offset, Data);\r
-}\r
-\r
-/**\r
-  Wait for memory set to the test Value.\r
-\r
-  @param  AhciBar           AHCI bar address.\r
-  @param  Offset            The memory offset to test.\r
-  @param  MaskValue         The mask Value of memory.\r
-  @param  TestValue         The test Value of memory.\r
-  @param  Timeout           The time out Value for wait memory set.\r
-\r
-  @retval EFI_DEVICE_ERROR  The memory is not set.\r
-  @retval EFI_TIMEOUT       The memory setting is time out.\r
-  @retval EFI_SUCCESS       The memory is correct set.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciWaitMmioSet (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT32                    Offset,\r
-  IN  UINT32                    MaskValue,\r
-  IN  UINT32                    TestValue,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32     Value;\r
-  UINT32     Delay;\r
-\r
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
-\r
-  do {\r
-    Value = AhciReadReg (AhciBar, Offset) & MaskValue;\r
-\r
-    if (Value == TestValue) {\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    //\r
-    // Stall for 100 microseconds.\r
-    //\r
-    MicroSecondDelay (100);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay > 0);\r
-\r
-  return EFI_TIMEOUT;\r
-}\r
-/**\r
-  Wait for the Value of the specified system memory set to the test Value.\r
-\r
-  @param  Address           The system memory address to test.\r
-  @param  MaskValue         The mask Value of memory.\r
-  @param  TestValue         The test Value of memory.\r
-  @param  Timeout           The time out Value for wait memory set, uses 100ns as a unit.\r
-\r
-  @retval EFI_TIMEOUT       The system memory setting is time out.\r
-  @retval EFI_SUCCESS       The system memory is correct set.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciWaitMemSet (\r
-  IN  EFI_PHYSICAL_ADDRESS      Address,\r
-  IN  UINT32                    MaskValue,\r
-  IN  UINT32                    TestValue,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32     Value;\r
-  UINT32     Delay;\r
-\r
-  Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
-\r
-  do {\r
-    //\r
-    // Access sytem memory to see if the Value is the tested one.\r
-    //\r
-    // The system memory pointed by Address will be updated by the\r
-    // SATA Host Controller, "volatile" is introduced to prevent\r
-    // compiler from optimizing the access to the memory address\r
-    // to only read once.\r
-    //\r
-    Value  = *(volatile UINT32 *) (UINTN) Address;\r
-    Value &= MaskValue;\r
-\r
-    if (Value == TestValue) {\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    //\r
-    // Stall for 100 microseconds.\r
-    //\r
-    MicroSecondDelay (100);\r
-\r
-    Delay--;\r
-\r
-  } while (Delay > 0);\r
-\r
-  return EFI_TIMEOUT;\r
-}\r
-\r
-/**\r
-  Check the memory status to the test Value.\r
-\r
-  @param[in]       Address           The memory address to test.\r
-  @param[in]       MaskValue         The mask Value of memory.\r
-  @param[in]       TestValue         The test Value of memory.\r
-  @param[in, out]  RetryTimes        The retry times Value for waitting memory set. If 0, then just try once.\r
-\r
-  @retval EFI_NOTREADY      The memory is not set.\r
-  @retval EFI_TIMEOUT       The memory setting retry times out.\r
-  @retval EFI_SUCCESS       The memory is correct set.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciCheckMemSet (\r
-  IN     UINTN                     Address,\r
-  IN     UINT32                    MaskValue,\r
-  IN     UINT32                    TestValue,\r
-  IN OUT UINTN                     *RetryTimes OPTIONAL\r
-  )\r
-{\r
-  UINT32     Value;\r
-\r
-  if (RetryTimes != NULL) {\r
-    (*RetryTimes)--;\r
-  }\r
-\r
-  Value  = *(volatile UINT32 *) Address;\r
-  Value &= MaskValue;\r
-\r
-  if (Value == TestValue) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if ((RetryTimes != NULL) && (*RetryTimes == 0)) {\r
-    return EFI_TIMEOUT;\r
-  } else {\r
-    return EFI_NOT_READY;\r
-  }\r
-}\r
-\r
-/**\r
-  Clear the port interrupt and error status. It will also clear\r
-  HBA interrupt status.\r
-\r
-  @param      AhciBar        AHCI bar address.\r
-  @param      Port           The number of port.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciClearPortStatus (\r
-  IN  UINT32                 AhciBar,\r
-  IN  UINT8                  Port\r
-  )\r
-{\r
-  UINT32 Offset;\r
-\r
-  //\r
-  // Clear any error status\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
-  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));\r
-\r
-  //\r
-  // Clear any port interrupt status\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;\r
-  AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));\r
-\r
-  //\r
-  // Clear any HBA interrupt status\r
-  //\r
-  AhciWriteReg (AhciBar, EFI_AHCI_IS_OFFSET, AhciReadReg (AhciBar, EFI_AHCI_IS_OFFSET));\r
-}\r
-\r
-/**\r
-  Enable the FIS running for giving port.\r
-\r
-  @param      AhciBar        AHCI bar address.\r
-  @param      Port           The number of port.\r
-  @param      Timeout        The timeout Value of enabling FIS.\r
-\r
-  @retval EFI_DEVICE_ERROR   The FIS enable setting fails.\r
-  @retval EFI_TIMEOUT        The FIS enable setting is time out.\r
-  @retval EFI_SUCCESS        The FIS enable successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciEnableFisReceive (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32 Offset;\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_FRE);\r
-\r
-  return AhciWaitMmioSet (\r
-           AhciBar,\r
-           Offset,\r
-           EFI_AHCI_PORT_CMD_FR,\r
-           EFI_AHCI_PORT_CMD_FR,\r
-           Timeout\r
-           );\r
-}\r
-\r
-/**\r
-  Disable the FIS running for giving port.\r
-\r
-  @param      AhciBar        AHCI bar address.\r
-  @param      Port           The number of port.\r
-  @param      Timeout        The timeout Value of disabling FIS.\r
-\r
-  @retval EFI_DEVICE_ERROR   The FIS disable setting fails.\r
-  @retval EFI_TIMEOUT        The FIS disable setting is time out.\r
-  @retval EFI_UNSUPPORTED    The port is in running state.\r
-  @retval EFI_SUCCESS        The FIS disable successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciDisableFisReceive (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32 Offset;\r
-  UINT32 Data;\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  Data   = AhciReadReg (AhciBar, Offset);\r
-\r
-  //\r
-  // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.\r
-  //\r
-  if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  //\r
-  // Check if the Fis receive DMA engine for the port is running.\r
-  //\r
-  if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));\r
-\r
-  return AhciWaitMmioSet (\r
-           AhciBar,\r
-           Offset,\r
-           EFI_AHCI_PORT_CMD_FR,\r
-           0,\r
-           Timeout\r
-           );\r
-}\r
-\r
-/**\r
-  Build the command list, command table and prepare the fis receiver.\r
-\r
-  @param    AhciContext           The pointer to the AHCI_CONTEXT.\r
-  @param    Port                  The number of port.\r
-  @param    PortMultiplier        The timeout Value of stop.\r
-  @param    CommandFis            The control fis will be used for the transfer.\r
-  @param    CommandList           The command list will be used for the transfer.\r
-  @param    AtapiCommand          The atapi command will be used for the transfer.\r
-  @param    AtapiCommandLength    The Length of the atapi command.\r
-  @param    CommandSlotNumber     The command slot will be used for the transfer.\r
-  @param    DataPhysicalAddr      The pointer to the Data Buffer pci bus master address.\r
-  @param    DataLength            The Data count to be transferred.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciBuildCommand (\r
-  IN     AHCI_CONTEXT               *AhciContext,\r
-  IN     UINT8                      Port,\r
-  IN     UINT8                      PortMultiplier,\r
-  IN     EFI_AHCI_COMMAND_FIS       *CommandFis,\r
-  IN     EFI_AHCI_COMMAND_LIST      *CommandList,\r
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,\r
-  IN     UINT8                      AtapiCommandLength,\r
-  IN     UINT8                      CommandSlotNumber,\r
-  IN OUT VOID                       *DataPhysicalAddr,\r
-  IN     UINT64                     DataLength\r
-  )\r
-{\r
-  EFI_AHCI_REGISTERS    *AhciRegisters;\r
-  UINT32                AhciBar;\r
-  UINT64                BaseAddr;\r
-  UINT64                PrdtNumber;\r
-  UINTN                 RemainedData;\r
-  UINTN                 MemAddr;\r
-  DATA_64               Data64;\r
-  UINT32                Offset;\r
-\r
-  AhciRegisters = &AhciContext->AhciRegisters;\r
-  AhciBar = AhciContext->AhciBar;\r
-\r
-  //\r
-  // Filling the PRDT\r
-  //\r
-  PrdtNumber = DivU64x32 (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1, EFI_AHCI_MAX_DATA_PER_PRDT);\r
-\r
-  //\r
-  // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB Data block.\r
-  // It also limits that the maximum amount of the PRDT entry in the command table\r
-  // is 65535.\r
-  //\r
-  ASSERT (PrdtNumber <= 1);\r
-\r
-  Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis);\r
-\r
-  BaseAddr = Data64.Uint64;\r
-\r
-  ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));\r
-\r
-  ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));\r
-\r
-  CommandFis->AhciCFisPmNum = PortMultiplier;\r
-\r
-  CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  if (AtapiCommand != NULL) {\r
-    CopyMem (\r
-      &AhciRegisters->AhciCommandTable->AtapiCmd,\r
-      AtapiCommand,\r
-      AtapiCommandLength\r
-      );\r
-\r
-    CommandList->AhciCmdA = 1;\r
-    CommandList->AhciCmdP = 1;\r
-\r
-    AhciOrReg (AhciBar, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));\r
-  } else {\r
-    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));\r
-  }\r
-\r
-  RemainedData = (UINTN) DataLength;\r
-  MemAddr      = (UINTN) DataPhysicalAddr;\r
-  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;\r
-\r
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbc = (UINT32)RemainedData - 1;\r
-\r
-  Data64.Uint64 = (UINT64)MemAddr;\r
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDba  = Data64.Uint32.Lower32;\r
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtDbau = Data64.Uint32.Upper32;\r
-\r
-  //\r
-  // Set the last PRDT to Interrupt On Complete\r
-  //\r
-  AhciRegisters->AhciCommandTable->PrdtTable.AhciPrdtIoc = 1;\r
-\r
-  CopyMem (\r
-    (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),\r
-    CommandList,\r
-    sizeof (EFI_AHCI_COMMAND_LIST)\r
-    );\r
-\r
-  Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTable;\r
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba  = Data64.Uint32.Lower32;\r
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;\r
-  AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp   = PortMultiplier;\r
-\r
-}\r
-\r
-/**\r
-  Buid a command FIS.\r
-\r
-  @param  CmdFis            A pointer to the EFI_AHCI_COMMAND_FIS Data structure.\r
-  @param  AtaCommandBlock   A pointer to the AhciBuildCommandFis Data structure.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciBuildCommandFis (\r
-  IN OUT EFI_AHCI_COMMAND_FIS    *CmdFis,\r
-  IN     EFI_ATA_COMMAND_BLOCK   *AtaCommandBlock\r
-  )\r
-{\r
-  ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));\r
-\r
-  CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;\r
-  //\r
-  // Indicator it's a command\r
-  //\r
-  CmdFis->AhciCFisCmdInd      = 0x1;\r
-  CmdFis->AhciCFisCmd         = AtaCommandBlock->AtaCommand;\r
-\r
-  CmdFis->AhciCFisFeature     = AtaCommandBlock->AtaFeatures;\r
-  CmdFis->AhciCFisFeatureExp  = AtaCommandBlock->AtaFeaturesExp;\r
-\r
-  CmdFis->AhciCFisSecNum      = AtaCommandBlock->AtaSectorNumber;\r
-  CmdFis->AhciCFisSecNumExp   = AtaCommandBlock->AtaSectorNumberExp;\r
-\r
-  CmdFis->AhciCFisClyLow      = AtaCommandBlock->AtaCylinderLow;\r
-  CmdFis->AhciCFisClyLowExp   = AtaCommandBlock->AtaCylinderLowExp;\r
-\r
-  CmdFis->AhciCFisClyHigh     = AtaCommandBlock->AtaCylinderHigh;\r
-  CmdFis->AhciCFisClyHighExp  = AtaCommandBlock->AtaCylinderHighExp;\r
-\r
-  CmdFis->AhciCFisSecCount    = AtaCommandBlock->AtaSectorCount;\r
-  CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;\r
-\r
-  CmdFis->AhciCFisDevHead     = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);\r
-}\r
-\r
-/**\r
-  Start a PIO Data transfer on specific port.\r
-\r
-  @param  AhciContext         The pointer to the AHCI_CONTEXT.\r
-  @param  Port                The number of port.\r
-  @param  PortMultiplier      The timeout Value of stop.\r
-  @param  AtapiCommand        The atapi command will be used for the transfer.\r
-  @param  AtapiCommandLength  The Length of the atapi command.\r
-  @param  Read                The transfer direction.\r
-  @param  AtaCommandBlock     The EFI_ATA_COMMAND_BLOCK Data.\r
-  @param  AtaStatusBlock      The EFI_ATA_STATUS_BLOCK Data.\r
-  @param  MemoryAddr          The pointer to the Data Buffer.\r
-  @param  DataCount           The Data count to be transferred.\r
-  @param  Timeout             The timeout Value of non Data transfer.\r
-\r
-  @retval EFI_DEVICE_ERROR    The PIO Data transfer abort with error occurs.\r
-  @retval EFI_TIMEOUT         The operation is time out.\r
-  @retval EFI_UNSUPPORTED     The device is not ready for transfer.\r
-  @retval EFI_SUCCESS         The PIO Data transfer executes successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciPioTransfer (\r
-  IN     AHCI_CONTEXT               *AhciContext,\r
-  IN     UINT8                      Port,\r
-  IN     UINT8                      PortMultiplier,\r
-  IN     EFI_AHCI_ATAPI_COMMAND     *AtapiCommand OPTIONAL,\r
-  IN     UINT8                      AtapiCommandLength,\r
-  IN     BOOLEAN                    Read,\r
-  IN     EFI_ATA_COMMAND_BLOCK      *AtaCommandBlock,\r
-  IN OUT EFI_ATA_STATUS_BLOCK       *AtaStatusBlock,\r
-  IN OUT VOID                       *MemoryAddr,\r
-  IN     UINT32                     DataCount,\r
-  IN     UINT64                     Timeout\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  EFI_AHCI_REGISTERS            *AhciRegisters;\r
-  UINT32                        AhciBar;\r
-  UINT32                        FisBaseAddr;\r
-  UINT32                        Offset;\r
-  UINT32                        Delay;\r
-  EFI_AHCI_COMMAND_FIS          CFis;\r
-  EFI_AHCI_COMMAND_LIST         CmdList;\r
-  UINT32                        PortTfd;\r
-  UINT32                        PrdCount;\r
-  UINT32                        OldRfisLo;\r
-  UINT32                        OldRfisHi;\r
-  UINT32                        OldCmdListLo;\r
-  UINT32                        OldCmdListHi;\r
-\r
-  AhciRegisters = &AhciContext->AhciRegisters;\r
-  AhciBar = AhciContext->AhciBar;\r
-\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
-  OldRfisLo = AhciReadReg (AhciBar, Offset);\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;\r
-  OldRfisHi = AhciReadReg (AhciBar, Offset);\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
-  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;\r
-  AhciWriteReg (AhciBar, Offset, 0);\r
-\r
-  //\r
-  // Single task envrionment, we only use one command table for all port\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
-  OldCmdListLo = AhciReadReg (AhciBar, Offset);\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;\r
-  OldCmdListHi = AhciReadReg (AhciBar, Offset);\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
-  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;\r
-  AhciWriteReg (AhciBar, Offset, 0);\r
-\r
-  //\r
-  // Package read needed\r
-  //\r
-  AhciBuildCommandFis (&CFis, AtaCommandBlock);\r
-\r
-  ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));\r
-\r
-  CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;\r
-  CmdList.AhciCmdW   = Read ? 0 : 1;\r
-\r
-  AhciBuildCommand (\r
-    AhciContext,\r
-    Port,\r
-    PortMultiplier,\r
-    &CFis,\r
-    &CmdList,\r
-    AtapiCommand,\r
-    AtapiCommandLength,\r
-    0,\r
-    MemoryAddr,\r
-    DataCount\r
-    );\r
-\r
-  Status = AhciStartCommand (\r
-             AhciBar,\r
-             Port,\r
-             0,\r
-             Timeout\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-\r
-  //\r
-  // Checking the status and wait the driver sending Data\r
-  //\r
-  FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis;\r
-  if (Read && (AtapiCommand == 0)) {\r
-    //\r
-    // Wait device sends the PIO setup fis before Data transfer\r
-    //\r
-    Status = EFI_TIMEOUT;\r
-    Delay  = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
-    do {\r
-      Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;\r
-\r
-      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0);\r
-      if (!EFI_ERROR (Status)) {\r
-        Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
-        PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);\r
-        //\r
-        // PxTFD will be updated if there is a D2H or SetupFIS received.\r
-        // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.\r
-        //\r
-        if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
-          Status = EFI_DEVICE_ERROR;\r
-          break;\r
-        }\r
-\r
-        PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));\r
-        if (PrdCount == DataCount) {\r
-          break;\r
-        }\r
-      }\r
-\r
-      Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
-      Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, 0);\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = EFI_DEVICE_ERROR;\r
-        break;\r
-      }\r
-\r
-      //\r
-      // Stall for 100 microseconds.\r
-      //\r
-      MicroSecondDelay(100);\r
-\r
-      Delay--;\r
-    } while (Delay > 0);\r
-  } else {\r
-    //\r
-    // Wait for D2H Fis is received\r
-    //\r
-    Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;\r
-    Status = AhciWaitMemSet (\r
-               Offset,\r
-               EFI_AHCI_FIS_TYPE_MASK,\r
-               EFI_AHCI_FIS_REGISTER_D2H,\r
-               Timeout\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      goto Exit;\r
-    }\r
-\r
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
-    PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);\r
-    if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
-      Status = EFI_DEVICE_ERROR;\r
-    }\r
-  }\r
-\r
-Exit:\r
-  AhciStopCommand (\r
-    AhciBar,\r
-    Port,\r
-    Timeout\r
-    );\r
-\r
-  AhciDisableFisReceive (\r
-    AhciBar,\r
-    Port,\r
-    Timeout\r
-    );\r
-\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
-  AhciWriteReg (AhciBar, Offset, OldRfisLo);\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;\r
-  AhciWriteReg (AhciBar, Offset, OldRfisHi);\r
-\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
-  AhciWriteReg (AhciBar, Offset, OldCmdListLo);\r
-  Offset    = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;\r
-  AhciWriteReg (AhciBar, Offset, OldCmdListHi);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Stop command running for giving port\r
-\r
-  @param  AhciBar            AHCI bar address.\r
-  @param  Port               The number of port.\r
-  @param  Timeout            The timeout Value of stop.\r
-\r
-  @retval EFI_DEVICE_ERROR   The command stop unsuccessfully.\r
-  @retval EFI_TIMEOUT        The operation is time out.\r
-  @retval EFI_SUCCESS        The command stop successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciStopCommand (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32 Offset;\r
-  UINT32 Data;\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  Data   = AhciReadReg (AhciBar, Offset);\r
-\r
-  if ((Data & (EFI_AHCI_PORT_CMD_ST |  EFI_AHCI_PORT_CMD_CR)) == 0) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {\r
-    AhciAndReg (AhciBar, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));\r
-  }\r
-\r
-  return AhciWaitMmioSet (\r
-           AhciBar,\r
-           Offset,\r
-           EFI_AHCI_PORT_CMD_CR,\r
-           0,\r
-           Timeout\r
-           );\r
-}\r
-\r
-/**\r
-  Start command for give slot on specific port.\r
-\r
-  @param  AhciBar            AHCI bar address.\r
-  @param  Port               The number of port.\r
-  @param  CommandSlot        The number of CommandSlot.\r
-  @param  Timeout            The timeout Value of start.\r
-\r
-  @retval EFI_DEVICE_ERROR   The command start unsuccessfully.\r
-  @retval EFI_TIMEOUT        The operation is time out.\r
-  @retval EFI_SUCCESS        The command start successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciStartCommand (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT8                     Port,\r
-  IN  UINT8                     CommandSlot,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32                        CmdSlotBit;\r
-  EFI_STATUS                    Status;\r
-  UINT32                        PortStatus;\r
-  UINT32                        StartCmd;\r
-  UINT32                        PortTfd;\r
-  UINT32                        Offset;\r
-  UINT32                        Capability;\r
-\r
-  //\r
-  // Collect AHCI controller information\r
-  //\r
-  Capability = AhciReadReg(AhciBar, EFI_AHCI_CAPABILITY_OFFSET);\r
-\r
-  CmdSlotBit = (UINT32) (1 << CommandSlot);\r
-\r
-  AhciClearPortStatus (\r
-    AhciBar,\r
-    Port\r
-    );\r
-\r
-  Status = AhciEnableFisReceive (\r
-             AhciBar,\r
-             Port,\r
-             Timeout\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  PortStatus = AhciReadReg (AhciBar, Offset);\r
-\r
-  StartCmd = 0;\r
-  if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {\r
-    StartCmd = AhciReadReg (AhciBar, Offset);\r
-    StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;\r
-    StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;\r
-  }\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
-  PortTfd = AhciReadReg (AhciBar, Offset);\r
-\r
-  if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {\r
-    if ((Capability & BIT24) != 0) {\r
-      Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-      AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_COL);\r
-\r
-      AhciWaitMmioSet (\r
-        AhciBar,\r
-        Offset,\r
-        EFI_AHCI_PORT_CMD_COL,\r
-        0,\r
-        Timeout\r
-        );\r
-    }\r
-  }\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);\r
-\r
-  //\r
-  // Setting the command\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;\r
-  AhciAndReg (AhciBar, Offset, 0);\r
-  AhciOrReg (AhciBar, Offset, CmdSlotBit);\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;\r
-  AhciAndReg (AhciBar, Offset, 0);\r
-  AhciOrReg (AhciBar, Offset, CmdSlotBit);\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Do AHCI HBA reset.\r
-\r
-  @param[in]  AhciBar        AHCI bar address.\r
-  @param[in]  Timeout        The timeout Value of reset.\r
-\r
-  @retval EFI_DEVICE_ERROR   AHCI controller is failed to complete hardware reset.\r
-  @retval EFI_TIMEOUT        The reset operation is time out.\r
-  @retval EFI_SUCCESS        AHCI controller is reset successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciReset (\r
-  IN  UINT32                    AhciBar,\r
-  IN  UINT64                    Timeout\r
-  )\r
-{\r
-  UINT32                 Delay;\r
-  UINT32                 Value;\r
-  UINT32                 Capability;\r
-\r
-  //\r
-  // Collect AHCI controller information\r
-  //\r
-  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);\r
-\r
-  //\r
-  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set\r
-  //\r
-  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {\r
-    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);\r
-  }\r
-\r
-  AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);\r
-\r
-  Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);\r
-\r
-  do {\r
-    Value = AhciReadReg(AhciBar, EFI_AHCI_GHC_OFFSET);\r
-    if ((Value & EFI_AHCI_GHC_RESET) == 0) {\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    //\r
-    // Stall for 100 microseconds.\r
-    //\r
-    MicroSecondDelay(100);\r
-\r
-    Delay--;\r
-  } while (Delay > 0);\r
-\r
-  return EFI_TIMEOUT;\r
-\r
-\r
-}\r
-\r
-/**\r
-  Allocate transfer-related data struct which is used at AHCI mode.\r
-\r
-  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.\r
-\r
-  @retval EFI_OUT_OF_RESOURCE   No enough resource.\r
-  @retval EFI_SUCCESS           Successful to allocate resource.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciAllocateResource (\r
-  IN OUT AHCI_CONTEXT       *AhciContext\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  EFI_AHCI_REGISTERS        *AhciRegisters;\r
-  EFI_PHYSICAL_ADDRESS      DeviceAddress;\r
-  VOID                      *Base;\r
-  VOID                      *Mapping;\r
-\r
-  AhciRegisters = &AhciContext->AhciRegisters;\r
-\r
-  //\r
-  // Allocate resources required by AHCI host controller.\r
-  //\r
-  Status = IoMmuAllocateBuffer (\r
-             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-             &Base,\r
-             &DeviceAddress,\r
-             &Mapping\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));\r
-  AhciRegisters->AhciRFisMapping = Mapping;\r
-  AhciRegisters->AhciRFis = Base;\r
-  ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)));\r
-\r
-  Status = IoMmuAllocateBuffer (\r
-             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),\r
-             &Base,\r
-             &DeviceAddress,\r
-             &Mapping\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-       AhciRegisters->AhciRFis,\r
-       AhciRegisters->AhciRFisMapping\r
-       );\r
-    AhciRegisters->AhciRFis = NULL;\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));\r
-  AhciRegisters->AhciCmdListMapping = Mapping;\r
-  AhciRegisters->AhciCmdList = Base;\r
-  ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)));\r
-\r
-  Status = IoMmuAllocateBuffer (\r
-             EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),\r
-             &Base,\r
-             &DeviceAddress,\r
-             &Mapping\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),\r
-       AhciRegisters->AhciCmdList,\r
-       AhciRegisters->AhciCmdListMapping\r
-       );\r
-    AhciRegisters->AhciCmdList = NULL;\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-       AhciRegisters->AhciRFis,\r
-       AhciRegisters->AhciRFisMapping\r
-       );\r
-    AhciRegisters->AhciRFis = NULL;\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));\r
-  AhciRegisters->AhciCommandTableMapping = Mapping;\r
-  AhciRegisters->AhciCommandTable = Base;\r
-  ZeroMem (AhciRegisters->AhciCommandTable, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)));\r
-\r
-  //\r
-  // Allocate resources for data transfer.\r
-  //\r
-  Status = IoMmuAllocateBuffer (\r
-             EFI_SIZE_TO_PAGES (HDD_PAYLOAD),\r
-             &Base,\r
-             &DeviceAddress,\r
-             &Mapping\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-       AhciRegisters->AhciCommandTable,\r
-       AhciRegisters->AhciCommandTableMapping\r
-       );\r
-    AhciRegisters->AhciCommandTable = NULL;\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),\r
-       AhciRegisters->AhciCmdList,\r
-       AhciRegisters->AhciCmdListMapping\r
-       );\r
-    AhciRegisters->AhciCmdList = NULL;\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-       AhciRegisters->AhciRFis,\r
-       AhciRegisters->AhciRFisMapping\r
-       );\r
-    AhciRegisters->AhciRFis = NULL;\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));\r
-  AhciContext->BufferMapping = Mapping;\r
-  AhciContext->Buffer = Base;\r
-  ZeroMem (AhciContext->Buffer, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (HDD_PAYLOAD));\r
-\r
-  DEBUG ((\r
-    DEBUG_INFO,\r
-    "%a() AhciContext 0x%x 0x%x 0x%x 0x%x\n",\r
-    __FUNCTION__,\r
-    AhciContext->Buffer,\r
-    AhciRegisters->AhciRFis,\r
-    AhciRegisters->AhciCmdList,\r
-    AhciRegisters->AhciCommandTable\r
-    ));\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Free allocated transfer-related data struct which is used at AHCI mode.\r
-\r
-  @param[in, out] AhciContext   The pointer to the AHCI_CONTEXT.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-AhciFreeResource (\r
-  IN OUT AHCI_CONTEXT       *AhciContext\r
-  )\r
-{\r
-  EFI_AHCI_REGISTERS        *AhciRegisters;\r
-\r
-  AhciRegisters = &AhciContext->AhciRegisters;\r
-\r
-  if (AhciContext->Buffer != NULL) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (HDD_PAYLOAD),\r
-       AhciContext->Buffer,\r
-       AhciContext->BufferMapping\r
-       );\r
-    AhciContext->Buffer = NULL;\r
-  }\r
-\r
-  if (AhciRegisters->AhciCommandTable != NULL) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_TABLE)),\r
-       AhciRegisters->AhciCommandTable,\r
-       AhciRegisters->AhciCommandTableMapping\r
-       );\r
-    AhciRegisters->AhciCommandTable = NULL;\r
-  }\r
-\r
-  if (AhciRegisters->AhciCmdList != NULL) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_COMMAND_LIST)),\r
-       AhciRegisters->AhciCmdList,\r
-       AhciRegisters->AhciCmdListMapping\r
-       );\r
-    AhciRegisters->AhciCmdList = NULL;\r
-  }\r
-\r
-  if (AhciRegisters->AhciRFis != NULL) {\r
-    IoMmuFreeBuffer (\r
-       EFI_SIZE_TO_PAGES (sizeof (EFI_AHCI_RECEIVED_FIS)),\r
-       AhciRegisters->AhciRFis,\r
-       AhciRegisters->AhciRFisMapping\r
-       );\r
-    AhciRegisters->AhciRFis = NULL;\r
-  }\r
-}\r
-\r
-/**\r
-  Initialize ATA host controller at AHCI mode.\r
-\r
-  The function is designed to initialize ATA host controller.\r
-\r
-  @param[in]  AhciContext   The pointer to the AHCI_CONTEXT.\r
-  @param[in]  Port          The port number to do initialization.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-AhciModeInitialize (\r
-  IN AHCI_CONTEXT    *AhciContext,\r
-  IN UINT8           Port\r
-  )\r
-{\r
-  EFI_STATUS         Status;\r
-  EFI_AHCI_REGISTERS *AhciRegisters;\r
-  UINT32             AhciBar;\r
-  UINT32             Capability;\r
-  UINT32             Offset;\r
-  UINT32             Data;\r
-  UINT32             PhyDetectDelay;\r
-\r
-  AhciRegisters = &AhciContext->AhciRegisters;\r
-  AhciBar = AhciContext->AhciBar;\r
-\r
-  Status = AhciReset (AhciBar, ATA_TIMEOUT);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Collect AHCI controller information\r
-  //\r
-  Capability = AhciReadReg (AhciBar, EFI_AHCI_CAPABILITY_OFFSET);\r
-\r
-  //\r
-  // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set\r
-  //\r
-  if ((Capability & EFI_AHCI_CAP_SAM) == 0) {\r
-    AhciOrReg (AhciBar, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);\r
-  }\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;\r
-  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciRFis);\r
-\r
-  //\r
-  // Single task envrionment, we only use one command table for all port\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;\r
-  AhciWriteReg (AhciBar, Offset, (UINT32)(UINTN)AhciRegisters->AhciCmdList);\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
-  Data = AhciReadReg (AhciBar, Offset);\r
-  if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {\r
-    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_POD);\r
-  }\r
-\r
-  if ((Capability & BIT27) != 0) {\r
-    AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_CMD_SUD);\r
-  }\r
-\r
-  //\r
-  // Disable aggressive power management.\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;\r
-  AhciOrReg (AhciBar, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);\r
-  //\r
-  // Disable the reporting of the corresponding interrupt to system software.\r
-  //\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;\r
-  AhciAndReg (AhciBar, Offset, 0);\r
-\r
-  Status = AhciEnableFisReceive (\r
-             AhciBar,\r
-             Port,\r
-             5000000\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ\r
-  // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.\r
-  //\r
-  PhyDetectDelay = 16 * 1000;\r
-  do {\r
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;\r
-    if (AhciReadReg(AhciBar, Offset) != 0) {\r
-      AhciWriteReg (AhciBar, Offset, AhciReadReg(AhciBar, Offset));\r
-    }\r
-    Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
-\r
-    Data = AhciReadReg (AhciBar, Offset) & EFI_AHCI_PORT_TFD_MASK;\r
-    if (Data == 0) {\r
-      break;\r
-    }\r
-\r
-    MicroSecondDelay (1000);\r
-    PhyDetectDelay--;\r
-  } while (PhyDetectDelay > 0);\r
-\r
-  if (PhyDetectDelay == 0) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;\r
-  Status = AhciWaitMmioSet (\r
-             AhciBar,\r
-             Offset,\r
-             0x0000FFFF,\r
-             0x00000101,\r
-             160000000\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r