}\r
\r
DataDirection = Packet->DataDirection;\r
- if (DataDirection == UfsDataIn) {\r
- DataSize = Packet->InTransferLength;\r
- Data = Packet->InDataBuffer;\r
- } else if (DataDirection == UfsDataOut) {\r
- DataSize = Packet->OutTransferLength;\r
- Data = Packet->OutDataBuffer;\r
- } else {\r
- DataSize = 0;\r
- Data = NULL;\r
- }\r
-\r
- if (((Opcode != UtpQueryFuncOpcodeSetFlag) && (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag))\r
- && ((DataSize == 0) || (Data == NULL))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (((Opcode == UtpQueryFuncOpcodeSetFlag) || (Opcode == UtpQueryFuncOpcodeClrFlag) || (Opcode == UtpQueryFuncOpcodeTogFlag))\r
- && ((DataSize != 0) || (Data != NULL))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((Opcode == UtpQueryFuncOpcodeWrAttr) && (DataSize != sizeof (UINT32))) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
+ DataSize = Packet->TransferLength;\r
+ Data = Packet->DataBuffer;\r
\r
if ((Opcode == UtpQueryFuncOpcodeWrDesc) || (Opcode == UtpQueryFuncOpcodeRdDesc)) {\r
+ if (DataSize == 0 || Data == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);\r
} else {\r
TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));\r
}\r
\r
/**\r
- Read or write specified device descriptor of a UFS device.\r
+ Extracts return data from query response upiu.\r
\r
- @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
- @param[in] Read The boolean variable to show r/w direction.\r
- @param[in] DescId The ID of device descriptor.\r
- @param[in] Index The Index of device descriptor.\r
- @param[in] Selector The Selector of device descriptor.\r
- @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
- @param[in] DescSize The size of device descriptor buffer.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+ @param[in] QueryResp Pointer to the query response.\r
\r
- @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
- @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+ @retval EFI_INVALID_PARAMETER Packet or QueryResp are empty or opcode is invalid.\r
+ @retval EFI_SUCCESS Data extracted.\r
\r
**/\r
EFI_STATUS\r
-UfsRwDeviceDesc (\r
- IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
- IN BOOLEAN Read,\r
- IN UINT8 DescId,\r
- IN UINT8 Index,\r
- IN UINT8 Selector,\r
- IN OUT VOID *Descriptor,\r
- IN UINT32 DescSize\r
+UfsGetReturnDataFromQueryResponse (\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet,\r
+ IN UTP_QUERY_RESP_UPIU *QueryResp\r
)\r
{\r
- EFI_STATUS Status;\r
- UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- UINT16 ReturnDataSize;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
+ UINT16 ReturnDataSize;\r
+ UINT32 ReturnData;\r
\r
- ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+ if (Packet == NULL || QueryResp == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (Read) {\r
- Packet.DataDirection = UfsDataIn;\r
- Packet.InDataBuffer = Descriptor;\r
- Packet.InTransferLength = DescSize;\r
- Packet.Opcode = UtpQueryFuncOpcodeRdDesc;\r
- } else {\r
- Packet.DataDirection = UfsDataOut;\r
- Packet.OutDataBuffer = Descriptor;\r
- Packet.OutTransferLength = DescSize;\r
- Packet.Opcode = UtpQueryFuncOpcodeWrDesc;\r
+ switch (Packet->Opcode) {\r
+ case UtpQueryFuncOpcodeRdDesc:\r
+ ReturnDataSize = QueryResp->Tsf.Length;\r
+ SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+ CopyMem (Packet->DataBuffer, (QueryResp + 1), ReturnDataSize);\r
+ Packet->TransferLength = ReturnDataSize;\r
+ break;\r
+ case UtpQueryFuncOpcodeWrDesc:\r
+ ReturnDataSize = QueryResp->Tsf.Length;\r
+ SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
+ Packet->TransferLength = ReturnDataSize;\r
+ break;\r
+ case UtpQueryFuncOpcodeRdFlag:\r
+ case UtpQueryFuncOpcodeSetFlag:\r
+ case UtpQueryFuncOpcodeClrFlag:\r
+ case UtpQueryFuncOpcodeTogFlag:\r
+ CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));\r
+ break;\r
+ case UtpQueryFuncOpcodeRdAttr:\r
+ case UtpQueryFuncOpcodeWrAttr:\r
+ ReturnData = QueryResp->Tsf.Value;\r
+ SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));\r
+ CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));\r
+ break;\r
+ default:\r
+ return EFI_INVALID_PARAMETER;\r
}\r
- Packet.DescId = DescId;\r
- Packet.Index = Index;\r
- Packet.Selector = Selector;\r
- Packet.Timeout = UFS_TIMEOUT;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Creates Transfer Request descriptor and sends Query Request to the device.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
+\r
+ @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequestRetry (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet\r
+ )\r
+{\r
+ UINT8 Slot;\r
+ UTP_TRD *Trd;\r
+ VOID *CmdDescHost;\r
+ VOID *CmdDescMapping;\r
+ UINT32 CmdDescSize;\r
+ EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
+ UTP_QUERY_RESP_UPIU *QueryResp;\r
+ EFI_STATUS Status;\r
\r
//\r
// Find out which slot of transfer request list is available.\r
//\r
// Fill transfer request descriptor to this slot.\r
//\r
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
+ Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));\r
return Status;\r
}\r
\r
- //\r
- // Check the transfer request result.\r
- //\r
UfsHc = Private->UfsHostController;\r
QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
ASSERT (QueryResp != NULL);\r
\r
//\r
// Wait for the completion of the transfer request.\r
- // \r
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
+ //\r
+ Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);\r
if (EFI_ERROR (Status)) {\r
goto Exit;\r
}\r
\r
- if (QueryResp->QueryResp != 0) {\r
+ if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));\r
DumpQueryResponseResult (QueryResp->QueryResp);\r
Status = EFI_DEVICE_ERROR;\r
goto Exit;\r
}\r
\r
- if (Trd->Ocs == 0) {\r
- ReturnDataSize = QueryResp->Tsf.Length;\r
- SwapLittleEndianToBigEndian ((UINT8*)&ReturnDataSize, sizeof (UINT16));\r
-\r
- if (Read) {\r
- CopyMem (Packet.InDataBuffer, (QueryResp + 1), ReturnDataSize);\r
- Packet.InTransferLength = ReturnDataSize;\r
- } else {\r
- Packet.OutTransferLength = ReturnDataSize;\r
- }\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
+ Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));\r
+ goto Exit;\r
}\r
\r
Exit:\r
return Status;\r
}\r
\r
+/**\r
+ Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.\r
+ @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.\r
+\r
+ @retval EFI_SUCCESS The device responded correctly to the Query request.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while waiting for the response from the device.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of the operation.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsSendDmRequest (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 Retry;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ for (Retry = 0; Retry < 5; Retry ++) {\r
+ Status = UfsSendDmRequestRetry (Private, Packet);\r
+ if (!EFI_ERROR (Status)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read or write specified device descriptor of a UFS device.\r
+\r
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] DescId The ID of device descriptor.\r
+ @param[in] Index The Index of device descriptor.\r
+ @param[in] Selector The Selector of device descriptor.\r
+ @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
+ @param[in] DescSize The size of device descriptor buffer.\r
+\r
+ @retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsRwDeviceDesc (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 DescId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT VOID *Descriptor,\r
+ IN UINT32 DescSize\r
+ )\r
+{\r
+ UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
+\r
+ ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
+\r
+ if (Read) {\r
+ Packet.DataDirection = UfsDataIn;\r
+ Packet.Opcode = UtpQueryFuncOpcodeRdDesc;\r
+ } else {\r
+ Packet.DataDirection = UfsDataOut;\r
+ Packet.Opcode = UtpQueryFuncOpcodeWrDesc;\r
+ }\r
+ Packet.DataBuffer = Descriptor;\r
+ Packet.TransferLength = DescSize;\r
+ Packet.DescId = DescId;\r
+ Packet.Index = Index;\r
+ Packet.Selector = Selector;\r
+ Packet.Timeout = UFS_TIMEOUT;\r
+\r
+ return UfsSendDmRequest (Private, &Packet);\r
+}\r
+\r
/**\r
Read or write specified attribute of a UFS device.\r
\r
IN OUT UINT32 *Attributes\r
)\r
{\r
- EFI_STATUS Status;\r
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- UINT32 ReturnData;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
\r
Packet.DataDirection = UfsDataOut;\r
Packet.Opcode = UtpQueryFuncOpcodeWrAttr;\r
}\r
+ Packet.DataBuffer = Attributes;\r
Packet.DescId = AttrId;\r
Packet.Index = Index;\r
Packet.Selector = Selector;\r
Packet.Timeout = UFS_TIMEOUT;\r
\r
- //\r
- // Find out which slot of transfer request list is available.\r
- //\r
- Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- \r
- Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
- //\r
- // Fill transfer request descriptor to this slot.\r
- //\r
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check the transfer request result.\r
- //\r
- UfsHc = Private->UfsHostController;\r
- QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
- ASSERT (QueryResp != NULL);\r
- CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
- //\r
- // Start to execute the transfer request.\r
- //\r
- UfsStartExecCmd (Private, Slot);\r
-\r
- //\r
- // Wait for the completion of the transfer request.\r
- // \r
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
-\r
- if (QueryResp->QueryResp != 0) {\r
- DumpQueryResponseResult (QueryResp->QueryResp);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
- }\r
-\r
- if (Trd->Ocs == 0) {\r
- ReturnData = QueryResp->Tsf.Value;\r
- SwapLittleEndianToBigEndian ((UINT8*)&ReturnData, sizeof (UINT32));\r
- *Attributes = ReturnData;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
-Exit:\r
- UfsHc->Flush (UfsHc);\r
-\r
- UfsStopExecCmd (Private, Slot);\r
-\r
- if (CmdDescMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, CmdDescMapping);\r
- }\r
-\r
- if (CmdDescHost != NULL) {\r
- UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
- }\r
-\r
- return Status;\r
+ return UfsSendDmRequest (Private, &Packet);\r
}\r
\r
/**\r
IN OUT UINT8 *Value\r
)\r
{\r
- EFI_STATUS Status;\r
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
- UINT8 Slot;\r
- UTP_TRD *Trd;\r
- UTP_QUERY_RESP_UPIU *QueryResp;\r
- UINT32 CmdDescSize;\r
- VOID *CmdDescHost;\r
- VOID *CmdDescMapping;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
if (Value == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
+ Packet.DataBuffer = Value;\r
Packet.DescId = FlagId;\r
Packet.Index = 0;\r
Packet.Selector = 0;\r
Packet.Timeout = UFS_TIMEOUT;\r
\r
- //\r
- // Find out which slot of transfer request list is available.\r
- //\r
- Status = UfsFindAvailableSlotInTrl (Private, &Slot);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Fill transfer request descriptor to this slot.\r
- //\r
- Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;\r
- Status = UfsCreateDMCommandDesc (Private, &Packet, Trd, &CmdDescHost, &CmdDescMapping);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check the transfer request result.\r
- //\r
- UfsHc = Private->UfsHostController;\r
- QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));\r
- ASSERT (QueryResp != NULL);\r
- CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);\r
-\r
- //\r
- // Start to execute the transfer request.\r
- //\r
- UfsStartExecCmd (Private, Slot);\r
-\r
- //\r
- // Wait for the completion of the transfer request.\r
- // \r
- Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, Packet.Timeout);\r
- if (EFI_ERROR (Status)) {\r
- goto Exit;\r
- }\r
-\r
- if (QueryResp->QueryResp != 0) {\r
- DumpQueryResponseResult (QueryResp->QueryResp);\r
- Status = EFI_DEVICE_ERROR;\r
- goto Exit;\r
- }\r
-\r
- if (Trd->Ocs == 0) {\r
- *Value = (UINT8)QueryResp->Tsf.Value;\r
- } else {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
-\r
-Exit:\r
- UfsHc->Flush (UfsHc);\r
-\r
- UfsStopExecCmd (Private, Slot);\r
-\r
- if (CmdDescMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, CmdDescMapping);\r
- }\r
- if (CmdDescHost != NULL) {\r
- UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);\r
- }\r
-\r
- return Status;\r
+ return UfsSendDmRequest (Private, &Packet);\r
}\r
\r
/**\r