]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsPassThruDxe / UfsPassThruHci.c
index 4cc32f07273f05ee97aa9812cad088aab74dbe7c..e868c8c07e1f801e1dbbe3a512d8690c81a0dc6a 100644 (file)
@@ -2,7 +2,7 @@
   UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface\r
   for upper layer application to execute UFS-supported SCSI cmds.\r
 \r
-  Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2014 - 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
 \r
 #include "UfsPassThru.h"\r
 \r
+/**\r
+  Read 32bits data from specified UFS MMIO register.\r
+\r
+  @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in]  Offset        The offset within the UFS Host Controller MMIO space to start\r
+                            the memory operation.\r
+  @param[out] Value         The data buffer to store.\r
+\r
+  @retval EFI_TIMEOUT       The operation is time out.\r
+  @retval EFI_SUCCESS       The operation succeeds.\r
+  @retval Others            The operation fails.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsMmioRead32 (\r
+  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN     UINTN                        Offset,\r
+     OUT UINT32                       *Value\r
+  )\r
+{\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;\r
+  EFI_STATUS                          Status;\r
+\r
+  UfsHc = Private->UfsHostController;\r
+\r
+  Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Write 32bits data to specified UFS MMIO register.\r
+\r
+  @param[in] Private        The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in] Offset         The offset within the UFS Host Controller MMIO space to start\r
+                            the memory operation.\r
+  @param[in] Value          The data to write.\r
+\r
+  @retval EFI_TIMEOUT       The operation is time out.\r
+  @retval EFI_SUCCESS       The operation succeeds.\r
+  @retval Others            The operation fails.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsMmioWrite32 (\r
+  IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN  UINTN                        Offset,\r
+  IN  UINT32                       Value\r
+  )\r
+{\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;\r
+  EFI_STATUS                          Status;\r
+\r
+  UfsHc = Private->UfsHostController;\r
+\r
+  Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);\r
+\r
+  return Status;\r
+}\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
+  @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in]  Offset        The offset within the UFS Host Controller MMIO space to start\r
+                            the memory operation.\r
+  @param[in]  MaskValue     The mask value of memory.\r
+  @param[in]  TestValue     The test value of memory.\r
+  @param[in]  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
+  @retval Others            The operation fails.\r
 \r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 UfsWaitMemSet (\r
-  IN  UINTN                     Address,\r
-  IN  UINT32                    MaskValue,\r
-  IN  UINT32                    TestValue,\r
-  IN  UINT64                    Timeout\r
+  IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN  UINTN                        Offset,\r
+  IN  UINT32                       MaskValue,\r
+  IN  UINT32                       TestValue,\r
+  IN  UINT64                       Timeout\r
   )\r
 {\r
   UINT32     Value;\r
   UINT64     Delay;\r
   BOOLEAN    InfiniteWait;\r
+  EFI_STATUS Status;\r
 \r
   if (Timeout == 0) {\r
     InfiniteWait = TRUE;\r
@@ -52,7 +116,12 @@ UfsWaitMemSet (
     //\r
     // Access PCI MMIO space to see if the value is the tested one.\r
     //\r
-    Value = MmioRead32 (Address) & MaskValue;\r
+    Status = UfsMmioRead32 (Private, Offset, &Value);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Value &= MaskValue;\r
 \r
     if (Value == TestValue) {\r
       return EFI_SUCCESS;\r
@@ -88,35 +157,35 @@ DumpUicCmdExecResult (
       case 0x00:\r
         break;\r
       case 0x01:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x02:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));\r
         break;\r
       case 0x03:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x04:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x05:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));\r
         break;\r
       case 0x06:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));\r
         break;\r
       case 0x07:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));\r
         break;\r
       case 0x08:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
-        break; \r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));\r
+        break;\r
       case 0x09:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - BUSY\n"));\r
         break;\r
       case 0x0A:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));\r
-        break;        \r
+        DEBUG ((DEBUG_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));\r
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -126,8 +195,8 @@ DumpUicCmdExecResult (
       case 0x00:\r
         break;\r
       case 0x01:\r
-        DEBUG ((EFI_D_VERBOSE, "UIC control command fails - FAILURE\n"));\r
-        break;     \r
+        DEBUG ((DEBUG_VERBOSE, "UIC control command fails - FAILURE\n"));\r
+        break;\r
       default :\r
         ASSERT (FALSE);\r
         break;\r
@@ -148,34 +217,34 @@ DumpQueryResponseResult (
 {\r
   switch (Result) {\r
     case 0xF6:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Readable\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Readable\n"));\r
       break;\r
     case 0xF7:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Writeable\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Not Writeable\n"));\r
       break;\r
     case 0xF8:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Already Written\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Parameter Already Written\n"));\r
       break;\r
     case 0xF9:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Length\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Length\n"));\r
       break;\r
     case 0xFA:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Value\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Value\n"));\r
       break;\r
     case 0xFB:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Selector\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Selector\n"));\r
       break;\r
     case 0xFC:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Index\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Index\n"));\r
       break;\r
     case 0xFD:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Idn\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Idn\n"));\r
       break;\r
     case 0xFE:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Opcode\n"));\r
-      break; \r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with Invalid Opcode\n"));\r
+      break;\r
     case 0xFF:\r
-      DEBUG ((EFI_D_VERBOSE, "Query Response with General Failure\n"));\r
+      DEBUG ((DEBUG_VERBOSE, "Query Response with General Failure\n"));\r
       break;\r
     default :\r
       ASSERT (FALSE);\r
@@ -245,7 +314,7 @@ UfsFillTsfOfQueryReqUpiu (
       SwapLittleEndianToBigEndian ((UINT8*)&Length, sizeof (Length));\r
       TsfBase->Length = Length;\r
     }\r
-  \r
+\r
     if (Opcode == UtpQueryFuncOpcodeWrAttr) {\r
       SwapLittleEndianToBigEndian ((UINT8*)&Value, sizeof (Value));\r
       TsfBase->Value  = Value;\r
@@ -331,6 +400,11 @@ UfsInitUtpPrdt (
   UINT8      *Remaining;\r
   UINTN      PrdtNumber;\r
 \r
+  if ((BufferSize & (BIT0 | BIT1)) != 0) {\r
+    BufferSize &= ~(BIT0 | BIT1);\r
+    DEBUG ((DEBUG_WARN, "UfsInitUtpPrdt: The BufferSize [%d] is not dword-aligned!\n", BufferSize));\r
+  }\r
+\r
   if (BufferSize == 0) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -404,6 +478,9 @@ UfsInitQueryRequestUpiu (
 \r
   if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
     CopyMem (QueryReq + 1, Data, DataSize);\r
+\r
+    SwapLittleEndianToBigEndian ((UINT8*)&DataSize, sizeof (UINT16));\r
+    QueryReq->DataSegLen = (UINT16)DataSize;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -477,6 +554,7 @@ UfsCreateScsiCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = DataDirection;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)), sizeof (UINT32));\r
@@ -527,32 +605,13 @@ UfsCreateDMCommandDesc (
   }\r
 \r
   DataDirection = Packet->DataDirection;\r
-  if (DataDirection == UfsDataIn) {\r
-    DataSize = Packet->InTransferLength;\r
-    Data     = Packet->InDataBuffer;\r
-  } else if (DataDirection == UfsDataOut) {\r
-    DataSize = Packet->OutTransferLength;\r
-    Data     = Packet->OutDataBuffer;\r
-  } else {\r
-    DataSize = 0;\r
-    Data     = NULL;\r
-  }\r
-\r
-  if (((Opcode != UtpQueryFuncOpcodeSetFlag) && (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag))\r
-    && ((DataSize == 0) || (Data == NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (((Opcode == UtpQueryFuncOpcodeSetFlag) || (Opcode == UtpQueryFuncOpcodeClrFlag) || (Opcode == UtpQueryFuncOpcodeTogFlag))\r
-    && ((DataSize != 0) || (Data != NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if ((Opcode == UtpQueryFuncOpcodeWrAttr) && (DataSize != sizeof (UINT32))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
+  DataSize      = Packet->TransferLength;\r
+  Data          = Packet->DataBuffer;\r
 \r
   if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {\r
+    if (DataSize == 0 || Data == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);\r
   } else {\r
     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));\r
@@ -586,14 +645,14 @@ UfsCreateDMCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = DataDirection;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
-  Trd->Ocs    = 0x0F;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   if (Opcode == UtpQueryFuncOpcodeWrDesc) {\r
     Trd->RuL  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));\r
-    Trd->RuO  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+    Trd->RuO  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
   } else {\r
-    Trd->RuL  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));\r
+    Trd->RuL  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));\r
     Trd->RuO  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));\r
   }\r
 \r
@@ -645,6 +704,7 @@ UfsCreateNopCommandDesc (
   Trd->Int    = UFS_INTERRUPT_COMMAND;\r
   Trd->Dd     = 0x00;\r
   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;\r
+  Trd->Ocs    = UFS_HC_TRD_OCS_INIT_VALUE;\r
   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);\r
   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);\r
   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));\r
@@ -660,6 +720,7 @@ UfsCreateNopCommandDesc (
   @param[out] Slot          The available slot.\r
 \r
   @retval EFI_SUCCESS       The available slot was found successfully.\r
+  @retval EFI_NOT_READY     No slot is available at this moment.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -668,15 +729,28 @@ UfsFindAvailableSlotInTrl (
      OUT UINT8                        *Slot\r
   )\r
 {\r
+  UINT8            Nutrs;\r
+  UINT8            Index;\r
+  UINT32           Data;\r
+  EFI_STATUS       Status;\r
+\r
   ASSERT ((Private != NULL) && (Slot != NULL));\r
 \r
-  //\r
-  // The simplest algo to always use slot 0.\r
-  // TODO: enhance it to support async transfer with multiple slot.\r
-  //\r
-  *Slot = 0;\r
+  Status  = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  return EFI_SUCCESS;\r
+  Nutrs   = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
+\r
+  for (Index = 0; Index < Nutrs; Index++) {\r
+    if ((Data & (BIT0 << Index)) == 0) {\r
+      *Slot = Index;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_READY;\r
 }\r
 \r
 /**\r
@@ -712,26 +786,33 @@ UfsFindAvailableSlotInTmrl (
   @param[in]  Slot          The slot to be started.\r
 \r
 **/\r
