Home | History | Annotate | Download | only in UfsPassThruDxe
      1 /** @file
      2   UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface
      3   for upper layer application to execute UFS-supported SCSI cmds.
      4 
      5   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "UfsPassThru.h"
     17 
     18 /**
     19   Read 32bits data from specified UFS MMIO register.
     20 
     21   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
     22   @param[in]  Offset        The offset within the UFS Host Controller MMIO space to start
     23                             the memory operation.
     24   @param[out] Value         The data buffer to store.
     25 
     26   @retval EFI_TIMEOUT       The operation is time out.
     27   @retval EFI_SUCCESS       The operation succeeds.
     28   @retval Others            The operation fails.
     29 
     30 **/
     31 EFI_STATUS
     32 UfsMmioRead32 (
     33   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
     34   IN     UINTN                        Offset,
     35      OUT UINT32                       *Value
     36   )
     37 {
     38   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;
     39   EFI_STATUS                          Status;
     40 
     41   UfsHc = Private->UfsHostController;
     42 
     43   Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);
     44 
     45   return Status;
     46 }
     47 
     48 /**
     49   Write 32bits data to specified UFS MMIO register.
     50 
     51   @param[in] Private        The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
     52   @param[in] Offset         The offset within the UFS Host Controller MMIO space to start
     53                             the memory operation.
     54   @param[in] Value          The data to write.
     55 
     56   @retval EFI_TIMEOUT       The operation is time out.
     57   @retval EFI_SUCCESS       The operation succeeds.
     58   @retval Others            The operation fails.
     59 
     60 **/
     61 EFI_STATUS
     62 UfsMmioWrite32 (
     63   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
     64   IN  UINTN                        Offset,
     65   IN  UINT32                       Value
     66   )
     67 {
     68   EDKII_UFS_HOST_CONTROLLER_PROTOCOL  *UfsHc;
     69   EFI_STATUS                          Status;
     70 
     71   UfsHc = Private->UfsHostController;
     72 
     73   Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);
     74 
     75   return Status;
     76 }
     77 
     78 /**
     79   Wait for the value of the specified system memory set to the test value.
     80 
     81   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
     82   @param[in]  Offset        The offset within the UFS Host Controller MMIO space to start
     83                             the memory operation.
     84   @param[in]  MaskValue     The mask value of memory.
     85   @param[in]  TestValue     The test value of memory.
     86   @param[in]  Timeout       The time out value for wait memory set, uses 100ns as a unit.
     87 
     88   @retval EFI_TIMEOUT       The system memory setting is time out.
     89   @retval EFI_SUCCESS       The system memory is correct set.
     90   @retval Others            The operation fails.
     91 
     92 **/
     93 EFI_STATUS
     94 UfsWaitMemSet (
     95   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
     96   IN  UINTN                        Offset,
     97   IN  UINT32                       MaskValue,
     98   IN  UINT32                       TestValue,
     99   IN  UINT64                       Timeout
    100   )
    101 {
    102   UINT32     Value;
    103   UINT64     Delay;
    104   BOOLEAN    InfiniteWait;
    105   EFI_STATUS Status;
    106 
    107   if (Timeout == 0) {
    108     InfiniteWait = TRUE;
    109   } else {
    110     InfiniteWait = FALSE;
    111   }
    112 
    113   Delay = DivU64x32 (Timeout, 10) + 1;
    114 
    115   do {
    116     //
    117     // Access PCI MMIO space to see if the value is the tested one.
    118     //
    119     Status = UfsMmioRead32 (Private, Offset, &Value);
    120     if (EFI_ERROR (Status)) {
    121       return Status;
    122     }
    123 
    124     Value &= MaskValue;
    125 
    126     if (Value == TestValue) {
    127       return EFI_SUCCESS;
    128     }
    129 
    130     //
    131     // Stall for 1 microseconds.
    132     //
    133     MicroSecondDelay (1);
    134 
    135     Delay--;
    136 
    137   } while (InfiniteWait || (Delay > 0));
    138 
    139   return EFI_TIMEOUT;
    140 }
    141 
    142 /**
    143   Dump UIC command execution result for debugging.
    144 
    145   @param[in]   UicOpcode  The executed UIC opcode.
    146   @param[in]   Result     The result to be parsed.
    147 
    148 **/
    149 VOID
    150 DumpUicCmdExecResult (
    151   IN  UINT8     UicOpcode,
    152   IN  UINT8     Result
    153   )
    154 {
    155   if (UicOpcode <= UfsUicDmePeerSet) {
    156     switch (Result) {
    157       case 0x00:
    158         break;
    159       case 0x01:
    160         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE\n"));
    161         break;
    162       case 0x02:
    163         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - INVALID_MIB_ATTRIBUTE_VALUE\n"));
    164         break;
    165       case 0x03:
    166         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - READ_ONLY_MIB_ATTRIBUTE\n"));
    167         break;
    168       case 0x04:
    169         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - WRITE_ONLY_MIB_ATTRIBUTE\n"));
    170         break;
    171       case 0x05:
    172         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_INDEX\n"));
    173         break;
    174       case 0x06:
    175         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - LOCKED_MIB_ATTRIBUTE\n"));
    176         break;
    177       case 0x07:
    178         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BAD_TEST_FEATURE_INDEX\n"));
    179         break;
    180       case 0x08:
    181         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - PEER_COMMUNICATION_FAILURE\n"));
    182         break;
    183       case 0x09:
    184         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - BUSY\n"));
    185         break;
    186       case 0x0A:
    187         DEBUG ((EFI_D_VERBOSE, "UIC configuration command fails - DME_FAILURE\n"));
    188         break;
    189       default :
    190         ASSERT (FALSE);
    191         break;
    192     }
    193   } else {
    194     switch (Result) {
    195       case 0x00:
    196         break;
    197       case 0x01:
    198         DEBUG ((EFI_D_VERBOSE, "UIC control command fails - FAILURE\n"));
    199         break;
    200       default :
    201         ASSERT (FALSE);
    202         break;
    203     }
    204   }
    205 }
    206 
    207 /**
    208   Dump QUERY RESPONSE UPIU result for debugging.
    209 
    210   @param[in]   Result  The result to be parsed.
    211 
    212 **/
    213 VOID
    214 DumpQueryResponseResult (
    215   IN  UINT8     Result
    216   )
    217 {
    218   switch (Result) {
    219     case 0xF6:
    220       DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Readable\n"));
    221       break;
    222     case 0xF7:
    223       DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Not Writeable\n"));
    224       break;
    225     case 0xF8:
    226       DEBUG ((EFI_D_VERBOSE, "Query Response with Parameter Already Written\n"));
    227       break;
    228     case 0xF9:
    229       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Length\n"));
    230       break;
    231     case 0xFA:
    232       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Value\n"));
    233       break;
    234     case 0xFB:
    235       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Selector\n"));
    236       break;
    237     case 0xFC:
    238       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Index\n"));
    239       break;
    240     case 0xFD:
    241       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Idn\n"));
    242       break;
    243     case 0xFE:
    244       DEBUG ((EFI_D_VERBOSE, "Query Response with Invalid Opcode\n"));
    245       break;
    246     case 0xFF:
    247       DEBUG ((EFI_D_VERBOSE, "Query Response with General Failure\n"));
    248       break;
    249     default :
    250       ASSERT (FALSE);
    251       break;
    252   }
    253 }
    254 
    255 /**
    256   Swap little endian to big endian.
    257 
    258   @param[in, out] Buffer      The data buffer. In input, it contains little endian data.
    259                               In output, it will become big endian.
    260   @param[in]      BufferSize  The length of converted data.
    261 
    262 **/
    263 VOID
    264 SwapLittleEndianToBigEndian (
    265   IN OUT UINT8         *Buffer,
    266   IN     UINT32        BufferSize
    267   )
    268 {
    269   UINT32 Index;
    270   UINT8  Temp;
    271   UINT32 SwapCount;
    272 
    273   SwapCount = BufferSize / 2;
    274   for (Index = 0; Index < SwapCount; Index++) {
    275     Temp = Buffer[Index];
    276     Buffer[Index] = Buffer[BufferSize - 1 - Index];
    277     Buffer[BufferSize - 1 - Index] = Temp;
    278   }
    279 }
    280 
    281 /**
    282   Fill TSF field of QUERY REQUEST UPIU.
    283 
    284   @param[in, out] TsfBase      The base address of TSF field of QUERY REQUEST UPIU.
    285   @param[in]      Opcode       The opcode of request.
    286   @param[in]      DescId       The descriptor ID of request.
    287   @param[in]      Index        The index of request.
    288   @param[in]      Selector     The selector of request.
    289   @param[in]      Length       The length of transferred data. The maximum is 4.
    290   @param[in]      Value        The value of transferred data.
    291 
    292 **/
    293 VOID
    294 UfsFillTsfOfQueryReqUpiu (
    295   IN OUT UTP_UPIU_TSF        *TsfBase,
    296   IN     UINT8               Opcode,
    297   IN     UINT8               DescId    OPTIONAL,
    298   IN     UINT8               Index     OPTIONAL,
    299   IN     UINT8               Selector  OPTIONAL,
    300   IN     UINT16              Length    OPTIONAL,
    301   IN     UINT32              Value     OPTIONAL
    302   )
    303 {
    304   ASSERT (TsfBase != NULL);
    305   ASSERT (Opcode <= UtpQueryFuncOpcodeTogFlag);
    306 
    307   TsfBase->Opcode   = Opcode;
    308   if (Opcode != UtpQueryFuncOpcodeNop) {
    309     TsfBase->DescId   = DescId;
    310     TsfBase->Index    = Index;
    311     TsfBase->Selector = Selector;
    312 
    313     if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeWrDesc)) {
    314       SwapLittleEndianToBigEndian ((UINT8*)&Length, sizeof (Length));
    315       TsfBase->Length = Length;
    316     }
    317 
    318     if (Opcode == UtpQueryFuncOpcodeWrAttr) {
    319       SwapLittleEndianToBigEndian ((UINT8*)&Value, sizeof (Value));
    320       TsfBase->Value  = Value;
    321     }
    322   }
    323 }
    324 
    325 /**
    326   Initialize COMMAND UPIU.
    327 
    328   @param[in, out] Command         The base address of COMMAND UPIU.
    329   @param[in]      Lun             The Lun on which the SCSI command is executed.
    330   @param[in]      TaskTag         The task tag of request.
    331   @param[in]      Cdb             The cdb buffer containing SCSI command.
    332   @param[in]      CdbLength       The cdb length.
    333   @param[in]      DataDirection   The direction of data transfer.
    334   @param[in]      ExpDataTranLen  The expected transfer data length.
    335 
    336   @retval EFI_SUCCESS     The initialization succeed.
    337 
    338 **/
    339 EFI_STATUS
    340 UfsInitCommandUpiu (
    341   IN OUT UTP_COMMAND_UPIU              *Command,
    342   IN     UINT8                         Lun,
    343   IN     UINT8                         TaskTag,
    344   IN     UINT8                         *Cdb,
    345   IN     UINT8                         CdbLength,
    346   IN     UFS_DATA_DIRECTION            DataDirection,
    347   IN     UINT32                        ExpDataTranLen
    348   )
    349 {
    350   UINT8                   Flags;
    351 
    352   ASSERT ((Command != NULL) && (Cdb != NULL));
    353 
    354   //
    355   // Task attribute is hard-coded to Ordered.
    356   //
    357   if (DataDirection == UfsDataIn) {
    358     Flags = BIT0 | BIT6;
    359   } else if (DataDirection == UfsDataOut) {
    360     Flags = BIT0 | BIT5;
    361   } else {
    362     Flags = BIT0;
    363   }
    364 
    365   //
    366   // Fill UTP COMMAND UPIU associated fields.
    367   //
    368   Command->TransCode = 0x01;
    369   Command->Flags     = Flags;
    370   Command->Lun       = Lun;
    371   Command->TaskTag   = TaskTag;
    372   Command->CmdSet    = 0x00;
    373   SwapLittleEndianToBigEndian ((UINT8*)&ExpDataTranLen, sizeof (ExpDataTranLen));
    374   Command->ExpDataTranLen = ExpDataTranLen;
    375 
    376   CopyMem (Command->Cdb, Cdb, CdbLength);
    377 
    378   return EFI_SUCCESS;
    379 }
    380 
    381 /**
    382   Initialize UTP PRDT for data transfer.
    383 
    384   @param[in] Prdt         The base address of PRDT.
    385   @param[in] Buffer       The buffer to be read or written.
    386   @param[in] BufferSize   The data size to be read or written.
    387 
    388   @retval EFI_SUCCESS     The initialization succeed.
    389 
    390 **/
    391 EFI_STATUS
    392 UfsInitUtpPrdt (
    393   IN  UTP_TR_PRD                       *Prdt,
    394   IN  VOID                             *Buffer,
    395   IN  UINT32                           BufferSize
    396   )
    397 {
    398   UINT32     PrdtIndex;
    399   UINT32     RemainingLen;
    400   UINT8      *Remaining;
    401   UINTN      PrdtNumber;
    402 
    403   if (BufferSize == 0) {
    404     return EFI_SUCCESS;
    405   }
    406 
    407   ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);
    408 
    409   RemainingLen = BufferSize;
    410   Remaining    = Buffer;
    411   PrdtNumber   = (UINTN)DivU64x32 ((UINT64)BufferSize + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);
    412 
    413   for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
    414     if (RemainingLen < UFS_MAX_DATA_LEN_PER_PRD) {
    415       Prdt[PrdtIndex].DbCount = (UINT32)RemainingLen - 1;
    416     } else {
    417       Prdt[PrdtIndex].DbCount = UFS_MAX_DATA_LEN_PER_PRD - 1;
    418     }
    419 
    420     Prdt[PrdtIndex].DbAddr  = (UINT32)RShiftU64 ((UINT64)(UINTN)Remaining, 2);
    421     Prdt[PrdtIndex].DbAddrU = (UINT32)RShiftU64 ((UINT64)(UINTN)Remaining, 32);
    422     RemainingLen -= UFS_MAX_DATA_LEN_PER_PRD;
    423     Remaining    += UFS_MAX_DATA_LEN_PER_PRD;
    424   }
    425 
    426   return EFI_SUCCESS;
    427 }
    428 
    429 /**
    430   Initialize QUERY REQUEST UPIU.
    431 
    432   @param[in, out] QueryReq      The base address of QUERY REQUEST UPIU.
    433   @param[in]      TaskTag       The task tag of request.
    434   @param[in]      Opcode        The opcode of request.
    435   @param[in]      DescId        The descriptor ID of request.
    436   @param[in]      Index         The index of request.
    437   @param[in]      Selector      The selector of request.
    438   @param[in]      DataSize      The data size to be read or written.
    439   @param[in]      Data          The buffer to be read or written.
    440 
    441   @retval EFI_SUCCESS           The initialization succeed.
    442 
    443 **/
    444 EFI_STATUS
    445 UfsInitQueryRequestUpiu (
    446   IN OUT UTP_QUERY_REQ_UPIU            *QueryReq,
    447   IN     UINT8                         TaskTag,
    448   IN     UINT8                         Opcode,
    449   IN     UINT8                         DescId,
    450   IN     UINT8                         Index,
    451   IN     UINT8                         Selector,
    452   IN     UINTN                         DataSize   OPTIONAL,
    453   IN     UINT8                         *Data      OPTIONAL
    454   )
    455 {
    456   ASSERT (QueryReq != NULL);
    457 
    458   QueryReq->TransCode = 0x16;
    459   QueryReq->TaskTag   = TaskTag;
    460   if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeRdFlag) || (Opcode == UtpQueryFuncOpcodeRdAttr)) {
    461     QueryReq->QueryFunc = QUERY_FUNC_STD_READ_REQ;
    462   } else {
    463     QueryReq->QueryFunc = QUERY_FUNC_STD_WRITE_REQ;
    464   }
    465 
    466   if (Opcode == UtpQueryFuncOpcodeWrAttr) {
    467     UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, 0, *(UINT32*)Data);
    468   } else if ((Opcode == UtpQueryFuncOpcodeRdDesc) || (Opcode == UtpQueryFuncOpcodeWrDesc)) {
    469     UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, (UINT16)DataSize, 0);
    470   } else {
    471     UfsFillTsfOfQueryReqUpiu (&QueryReq->Tsf, Opcode, DescId, Index, Selector, 0, 0);
    472   }
    473 
    474   if (Opcode == UtpQueryFuncOpcodeWrDesc) {
    475     CopyMem (QueryReq + 1, Data, DataSize);
    476   }
    477 
    478   return EFI_SUCCESS;
    479 }
    480 
    481 /**
    482   Allocate COMMAND/RESPONSE UPIU for filling UTP TRD's command descriptor field.
    483 
    484   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    485   @param[in]  Lun               The Lun on which the SCSI command is executed.
    486   @param[in]  Packet            The pointer to the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET data structure.
    487   @param[in]  Trd               The pointer to the UTP Transfer Request Descriptor.
    488   @param[out] CmdDescHost       A pointer to store the base system memory address of the allocated range.
    489   @param[out] CmdDescMapping    A resulting value to pass to Unmap().
    490 
    491   @retval EFI_SUCCESS           The creation succeed.
    492   @retval EFI_DEVICE_ERROR      The creation failed.
    493   @retval EFI_OUT_OF_RESOURCES  The memory resource is insufficient.
    494 
    495 **/
    496 EFI_STATUS
    497 UfsCreateScsiCommandDesc (
    498   IN     UFS_PASS_THRU_PRIVATE_DATA                  *Private,
    499   IN     UINT8                                       Lun,
    500   IN     EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet,
    501   IN     UTP_TRD                                     *Trd,
    502      OUT VOID                                        **CmdDescHost,
    503      OUT VOID                                        **CmdDescMapping
    504   )
    505 {
    506   UINTN                             TotalLen;
    507   UINTN                             PrdtNumber;
    508   UTP_COMMAND_UPIU                  *CommandUpiu;
    509   EFI_PHYSICAL_ADDRESS              CmdDescPhyAddr;
    510   EFI_STATUS                        Status;
    511   UINT32                            DataLen;
    512   UFS_DATA_DIRECTION                DataDirection;
    513 
    514   ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));
    515 
    516   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
    517     DataLen       = Packet->InTransferLength;
    518     DataDirection = UfsDataIn;
    519   } else {
    520     DataLen       = Packet->OutTransferLength;
    521     DataDirection = UfsDataOut;
    522   }
    523 
    524   if (DataLen == 0) {
    525     DataDirection = UfsNoData;
    526   }
    527 
    528   PrdtNumber = (UINTN)DivU64x32 ((UINT64)DataLen + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);
    529 
    530   TotalLen   = ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)) + PrdtNumber * sizeof (UTP_TR_PRD);
    531 
    532   Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
    533   if (EFI_ERROR (Status)) {
    534     return Status;
    535   }
    536 
    537   CommandUpiu = (UTP_COMMAND_UPIU*)*CmdDescHost;
    538 
    539   UfsInitCommandUpiu (CommandUpiu, Lun, Private->TaskTag++, Packet->Cdb, Packet->CdbLength, DataDirection, DataLen);
    540 
    541   //
    542   // Fill UTP_TRD associated fields
    543   // NOTE: Some UFS host controllers request the Response UPIU and the Physical Region Description Table
    544   // *MUST* be located at a 64-bit aligned boundary.
    545   //
    546   Trd->Int    = UFS_INTERRUPT_COMMAND;
    547   Trd->Dd     = DataDirection;
    548   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;
    549   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
    550   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
    551   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)), sizeof (UINT32));
    552   Trd->RuO    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)), sizeof (UINT32));
    553   Trd->PrdtL  = (UINT16)PrdtNumber;
    554   Trd->PrdtO  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU))), sizeof (UINT32));
    555   return EFI_SUCCESS;
    556 }
    557 
    558 /**
    559   Allocate QUERY REQUEST/QUERY RESPONSE UPIU for filling UTP TRD's command descriptor field.
    560 
    561   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    562   @param[in]  Packet            The pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET data structure.
    563   @param[in]  Trd               The pointer to the UTP Transfer Request Descriptor.
    564   @param[out] CmdDescHost       A pointer to store the base system memory address of the allocated range.
    565   @param[out] CmdDescMapping    A resulting value to pass to Unmap().
    566 
    567   @retval EFI_SUCCESS           The creation succeed.
    568   @retval EFI_DEVICE_ERROR      The creation failed.
    569   @retval EFI_OUT_OF_RESOURCES  The memory resource is insufficient.
    570   @retval EFI_INVALID_PARAMETER The parameter passed in is invalid.
    571 
    572 **/
    573 EFI_STATUS
    574 UfsCreateDMCommandDesc (
    575   IN     UFS_PASS_THRU_PRIVATE_DATA            *Private,
    576   IN     UFS_DEVICE_MANAGEMENT_REQUEST_PACKET  *Packet,
    577   IN     UTP_TRD                               *Trd,
    578      OUT VOID                                  **CmdDescHost,
    579      OUT VOID                                  **CmdDescMapping
    580   )
    581 {
    582   UINTN                         TotalLen;
    583   UTP_QUERY_REQ_UPIU            *QueryReqUpiu;
    584   UINT8                         Opcode;
    585   UINT32                        DataSize;
    586   UINT8                         *Data;
    587   UINT8                         DataDirection;
    588   EFI_PHYSICAL_ADDRESS          CmdDescPhyAddr;
    589   EFI_STATUS                    Status;
    590 
    591   ASSERT ((Private != NULL) && (Packet != NULL) && (Trd != NULL));
    592 
    593   Opcode = Packet->Opcode;
    594   if ((Opcode > UtpQueryFuncOpcodeTogFlag) || (Opcode == UtpQueryFuncOpcodeNop)) {
    595     return EFI_INVALID_PARAMETER;
    596   }
    597 
    598   DataDirection = Packet->DataDirection;
    599   if (DataDirection == UfsDataIn) {
    600     DataSize = Packet->InTransferLength;
    601     Data     = Packet->InDataBuffer;
    602   } else if (DataDirection == UfsDataOut) {
    603     DataSize = Packet->OutTransferLength;
    604     Data     = Packet->OutDataBuffer;
    605   } else {
    606     DataSize = 0;
    607     Data     = NULL;
    608   }
    609 
    610   if (((Opcode != UtpQueryFuncOpcodeSetFlag) && (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag))
    611     && ((DataSize == 0) || (Data == NULL))) {
    612     return EFI_INVALID_PARAMETER;
    613   }
    614 
    615   if (((Opcode == UtpQueryFuncOpcodeSetFlag) || (Opcode == UtpQueryFuncOpcodeClrFlag) || (Opcode == UtpQueryFuncOpcodeTogFlag))
    616     && ((DataSize != 0) || (Data != NULL))) {
    617     return EFI_INVALID_PARAMETER;
    618   }
    619 
    620   if ((Opcode == UtpQueryFuncOpcodeWrAttr) && (DataSize != sizeof (UINT32))) {
    621     return EFI_INVALID_PARAMETER;
    622   }
    623 
    624   if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {
    625     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);
    626   } else {
    627     TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));
    628   }
    629 
    630   Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
    631   if (EFI_ERROR (Status)) {
    632     return Status;
    633   }
    634 
    635   //
    636   // Initialize UTP QUERY REQUEST UPIU
    637   //
    638   QueryReqUpiu = (UTP_QUERY_REQ_UPIU*)*CmdDescHost;
    639   ASSERT (QueryReqUpiu != NULL);
    640   UfsInitQueryRequestUpiu (
    641     QueryReqUpiu,
    642     Private->TaskTag++,
    643     Opcode,
    644     Packet->DescId,
    645     Packet->Index,
    646     Packet->Selector,
    647     DataSize,
    648     Data
    649     );
    650 
    651   //
    652   // Fill UTP_TRD associated fields
    653   // NOTE: Some UFS host controllers request the Query Response UPIU *MUST* be located at a 64-bit aligned boundary.
    654   //
    655   Trd->Int    = UFS_INTERRUPT_COMMAND;
    656   Trd->Dd     = DataDirection;
    657   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;
    658   Trd->Ocs    = 0x0F;
    659   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
    660   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
    661   if (Opcode == UtpQueryFuncOpcodeWrDesc) {
    662     Trd->RuL  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));
    663     Trd->RuO  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));
    664   } else {
    665     Trd->RuL  = (UINT16)DivU64x32 ((UINT64)(ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize)), sizeof (UINT32));
    666     Trd->RuO  = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));
    667   }
    668 
    669   return EFI_SUCCESS;
    670 }
    671 
    672 /**
    673   Allocate NOP IN and NOP OUT UPIU for filling UTP TRD's command descriptor field.
    674 
    675   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    676   @param[in]  Trd               The pointer to the UTP Transfer Request Descriptor.
    677   @param[out] CmdDescHost       A pointer to store the base system memory address of the allocated range.
    678   @param[out] CmdDescMapping    A resulting value to pass to Unmap().
    679 
    680   @retval EFI_SUCCESS           The creation succeed.
    681   @retval EFI_DEVICE_ERROR      The creation failed.
    682   @retval EFI_OUT_OF_RESOURCES  The memory resource is insufficient.
    683 
    684 **/
    685 EFI_STATUS
    686 UfsCreateNopCommandDesc (
    687   IN     UFS_PASS_THRU_PRIVATE_DATA        *Private,
    688   IN     UTP_TRD                           *Trd,
    689      OUT VOID                              **CmdDescHost,
    690      OUT VOID                              **CmdDescMapping
    691   )
    692 {
    693   UINTN                    TotalLen;
    694   UTP_NOP_OUT_UPIU         *NopOutUpiu;
    695   EFI_STATUS               Status;
    696   EFI_PHYSICAL_ADDRESS     CmdDescPhyAddr;
    697 
    698   ASSERT ((Private != NULL) && (Trd != NULL));
    699 
    700   TotalLen = ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)) + ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU));
    701   Status   = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
    702   if (EFI_ERROR (Status)) {
    703     return Status;
    704   }
    705 
    706   NopOutUpiu = (UTP_NOP_OUT_UPIU*)*CmdDescHost;
    707   ASSERT (NopOutUpiu != NULL);
    708   NopOutUpiu->TaskTag = Private->TaskTag++;
    709 
    710   //
    711   // Fill UTP_TRD associated fields
    712   // NOTE: Some UFS host controllers request the Nop Out UPIU *MUST* be located at a 64-bit aligned boundary.
    713   //
    714   Trd->Int    = UFS_INTERRUPT_COMMAND;
    715   Trd->Dd     = 0x00;
    716   Trd->Ct     = UFS_STORAGE_COMMAND_TYPE;
    717   Trd->UcdBa  = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
    718   Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
    719   Trd->RuL    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));
    720   Trd->RuO    = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)), sizeof (UINT32));
    721 
    722   return EFI_SUCCESS;
    723 }
    724 
    725 /**
    726   Find out available slot in transfer list of a UFS device.
    727 
    728   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    729   @param[out] Slot          The available slot.
    730 
    731   @retval EFI_SUCCESS       The available slot was found successfully.
    732   @retval EFI_NOT_READY     No slot is available at this moment.
    733 
    734 **/
    735 EFI_STATUS
    736 UfsFindAvailableSlotInTrl (
    737   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
    738      OUT UINT8                        *Slot
    739   )
    740 {
    741   UINT8            Nutrs;
    742   UINT8            Index;
    743   UINT32           Data;
    744   EFI_STATUS       Status;
    745 
    746   ASSERT ((Private != NULL) && (Slot != NULL));
    747 
    748   Status  = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
    749   if (EFI_ERROR (Status)) {
    750     return Status;
    751   }
    752 
    753   Nutrs   = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);
    754 
    755   for (Index = 0; Index < Nutrs; Index++) {
    756     if ((Data & (BIT0 << Index)) == 0) {
    757       *Slot = Index;
    758       return EFI_SUCCESS;
    759     }
    760   }
    761 
    762   return EFI_NOT_READY;
    763 }
    764 
    765 /**
    766   Find out available slot in task management transfer list of a UFS device.
    767 
    768   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    769   @param[out] Slot          The available slot.
    770 
    771   @retval EFI_SUCCESS       The available slot was found successfully.
    772 
    773 **/
    774 EFI_STATUS
    775 UfsFindAvailableSlotInTmrl (
    776   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
    777      OUT UINT8                        *Slot
    778   )
    779 {
    780   ASSERT ((Private != NULL) && (Slot != NULL));
    781 
    782   //
    783   // The simplest algo to always use slot 0.
    784   // TODO: enhance it to support async transfer with multiple slot.
    785   //
    786   *Slot = 0;
    787 
    788   return EFI_SUCCESS;
    789 }
    790 
    791 /**
    792   Start specified slot in transfer list of a UFS device.
    793 
    794   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    795   @param[in]  Slot          The slot to be started.
    796 
    797 **/
    798 EFI_STATUS
    799 UfsStartExecCmd (
    800   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
    801   IN  UINT8                        Slot
    802   )
    803 {
    804   UINT32        Data;
    805   EFI_STATUS    Status;
    806 
    807   Status = UfsMmioRead32 (Private, UFS_HC_UTRLRSR_OFFSET, &Data);
    808   if (EFI_ERROR (Status)) {
    809     return Status;
    810   }
    811 
    812   if ((Data & UFS_HC_UTRLRSR) != UFS_HC_UTRLRSR) {
    813     Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
    814     if (EFI_ERROR (Status)) {
    815       return Status;
    816     }
    817   }
    818 
    819   Status = UfsMmioWrite32 (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot);
    820   if (EFI_ERROR (Status)) {
    821     return Status;
    822   }
    823 
    824   return EFI_SUCCESS;
    825 }
    826 
    827 /**
    828   Stop specified slot in transfer list of a UFS device.
    829 
    830   @param[in]  Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    831   @param[in]  Slot          The slot to be stop.
    832 
    833 **/
    834 EFI_STATUS
    835 UfsStopExecCmd (
    836   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
    837   IN  UINT8                        Slot
    838   )
    839 {
    840   UINT32        Data;
    841   EFI_STATUS    Status;
    842 
    843   Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
    844   if (EFI_ERROR (Status)) {
    845     return Status;
    846   }
    847 
    848   if ((Data & (BIT0 << Slot)) != 0) {
    849     Status = UfsMmioRead32 (Private, UFS_HC_UTRLCLR_OFFSET, &Data);
    850     if (EFI_ERROR (Status)) {
    851       return Status;
    852     }
    853 
    854     Status = UfsMmioWrite32 (Private, UFS_HC_UTRLCLR_OFFSET, Data & ~(BIT0 << Slot));
    855     if (EFI_ERROR (Status)) {
    856       return Status;
    857     }
    858   }
    859 
    860   return EFI_SUCCESS;
    861 }
    862 
    863 /**
    864   Read or write specified device descriptor of a UFS device.
    865 
    866   @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    867   @param[in]      Read          The boolean variable to show r/w direction.
    868   @param[in]      DescId        The ID of device descriptor.
    869   @param[in]      Index         The Index of device descriptor.
    870   @param[in]      Selector      The Selector of device descriptor.
    871   @param[in, out] Descriptor    The buffer of device descriptor to be read or written.
    872   @param[in]      DescSize      The size of device descriptor buffer.
    873 
    874   @retval EFI_SUCCESS           The device descriptor was read/written successfully.
    875   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the device descriptor.
    876   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the device descriptor.
    877 
    878 **/
    879 EFI_STATUS
    880 UfsRwDeviceDesc (
    881   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
    882   IN     BOOLEAN                      Read,
    883   IN     UINT8                        DescId,
    884   IN     UINT8                        Index,
    885   IN     UINT8                        Selector,
    886   IN OUT VOID                         *Descriptor,
    887   IN     UINT32                       DescSize
    888   )
    889 {
    890   EFI_STATUS                           Status;
    891   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
    892   UINT8                                Slot;
    893   UTP_TRD                              *Trd;
    894   UTP_QUERY_RESP_UPIU                  *QueryResp;
    895   UINT32                               CmdDescSize;
    896   UINT16                               ReturnDataSize;
    897   VOID                                 *CmdDescHost;
    898   VOID                                 *CmdDescMapping;
    899   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
    900 
    901   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
    902 
    903   if (Read) {
    904     Packet.DataDirection     = UfsDataIn;
    905     Packet.InDataBuffer      = Descriptor;
    906     Packet.InTransferLength  = DescSize;
    907     Packet.Opcode            = UtpQueryFuncOpcodeRdDesc;
    908   } else {
    909     Packet.DataDirection     = UfsDataOut;
    910     Packet.OutDataBuffer     = Descriptor;
    911     Packet.OutTransferLength = DescSize;
    912     Packet.Opcode            = UtpQueryFuncOpcodeWrDesc;
    913   }
    914   Packet.DescId              = DescId;
    915   Packet.Index               = Index;
    916   Packet.Selector            = Selector;
    917   Packet.Timeout             = UFS_TIMEOUT;
    918 
    919   //
    920   // Find out which slot of transfer request list is available.
    921   //
    922   Status = UfsFindAvailableSlotInTrl (Private, &Slot);
    923   if (EFI_ERROR (Status)) {
    924     return Status;
    925   }
    926 
    927   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
    928   //
    929   // Fill transfer request descriptor to this slot.
    930   //
    931   Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);
    932   if (EFI_ERROR (Status)) {
    933     return Status;
    934   }
    935 
    936   //
    937   // Check the transfer request result.
    938   //
    939   UfsHc       = Private->UfsHostController;
    940   QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
    941   ASSERT (QueryResp != NULL);
    942   CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
    943 
    944   //
    945   // Start to execute the transfer request.
    946   //
    947   UfsStartExecCmd (Private, Slot);
    948 
    949   //
    950   // Wait for the completion of the transfer request.
    951   //
    952   Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
    953   if (EFI_ERROR (Status)) {
    954     goto Exit;
    955   }
    956 
    957   if (QueryResp->QueryResp != 0) {
    958     DumpQueryResponseResult (QueryResp->QueryResp);
    959     Status = EFI_DEVICE_ERROR;
    960     goto Exit;
    961   }
    962 
    963   if (Trd->Ocs == 0) {
    964     ReturnDataSize = QueryResp->Tsf.Length;
    965     SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));
    966 
    967     if (Read) {
    968       CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);
    969       Packet.InTransferLength = ReturnDataSize;
    970     } else {
    971       Packet.OutTransferLength = ReturnDataSize;
    972     }
    973   } else {
    974     Status = EFI_DEVICE_ERROR;
    975   }
    976 
    977 Exit:
    978   UfsHc->Flush (UfsHc);
    979 
    980   UfsStopExecCmd (Private, Slot);
    981 
    982   if (CmdDescMapping != NULL) {
    983     UfsHc->Unmap (UfsHc, CmdDescMapping);
    984   }
    985   if (CmdDescHost != NULL) {
    986     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
    987   }
    988 
    989   return Status;
    990 }
    991 
    992 /**
    993   Read or write specified attribute of a UFS device.
    994 
    995   @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
    996   @param[in]      Read          The boolean variable to show r/w direction.
    997   @param[in]      AttrId        The ID of Attribute.
    998   @param[in]      Index         The Index of Attribute.
    999   @param[in]      Selector      The Selector of Attribute.
   1000   @param[in, out] Attributes    The value of Attribute to be read or written.
   1001 
   1002   @retval EFI_SUCCESS           The Attribute was read/written successfully.
   1003   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the Attribute.
   1004   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the Attribute.
   1005 
   1006 **/
   1007 EFI_STATUS
   1008 UfsRwAttributes (
   1009   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
   1010   IN     BOOLEAN                      Read,
   1011   IN     UINT8                        AttrId,
   1012   IN     UINT8                        Index,
   1013   IN     UINT8                        Selector,
   1014   IN OUT UINT32                       *Attributes
   1015   )
   1016 {
   1017   EFI_STATUS                           Status;
   1018   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
   1019   UINT8                                Slot;
   1020   UTP_TRD                              *Trd;
   1021   UTP_QUERY_RESP_UPIU                  *QueryResp;
   1022   UINT32                               CmdDescSize;
   1023   UINT32                               ReturnData;
   1024   VOID                                 *CmdDescHost;
   1025   VOID                                 *CmdDescMapping;
   1026   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
   1027 
   1028   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
   1029 
   1030   if (Read) {
   1031     Packet.DataDirection     = UfsDataIn;
   1032     Packet.Opcode            = UtpQueryFuncOpcodeRdAttr;
   1033   } else {
   1034     Packet.DataDirection     = UfsDataOut;
   1035     Packet.Opcode            = UtpQueryFuncOpcodeWrAttr;
   1036   }
   1037   Packet.DescId              = AttrId;
   1038   Packet.Index               = Index;
   1039   Packet.Selector            = Selector;
   1040   Packet.Timeout             = UFS_TIMEOUT;
   1041 
   1042   //
   1043   // Find out which slot of transfer request list is available.
   1044   //
   1045   Status = UfsFindAvailableSlotInTrl (Private, &Slot);
   1046   if (EFI_ERROR (Status)) {
   1047     return Status;
   1048   }
   1049 
   1050   Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
   1051   //
   1052   // Fill transfer request descriptor to this slot.
   1053   //
   1054   Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);
   1055   if (EFI_ERROR (Status)) {
   1056     return Status;
   1057   }
   1058 
   1059   //
   1060   // Check the transfer request result.
   1061   //
   1062   UfsHc       = Private->UfsHostController;
   1063   QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
   1064   ASSERT (QueryResp != NULL);
   1065   CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
   1066 
   1067   //
   1068   // Start to execute the transfer request.
   1069   //
   1070   UfsStartExecCmd (Private, Slot);
   1071 
   1072   //
   1073   // Wait for the completion of the transfer request.
   1074   //
   1075   Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
   1076   if (EFI_ERROR (Status)) {
   1077     goto Exit;
   1078   }
   1079 
   1080   if (QueryResp->QueryResp != 0) {
   1081     DumpQueryResponseResult (QueryResp->QueryResp);
   1082     Status = EFI_DEVICE_ERROR;
   1083     goto Exit;
   1084   }
   1085 
   1086   if (Trd->Ocs == 0) {
   1087     ReturnData = QueryResp->Tsf.Value;
   1088     SwapLittleEndianToBigEndian ((UINT8*)&ReturnData, sizeof (UINT32));
   1089     *Attributes = ReturnData;
   1090   } else {
   1091     Status = EFI_DEVICE_ERROR;
   1092   }
   1093 
   1094 Exit:
   1095   UfsHc->Flush (UfsHc);
   1096 
   1097   UfsStopExecCmd (Private, Slot);
   1098 
   1099   if (CmdDescMapping != NULL) {
   1100     UfsHc->Unmap (UfsHc, CmdDescMapping);
   1101   }
   1102 
   1103   if (CmdDescHost != NULL) {
   1104     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
   1105   }
   1106 
   1107   return Status;
   1108 }
   1109 
   1110 /**
   1111   Read or write specified flag of a UFS device.
   1112 
   1113   @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1114   @param[in]      Read          The boolean variable to show r/w direction.
   1115   @param[in]      FlagId        The ID of flag to be read or written.
   1116   @param[in, out] Value         The value to set or clear flag.
   1117 
   1118   @retval EFI_SUCCESS           The flag was read/written successfully.
   1119   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to r/w the flag.
   1120   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of r/w the flag.
   1121 
   1122 **/
   1123 EFI_STATUS
   1124 UfsRwFlags (
   1125   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
   1126   IN     BOOLEAN                      Read,
   1127   IN     UINT8                        FlagId,
   1128   IN OUT UINT8                        *Value
   1129   )
   1130 {
   1131   EFI_STATUS                           Status;
   1132   UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
   1133   UINT8                                Slot;
   1134   UTP_TRD                              *Trd;
   1135   UTP_QUERY_RESP_UPIU                  *QueryResp;
   1136   UINT32                               CmdDescSize;
   1137   VOID                                 *CmdDescHost;
   1138   VOID                                 *CmdDescMapping;
   1139   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
   1140 
   1141   if (Value == NULL) {
   1142     return EFI_INVALID_PARAMETER;
   1143   }
   1144 
   1145   ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
   1146 
   1147   if (Read) {
   1148     ASSERT (Value != NULL);
   1149     Packet.DataDirection     = UfsDataIn;
   1150     Packet.Opcode            = UtpQueryFuncOpcodeRdFlag;
   1151   } else {
   1152     Packet.DataDirection     = UfsDataOut;
   1153     if (*Value == 1) {
   1154       Packet.Opcode          = UtpQueryFuncOpcodeSetFlag;
   1155     } else if (*Value == 0) {
   1156       Packet.Opcode          = UtpQueryFuncOpcodeClrFlag;
   1157     } else {
   1158       return EFI_INVALID_PARAMETER;
   1159     }
   1160   }
   1161   Packet.DescId              = FlagId;
   1162   Packet.Index               = 0;
   1163   Packet.Selector            = 0;
   1164   Packet.Timeout             = UFS_TIMEOUT;
   1165 
   1166   //
   1167   // Find out which slot of transfer request list is available.
   1168   //
   1169   Status = UfsFindAvailableSlotInTrl (Private, &Slot);
   1170   if (EFI_ERROR (Status)) {
   1171     return Status;
   1172   }
   1173 
   1174   //
   1175   // Fill transfer request descriptor to this slot.
   1176   //
   1177   Trd    = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
   1178   Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);
   1179   if (EFI_ERROR (Status)) {
   1180     return Status;
   1181   }
   1182 
   1183   //
   1184   // Check the transfer request result.
   1185   //
   1186   UfsHc       = Private->UfsHostController;
   1187   QueryResp   = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
   1188   ASSERT (QueryResp != NULL);
   1189   CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
   1190 
   1191   //
   1192   // Start to execute the transfer request.
   1193   //
   1194   UfsStartExecCmd (Private, Slot);
   1195 
   1196   //
   1197   // Wait for the completion of the transfer request.
   1198   //
   1199   Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet.Timeout);
   1200   if (EFI_ERROR (Status)) {
   1201     goto Exit;
   1202   }
   1203 
   1204   if (QueryResp->QueryResp != 0) {
   1205     DumpQueryResponseResult (QueryResp->QueryResp);
   1206     Status = EFI_DEVICE_ERROR;
   1207     goto Exit;
   1208   }
   1209 
   1210   if (Trd->Ocs == 0) {
   1211     *Value = (UINT8)QueryResp->Tsf.Value;
   1212   } else {
   1213     Status = EFI_DEVICE_ERROR;
   1214   }
   1215 
   1216 Exit:
   1217   UfsHc->Flush (UfsHc);
   1218 
   1219   UfsStopExecCmd (Private, Slot);
   1220 
   1221   if (CmdDescMapping != NULL) {
   1222     UfsHc->Unmap (UfsHc, CmdDescMapping);
   1223   }
   1224   if (CmdDescHost != NULL) {
   1225     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
   1226   }
   1227 
   1228   return Status;
   1229 }
   1230 
   1231 /**
   1232   Set specified flag to 1 on a UFS device.
   1233 
   1234   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1235   @param[in]  FlagId            The ID of flag to be set.
   1236 
   1237   @retval EFI_SUCCESS           The flag was set successfully.
   1238   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to set the flag.
   1239   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of setting the flag.
   1240 
   1241 **/
   1242 EFI_STATUS
   1243 UfsSetFlag (
   1244   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
   1245   IN  UINT8                        FlagId
   1246   )
   1247 {
   1248   EFI_STATUS             Status;
   1249   UINT8                  Value;
   1250 
   1251   Value  = 1;
   1252   Status = UfsRwFlags (Private, FALSE, FlagId, &Value);
   1253 
   1254   return Status;
   1255 }
   1256 
   1257 /**
   1258   Clear specified flag to 0 on a UFS device.
   1259 
   1260   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1261   @param[in]  FlagId            The ID of flag to be cleared.
   1262 
   1263   @retval EFI_SUCCESS           The flag was cleared successfully.
   1264   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to clear the flag.
   1265   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of clearing the flag.
   1266 
   1267 **/
   1268 EFI_STATUS
   1269 UfsClearFlag (
   1270   IN  UFS_PASS_THRU_PRIVATE_DATA   *Private,
   1271   IN  UINT8                        FlagId
   1272   )
   1273 {
   1274   EFI_STATUS             Status;
   1275   UINT8                  Value;
   1276 
   1277   Value  = 0;
   1278   Status = UfsRwFlags (Private, FALSE, FlagId, &Value);
   1279 
   1280   return Status;
   1281 }
   1282 
   1283 /**
   1284   Read specified flag from a UFS device.
   1285 
   1286   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1287   @param[in]  FlagId            The ID of flag to be read.
   1288   @param[out] Value             The flag's value.
   1289 
   1290   @retval EFI_SUCCESS           The flag was read successfully.
   1291   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to read the flag.
   1292   @retval EFI_TIMEOUT           A timeout occurred while waiting for the completion of reading the flag.
   1293 
   1294 **/
   1295 EFI_STATUS
   1296 UfsReadFlag (
   1297   IN     UFS_PASS_THRU_PRIVATE_DATA   *Private,
   1298   IN     UINT8                        FlagId,
   1299      OUT UINT8                        *Value
   1300   )
   1301 {
   1302   EFI_STATUS                           Status;
   1303 
   1304   Status = UfsRwFlags (Private, TRUE, FlagId, Value);
   1305 
   1306   return Status;
   1307 }
   1308 
   1309 /**
   1310   Sends NOP IN cmd to a UFS device for initialization process request.
   1311   For more details, please refer to UFS 2.0 spec Figure 13.3.
   1312 
   1313   @param[in]  Private           The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1314 
   1315   @retval EFI_SUCCESS           The NOP IN command was sent by the host. The NOP OUT response was
   1316                                 received successfully.
   1317   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to execute NOP IN command.
   1318   @retval EFI_OUT_OF_RESOURCES  The resource for transfer is not available.
   1319   @retval EFI_TIMEOUT           A timeout occurred while waiting for the NOP IN command to execute.
   1320 
   1321 **/
   1322 EFI_STATUS
   1323 UfsExecNopCmds (
   1324   IN  UFS_PASS_THRU_PRIVATE_DATA       *Private
   1325   )
   1326 {
   1327   EFI_STATUS                           Status;
   1328   UINT8                                Slot;
   1329   UTP_TRD                              *Trd;
   1330   UTP_NOP_IN_UPIU                      *NopInUpiu;
   1331   UINT32                               CmdDescSize;
   1332   VOID                                 *CmdDescHost;
   1333   VOID                                 *CmdDescMapping;
   1334   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
   1335 
   1336   //
   1337   // Find out which slot of transfer request list is available.
   1338   //
   1339   Status = UfsFindAvailableSlotInTrl (Private, &Slot);
   1340   if (EFI_ERROR (Status)) {
   1341     return Status;
   1342   }
   1343 
   1344   Trd    = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
   1345   Status = UfsCreateNopCommandDesc (Private, Trd, &CmdDescHost, &CmdDescMapping);
   1346   if (EFI_ERROR (Status)) {
   1347     return Status;
   1348   }
   1349 
   1350   //
   1351   // Check the transfer request result.
   1352   //
   1353   UfsHc       = Private->UfsHostController;
   1354   NopInUpiu   = (UTP_NOP_IN_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
   1355   ASSERT (NopInUpiu != NULL);
   1356   CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
   1357 
   1358   //
   1359   // Start to execute the transfer request.
   1360   //
   1361   UfsStartExecCmd (Private, Slot);
   1362 
   1363   //
   1364   // Wait for the completion of the transfer request.
   1365   //
   1366   Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, UFS_TIMEOUT);
   1367   if (EFI_ERROR (Status)) {
   1368     goto Exit;
   1369   }
   1370 
   1371   if (NopInUpiu->Resp != 0) {
   1372     Status = EFI_DEVICE_ERROR;
   1373   } else {
   1374     Status = EFI_SUCCESS;
   1375   }
   1376 
   1377 Exit:
   1378   UfsHc->Flush (UfsHc);
   1379 
   1380   UfsStopExecCmd (Private, Slot);
   1381 
   1382   if (CmdDescMapping != NULL) {
   1383     UfsHc->Unmap (UfsHc, CmdDescMapping);
   1384   }
   1385   if (CmdDescHost != NULL) {
   1386     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
   1387   }
   1388 
   1389   return Status;
   1390 }
   1391 
   1392 /**
   1393   Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
   1394 
   1395   @param[in]      Private       The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1396   @param[in]      Lun           The LUN of the UFS device to send the SCSI Request Packet.
   1397   @param[in, out] Packet        A pointer to the SCSI Request Packet to send to a specified Lun of the
   1398                                 UFS device.
   1399   @param[in]      Event         If nonblocking I/O is not supported then Event is ignored, and blocking
   1400                                 I/O is performed. If Event is NULL, then blocking I/O is performed. If
   1401                                 Event is not NULL and non blocking I/O is supported, then
   1402                                 nonblocking I/O is performed, and Event will be signaled when the
   1403                                 SCSI Request Packet completes.
   1404 
   1405   @retval EFI_SUCCESS           The SCSI Request Packet was sent by the host. For bi-directional
   1406                                 commands, InTransferLength bytes were transferred from
   1407                                 InDataBuffer. For write and bi-directional commands,
   1408                                 OutTransferLength bytes were transferred by
   1409                                 OutDataBuffer.
   1410   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SCSI Request
   1411                                 Packet.
   1412   @retval EFI_OUT_OF_RESOURCES  The resource for transfer is not available.
   1413   @retval EFI_TIMEOUT           A timeout occurred while waiting for the SCSI Request Packet to execute.
   1414 
   1415 **/
   1416 EFI_STATUS
   1417 UfsExecScsiCmds (
   1418   IN     UFS_PASS_THRU_PRIVATE_DATA                  *Private,
   1419   IN     UINT8                                       Lun,
   1420   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *Packet,
   1421   IN     EFI_EVENT                                   Event    OPTIONAL
   1422   )
   1423 {
   1424   EFI_STATUS                           Status;
   1425   UTP_RESPONSE_UPIU                    *Response;
   1426   UINT16                               SenseDataLen;
   1427   UINT32                               ResTranCount;
   1428   VOID                                 *DataBuf;
   1429   EFI_PHYSICAL_ADDRESS                 DataBufPhyAddr;
   1430   UINT32                               DataLen;
   1431   UINTN                                MapLength;
   1432   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
   1433   EDKII_UFS_HOST_CONTROLLER_OPERATION  Flag;
   1434   UFS_DATA_DIRECTION                   DataDirection;
   1435   UTP_TR_PRD                           *PrdtBase;
   1436   EFI_TPL                              OldTpl;
   1437   UFS_PASS_THRU_TRANS_REQ              *TransReq;
   1438 
   1439   TransReq       = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));
   1440   if (TransReq == NULL) {
   1441     return EFI_OUT_OF_RESOURCES;
   1442   }
   1443 
   1444   TransReq->Signature     = UFS_PASS_THRU_TRANS_REQ_SIG;
   1445   TransReq->TimeoutRemain = Packet->Timeout;
   1446   DataBufPhyAddr = 0;
   1447   UfsHc          = Private->UfsHostController;
   1448   //
   1449   // Find out which slot of transfer request list is available.
   1450   //
   1451   Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);
   1452   if (EFI_ERROR (Status)) {
   1453     return Status;
   1454   }
   1455 
   1456   TransReq->Trd = ((UTP_TRD*)Private->UtpTrlBase) + TransReq->Slot;
   1457 
   1458   //
   1459   // Fill transfer request descriptor to this slot.
   1460   //
   1461   Status = UfsCreateScsiCommandDesc (
   1462              Private,
   1463              Lun,
   1464              Packet,
   1465              TransReq->Trd,
   1466              &TransReq->CmdDescHost,
   1467              &TransReq->CmdDescMapping
   1468              );
   1469   if (EFI_ERROR (Status)) {
   1470     return Status;
   1471   }
   1472 
   1473   TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);
   1474 
   1475   if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
   1476     DataBuf       = Packet->InDataBuffer;
   1477     DataLen       = Packet->InTransferLength;
   1478     DataDirection = UfsDataIn;
   1479     Flag          = EdkiiUfsHcOperationBusMasterWrite;
   1480   } else {
   1481     DataBuf       = Packet->OutDataBuffer;
   1482     DataLen       = Packet->OutTransferLength;
   1483     DataDirection = UfsDataOut;
   1484     Flag          = EdkiiUfsHcOperationBusMasterRead;
   1485   }
   1486 
   1487   if (DataLen == 0) {
   1488     DataDirection = UfsNoData;
   1489   } else {
   1490     MapLength = DataLen;
   1491     Status    = UfsHc->Map (
   1492                          UfsHc,
   1493                          Flag,
   1494                          DataBuf,
   1495                          &MapLength,
   1496                          &DataBufPhyAddr,
   1497                          &TransReq->DataBufMapping
   1498                          );
   1499 
   1500     if (EFI_ERROR (Status) || (DataLen != MapLength)) {
   1501       goto Exit1;
   1502     }
   1503   }
   1504   //
   1505   // Fill PRDT table of Command UPIU for executed SCSI cmd.
   1506   //
   1507   PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));
   1508   ASSERT (PrdtBase != NULL);
   1509   UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);
   1510 
   1511   //
   1512   // Insert the async SCSI cmd to the Async I/O list
   1513   //
   1514   if (Event != NULL) {
   1515     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   1516     TransReq->Packet      = Packet;
   1517     TransReq->CallerEvent = Event;
   1518     InsertTailList (&Private->Queue, &TransReq->TransferList);
   1519     gBS->RestoreTPL (OldTpl);
   1520   }
   1521 
   1522   //
   1523   // Start to execute the transfer request.
   1524   //
   1525   UfsStartExecCmd (Private, TransReq->Slot);
   1526 
   1527   //
   1528   // Immediately return for async I/O.
   1529   //
   1530   if (Event != NULL) {
   1531     return EFI_SUCCESS;
   1532   }
   1533 
   1534   //
   1535   // Wait for the completion of the transfer request.
   1536   //
   1537   Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);
   1538   if (EFI_ERROR (Status)) {
   1539     goto Exit;
   1540   }
   1541 
   1542   //
   1543   // Get sense data if exists
   1544   //
   1545   Response     = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
   1546   ASSERT (Response != NULL);
   1547   SenseDataLen = Response->SenseDataLen;
   1548   SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
   1549 
   1550   if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
   1551     CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
   1552     Packet->SenseDataLength = (UINT8)SenseDataLen;
   1553   }
   1554 
   1555   //
   1556   // Check the transfer request result.
   1557   //
   1558   Packet->TargetStatus = Response->Status;
   1559   if (Response->Response != 0) {
   1560     DEBUG ((EFI_D_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));
   1561     Status = EFI_DEVICE_ERROR;
   1562     goto Exit;
   1563   }
   1564 
   1565   if (TransReq->Trd->Ocs == 0) {
   1566     if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
   1567       if ((Response->Flags & BIT5) == BIT5) {
   1568         ResTranCount = Response->ResTranCount;
   1569         SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
   1570         Packet->InTransferLength -= ResTranCount;
   1571       }
   1572     } else {
   1573       if ((Response->Flags & BIT5) == BIT5) {
   1574         ResTranCount = Response->ResTranCount;
   1575         SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
   1576         Packet->OutTransferLength -= ResTranCount;
   1577       }
   1578     }
   1579   } else {
   1580     Status = EFI_DEVICE_ERROR;
   1581   }
   1582 
   1583 Exit:
   1584   UfsHc->Flush (UfsHc);
   1585 
   1586   UfsStopExecCmd (Private, TransReq->Slot);
   1587 
   1588   if (TransReq->DataBufMapping != NULL) {
   1589     UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);
   1590   }
   1591 
   1592 Exit1:
   1593   if (TransReq->CmdDescMapping != NULL) {
   1594     UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
   1595   }
   1596   if (TransReq->CmdDescHost != NULL) {
   1597     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);
   1598   }
   1599   if (TransReq != NULL) {
   1600     FreePool (TransReq);
   1601   }
   1602   return Status;
   1603 }
   1604 
   1605 
   1606 /**
   1607   Sent UIC DME_LINKSTARTUP command to start the link startup procedure.
   1608 
   1609   @param[in] Private          The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1610   @param[in] UicOpcode        The opcode of the UIC command.
   1611   @param[in] Arg1             The value for 1st argument of the UIC command.
   1612   @param[in] Arg2             The value for 2nd argument of the UIC command.
   1613   @param[in] Arg3             The value for 3rd argument of the UIC command.
   1614 
   1615   @return EFI_SUCCESS      Successfully execute this UIC command and detect attached UFS device.
   1616   @return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.
   1617   @return EFI_NOT_FOUND    The presence of the UFS device isn't detected.
   1618 
   1619 **/
   1620 EFI_STATUS
   1621 UfsExecUicCommands (
   1622   IN  UFS_PASS_THRU_PRIVATE_DATA    *Private,
   1623   IN  UINT8                         UicOpcode,
   1624   IN  UINT32                        Arg1,
   1625   IN  UINT32                        Arg2,
   1626   IN  UINT32                        Arg3
   1627   )
   1628 {
   1629   EFI_STATUS  Status;
   1630   UINT32      Data;
   1631 
   1632   Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
   1633   if (EFI_ERROR (Status)) {
   1634     return Status;
   1635   }
   1636 
   1637   if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
   1638     //
   1639     // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
   1640     //
   1641     Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
   1642     if (EFI_ERROR (Status)) {
   1643       return Status;
   1644     }
   1645   }
   1646 
   1647   //
   1648   // When programming UIC command registers, host software shall set the register UICCMD
   1649   // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
   1650   // are set.
   1651   //
   1652   Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);
   1653   if (EFI_ERROR (Status)) {
   1654     return Status;
   1655   }
   1656 
   1657   Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);
   1658   if (EFI_ERROR (Status)) {
   1659     return Status;
   1660   }
   1661 
   1662   Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);
   1663   if (EFI_ERROR (Status)) {
   1664     return Status;
   1665   }
   1666 
   1667   //
   1668   // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
   1669   //
   1670   Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
   1671   if (EFI_ERROR (Status)) {
   1672     return Status;
   1673   }
   1674 
   1675   Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);
   1676   if (EFI_ERROR (Status)) {
   1677     return Status;
   1678   }
   1679 
   1680   //
   1681   // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
   1682   // This bit is set to '1' by the host controller upon completion of a UIC command.
   1683   //
   1684   Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
   1685   if (EFI_ERROR (Status)) {
   1686     return Status;
   1687   }
   1688 
   1689   if (UicOpcode != UfsUicDmeReset) {
   1690     Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);
   1691     if (EFI_ERROR (Status)) {
   1692       return Status;
   1693     }
   1694     if ((Data & 0xFF) != 0) {
   1695       DEBUG_CODE_BEGIN();
   1696         DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));
   1697       DEBUG_CODE_END();
   1698       return EFI_DEVICE_ERROR;
   1699     }
   1700   }
   1701 
   1702   //
   1703   // Check value of HCS.DP and make sure that there is a device attached to the Link.
   1704   //
   1705   Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
   1706   if (EFI_ERROR (Status)) {
   1707     return Status;
   1708   }
   1709 
   1710   if ((Data & UFS_HC_HCS_DP) == 0) {
   1711     Status  = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
   1712     if (EFI_ERROR (Status)) {
   1713       return EFI_DEVICE_ERROR;
   1714     }
   1715     return EFI_NOT_FOUND;
   1716   }
   1717 
   1718   DEBUG ((EFI_D_INFO, "UfsPassThruDxe: found a attached UFS device\n"));
   1719 
   1720   return EFI_SUCCESS;
   1721 }
   1722 
   1723 /**
   1724   Allocate common buffer for host and UFS bus master access simultaneously.
   1725 
   1726   @param[in]  Private                The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1727   @param[in]  Size                   The length of buffer to be allocated.
   1728   @param[out] CmdDescHost            A pointer to store the base system memory address of the allocated range.
   1729   @param[out] CmdDescPhyAddr         The resulting map address for the UFS bus master to use to access the hosts CmdDescHost.
   1730   @param[out] CmdDescMapping         A resulting value to pass to Unmap().
   1731 
   1732   @retval EFI_SUCCESS                The common buffer was allocated successfully.
   1733   @retval EFI_DEVICE_ERROR           The allocation fails.
   1734   @retval EFI_OUT_OF_RESOURCES       The memory resource is insufficient.
   1735 
   1736 **/
   1737 EFI_STATUS
   1738 UfsAllocateAlignCommonBuffer (
   1739   IN     UFS_PASS_THRU_PRIVATE_DATA    *Private,
   1740   IN     UINTN                         Size,
   1741      OUT VOID                          **CmdDescHost,
   1742      OUT EFI_PHYSICAL_ADDRESS          *CmdDescPhyAddr,
   1743      OUT VOID                          **CmdDescMapping
   1744   )
   1745 {
   1746   EFI_STATUS                           Status;
   1747   UINTN                                Bytes;
   1748   BOOLEAN                              Is32BitAddr;
   1749   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHc;
   1750 
   1751   if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {
   1752     Is32BitAddr = TRUE;
   1753   } else {
   1754     Is32BitAddr = FALSE;
   1755   }
   1756 
   1757   UfsHc  = Private->UfsHostController;
   1758   Status = UfsHc->AllocateBuffer (
   1759                     UfsHc,
   1760                     AllocateAnyPages,
   1761                     EfiBootServicesData,
   1762                     EFI_SIZE_TO_PAGES (Size),
   1763                     CmdDescHost,
   1764                     0
   1765                     );
   1766   if (EFI_ERROR (Status)) {
   1767     *CmdDescMapping = NULL;
   1768     *CmdDescHost    = NULL;
   1769     *CmdDescPhyAddr = 0;
   1770     return EFI_OUT_OF_RESOURCES;
   1771   }
   1772 
   1773   Bytes  = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size));
   1774   Status = UfsHc->Map (
   1775                     UfsHc,
   1776                     EdkiiUfsHcOperationBusMasterCommonBuffer,
   1777                     *CmdDescHost,
   1778                     &Bytes,
   1779                     CmdDescPhyAddr,
   1780                     CmdDescMapping
   1781                     );
   1782 
   1783   if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
   1784     UfsHc->FreeBuffer (
   1785              UfsHc,
   1786              EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
   1787              *CmdDescHost
   1788              );
   1789     *CmdDescHost = NULL;
   1790     return EFI_OUT_OF_RESOURCES;
   1791   }
   1792 
   1793   if (Is32BitAddr && ((*CmdDescPhyAddr) > 0x100000000ULL)) {
   1794     //
   1795     // The UFS host controller doesn't support 64bit addressing, so should not get a >4G UFS bus master address.
   1796     //
   1797     UfsHc->Unmap (
   1798              UfsHc,
   1799              *CmdDescMapping
   1800              );
   1801     UfsHc->FreeBuffer (
   1802              UfsHc,
   1803              EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
   1804              *CmdDescHost
   1805              );
   1806     *CmdDescMapping = NULL;
   1807     *CmdDescHost    = NULL;
   1808     return EFI_DEVICE_ERROR;
   1809   }
   1810 
   1811   ZeroMem (*CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)));
   1812   return EFI_SUCCESS;
   1813 }
   1814 
   1815 /**
   1816   Enable the UFS host controller for accessing.
   1817 
   1818   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1819 
   1820   @retval EFI_SUCCESS                The UFS host controller enabling was executed successfully.
   1821   @retval EFI_DEVICE_ERROR           A device error occurred while enabling the UFS host controller.
   1822 
   1823 **/
   1824 EFI_STATUS
   1825 UfsEnableHostController (
   1826   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   1827   )
   1828 {
   1829   EFI_STATUS             Status;
   1830   UINT32                 Data;
   1831 
   1832   //
   1833   // UFS 2.0 spec section 7.1.1 - Host Controller Initialization
   1834   //
   1835   // Reinitialize the UFS host controller if HCE bit of HC register is set.
   1836   //
   1837   Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
   1838   if (EFI_ERROR (Status)) {
   1839     return Status;
   1840   }
   1841 
   1842   if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
   1843     //
   1844     // Write a 0 to the HCE register at first to disable the host controller.
   1845     //
   1846     Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
   1847     if (EFI_ERROR (Status)) {
   1848       return Status;
   1849     }
   1850     //
   1851     // Wait until HCE is read as '0' before continuing.
   1852     //
   1853     Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
   1854     if (EFI_ERROR (Status)) {
   1855       return EFI_DEVICE_ERROR;
   1856     }
   1857   }
   1858 
   1859   //
   1860   // Write a 1 to the HCE register to enable the UFS host controller.
   1861   //
   1862   Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
   1863   if (EFI_ERROR (Status)) {
   1864     return Status;
   1865   }
   1866 
   1867   //
   1868   // Wait until HCE is read as '1' before continuing.
   1869   //
   1870   Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
   1871   if (EFI_ERROR (Status)) {
   1872     return EFI_DEVICE_ERROR;
   1873   }
   1874 
   1875   return EFI_SUCCESS;
   1876 }
   1877 
   1878 /**
   1879   Detect if a UFS device attached.
   1880 
   1881   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1882 
   1883   @retval EFI_SUCCESS                The UFS device detection was executed successfully.
   1884   @retval EFI_NOT_FOUND              Not found a UFS device attached.
   1885   @retval EFI_DEVICE_ERROR           A device error occurred while detecting the UFS device.
   1886 
   1887 **/
   1888 EFI_STATUS
   1889 UfsDeviceDetection (
   1890   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   1891   )
   1892 {
   1893   UINTN                  Retry;
   1894   EFI_STATUS             Status;
   1895 
   1896   //
   1897   // Start UFS device detection.
   1898   // Try up to 3 times for establishing data link with device.
   1899   //
   1900   for (Retry = 0; Retry < 3; Retry++) {
   1901     Status = UfsExecUicCommands (Private, UfsUicDmeLinkStartup, 0, 0, 0);
   1902     if (!EFI_ERROR (Status)) {
   1903       break;
   1904     }
   1905 
   1906     if (Status == EFI_NOT_FOUND) {
   1907       continue;
   1908     }
   1909 
   1910     return EFI_DEVICE_ERROR;
   1911   }
   1912 
   1913   if (Retry == 3) {
   1914     return EFI_NOT_FOUND;
   1915   }
   1916 
   1917   return EFI_SUCCESS;
   1918 }
   1919 
   1920 /**
   1921   Initialize UFS task management request list related h/w context.
   1922 
   1923   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1924 
   1925   @retval EFI_SUCCESS                The UFS task management list was initialzed successfully.
   1926   @retval EFI_DEVICE_ERROR           The initialization fails.
   1927 
   1928 **/
   1929 EFI_STATUS
   1930 UfsInitTaskManagementRequestList (
   1931   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   1932   )
   1933 {
   1934   UINT32                 Data;
   1935   UINT8                  Nutmrs;
   1936   VOID                   *CmdDescHost;
   1937   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;
   1938   VOID                   *CmdDescMapping;
   1939   EFI_STATUS             Status;
   1940 
   1941   //
   1942   // Initial h/w and s/w context for future operations.
   1943   //
   1944   CmdDescHost    = NULL;
   1945   CmdDescMapping = NULL;
   1946   CmdDescPhyAddr = 0;
   1947 
   1948   Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
   1949   if (EFI_ERROR (Status)) {
   1950     return Status;
   1951   }
   1952 
   1953   Private->Capabilities = Data;
   1954 
   1955   //
   1956   // Allocate and initialize UTP Task Management Request List.
   1957   //
   1958   Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);
   1959   Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
   1960   if (EFI_ERROR (Status)) {
   1961     return Status;
   1962   }
   1963 
   1964   //
   1965   // Program the UTP Task Management Request List Base Address and UTP Task Management
   1966   // Request List Base Address with a 64-bit address allocated at step 6.
   1967   //
   1968   Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
   1969   if (EFI_ERROR (Status)) {
   1970     return Status;
   1971   }
   1972 
   1973   Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
   1974   if (EFI_ERROR (Status)) {
   1975     return Status;
   1976   }
   1977   Private->UtpTmrlBase = CmdDescHost;
   1978   Private->Nutmrs      = Nutmrs;
   1979   Private->TmrlMapping = CmdDescMapping;
   1980 
   1981   //
   1982   // Enable the UTP Task Management Request List by setting the UTP Task Management
   1983   // Request List RunStop Register (UTMRLRSR) to '1'.
   1984   //
   1985   Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
   1986   if (EFI_ERROR (Status)) {
   1987     return Status;
   1988   }
   1989 
   1990   return EFI_SUCCESS;
   1991 }
   1992 
   1993 /**
   1994   Initialize UFS transfer request list related h/w context.
   1995 
   1996   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   1997 
   1998   @retval EFI_SUCCESS                The UFS transfer list was initialzed successfully.
   1999   @retval EFI_DEVICE_ERROR           The initialization fails.
   2000 
   2001 **/
   2002 EFI_STATUS
   2003 UfsInitTransferRequestList (
   2004   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   2005   )
   2006 {
   2007   UINT32                 Data;
   2008   UINT8                  Nutrs;
   2009   VOID                   *CmdDescHost;
   2010   EFI_PHYSICAL_ADDRESS   CmdDescPhyAddr;
   2011   VOID                   *CmdDescMapping;
   2012   EFI_STATUS             Status;
   2013 
   2014   //
   2015   // Initial h/w and s/w context for future operations.
   2016   //
   2017   CmdDescHost    = NULL;
   2018   CmdDescMapping = NULL;
   2019   CmdDescPhyAddr = 0;
   2020 
   2021   Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
   2022   if (EFI_ERROR (Status)) {
   2023     return Status;
   2024   }
   2025 
   2026   Private->Capabilities = Data;
   2027 
   2028   //
   2029   // Allocate and initialize UTP Transfer Request List.
   2030   //
   2031   Nutrs  = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);
   2032   Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
   2033   if (EFI_ERROR (Status)) {
   2034     return Status;
   2035   }
   2036 
   2037   //
   2038   // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
   2039   // Base Address with a 64-bit address allocated at step 8.
   2040   //
   2041   Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
   2042   if (EFI_ERROR (Status)) {
   2043     return Status;
   2044   }
   2045 
   2046   Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
   2047   if (EFI_ERROR (Status)) {
   2048     return Status;
   2049   }
   2050 
   2051   Private->UtpTrlBase = CmdDescHost;
   2052   Private->Nutrs      = Nutrs;
   2053   Private->TrlMapping = CmdDescMapping;
   2054 
   2055   //
   2056   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
   2057   // RunStop Register (UTRLRSR) to '1'.
   2058   //
   2059   Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
   2060   if (EFI_ERROR (Status)) {
   2061     return Status;
   2062   }
   2063 
   2064   return EFI_SUCCESS;
   2065 }
   2066 
   2067 /**
   2068   Initialize the UFS host controller.
   2069 
   2070   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   2071 
   2072   @retval EFI_SUCCESS                The Ufs Host Controller is initialized successfully.
   2073   @retval Others                     A device error occurred while initializing the controller.
   2074 
   2075 **/
   2076 EFI_STATUS
   2077 UfsControllerInit (
   2078   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   2079   )
   2080 {
   2081   EFI_STATUS             Status;
   2082 
   2083   Status = UfsEnableHostController (Private);
   2084   if (EFI_ERROR (Status)) {
   2085     DEBUG ((EFI_D_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));
   2086     return Status;
   2087   }
   2088 
   2089   Status = UfsDeviceDetection (Private);
   2090   if (EFI_ERROR (Status)) {
   2091     DEBUG ((EFI_D_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));
   2092     return Status;
   2093   }
   2094 
   2095   Status = UfsInitTaskManagementRequestList (Private);
   2096   if (EFI_ERROR (Status)) {
   2097     DEBUG ((EFI_D_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));
   2098     return Status;
   2099   }
   2100 
   2101   Status = UfsInitTransferRequestList (Private);
   2102   if (EFI_ERROR (Status)) {
   2103     DEBUG ((EFI_D_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));
   2104     return Status;
   2105   }
   2106 
   2107   DEBUG ((EFI_D_INFO, "UfsControllerInit Finished\n"));
   2108   return EFI_SUCCESS;
   2109 }
   2110 
   2111 /**
   2112   Stop the UFS host controller.
   2113 
   2114   @param[in] Private                 The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
   2115 
   2116   @retval EFI_SUCCESS                The Ufs Host Controller is stopped successfully.
   2117   @retval Others                     A device error occurred while stopping the controller.
   2118 
   2119 **/
   2120 EFI_STATUS
   2121 UfsControllerStop (
   2122   IN  UFS_PASS_THRU_PRIVATE_DATA     *Private
   2123   )
   2124 {
   2125   EFI_STATUS             Status;
   2126   UINT32                 Data;
   2127 
   2128   //
   2129   // Enable the UTP Task Management Request List by setting the UTP Task Management
   2130   // Request List RunStop Register (UTMRLRSR) to '1'.
   2131   //
   2132   Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
   2133   if (EFI_ERROR (Status)) {
   2134     return Status;
   2135   }
   2136 
   2137   //
   2138   // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
   2139   // RunStop Register (UTRLRSR) to '1'.
   2140   //
   2141   Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
   2142   if (EFI_ERROR (Status)) {
   2143     return Status;
   2144   }
   2145 
   2146   //
   2147   // Write a 0 to the HCE register in order to disable the host controller.
   2148   //
   2149   Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
   2150   if (EFI_ERROR (Status)) {
   2151     return Status;
   2152   }
   2153   ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
   2154 
   2155   Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
   2156   if (EFI_ERROR (Status)) {
   2157     return Status;
   2158   }
   2159 
   2160   //
   2161   // Wait until HCE is read as '0' before continuing.
   2162   //
   2163   Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
   2164   if (EFI_ERROR (Status)) {
   2165     return EFI_DEVICE_ERROR;
   2166   }
   2167 
   2168   DEBUG ((EFI_D_INFO, "UfsController is stopped\n"));
   2169 
   2170   return EFI_SUCCESS;
   2171 }
   2172 
   2173 
   2174 /**
   2175   Internal helper function which will signal the caller event and clean up
   2176   resources.
   2177 
   2178   @param[in] Private   The pointer to the UFS_PASS_THRU_PRIVATE_DATA data
   2179                        structure.
   2180   @param[in] TransReq  The pointer to the UFS_PASS_THRU_TRANS_REQ data
   2181                        structure.
   2182 
   2183 **/
   2184 VOID
   2185 EFIAPI
   2186 SignalCallerEvent (
   2187   IN UFS_PASS_THRU_PRIVATE_DATA      *Private,
   2188   IN UFS_PASS_THRU_TRANS_REQ         *TransReq
   2189   )
   2190 {
   2191   EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
   2192   EFI_EVENT                          CallerEvent;
   2193 
   2194   ASSERT ((Private != NULL) && (TransReq != NULL));
   2195 
   2196   UfsHc        = Private->UfsHostController;
   2197   CallerEvent  = TransReq->CallerEvent;
   2198 
   2199   RemoveEntryList (&TransReq->TransferList);
   2200 
   2201   UfsHc->Flush (UfsHc);
   2202 
   2203   UfsStopExecCmd (Private, TransReq->Slot);
   2204 
   2205   if (TransReq->DataBufMapping != NULL) {
   2206     UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);
   2207   }
   2208 
   2209   if (TransReq->CmdDescMapping != NULL) {
   2210     UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
   2211   }
   2212   if (TransReq->CmdDescHost != NULL) {
   2213     UfsHc->FreeBuffer (
   2214              UfsHc,
   2215              EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),
   2216              TransReq->CmdDescHost
   2217              );
   2218   }
   2219 
   2220   FreePool (TransReq);
   2221 
   2222   gBS->SignalEvent (CallerEvent);
   2223   return;
   2224 }
   2225 
   2226 /**
   2227   Call back function when the timer event is signaled.
   2228 
   2229   @param[in]  Event     The Event this notify function registered to.
   2230   @param[in]  Context   Pointer to the context data registered to the Event.
   2231 
   2232 **/
   2233 VOID
   2234 EFIAPI
   2235 ProcessAsyncTaskList (
   2236   IN EFI_EVENT          Event,
   2237   IN VOID               *Context
   2238   )
   2239 {
   2240   UFS_PASS_THRU_PRIVATE_DATA                    *Private;
   2241   LIST_ENTRY                                    *Entry;
   2242   LIST_ENTRY                                    *NextEntry;
   2243   UFS_PASS_THRU_TRANS_REQ                       *TransReq;
   2244   EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET    *Packet;
   2245   UTP_RESPONSE_UPIU                             *Response;
   2246   UINT16                                        SenseDataLen;
   2247   UINT32                                        ResTranCount;
   2248   UINT32                                        SlotsMap;
   2249   UINT32                                        Value;
   2250   EFI_STATUS                                    Status;
   2251 
   2252   Private   = (UFS_PASS_THRU_PRIVATE_DATA*) Context;
   2253   SlotsMap  = 0;
   2254 
   2255   //
   2256   // Check the entries in the async I/O queue are done or not.
   2257   //
   2258   if (!IsListEmpty(&Private->Queue)) {
   2259     EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
   2260       TransReq  = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
   2261       Packet    = TransReq->Packet;
   2262 
   2263       if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {
   2264         return;
   2265       }
   2266       SlotsMap |= BIT0 << TransReq->Slot;
   2267 
   2268       Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);
   2269       if (EFI_ERROR (Status)) {
   2270         //
   2271         // TODO: Should find/add a proper host adapter return status for this
   2272         // case.
   2273         //
   2274         Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
   2275         DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));
   2276         SignalCallerEvent (Private, TransReq);
   2277         continue;
   2278       }
   2279 
   2280       if ((Value & (BIT0 << TransReq->Slot)) != 0) {
   2281         //
   2282         // Scsi cmd not finished yet.
   2283         //
   2284         if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {
   2285           TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;
   2286           continue;
   2287         } else {
   2288           //
   2289           // Timeout occurs.
   2290           //
   2291           Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
   2292           DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));
   2293           SignalCallerEvent (Private, TransReq);
   2294           continue;
   2295         }
   2296       } else {
   2297         //
   2298         // Scsi cmd finished.
   2299         //
   2300         // Get sense data if exists
   2301         //
   2302         Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
   2303         ASSERT (Response != NULL);
   2304         SenseDataLen = Response->SenseDataLen;
   2305         SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
   2306 
   2307         if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
   2308           CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
   2309           Packet->SenseDataLength = (UINT8)SenseDataLen;
   2310         }
   2311 
   2312         //
   2313         // Check the transfer request result.
   2314         //
   2315         Packet->TargetStatus = Response->Status;
   2316         if (Response->Response != 0) {
   2317           DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));
   2318           SignalCallerEvent (Private, TransReq);
   2319           continue;
   2320         }
   2321 
   2322         if (TransReq->Trd->Ocs == 0) {
   2323           if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
   2324             if ((Response->Flags & BIT5) == BIT5) {
   2325               ResTranCount = Response->ResTranCount;
   2326               SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
   2327               Packet->InTransferLength -= ResTranCount;
   2328             }
   2329           } else {
   2330             if ((Response->Flags & BIT5) == BIT5) {
   2331               ResTranCount = Response->ResTranCount;
   2332               SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
   2333               Packet->OutTransferLength -= ResTranCount;
   2334             }
   2335           }
   2336         } else {
   2337           DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));
   2338           SignalCallerEvent (Private, TransReq);
   2339           continue;
   2340         }
   2341 
   2342         DEBUG ((EFI_D_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));
   2343         SignalCallerEvent (Private, TransReq);
   2344       }
   2345     }
   2346   }
   2347 }
   2348 
   2349