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