-VOID\r
+EFI_STATUS\r
 UfsStartExecCmd (\r
   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
-  UINTN         UfsHcBase;\r
-  UINTN         Address;\r
   UINT32        Data;\r
+  EFI_STATUS    Status;\r
 \r
-  UfsHcBase = Private->UfsHcBase;\r
+  Status = UfsMmioRead32 (Private, UFS_HC_UTRLRSR_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  Address = UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
-  Data    = MmioRead32 (Address);\r
   if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {\r
-    MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
+    Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
-  Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET;\r
-  MmioWrite32 (Address, BIT0 << Slot);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -741,83 +822,116 @@ UfsStartExecCmd (
   @param[in]  Slot          The slot to be stop.\r
 \r
 **/\r
-VOID\r
+EFI_STATUS\r
 UfsStopExecCmd (\r
   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN  UINT8                        Slot\r
-  ) \r
+  )\r
 {\r
-  UINTN         UfsHcBase;\r
-  UINTN         Address;\r
   UINT32        Data;\r
+  EFI_STATUS    Status;\r
 \r
-  UfsHcBase = Private->UfsHcBase;\r
+  Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  Address = UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Data    = MmioRead32 (Address);\r
   if ((Data & (BIT0 << Slot)) != 0) {\r
-    Address = UfsHcBase + UFS_HC_UTRLCLR_OFFSET;  \r
-    Data    = MmioRead32 (Address);\r
-    MmioWrite32 (Address, (Data & ~(BIT0 << Slot)));\r
+    Status = UfsMmioRead32 (Private, UFS_HC_UTRLCLR_OFFSET, &Data);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = UfsMmioWrite32 (Private, UFS_HC_UTRLCLR_OFFSET, Data & ~(BIT0 << Slot));\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Read or write specified device descriptor of a UFS device.\r
+  Extracts return data from query response upiu.\r
 \r
-  @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
-  @param[in]      Read          The boolean variable to show r/w direction.\r
-  @param[in]      DescId        The ID of device descriptor.\r
-  @param[in]      Index         The Index of device descriptor.\r
-  @param[in]      Selector      The Selector of device descriptor.\r
-  @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
-  @param[in]      DescSize      The size of device descriptor buffer.\r
+  @param[in] Packet     Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+  @param[in] QueryResp  Pointer to the query response.\r
 \r
-  @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
-  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
-  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+  @retval EFI_INVALID_PARAMETER Packet or QueryResp are empty or opcode is invalid.\r
+  @retval EFI_SUCCESS           Data extracted.\r
 \r
 **/\r
 EFI_STATUS\r
-UfsRwDeviceDesc (\r
-  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
-  IN     BOOLEAN                      Read,\r
-  IN     UINT8                        DescId,\r
-  IN     UINT8                        Index,\r
-  IN     UINT8                        Selector,\r
-  IN OUT VOID                         *Descriptor,\r
-  IN     UINT32                       DescSize\r
+UfsGetReturnDataFromQueryResponse (\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet,\r
+  IN UTP_QUERY_RESP_UPIU                   *QueryResp\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
-  UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UINTN                                Address;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  UINT16                               ReturnDataSize;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
+  UINT16  ReturnDataSize;\r
+  UINT32  ReturnData;\r
 \r
-  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+  if (Packet == NULL || QueryResp == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  if (Read) {\r
-    Packet.DataDirection     = UfsDataIn;\r
-    Packet.InDataBuffer      = Descriptor;\r
-    Packet.InTransferLength  = DescSize;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeRdDesc;\r
-  } else {\r
-    Packet.DataDirection     = UfsDataOut;\r
-    Packet.OutDataBuffer     = Descriptor;\r
-    Packet.OutTransferLength = DescSize;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;\r
+  switch (Packet->Opcode) {\r
+    case UtpQueryFuncOpcodeRdDesc:\r
+      ReturnDataSize = QueryResp->Tsf.Length;\r
+      SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+      CopyMem (Packet->DataBuffer, (QueryResp + 1), ReturnDataSize);\r
+      Packet->TransferLength = ReturnDataSize;\r
+      break;\r
+    case UtpQueryFuncOpcodeWrDesc:\r
+      ReturnDataSize = QueryResp->Tsf.Length;\r
+      SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+      Packet->TransferLength = ReturnDataSize;\r
+      break;\r
+    case UtpQueryFuncOpcodeRdFlag:\r
+    case UtpQueryFuncOpcodeSetFlag:\r
+    case UtpQueryFuncOpcodeClrFlag:\r
+    case UtpQueryFuncOpcodeTogFlag:\r
+      CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));\r
+      break;\r
+    case UtpQueryFuncOpcodeRdAttr:\r
+    case UtpQueryFuncOpcodeWrAttr:\r
+      ReturnData = QueryResp->Tsf.Value;\r
+      SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));\r
+      CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));\r
+      break;\r
+    default:\r
+      return EFI_INVALID_PARAMETER;\r
   }\r
-  Packet.DescId              = DescId;\r
-  Packet.Index               = Index;\r
-  Packet.Selector            = Selector;\r
-  Packet.Timeout             = UFS_TIMEOUT;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Creates Transfer Request descriptor and sends Query Request to the device.\r
+\r
+  @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+  @param[in] Packet  Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+\r
+  @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+                                combination to point to a type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
+  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequestRetry (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA            *Private,\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet\r
+  )\r
+{\r
+  UINT8                               Slot;\r
+  UTP_TRD                             *Trd;\r
+  VOID                                *CmdDescHost;\r
+  VOID                                *CmdDescMapping;\r
+  UINT32                              CmdDescSize;\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;\r
+  UTP_QUERY_RESP_UPIU                 *QueryResp;\r
+  EFI_STATUS                          Status;\r
 \r
   //\r
   // Find out which slot of transfer request list is available.\r
@@ -826,19 +940,17 @@ UfsRwDeviceDesc (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  \r
+\r
   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
   //\r
   // Fill transfer request descriptor to this slot.\r
   //\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+  Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
   if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));\r
     return Status;\r
   }\r
 \r
-  //\r
-  // Check the transfer request result.\r
-  //\r
   UfsHc       = Private->UfsHostController;\r
   QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
   ASSERT (QueryResp != NULL);\r
@@ -851,31 +963,30 @@ UfsRwDeviceDesc (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
 \r
-  if (QueryResp->QueryResp != 0) {\r
+  if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));\r
     DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
-  }\r
 \r
-  if (Trd->Ocs == 0) {\r
-    ReturnDataSize = QueryResp->Tsf.Length;\r
-    SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
-\r
-    if (Read) {\r
-      CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
-      Packet.InTransferLength = ReturnDataSize;\r
+    if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||\r
+        (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
     } else {\r
-      Packet.OutTransferLength = ReturnDataSize;\r
+      Status = EFI_DEVICE_ERROR;\r
     }\r
-  } else {\r
-    Status = EFI_DEVICE_ERROR;\r
+    goto Exit;\r
+  }\r
+\r
+  Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));\r
+    goto Exit;\r
   }\r
 \r
 Exit:\r
