]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
MdeModulePkg: Refine casting expression result to bigger size
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsPassThruDxe / UfsPassThruHci.c
index 9f9abab40fded3ea72fc10e08669bcdfcd04ea38..3dd8cbfe7a76e7f2f346bf76c9d1781f66fa4350 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 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2014 - 2017, 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
@@ -400,6 +400,11 @@ UfsInitUtpPrdt (
   UINT8      *Remaining;\r
   UINTN      PrdtNumber;\r
 \r
+  if ((BufferSize & (BIT0 | BIT1)) != 0) {\r
+    BufferSize &= ~(BIT0 | BIT1);\r
+    DEBUG ((EFI_D_WARN, "UfsInitUtpPrdt: The BufferSize [%d] is not dword-aligned!\n", BufferSize));\r
+  }\r
+\r
   if (BufferSize == 0) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -546,6 +551,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
@@ -655,14 +661,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
@@ -714,6 +720,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
@@ -729,6 +736,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
@@ -737,15 +745,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
@@ -935,7 +956,7 @@ UfsRwDeviceDesc (
   //\r
   // Wait for the completion of the transfer request.\r
   //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1058,7 +1079,7 @@ UfsRwAttributes (
   //\r
   // Wait for the completion of the transfer request.\r
   //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1182,7 +1203,7 @@ UfsRwFlags (
   //\r
   // Wait for the completion of the transfer request.\r
   //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1349,7 +1370,7 @@ UfsExecNopCmds (
   //\r
   // Wait for the completion of the transfer request.\r
   //  \r
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, UFS_TIMEOUT);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1382,6 +1403,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
@@ -1398,69 +1424,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
-  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
@@ -1468,7 +1496,7 @@ UfsExecScsiCmds (
                          DataBuf,\r
                          &MapLength,\r
                          &DataBufPhyAddr,\r
-                         &DataBufMapping\r
+                         &TransReq->DataBufMapping\r
                          );\r
 \r
     if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
@@ -1478,19 +1506,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
-  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
+  Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);\r
   if (EFI_ERROR (Status)) {\r
     goto Exit;\r
   }\r
@@ -1498,7 +1544,7 @@ 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
@@ -1518,7 +1564,7 @@ UfsExecScsiCmds (
     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
@@ -1539,18 +1585,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
@@ -1702,9 +1751,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
@@ -2123,3 +2172,179 @@ UfsControllerStop (
   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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));\r
+          SignalCallerEvent (Private, TransReq);\r
+          continue;\r
+        }\r
+\r
+        DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));\r
+        SignalCallerEvent (Private, TransReq);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r