@@ -894,123 +1005,149 @@ Exit:
 }\r
 \r
 /**\r
-  Read or write specified attribute of a UFS device.\r
+  Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.\r
+\r
+  @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+  @param[in] Packet  Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.\r
+\r
+  @retval EFI_SUCCESS           The device responded correctly to the Query request.\r
+  @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+                                combination to point to a type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      A device error occurred while waiting for the response from the device.\r
+  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of the operation.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequest (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA            *Private,\r
+  IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT8       Retry;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  for (Retry = 0; Retry < 5; Retry ++) {\r
+    Status = UfsSendDmRequestRetry (Private, Packet);\r
+    if (!EFI_ERROR (Status)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Read or write specified device descriptor of a UFS device.\r
 \r
   @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
   @param[in]      Read          The boolean variable to show r/w direction.\r
-  @param[in]      AttrId        The ID of Attribute.\r
-  @param[in]      Index         The Index of Attribute.\r
-  @param[in]      Selector      The Selector of Attribute.\r
-  @param[in, out] Attributes    The value of Attribute to be read or written.\r
+  @param[in]      DescId        The ID of device descriptor.\r
+  @param[in]      Index         The Index of device descriptor.\r
+  @param[in]      Selector      The Selector of device descriptor.\r
+  @param[in, out] Descriptor    The buffer of device descriptor to be read or written.\r
+  @param[in, out] DescSize      The size of device descriptor buffer. On input, the size, in bytes,\r
+                                of the data buffer specified by Descriptor. On output, the number\r
+                                of bytes that were actually transferred.\r
 \r
-  @retval EFI_SUCCESS           The Attribute was read/written successfully.\r
-  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the Attribute.\r
-  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the Attribute.\r
+  @retval EFI_SUCCESS           The device descriptor was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.\r
+  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.\r
 \r
 **/\r
 EFI_STATUS\r
-UfsRwAttributes (\r
+UfsRwDeviceDesc (\r
   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
   IN     BOOLEAN                      Read,\r
-  IN     UINT8                        AttrId,\r
+  IN     UINT8                        DescId,\r
   IN     UINT8                        Index,\r
   IN     UINT8                        Selector,\r
-  IN OUT UINT32                       *Attributes\r
+  IN OUT VOID                         *Descriptor,\r
+  IN OUT UINT32                       *DescSize\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UINTN                                Address;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  UINT32                               ReturnData;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
+  EFI_STATUS                           Status;\r
+\r
+  if (DescSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
 \r
   if (Read) {\r
     Packet.DataDirection     = UfsDataIn;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeRdAttr;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeRdDesc;\r
   } else {\r
     Packet.DataDirection     = UfsDataOut;\r
-    Packet.Opcode            = UtpQueryFuncOpcodeWrAttr;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;\r
   }\r
-  Packet.DescId              = AttrId;\r
+  Packet.DataBuffer          = Descriptor;\r
+  Packet.TransferLength      = *DescSize;\r
+  Packet.DescId              = DescId;\r
   Packet.Index               = Index;\r
   Packet.Selector            = Selector;\r
   Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  //\r
-  // Find out which slot of transfer request list is available.\r
-  //\r
-  Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-  \r
-  Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
-  //\r
-  // Fill transfer request descriptor to this slot.\r
-  //\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+  Status = UfsSendDmRequest (Private, &Packet);\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    *DescSize = 0;\r
+  } else {\r
+    *DescSize = Packet.TransferLength;\r
   }\r
 \r
-  //\r
-  // Check the transfer request result.\r
-  //\r
-  UfsHc       = Private->UfsHostController;\r
-  QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
-  ASSERT (QueryResp != NULL);\r
-  CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
-  //\r
-  // Start to execute the transfer request.\r
-  //\r
-  UfsStartExecCmd (Private, Slot);\r
-\r
-  //\r
-  // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
+  return Status;\r
+}\r
 \r
-  if (QueryResp->QueryResp != 0) {\r
-    DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
-  }\r
+/**\r
+  Read or write specified attribute of a UFS device.\r
 \r
-  if (Trd->Ocs == 0) {\r
-    ReturnData = QueryResp->Tsf.Value;\r
-    SwapLittleEndianToBigEndian ((UINT8*)&ReturnData, sizeof (UINT32));\r
-    *Attributes = ReturnData;\r
-  } else {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
+  @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+  @param[in]      Read          The boolean variable to show r/w direction.\r
+  @param[in]      AttrId        The ID of Attribute.\r
+  @param[in]      Index         The Index of Attribute.\r
+  @param[in]      Selector      The Selector of Attribute.\r
+  @param[in, out] Attributes    The value of Attribute to be read or written.\r
 \r
-Exit:\r
-  UfsHc->Flush (UfsHc);\r
+  @retval EFI_SUCCESS           The Attribute was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a\r
+                                type of UFS device descriptor.\r
+  @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the Attribute.\r
+  @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the Attribute.\r
 \r
-  UfsStopExecCmd (Private, Slot);\r
+**/\r
+EFI_STATUS\r
+UfsRwAttributes (\r
+  IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,\r
+  IN     BOOLEAN                      Read,\r
+  IN     UINT8                        AttrId,\r
+  IN     UINT8                        Index,\r
+  IN     UINT8                        Selector,\r
+  IN OUT UINT32                       *Attributes\r
+  )\r
+{\r
+  UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
 \r
-  if (CmdDescMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, CmdDescMapping);\r
-  }\r
+  ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
 \r
-  if (CmdDescHost != NULL) {\r
-    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
+  if (Read) {\r
+    Packet.DataDirection     = UfsDataIn;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeRdAttr;\r
+  } else {\r
+    Packet.DataDirection     = UfsDataOut;\r
+    Packet.Opcode            = UtpQueryFuncOpcodeWrAttr;\r
   }\r
+  Packet.DataBuffer          = Attributes;\r
+  Packet.DescId              = AttrId;\r
+  Packet.Index               = Index;\r
+  Packet.Selector            = Selector;\r
+  Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  return Status;\r
+  return UfsSendDmRequest (Private, &Packet);\r
 }\r
 \r
 /**\r
@@ -1022,6 +1159,7 @@ Exit:
   @param[in, out] Value         The value to set or clear flag.\r
 \r
   @retval EFI_SUCCESS           The flag was read/written successfully.\r
+  @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.\r
   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the flag.\r
   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the flag.\r
 \r
@@ -1034,16 +1172,7 @@ UfsRwFlags (
   IN OUT UINT8                        *Value\r
   )\r
 {\r
-  EFI_STATUS                           Status;\r
   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UINTN                                Address;\r
-  UTP_QUERY_RESP_UPIU                  *QueryResp;\r
-  UINT32                               CmdDescSize;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
 \r
   if (Value == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1065,75 +1194,13 @@ UfsRwFlags (
       return EFI_INVALID_PARAMETER;\r
     }\r
   }\r
+  Packet.DataBuffer          = Value;\r
   Packet.DescId              = FlagId;\r
   Packet.Index               = 0;\r
   Packet.Selector            = 0;\r
   Packet.Timeout             = UFS_TIMEOUT;\r
 \r
-  //\r
-  // Find out which slot of transfer request list is available.\r
-  //\r
-  Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Fill transfer request descriptor to this slot.\r
-  //\r
-  Trd    = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
-  Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check the transfer request result.\r
-  //\r
-  UfsHc       = Private->UfsHostController;\r
-  QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
-  ASSERT (QueryResp != NULL);\r
-  CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
-  //\r
-  // Start to execute the transfer request.\r
-  //\r
-  UfsStartExecCmd (Private, Slot);\r
-\r
-  //\r
-  // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0, 0, Packet.Timeout);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-\r
-  if (QueryResp->QueryResp != 0) {\r
-    DumpQueryResponseResult (QueryResp->QueryResp);\r
-    Status = EFI_DEVICE_ERROR;\r
-    goto Exit;\r
-  }\r
-\r
-  if (Trd->Ocs == 0) {\r
-    *Value = (UINT8)QueryResp->Tsf.Value;\r
-  } else {\r
-    Status = EFI_DEVICE_ERROR;\r
-  }\r
-\r
-Exit:\r
-  UfsHc->Flush (UfsHc);\r
-\r
-  UfsStopExecCmd (Private, Slot);\r
-\r
-  if (CmdDescMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, CmdDescMapping);\r
-  }\r
-  if (CmdDescHost != NULL) {\r
-    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
-  }\r
-\r
-  return Status;\r
+  return UfsSendDmRequest (Private, &Packet);\r
 }\r
 \r
 /**\r
@@ -1237,7 +1304,6 @@ UfsExecNopCmds (
   UTP_TRD                              *Trd;\r
   UTP_NOP_IN_UPIU                      *NopInUpiu;\r
   UINT32                               CmdDescSize;\r
-  UINTN                                Address;\r
   VOID                                 *CmdDescHost;\r
   VOID                                 *CmdDescMapping;\r
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
@@ -1271,9 +1337,8 @@ UfsExecNopCmds (
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0, 0, UFS_TIMEOUT);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1306,6 +1371,11 @@ Exit:
   @param[in]      Lun           The LUN of the UFS device to send the SCSI Request Packet.\r
   @param[in, out] Packet        A pointer to the SCSI Request Packet to send to a specified Lun of the\r
                                 UFS device.\r
+  @param[in]      Event         If nonblocking I/O is not supported then Event is ignored, and blocking\r
+                                I/O is performed. If Event is NULL, then blocking I/O is performed. If\r
+                                Event is not NULL and non blocking I/O is supported, then\r
+                                nonblocking I/O is performed, and Event will be signaled when the\r
+                                SCSI Request Packet completes.\r
 \r
   @retval EFI_SUCCESS           The SCSI Request Packet was sent by the host. For bi-directional\r
                                 commands, InTransferLength bytes were transferred from\r
@@ -1322,70 +1392,71 @@ EFI_STATUS
 UfsExecScsiCmds (\r
   IN     UFS_PASS_THRU_PRIVATE_DATA                  *Private,\r
   IN     UINT8                                       Lun,\r
-  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet\r
+  IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet,\r
+  IN     EFI_EVENT                                   Event    OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                           Status;\r
-  UINT8                                Slot;\r
-  UTP_TRD                              *Trd;\r
-  UINTN                                Address;\r
-  UINT32                               CmdDescSize;\r
   UTP_RESPONSE_UPIU                    *Response;\r
   UINT16                               SenseDataLen;\r
   UINT32                               ResTranCount;\r
-  VOID                                 *CmdDescHost;\r
-  VOID                                 *CmdDescMapping;\r
-  VOID                                 *DataBufMapping;\r
   VOID                                 *DataBuf;\r
   EFI_PHYSICAL_ADDRESS                 DataBufPhyAddr;\r
   UINT32                               DataLen;\r
   UINTN                                MapLength;\r
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
   EDKII_UFS_HOST_CONTROLLER_OPERATION  Flag;\r
-  UFS_DATA_DIRECTION                   DataDirection;\r
   UTP_TR_PRD                           *PrdtBase;\r
+  EFI_TPL                              OldTpl;\r
+  UFS_PASS_THRU_TRANS_REQ              *TransReq;\r
 \r
-  Trd            = NULL;\r
-  CmdDescHost    = NULL;\r
-  CmdDescMapping = NULL;\r
-  DataBufMapping = NULL;\r
+  TransReq       = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));\r
+  if (TransReq == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TransReq->Signature     = UFS_PASS_THRU_TRANS_REQ_SIG;\r
+  TransReq->TimeoutRemain = Packet->Timeout;\r
   DataBufPhyAddr = 0;\r
   UfsHc          = Private->UfsHostController;\r
   //\r
   // Find out which slot of transfer request list is available.\r
   //\r
-  Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
+  Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
+  TransReq->Trd = ((UTP_TRD*)Private->UtpTrlBase) + TransReq->Slot;\r
 \r
   //\r
   // Fill transfer request descriptor to this slot.\r
   //\r
-  Status = UfsCreateScsiCommandDesc (Private, Lun, Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+  Status = UfsCreateScsiCommandDesc (\r
+             Private,\r
+             Lun,\r
+             Packet,\r
+             TransReq->Trd,\r
+             &TransReq->CmdDescHost,\r
+             &TransReq->CmdDescMapping\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  CmdDescSize = Trd->PrdtO * sizeof (UINT32) + Trd->PrdtL * sizeof (UTP_TR_PRD);\r
+  TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);\r
 \r
   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
     DataBuf       = Packet->InDataBuffer;\r
     DataLen       = Packet->InTransferLength;\r
-    DataDirection = UfsDataIn;\r
     Flag          = EdkiiUfsHcOperationBusMasterWrite;\r
   } else {\r
     DataBuf       = Packet->OutDataBuffer;\r
     DataLen       = Packet->OutTransferLength;\r
-    DataDirection = UfsDataOut;\r
     Flag          = EdkiiUfsHcOperationBusMasterRead;\r
   }\r
 \r
-  if (DataLen == 0) {\r
-    DataDirection = UfsNoData;\r
-  } else {\r
+  if (DataLen != 0) {\r
     MapLength = DataLen;\r
     Status    = UfsHc->Map (\r
                          UfsHc,\r
@@ -1393,7 +1464,7 @@ UfsExecScsiCmds (
                          DataBuf,\r
                          &MapLength,\r
                          &DataBufPhyAddr,\r
-                         &DataBufMapping\r
+                         &TransReq->DataBufMapping\r
                          );\r
 \r
     if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
@@ -1403,20 +1474,37 @@ UfsExecScsiCmds (
   //\r
   // Fill PRDT table of Command UPIU for executed SCSI cmd.\r
   //\r
-  PrdtBase = (UTP_TR_PRD*)((UINT8*)CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
+  PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
   ASSERT (PrdtBase != NULL);\r
   UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);\r
 \r
+  //\r
+  // Insert the async SCSI cmd to the Async I/O list\r
+  //\r
+  if (Event != NULL) {\r
+    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+    TransReq->Packet      = Packet;\r
+    TransReq->CallerEvent = Event;\r
+    InsertTailList (&Private->Queue, &TransReq->TransferList);\r
+    gBS->RestoreTPL (OldTpl);\r
+  }\r
+\r
   //\r
   // Start to execute the transfer request.\r
   //\r
-  UfsStartExecCmd (Private, Slot);\r
+  UfsStartExecCmd (Private, TransReq->Slot);\r
+\r
+  //\r
+  // Immediately return for async I/O.\r
+  //\r
+  if (Event != NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
 \r
   //\r
   // Wait for the completion of the transfer request.\r
-  //  \r
-  Address = Private->UfsHcBase + UFS_HC_UTRLDBR_OFFSET;  \r
-  Status = UfsWaitMemSet (Address, BIT0, 0, Packet->Timeout);\r
+  //\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1424,11 +1512,11 @@ UfsExecScsiCmds (
   //\r
   // Get sense data if exists\r
   //\r
-  Response     = (UTP_RESPONSE_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
+  Response     = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));\r
   ASSERT (Response != NULL);\r
   SenseDataLen = Response->SenseDataLen;\r
   SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\r
-  \r
+\r
   if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {\r
     CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
     Packet->SenseDataLength = (UINT8)SenseDataLen;\r
@@ -1439,12 +1527,12 @@ UfsExecScsiCmds (
   //\r
   Packet->TargetStatus = Response->Status;\r
   if (Response->Response != 0) {\r
-    DEBUG ((EFI_D_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));\r
+    DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));\r
     Status = EFI_DEVICE_ERROR;\r
     goto Exit;\r
   }\r
 \r
-  if (Trd->Ocs == 0) {\r
+  if (TransReq->Trd->Ocs == 0) {\r
     if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
       if ((Response->Flags & BIT5) == BIT5) {\r
         ResTranCount = Response->ResTranCount;\r
@@ -1465,18 +1553,21 @@ UfsExecScsiCmds (
 Exit:\r
   UfsHc->Flush (UfsHc);\r
 \r
-  UfsStopExecCmd (Private, Slot);\r
+  UfsStopExecCmd (Private, TransReq->Slot);\r
 \r
-  if (DataBufMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, DataBufMapping);\r
+  if (TransReq->DataBufMapping != NULL) {\r
+    UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
   }\r
 \r
 Exit1:\r
-  if (CmdDescMapping != NULL) {\r
-    UfsHc->Unmap (UfsHc, CmdDescMapping);\r
+  if (TransReq->CmdDescMapping != NULL) {\r
+    UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);\r
   }\r
-  if (CmdDescHost != NULL) {\r
-    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
+  if (TransReq->CmdDescHost != NULL) {\r
+    UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);\r
+  }\r
+  if (TransReq != NULL) {\r
+    FreePool (TransReq);\r
   }\r
   return Status;\r
 }\r
@@ -1506,18 +1597,21 @@ UfsExecUicCommands (
   )\r
 {\r
   EFI_STATUS  Status;\r
-  UINTN       Address;\r
   UINT32      Data;\r
-  UINTN       UfsHcBase;\r
 \r
-  UfsHcBase = Private->UfsHcBase;\r
-  Address   = UfsHcBase + UFS_HC_IS_OFFSET;\r
-  Data      = MmioRead32 (Address);\r
+  Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {\r
     //\r
     // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.\r
     //\r
-    MmioWrite32 (Address, Data);\r
+    Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   //\r
@@ -1525,41 +1619,48 @@ UfsExecUicCommands (
   // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)\r
   // are set.\r
   //\r
-  Address = UfsHcBase + UFS_HC_UCMD_ARG1_OFFSET;\r
-  MmioWrite32 (Address, Arg1);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  Address = UfsHcBase + UFS_HC_UCMD_ARG2_OFFSET;\r
-  MmioWrite32 (Address, Arg2);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
-  Address = UfsHcBase + UFS_HC_UCMD_ARG3_OFFSET;\r
-  MmioWrite32 (Address, Arg3);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_STATUS_OFFSET;\r
-  Status = UfsWaitMemSet (Address, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Address = UfsHcBase + UFS_HC_UIC_CMD_OFFSET;\r
-  MmioWrite32 (Address, (UINT32)UicOpcode);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)\r
-  // This bit is set to '1' by the host controller upon completion of a UIC command. \r
+  // This bit is set to '1' by the host controller upon completion of a UIC command.\r
   //\r
-  Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
-  Data    = MmioRead32 (Address);\r
-  Status  = UfsWaitMemSet (Address, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);\r
+  Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   if (UicOpcode != UfsUicDmeReset) {\r
-    Address = UfsHcBase + UFS_HC_UCMD_ARG2_OFFSET;\r
-    Data    = MmioRead32 (Address);\r
+    Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
     if ((Data & 0xFF) != 0) {\r
       DEBUG_CODE_BEGIN();\r
         DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));\r
@@ -1571,18 +1672,20 @@ UfsExecUicCommands (
   //\r
   // Check value of HCS.DP and make sure that there is a device attached to the Link.\r
   //\r
-  Address = UfsHcBase + UFS_HC_STATUS_OFFSET;  \r
-  Data    = MmioRead32 (Address);\r
+  Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   if ((Data & UFS_HC_HCS_DP) == 0) {\r
-    Address = UfsHcBase + UFS_HC_IS_OFFSET;\r
-    Status  = UfsWaitMemSet (Address, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
+    Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
     if (EFI_ERROR (Status)) {\r
       return EFI_DEVICE_ERROR;\r
     }\r
     return EFI_NOT_FOUND;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "UfsPassThruDxe: found a attached UFS device\n"));\r
+  DEBUG ((DEBUG_INFO, "UfsPassThruDxe: found a attached UFS device\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1616,9 +1719,9 @@ UfsAllocateAlignCommonBuffer (
   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;\r
 \r
   if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {\r
-    Is32BitAddr = TRUE;\r
-  } else {\r
     Is32BitAddr = FALSE;\r
+  } else {\r
+    Is32BitAddr = TRUE;\r
   }\r
 \r
   UfsHc  = Private->UfsHostController;\r
@@ -1694,7 +1797,6 @@ UfsEnableHostController (
   )\r
 {\r
   EFI_STATUS             Status;\r
-  UINTN                  Address;\r
   UINT32                 Data;\r
 \r
   //\r
@@ -1702,17 +1804,23 @@ UfsEnableHostController (
   //\r
   // Reinitialize the UFS host controller if HCE bit of HC register is set.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_ENABLE_OFFSET;\r
-  Data    = MmioRead32 (Address);\r
+  Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {\r
     //\r
     // Write a 0 to the HCE register at first to disable the host controller.\r
     //\r
-    MmioWrite32 (Address, 0);\r
+    Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
     //\r
     // Wait until HCE is read as '0' before continuing.\r
     //\r
-    Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);\r
+    Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);\r
     if (EFI_ERROR (Status)) {\r
       return EFI_DEVICE_ERROR;\r
     }\r
@@ -1721,11 +1829,15 @@ UfsEnableHostController (
   //\r
   // Write a 1 to the HCE register to enable the UFS host controller.\r
   //\r
-  MmioWrite32 (Address, UFS_HC_HCE_EN);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   //\r
   // Wait until HCE is read as '1' before continuing.\r
   //\r
-  Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
@@ -1789,22 +1901,25 @@ UfsInitTaskManagementRequestList (
   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private\r
   )\r
 {\r
-  UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutmrs;\r
   VOID                   *CmdDescHost;\r
   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
   VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
-  \r
+\r
   //\r
   // Initial h/w and s/w context for future operations.\r
   //\r
   CmdDescHost    = NULL;\r
   CmdDescMapping = NULL;\r
   CmdDescPhyAddr = 0;\r
-  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;  \r
-  Data    = MmioRead32 (Address);\r
+\r
+  Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Private->Capabilities = Data;\r
 \r
   //\r
@@ -1820,10 +1935,15 @@ UfsInitTaskManagementRequestList (
   // Program the UTP Task Management Request List Base Address and UTP Task Management\r
   // Request List Base Address with a 64-bit address allocated at step 6.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
   Private->UtpTmrlBase = CmdDescHost;\r
   Private->Nutmrs      = Nutmrs;\r
   Private->TmrlMapping = CmdDescMapping;\r
@@ -1832,8 +1952,10 @@ UfsInitTaskManagementRequestList (
   // Enable the UTP Task Management Request List by setting the UTP Task Management\r
   // Request List RunStop Register (UTMRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;  \r
-  MmioWrite32 (Address, UFS_HC_UTMRLRSR);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1852,12 +1974,11 @@ UfsInitTransferRequestList (
   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private\r
   )\r
 {\r
-  UINTN                  Address;\r
   UINT32                 Data;\r
   UINT8                  Nutrs;\r
   VOID                   *CmdDescHost;\r
   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;\r
-  VOID                   *CmdDescMapping;  \r
+  VOID                   *CmdDescMapping;\r
   EFI_STATUS             Status;\r
 \r
   //\r
@@ -1866,8 +1987,12 @@ UfsInitTransferRequestList (
   CmdDescHost    = NULL;\r
   CmdDescMapping = NULL;\r
   CmdDescPhyAddr = 0;\r
-  Address = Private->UfsHcBase + UFS_HC_CAP_OFFSET;  \r
-  Data    = MmioRead32 (Address);\r
+\r
+  Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Private->Capabilities = Data;\r
 \r
   //\r
@@ -1883,20 +2008,28 @@ UfsInitTransferRequestList (
   // Program the UTP Transfer Request List Base Address and UTP Transfer Request List\r
   // Base Address with a 64-bit address allocated at step 8.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLBA_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)(UINTN)CmdDescPhyAddr);\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLBAU_OFFSET;  \r
-  MmioWrite32 (Address, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   Private->UtpTrlBase = CmdDescHost;\r
-  Private->Nutrs      = Nutrs;  \r
+  Private->Nutrs      = Nutrs;\r
   Private->TrlMapping = CmdDescMapping;\r
 \r
   //\r
   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
   // RunStop Register (UTRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
-  MmioWrite32 (Address, UFS_HC_UTRLRSR);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -1919,29 +2052,29 @@ UfsControllerInit (
 \r
   Status = UfsEnableHostController (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsDeviceDetection (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsInitTaskManagementRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
   Status = UfsInitTransferRequestList (Private);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));\r
     return Status;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "UfsControllerInit Finished\n"));\r
+  DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1960,41 +2093,226 @@ UfsControllerStop (
   )\r
 {\r
   EFI_STATUS             Status;\r
-  UINTN                  Address;\r
   UINT32                 Data;\r
 \r
   //\r
   // Enable the UTP Task Management Request List by setting the UTP Task Management\r
   // Request List RunStop Register (UTMRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTMRLRSR_OFFSET;  \r
-  MmioWrite32 (Address, 0);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List\r
   // RunStop Register (UTRLRSR) to '1'.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_UTRLRSR_OFFSET;  \r
-  MmioWrite32 (Address, 0);\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Write a 0 to the HCE register in order to disable the host controller.\r
   //\r
-  Address = Private->UfsHcBase + UFS_HC_ENABLE_OFFSET;\r
-  Data    = MmioRead32 (Address);\r
+  Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
   ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);\r
-  MmioWrite32 (Address, 0);\r
+\r
+  Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
 \r
   //\r
   // Wait until HCE is read as '0' before continuing.\r
   //\r
-  Status = UfsWaitMemSet (Address, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  DEBUG ((EFI_D_INFO, "UfsController is stopped\n"));\r
+  DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+/**\r
+  Internal helper function which will signal the caller event and clean up\r
+  resources.\r
+\r
+  @param[in] Private   The pointer to the UFS_PASS_THRU_PRIVATE_DATA data\r
+                       structure.\r
+  @param[in] TransReq  The pointer to the UFS_PASS_THRU_TRANS_REQ data\r
+                       structure.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SignalCallerEvent (\r
+  IN UFS_PASS_THRU_PRIVATE_DATA      *Private,\r
+  IN UFS_PASS_THRU_TRANS_REQ         *TransReq\r
+  )\r
+{\r
+  EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
+  EFI_EVENT                          CallerEvent;\r
+\r
+  ASSERT ((Private != NULL) && (TransReq != NULL));\r
+\r
+  UfsHc        = Private->UfsHostController;\r
+  CallerEvent  = TransReq->CallerEvent;\r
+\r
+  RemoveEntryList (&TransReq->TransferList);\r
+\r
+  UfsHc->Flush (UfsHc);\r
+\r
+  UfsStopExecCmd (Private, TransReq->Slot);\r
+\r
+  if (TransReq->DataBufMapping != NULL) {\r
+    UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
+  }\r
+\r
+  if (TransReq->CmdDescMapping != NULL) {\r
+    UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);\r
+  }\r
+  if (TransReq->CmdDescHost != NULL) {\r
+    UfsHc->FreeBuffer (\r
+             UfsHc,\r
+             EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),\r
+             TransReq->CmdDescHost\r
+             );\r
+  }\r
+\r
+  FreePool (TransReq);\r
+\r
+  gBS->SignalEvent (CallerEvent);\r
+  return;\r
+}\r
+\r
+/**\r
+  Call back function when the timer event is signaled.\r
+\r
+  @param[in]  Event     The Event this notify function registered to.\r
+  @param[in]  Context   Pointer to the context data registered to the Event.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ProcessAsyncTaskList (\r
+  IN EFI_EVENT          Event,\r
+  IN VOID               *Context\r
+  )\r
+{\r
+  UFS_PASS_THRU_PRIVATE_DATA                    *Private;\r
+  LIST_ENTRY                                    *Entry;\r
+  LIST_ENTRY                                    *NextEntry;\r
+  UFS_PASS_THRU_TRANS_REQ                       *TransReq;\r
+  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet;\r
+  UTP_RESPONSE_UPIU                             *Response;\r
+  UINT16                                        SenseDataLen;\r
+  UINT32                                        ResTranCount;\r
+  UINT32                                        SlotsMap;\r
+  UINT32                                        Value;\r
+  EFI_STATUS                                    Status;\r
+\r
+  Private   = (UFS_PASS_THRU_PRIVATE_DATA*) Context;\r
+  SlotsMap  = 0;\r
+\r
+  //\r
+  // Check the entries in the async I/O queue are done or not.\r
+  //\r
+  if (!IsListEmpty(&Private->Queue)) {\r
+    EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {\r
+      TransReq  = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);\r
+      Packet    = TransReq->Packet;\r
+\r
+      if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {\r
+        return;\r
+      }\r
+      SlotsMap |= BIT0 << TransReq->Slot;\r
+\r
+      Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // TODO: Should find/add a proper host adapter return status for this\r
+        // case.\r
+        //\r
+        Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;\r
+        DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));\r
+        SignalCallerEvent (Private, TransReq);\r
+        continue;\r
+      }\r
+\r
+      if ((Value & (BIT0 << TransReq->Slot)) != 0) {\r
+        //\r
+        // Scsi cmd not finished yet.\r
+        //\r
+        if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {\r
+          TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;\r
+          continue;\r
+        } else {\r
+          //\r
+          // Timeout occurs.\r
+          //\r
+          Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));\r
+          SignalCallerEvent (Private, TransReq);\r
+          continue;\r
+        }\r
+      } else {\r
+        //\r
+        // Scsi cmd finished.\r
+        //\r
+        // Get sense data if exists\r
+        //\r
+        Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));\r
+        ASSERT (Response != NULL);\r
+        SenseDataLen = Response->SenseDataLen;\r
+        SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));\r
+\r
+        if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {\r
+          CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);\r
+          Packet->SenseDataLength = (UINT8)SenseDataLen;\r
+        }\r
+\r
+        //\r
+        // Check the transfer request result.\r
+        //\r
+        Packet->TargetStatus = Response->Status;\r
+        if (Response->Response != 0) {\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));\r
+          SignalCallerEvent (Private, TransReq);\r
+          continue;\r
+        }\r
+\r
+        if (TransReq->Trd->Ocs == 0) {\r
+          if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
+            if ((Response->Flags & BIT5) == BIT5) {\r
+              ResTranCount = Response->ResTranCount;\r
+              SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));\r
+              Packet->InTransferLength -= ResTranCount;\r
+            }\r
+          } else {\r
+            if ((Response->Flags & BIT5) == BIT5) {\r
+              ResTranCount = Response->ResTranCount;\r
+              SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));\r
+              Packet->OutTransferLength -= ResTranCount;\r
+            }\r
+          }\r
+        } else {\r
+          DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));\r
+          SignalCallerEvent (Private, TransReq);\r
+          continue;\r
+        }\r
+\r
+        DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));\r
+        SignalCallerEvent (Private, TransReq);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r