]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
MdeModulePkg/UfsPassThruDxe: Check for RPMB W-LUN (SecurityLun)
[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 - 2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UfsPassThru.h"
11
12 /**
13 Read 32bits data from specified UFS MMIO register.
14
15 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
16 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
17 the memory operation.
18 @param[out] Value The data buffer to store.
19
20 @retval EFI_TIMEOUT The operation is time out.
21 @retval EFI_SUCCESS The operation succeeds.
22 @retval Others The operation fails.
23
24 **/
25 EFI_STATUS
26 UfsMmioRead32 (
27 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
28 IN UINTN Offset,
29 OUT UINT32 *Value
30 )
31 {
32 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
33 EFI_STATUS Status;
34
35 UfsHc = Private->UfsHostController;
36
37 Status = UfsHc->Read (UfsHc, EfiUfsHcWidthUint32, Offset, 1, Value);
38
39 return Status;
40 }
41
42 /**
43 Write 32bits data to specified UFS MMIO register.
44
45 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
46 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
47 the memory operation.
48 @param[in] Value The data to write.
49
50 @retval EFI_TIMEOUT The operation is time out.
51 @retval EFI_SUCCESS The operation succeeds.
52 @retval Others The operation fails.
53
54 **/
55 EFI_STATUS
56 UfsMmioWrite32 (
57 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
58 IN UINTN Offset,
59 IN UINT32 Value
60 )
61 {
62 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
63 EFI_STATUS Status;
64
65 UfsHc = Private->UfsHostController;
66
67 Status = UfsHc->Write (UfsHc, EfiUfsHcWidthUint32, Offset, 1, &Value);
68
69 return Status;
70 }
71
72 /**
73 Wait for the value of the specified system memory set to the test value.
74
75 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
76 @param[in] Offset The offset within the UFS Host Controller MMIO space to start
77 the memory operation.
78 @param[in] MaskValue The mask value of memory.
79 @param[in] TestValue The test value of memory.
80 @param[in] Timeout The time out value for wait memory set, uses 100ns as a unit.
81
82 @retval EFI_TIMEOUT The system memory setting is time out.
83 @retval EFI_SUCCESS The system memory is correct set.
84 @retval Others The operation fails.
85
86 **/
87 EFI_STATUS
88 UfsWaitMemSet (
89 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
90 IN UINTN Offset,
91 IN UINT32 MaskValue,
92 IN UINT32 TestValue,
93 IN UINT64 Timeout
94 )
95 {
96 UINT32 Value;
97 UINT64 Delay;
98 BOOLEAN InfiniteWait;
99 EFI_STATUS Status;
100
101 if (Timeout == 0) {
102 InfiniteWait = TRUE;
103 } else {
104 InfiniteWait = FALSE;
105 }
106
107 Delay = DivU64x32 (Timeout, 10) + 1;
108
109 do {
110 //
111 // Access PCI MMIO space to see if the value is the tested one.
112 //
113 Status = UfsMmioRead32 (Private, Offset, &Value);
114 if (EFI_ERROR (Status)) {
115 return Status;
116 }
117
118 Value &= MaskValue;
119
120 if (Value == TestValue) {
121 return EFI_SUCCESS;
122 }
123
124 //
125 // Stall for 1 microseconds.
126 //
127 MicroSecondDelay (1);
128
129 Delay--;
130
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 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize);
606 } else {
607 TotalLen = ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU));
608 }
609
610 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
611 if (EFI_ERROR (Status)) {
612 return Status;
613 }
614
615 //
616 // Initialize UTP QUERY REQUEST UPIU
617 //
618 QueryReqUpiu = (UTP_QUERY_REQ_UPIU*)*CmdDescHost;
619 ASSERT (QueryReqUpiu != NULL);
620 UfsInitQueryRequestUpiu (
621 QueryReqUpiu,
622 Private->TaskTag++,
623 Opcode,
624 Packet->DescId,
625 Packet->Index,
626 Packet->Selector,
627 DataSize,
628 Data
629 );
630
631 //
632 // Fill UTP_TRD associated fields
633 // NOTE: Some UFS host controllers request the Query Response UPIU *MUST* be located at a 64-bit aligned boundary.
634 //
635 Trd->Int = UFS_INTERRUPT_COMMAND;
636 Trd->Dd = DataDirection;
637 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
638 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
639 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
640 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
641 if (Opcode == UtpQueryFuncOpcodeWrDesc) {
642 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)), sizeof (UINT32));
643 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
644 } else {
645 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_RESP_UPIU)) + ROUNDUP8 (DataSize), sizeof (UINT32));
646 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_QUERY_REQ_UPIU)), sizeof (UINT32));
647 }
648
649 return EFI_SUCCESS;
650 }
651
652 /**
653 Allocate NOP IN and NOP OUT UPIU for filling UTP TRD's command descriptor field.
654
655 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
656 @param[in] Trd The pointer to the UTP Transfer Request Descriptor.
657 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
658 @param[out] CmdDescMapping A resulting value to pass to Unmap().
659
660 @retval EFI_SUCCESS The creation succeed.
661 @retval EFI_DEVICE_ERROR The creation failed.
662 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
663
664 **/
665 EFI_STATUS
666 UfsCreateNopCommandDesc (
667 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
668 IN UTP_TRD *Trd,
669 OUT VOID **CmdDescHost,
670 OUT VOID **CmdDescMapping
671 )
672 {
673 UINTN TotalLen;
674 UTP_NOP_OUT_UPIU *NopOutUpiu;
675 EFI_STATUS Status;
676 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
677
678 ASSERT ((Private != NULL) && (Trd != NULL));
679
680 TotalLen = ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)) + ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU));
681 Status = UfsAllocateAlignCommonBuffer (Private, TotalLen, CmdDescHost, &CmdDescPhyAddr, CmdDescMapping);
682 if (EFI_ERROR (Status)) {
683 return Status;
684 }
685
686 NopOutUpiu = (UTP_NOP_OUT_UPIU*)*CmdDescHost;
687 ASSERT (NopOutUpiu != NULL);
688 NopOutUpiu->TaskTag = Private->TaskTag++;
689
690 //
691 // Fill UTP_TRD associated fields
692 // NOTE: Some UFS host controllers request the Nop Out UPIU *MUST* be located at a 64-bit aligned boundary.
693 //
694 Trd->Int = UFS_INTERRUPT_COMMAND;
695 Trd->Dd = 0x00;
696 Trd->Ct = UFS_STORAGE_COMMAND_TYPE;
697 Trd->Ocs = UFS_HC_TRD_OCS_INIT_VALUE;
698 Trd->UcdBa = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 7);
699 Trd->UcdBaU = (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32);
700 Trd->RuL = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_IN_UPIU)), sizeof (UINT32));
701 Trd->RuO = (UINT16)DivU64x32 ((UINT64)ROUNDUP8 (sizeof (UTP_NOP_OUT_UPIU)), sizeof (UINT32));
702
703 return EFI_SUCCESS;
704 }
705
706 /**
707 Find out available slot in transfer list of a UFS device.
708
709 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
710 @param[out] Slot The available slot.
711
712 @retval EFI_SUCCESS The available slot was found successfully.
713 @retval EFI_NOT_READY No slot is available at this moment.
714
715 **/
716 EFI_STATUS
717 UfsFindAvailableSlotInTrl (
718 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
719 OUT UINT8 *Slot
720 )
721 {
722 UINT8 Nutrs;
723 UINT8 Index;
724 UINT32 Data;
725 EFI_STATUS Status;
726
727 ASSERT ((Private != NULL) && (Slot != NULL));
728
729 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Data);
730 if (EFI_ERROR (Status)) {
731 return Status;
732 }
733
734 Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);
735
736 for (Index = 0; Index < Nutrs; Index++) {
737 if ((Data & (BIT0 << Index)) == 0) {
738 *Slot = Index;
739 return EFI_SUCCESS;
740 }
741 }
742
743 return EFI_NOT_READY;
744 }
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 CopyMem (Packet->DataBuffer, &QueryResp->Tsf.Value, sizeof (UINT8));
867 break;
868 case UtpQueryFuncOpcodeRdAttr:
869 case UtpQueryFuncOpcodeWrAttr:
870 ReturnData = QueryResp->Tsf.Value;
871 SwapLittleEndianToBigEndian ((UINT8*) &ReturnData, sizeof (UINT32));
872 CopyMem (Packet->DataBuffer, &ReturnData, sizeof (UINT32));
873 break;
874 default:
875 return EFI_INVALID_PARAMETER;
876 }
877
878 return EFI_SUCCESS;
879 }
880
881 /**
882 Creates Transfer Request descriptor and sends Query Request to the device.
883
884 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.
885 @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.
886
887 @retval EFI_SUCCESS The device descriptor was read/written successfully.
888 @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid
889 combination to point to a type of UFS device descriptor.
890 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
891 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
892
893 **/
894 EFI_STATUS
895 UfsSendDmRequestRetry (
896 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
897 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet
898 )
899 {
900 UINT8 Slot;
901 UTP_TRD *Trd;
902 VOID *CmdDescHost;
903 VOID *CmdDescMapping;
904 UINT32 CmdDescSize;
905 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
906 UTP_QUERY_RESP_UPIU *QueryResp;
907 EFI_STATUS Status;
908
909 //
910 // Find out which slot of transfer request list is available.
911 //
912 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
913 if (EFI_ERROR (Status)) {
914 return Status;
915 }
916
917 Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
918 //
919 // Fill transfer request descriptor to this slot.
920 //
921 Status = UfsCreateDMCommandDesc (Private, Packet, Trd, &CmdDescHost, &CmdDescMapping);
922 if (EFI_ERROR (Status)) {
923 DEBUG ((DEBUG_ERROR, "Failed to create DM command descriptor\n"));
924 return Status;
925 }
926
927 UfsHc = Private->UfsHostController;
928 QueryResp = (UTP_QUERY_RESP_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
929 ASSERT (QueryResp != NULL);
930 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
931
932 //
933 // Start to execute the transfer request.
934 //
935 UfsStartExecCmd (Private, Slot);
936
937 //
938 // Wait for the completion of the transfer request.
939 //
940 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0, 0, Packet->Timeout);
941 if (EFI_ERROR (Status)) {
942 goto Exit;
943 }
944
945 if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {
946 DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));
947 DumpQueryResponseResult (QueryResp->QueryResp);
948
949 if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||
950 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||
951 (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {
952 Status = EFI_INVALID_PARAMETER;
953 } else {
954 Status = EFI_DEVICE_ERROR;
955 }
956 goto Exit;
957 }
958
959 Status = UfsGetReturnDataFromQueryResponse (Packet, QueryResp);
960 if (EFI_ERROR (Status)) {
961 DEBUG ((DEBUG_ERROR, "Failed to get return data from query response\n"));
962 goto Exit;
963 }
964
965 Exit:
966 UfsHc->Flush (UfsHc);
967
968 UfsStopExecCmd (Private, Slot);
969
970 if (CmdDescMapping != NULL) {
971 UfsHc->Unmap (UfsHc, CmdDescMapping);
972 }
973 if (CmdDescHost != NULL) {
974 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
975 }
976
977 return Status;
978 }
979
980 /**
981 Sends Query Request to the device. Query is sent until device responds correctly or counter runs out.
982
983 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.
984 @param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.
985
986 @retval EFI_SUCCESS The device responded correctly to the Query request.
987 @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid
988 combination to point to a type of UFS device descriptor.
989 @retval EFI_DEVICE_ERROR A device error occurred while waiting for the response from the device.
990 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of the operation.
991
992 **/
993 EFI_STATUS
994 UfsSendDmRequest (
995 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
996 IN UFS_DEVICE_MANAGEMENT_REQUEST_PACKET *Packet
997 )
998 {
999 EFI_STATUS Status;
1000 UINT8 Retry;
1001
1002 Status = EFI_SUCCESS;
1003
1004 for (Retry = 0; Retry < 5; Retry ++) {
1005 Status = UfsSendDmRequestRetry (Private, Packet);
1006 if (!EFI_ERROR (Status)) {
1007 return EFI_SUCCESS;
1008 }
1009 }
1010
1011 DEBUG ((DEBUG_ERROR, "Failed to get response from the device after %d retries\n", Retry));
1012 return Status;
1013 }
1014
1015 /**
1016 Read or write specified device descriptor of a UFS device.
1017
1018 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1019 @param[in] Read The boolean variable to show r/w direction.
1020 @param[in] DescId The ID of device descriptor.
1021 @param[in] Index The Index of device descriptor.
1022 @param[in] Selector The Selector of device descriptor.
1023 @param[in, out] Descriptor The buffer of device descriptor to be read or written.
1024 @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,
1025 of the data buffer specified by Descriptor. On output, the number
1026 of bytes that were actually transferred.
1027
1028 @retval EFI_SUCCESS The device descriptor was read/written successfully.
1029 @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a
1030 type of UFS device descriptor.
1031 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
1032 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
1033
1034 **/
1035 EFI_STATUS
1036 UfsRwDeviceDesc (
1037 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1038 IN BOOLEAN Read,
1039 IN UINT8 DescId,
1040 IN UINT8 Index,
1041 IN UINT8 Selector,
1042 IN OUT VOID *Descriptor,
1043 IN OUT UINT32 *DescSize
1044 )
1045 {
1046 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1047 EFI_STATUS Status;
1048
1049 if (DescSize == NULL) {
1050 return EFI_INVALID_PARAMETER;
1051 }
1052
1053 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1054
1055 if (Read) {
1056 Packet.DataDirection = UfsDataIn;
1057 Packet.Opcode = UtpQueryFuncOpcodeRdDesc;
1058 } else {
1059 Packet.DataDirection = UfsDataOut;
1060 Packet.Opcode = UtpQueryFuncOpcodeWrDesc;
1061 }
1062 Packet.DataBuffer = Descriptor;
1063 Packet.TransferLength = *DescSize;
1064 Packet.DescId = DescId;
1065 Packet.Index = Index;
1066 Packet.Selector = Selector;
1067 Packet.Timeout = UFS_TIMEOUT;
1068
1069 Status = UfsSendDmRequest (Private, &Packet);
1070 if (EFI_ERROR (Status)) {
1071 *DescSize = 0;
1072 } else {
1073 *DescSize = Packet.TransferLength;
1074 }
1075
1076 return Status;
1077 }
1078
1079 /**
1080 Read or write specified attribute of a UFS device.
1081
1082 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1083 @param[in] Read The boolean variable to show r/w direction.
1084 @param[in] AttrId The ID of Attribute.
1085 @param[in] Index The Index of Attribute.
1086 @param[in] Selector The Selector of Attribute.
1087 @param[in, out] Attributes The value of Attribute to be read or written.
1088
1089 @retval EFI_SUCCESS The Attribute was read/written successfully.
1090 @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
1091 type of UFS device descriptor.
1092 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
1093 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
1094
1095 **/
1096 EFI_STATUS
1097 UfsRwAttributes (
1098 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1099 IN BOOLEAN Read,
1100 IN UINT8 AttrId,
1101 IN UINT8 Index,
1102 IN UINT8 Selector,
1103 IN OUT UINT32 *Attributes
1104 )
1105 {
1106 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1107
1108 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1109
1110 if (Read) {
1111 Packet.DataDirection = UfsDataIn;
1112 Packet.Opcode = UtpQueryFuncOpcodeRdAttr;
1113 } else {
1114 Packet.DataDirection = UfsDataOut;
1115 Packet.Opcode = UtpQueryFuncOpcodeWrAttr;
1116 }
1117 Packet.DataBuffer = Attributes;
1118 Packet.DescId = AttrId;
1119 Packet.Index = Index;
1120 Packet.Selector = Selector;
1121 Packet.Timeout = UFS_TIMEOUT;
1122
1123 return UfsSendDmRequest (Private, &Packet);
1124 }
1125
1126 /**
1127 Read or write specified flag of a UFS device.
1128
1129 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1130 @param[in] Read The boolean variable to show r/w direction.
1131 @param[in] FlagId The ID of flag to be read or written.
1132 @param[in, out] Value The value to set or clear flag.
1133
1134 @retval EFI_SUCCESS The flag was read/written successfully.
1135 @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.
1136 @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the flag.
1137 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the flag.
1138
1139 **/
1140 EFI_STATUS
1141 UfsRwFlags (
1142 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1143 IN BOOLEAN Read,
1144 IN UINT8 FlagId,
1145 IN OUT UINT8 *Value
1146 )
1147 {
1148 UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
1149
1150 if (Value == NULL) {
1151 return EFI_INVALID_PARAMETER;
1152 }
1153
1154 ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
1155
1156 if (Read) {
1157 ASSERT (Value != NULL);
1158 Packet.DataDirection = UfsDataIn;
1159 Packet.Opcode = UtpQueryFuncOpcodeRdFlag;
1160 } else {
1161 Packet.DataDirection = UfsDataOut;
1162 if (*Value == 1) {
1163 Packet.Opcode = UtpQueryFuncOpcodeSetFlag;
1164 } else if (*Value == 0) {
1165 Packet.Opcode = UtpQueryFuncOpcodeClrFlag;
1166 } else {
1167 return EFI_INVALID_PARAMETER;
1168 }
1169 }
1170 Packet.DataBuffer = Value;
1171 Packet.DescId = FlagId;
1172 Packet.Index = 0;
1173 Packet.Selector = 0;
1174 Packet.Timeout = UFS_TIMEOUT;
1175
1176 return UfsSendDmRequest (Private, &Packet);
1177 }
1178
1179 /**
1180 Set specified flag to 1 on a UFS device.
1181
1182 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1183 @param[in] FlagId The ID of flag to be set.
1184
1185 @retval EFI_SUCCESS The flag was set successfully.
1186 @retval EFI_DEVICE_ERROR A device error occurred while attempting to set the flag.
1187 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of setting the flag.
1188
1189 **/
1190 EFI_STATUS
1191 UfsSetFlag (
1192 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1193 IN UINT8 FlagId
1194 )
1195 {
1196 EFI_STATUS Status;
1197 UINT8 Value;
1198
1199 Value = 1;
1200 Status = UfsRwFlags (Private, FALSE, FlagId, &Value);
1201
1202 return Status;
1203 }
1204
1205 /**
1206 Read specified flag from a UFS device.
1207
1208 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1209 @param[in] FlagId The ID of flag to be read.
1210 @param[out] Value The flag's value.
1211
1212 @retval EFI_SUCCESS The flag was read successfully.
1213 @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
1214 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
1215
1216 **/
1217 EFI_STATUS
1218 UfsReadFlag (
1219 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1220 IN UINT8 FlagId,
1221 OUT UINT8 *Value
1222 )
1223 {
1224 EFI_STATUS Status;
1225
1226 Status = UfsRwFlags (Private, TRUE, FlagId, Value);
1227
1228 return Status;
1229 }
1230
1231 /**
1232 Sends NOP IN cmd to a UFS device for initialization process request.
1233 For more details, please refer to UFS 2.0 spec Figure 13.3.
1234
1235 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1236
1237 @retval EFI_SUCCESS The NOP IN command was sent by the host. The NOP OUT response was
1238 received successfully.
1239 @retval EFI_DEVICE_ERROR A device error occurred while attempting to execute NOP IN command.
1240 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1241 @retval EFI_TIMEOUT A timeout occurred while waiting for the NOP IN command to execute.
1242
1243 **/
1244 EFI_STATUS
1245 UfsExecNopCmds (
1246 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1247 )
1248 {
1249 EFI_STATUS Status;
1250 UINT8 Slot;
1251 UTP_TRD *Trd;
1252 UTP_NOP_IN_UPIU *NopInUpiu;
1253 UINT32 CmdDescSize;
1254 VOID *CmdDescHost;
1255 VOID *CmdDescMapping;
1256 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1257
1258 //
1259 // Find out which slot of transfer request list is available.
1260 //
1261 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
1262 if (EFI_ERROR (Status)) {
1263 return Status;
1264 }
1265
1266 Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
1267 Status = UfsCreateNopCommandDesc (Private, Trd, &CmdDescHost, &CmdDescMapping);
1268 if (EFI_ERROR (Status)) {
1269 return Status;
1270 }
1271
1272 //
1273 // Check the transfer request result.
1274 //
1275 UfsHc = Private->UfsHostController;
1276 NopInUpiu = (UTP_NOP_IN_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
1277 ASSERT (NopInUpiu != NULL);
1278 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
1279
1280 //
1281 // Start to execute the transfer request.
1282 //
1283 UfsStartExecCmd (Private, Slot);
1284
1285 //
1286 // Wait for the completion of the transfer request.
1287 //
1288 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);
1289 if (EFI_ERROR (Status)) {
1290 goto Exit;
1291 }
1292
1293 if (NopInUpiu->Resp != 0) {
1294 Status = EFI_DEVICE_ERROR;
1295 } else {
1296 Status = EFI_SUCCESS;
1297 }
1298
1299 Exit:
1300 UfsHc->Flush (UfsHc);
1301
1302 UfsStopExecCmd (Private, Slot);
1303
1304 if (CmdDescMapping != NULL) {
1305 UfsHc->Unmap (UfsHc, CmdDescMapping);
1306 }
1307 if (CmdDescHost != NULL) {
1308 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
1309 }
1310
1311 return Status;
1312 }
1313
1314 /**
1315 Cleanup data buffers after data transfer. This function
1316 also takes care to copy all data to user memory pool for
1317 unaligned data transfers.
1318
1319 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1320 @param[in] TransReq Pointer to the transfer request
1321 **/
1322 VOID
1323 UfsReconcileDataTransferBuffer (
1324 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1325 IN UFS_PASS_THRU_TRANS_REQ *TransReq
1326 )
1327 {
1328 if (TransReq->DataBufMapping != NULL) {
1329 Private->UfsHostController->Unmap (
1330 Private->UfsHostController,
1331 TransReq->DataBufMapping
1332 );
1333 }
1334
1335 //
1336 // Check if unaligned transfer was performed. If it was and we read
1337 // data from device copy memory to user data buffers before cleanup.
1338 // The assumption is if auxiliary aligned data buffer is not NULL then
1339 // unaligned transfer has been performed.
1340 //
1341 if (TransReq->AlignedDataBuf != NULL) {
1342 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1343 CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);
1344 }
1345 //
1346 // Wipe out the transfer buffer in case it contains sensitive data.
1347 //
1348 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1349 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1350 TransReq->AlignedDataBuf = NULL;
1351 }
1352 }
1353
1354 /**
1355 Prepare data buffer for transfer.
1356
1357 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1358 @param[in, out] TransReq Pointer to the transfer request
1359
1360 @retval EFI_DEVICE_ERROR Failed to prepare buffer for transfer
1361 @retval EFI_SUCCESS Buffer ready for transfer
1362 **/
1363 EFI_STATUS
1364 UfsPrepareDataTransferBuffer (
1365 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1366 IN OUT UFS_PASS_THRU_TRANS_REQ *TransReq
1367 )
1368 {
1369 EFI_STATUS Status;
1370 VOID *DataBuf;
1371 UINT32 DataLen;
1372 UINTN MapLength;
1373 EFI_PHYSICAL_ADDRESS DataBufPhyAddr;
1374 EDKII_UFS_HOST_CONTROLLER_OPERATION Flag;
1375 UTP_TR_PRD *PrdtBase;
1376
1377 DataBufPhyAddr = 0;
1378 DataBuf = NULL;
1379
1380 //
1381 // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.
1382 // When command is finished auxiliary memory pool is copied into actual user memory.
1383 // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)
1384 //
1385 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1386 if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {
1387 DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));
1388 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1389 if (DataBuf == NULL) {
1390 return EFI_DEVICE_ERROR;
1391 }
1392 ZeroMem (DataBuf, DataLen);
1393 TransReq->AlignedDataBuf = DataBuf;
1394 TransReq->AlignedDataBufSize = DataLen;
1395 } else {
1396 DataLen = TransReq->Packet->InTransferLength;
1397 DataBuf = TransReq->Packet->InDataBuffer;
1398 }
1399 Flag = EdkiiUfsHcOperationBusMasterWrite;
1400 } else {
1401 if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {
1402 DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));
1403 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1404 if (DataBuf == NULL) {
1405 return EFI_DEVICE_ERROR;
1406 }
1407 CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);
1408 TransReq->AlignedDataBuf = DataBuf;
1409 TransReq->AlignedDataBufSize = DataLen;
1410 } else {
1411 DataLen = TransReq->Packet->OutTransferLength;
1412 DataBuf = TransReq->Packet->OutDataBuffer;
1413 }
1414 Flag = EdkiiUfsHcOperationBusMasterRead;
1415 }
1416
1417 if (DataLen != 0) {
1418 MapLength = DataLen;
1419 Status = Private->UfsHostController->Map (
1420 Private->UfsHostController,
1421 Flag,
1422 DataBuf,
1423 &MapLength,
1424 &DataBufPhyAddr,
1425 &TransReq->DataBufMapping
1426 );
1427
1428 if (EFI_ERROR (Status) || (DataLen != MapLength)) {
1429 if (TransReq->AlignedDataBuf != NULL) {
1430 //
1431 // Wipe out the transfer buffer in case it contains sensitive data.
1432 //
1433 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1434 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1435 TransReq->AlignedDataBuf = NULL;
1436 }
1437 return EFI_DEVICE_ERROR;
1438 }
1439 }
1440
1441 //
1442 // Fill PRDT table of Command UPIU for executed SCSI cmd.
1443 //
1444 PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));
1445 ASSERT (PrdtBase != NULL);
1446 UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);
1447
1448 return EFI_SUCCESS;
1449 }
1450
1451 /**
1452 Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
1453
1454 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1455 @param[in] Lun The LUN of the UFS device to send the SCSI Request Packet.
1456 @param[in, out] Packet A pointer to the SCSI Request Packet to send to a specified Lun of the
1457 UFS device.
1458 @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking
1459 I/O is performed. If Event is NULL, then blocking I/O is performed. If
1460 Event is not NULL and non blocking I/O is supported, then
1461 nonblocking I/O is performed, and Event will be signaled when the
1462 SCSI Request Packet completes.
1463
1464 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
1465 commands, InTransferLength bytes were transferred from
1466 InDataBuffer. For write and bi-directional commands,
1467 OutTransferLength bytes were transferred by
1468 OutDataBuffer.
1469 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
1470 Packet.
1471 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1472 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1473
1474 **/
1475 EFI_STATUS
1476 UfsExecScsiCmds (
1477 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1478 IN UINT8 Lun,
1479 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
1480 IN EFI_EVENT Event OPTIONAL
1481 )
1482 {
1483 EFI_STATUS Status;
1484 UTP_RESPONSE_UPIU *Response;
1485 UINT16 SenseDataLen;
1486 UINT32 ResTranCount;
1487 EFI_TPL OldTpl;
1488 UFS_PASS_THRU_TRANS_REQ *TransReq;
1489 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1490
1491 TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));
1492 if (TransReq == NULL) {
1493 return EFI_OUT_OF_RESOURCES;
1494 }
1495
1496 TransReq->Signature = UFS_PASS_THRU_TRANS_REQ_SIG;
1497 TransReq->TimeoutRemain = Packet->Timeout;
1498 TransReq->Packet = Packet;
1499
1500 UfsHc = Private->UfsHostController;
1501 //
1502 // Find out which slot of transfer request list is available.
1503 //
1504 Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);
1505 if (EFI_ERROR (Status)) {
1506 return Status;
1507 }
1508
1509 TransReq->Trd = ((UTP_TRD*)Private->UtpTrlBase) + TransReq->Slot;
1510
1511 //
1512 // Fill transfer request descriptor to this slot.
1513 //
1514 Status = UfsCreateScsiCommandDesc (
1515 Private,
1516 Lun,
1517 Packet,
1518 TransReq->Trd,
1519 &TransReq->CmdDescHost,
1520 &TransReq->CmdDescMapping
1521 );
1522 if (EFI_ERROR (Status)) {
1523 return Status;
1524 }
1525
1526 TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);
1527
1528 Status = UfsPrepareDataTransferBuffer (Private, TransReq);
1529 if (EFI_ERROR (Status)) {
1530 goto Exit1;
1531 }
1532
1533 //
1534 // Insert the async SCSI cmd to the Async I/O list
1535 //
1536 if (Event != NULL) {
1537 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1538 TransReq->CallerEvent = Event;
1539 InsertTailList (&Private->Queue, &TransReq->TransferList);
1540 gBS->RestoreTPL (OldTpl);
1541 }
1542
1543 //
1544 // Start to execute the transfer request.
1545 //
1546 UfsStartExecCmd (Private, TransReq->Slot);
1547
1548 //
1549 // Immediately return for async I/O.
1550 //
1551 if (Event != NULL) {
1552 return EFI_SUCCESS;
1553 }
1554
1555 //
1556 // Wait for the completion of the transfer request.
1557 //
1558 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);
1559 if (EFI_ERROR (Status)) {
1560 goto Exit;
1561 }
1562
1563 //
1564 // Get sense data if exists
1565 //
1566 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
1567 ASSERT (Response != NULL);
1568 SenseDataLen = Response->SenseDataLen;
1569 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
1570
1571 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
1572 //
1573 // Make sure the hardware device does not return more data than expected.
1574 //
1575 if (SenseDataLen <= Packet->SenseDataLength) {
1576 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
1577 Packet->SenseDataLength = (UINT8)SenseDataLen;
1578 } else {
1579 Packet->SenseDataLength = 0;
1580 }
1581 }
1582
1583 //
1584 // Check the transfer request result.
1585 //
1586 Packet->TargetStatus = Response->Status;
1587 if (Response->Response != 0) {
1588 DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));
1589 Status = EFI_DEVICE_ERROR;
1590 goto Exit;
1591 }
1592
1593 if (TransReq->Trd->Ocs == 0) {
1594 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1595 if ((Response->Flags & BIT5) == BIT5) {
1596 ResTranCount = Response->ResTranCount;
1597 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1598 Packet->InTransferLength -= ResTranCount;
1599 }
1600 } else {
1601 if ((Response->Flags & BIT5) == BIT5) {
1602 ResTranCount = Response->ResTranCount;
1603 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1604 Packet->OutTransferLength -= ResTranCount;
1605 }
1606 }
1607 } else {
1608 Status = EFI_DEVICE_ERROR;
1609 }
1610
1611 Exit:
1612 UfsHc->Flush (UfsHc);
1613
1614 UfsStopExecCmd (Private, TransReq->Slot);
1615
1616 UfsReconcileDataTransferBuffer (Private, TransReq);
1617
1618 Exit1:
1619 if (TransReq->CmdDescMapping != NULL) {
1620 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
1621 }
1622 if (TransReq->CmdDescHost != NULL) {
1623 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);
1624 }
1625 if (TransReq != NULL) {
1626 FreePool (TransReq);
1627 }
1628 return Status;
1629 }
1630
1631 /**
1632 Send UIC command.
1633
1634 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1635 @param[in, out] UicCommand UIC command descriptor. On exit contains UIC command results.
1636
1637 @return EFI_SUCCESS Successfully execute this UIC command and detect attached UFS device.
1638 @return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.
1639
1640 **/
1641 EFI_STATUS
1642 UfsExecUicCommands (
1643 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1644 IN OUT EDKII_UIC_COMMAND *UicCommand
1645 )
1646 {
1647 EFI_STATUS Status;
1648 UINT32 Data;
1649
1650 Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
1651 if (EFI_ERROR (Status)) {
1652 return Status;
1653 }
1654
1655 if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
1656 //
1657 // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
1658 //
1659 Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
1660 if (EFI_ERROR (Status)) {
1661 return Status;
1662 }
1663 }
1664
1665 //
1666 // When programming UIC command registers, host software shall set the register UICCMD
1667 // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
1668 // are set.
1669 //
1670 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, UicCommand->Arg1);
1671 if (EFI_ERROR (Status)) {
1672 return Status;
1673 }
1674
1675 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, UicCommand->Arg2);
1676 if (EFI_ERROR (Status)) {
1677 return Status;
1678 }
1679
1680 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, UicCommand->Arg3);
1681 if (EFI_ERROR (Status)) {
1682 return Status;
1683 }
1684
1685 //
1686 // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
1687 //
1688 Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
1689 if (EFI_ERROR (Status)) {
1690 return Status;
1691 }
1692
1693 Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, UicCommand->Opcode);
1694 if (EFI_ERROR (Status)) {
1695 return Status;
1696 }
1697
1698 //
1699 // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
1700 // This bit is set to '1' by the host controller upon completion of a UIC command.
1701 //
1702 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
1703 if (EFI_ERROR (Status)) {
1704 return Status;
1705 }
1706
1707 if (UicCommand->Opcode != UfsUicDmeReset) {
1708 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &UicCommand->Arg2);
1709 if (EFI_ERROR (Status)) {
1710 return Status;
1711 }
1712 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG3_OFFSET, &UicCommand->Arg3);
1713 if (EFI_ERROR (Status)) {
1714 return Status;
1715 }
1716 if ((UicCommand->Arg2 & 0xFF) != 0) {
1717 DEBUG_CODE_BEGIN();
1718 DumpUicCmdExecResult ((UINT8)UicCommand->Opcode, (UINT8)(UicCommand->Arg2 & 0xFF));
1719 DEBUG_CODE_END();
1720 return EFI_DEVICE_ERROR;
1721 }
1722 }
1723
1724 return EFI_SUCCESS;
1725 }
1726
1727 /**
1728 Allocate common buffer for host and UFS bus master access simultaneously.
1729
1730 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1731 @param[in] Size The length of buffer to be allocated.
1732 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
1733 @param[out] CmdDescPhyAddr The resulting map address for the UFS bus master to use to access the hosts CmdDescHost.
1734 @param[out] CmdDescMapping A resulting value to pass to Unmap().
1735
1736 @retval EFI_SUCCESS The common buffer was allocated successfully.
1737 @retval EFI_DEVICE_ERROR The allocation fails.
1738 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
1739
1740 **/
1741 EFI_STATUS
1742 UfsAllocateAlignCommonBuffer (
1743 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1744 IN UINTN Size,
1745 OUT VOID **CmdDescHost,
1746 OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr,
1747 OUT VOID **CmdDescMapping
1748 )
1749 {
1750 EFI_STATUS Status;
1751 UINTN Bytes;
1752 BOOLEAN Is32BitAddr;
1753 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1754
1755 if ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {
1756 Is32BitAddr = FALSE;
1757 } else {
1758 Is32BitAddr = TRUE;
1759 }
1760
1761 UfsHc = Private->UfsHostController;
1762 Status = UfsHc->AllocateBuffer (
1763 UfsHc,
1764 AllocateAnyPages,
1765 EfiBootServicesData,
1766 EFI_SIZE_TO_PAGES (Size),
1767 CmdDescHost,
1768 0
1769 );
1770 if (EFI_ERROR (Status)) {
1771 *CmdDescMapping = NULL;
1772 *CmdDescHost = NULL;
1773 *CmdDescPhyAddr = 0;
1774 return EFI_OUT_OF_RESOURCES;
1775 }
1776
1777 Bytes = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size));
1778 Status = UfsHc->Map (
1779 UfsHc,
1780 EdkiiUfsHcOperationBusMasterCommonBuffer,
1781 *CmdDescHost,
1782 &Bytes,
1783 CmdDescPhyAddr,
1784 CmdDescMapping
1785 );
1786
1787 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
1788 UfsHc->FreeBuffer (
1789 UfsHc,
1790 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1791 *CmdDescHost
1792 );
1793 *CmdDescHost = NULL;
1794 return EFI_OUT_OF_RESOURCES;
1795 }
1796
1797 if (Is32BitAddr && ((*CmdDescPhyAddr) > 0x100000000ULL)) {
1798 //
1799 // The UFS host controller doesn't support 64bit addressing, so should not get a >4G UFS bus master address.
1800 //
1801 UfsHc->Unmap (
1802 UfsHc,
1803 *CmdDescMapping
1804 );
1805 UfsHc->FreeBuffer (
1806 UfsHc,
1807 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1808 *CmdDescHost
1809 );
1810 *CmdDescMapping = NULL;
1811 *CmdDescHost = NULL;
1812 return EFI_DEVICE_ERROR;
1813 }
1814
1815 ZeroMem (*CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)));
1816 return EFI_SUCCESS;
1817 }
1818
1819 /**
1820 Enable the UFS host controller for accessing.
1821
1822 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1823
1824 @retval EFI_SUCCESS The UFS host controller enabling was executed successfully.
1825 @retval EFI_DEVICE_ERROR A device error occurred while enabling the UFS host controller.
1826
1827 **/
1828 EFI_STATUS
1829 UfsEnableHostController (
1830 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1831 )
1832 {
1833 EFI_STATUS Status;
1834 UINT32 Data;
1835
1836 if (mUfsHcPlatform != NULL && mUfsHcPlatform->Callback != NULL) {
1837 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPreHce, &Private->UfsHcDriverInterface);
1838 if (EFI_ERROR (Status)) {
1839 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreHce, Status = %r\n", Status));
1840 return Status;
1841 }
1842 }
1843
1844 //
1845 // UFS 2.0 spec section 7.1.1 - Host Controller Initialization
1846 //
1847 // Reinitialize the UFS host controller if HCE bit of HC register is set.
1848 //
1849 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
1850 if (EFI_ERROR (Status)) {
1851 return Status;
1852 }
1853
1854 if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
1855 //
1856 // Write a 0 to the HCE register at first to disable the host controller.
1857 //
1858 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
1859 if (EFI_ERROR (Status)) {
1860 return Status;
1861 }
1862 //
1863 // Wait until HCE is read as '0' before continuing.
1864 //
1865 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
1866 if (EFI_ERROR (Status)) {
1867 return EFI_DEVICE_ERROR;
1868 }
1869 }
1870
1871 //
1872 // Write a 1 to the HCE register to enable the UFS host controller.
1873 //
1874 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
1875 if (EFI_ERROR (Status)) {
1876 return Status;
1877 }
1878
1879 //
1880 // Wait until HCE is read as '1' before continuing.
1881 //
1882 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
1883 if (EFI_ERROR (Status)) {
1884 return EFI_DEVICE_ERROR;
1885 }
1886
1887 if (mUfsHcPlatform != NULL && mUfsHcPlatform->Callback != NULL) {
1888 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPostHce, &Private->UfsHcDriverInterface);
1889 if (EFI_ERROR (Status)) {
1890 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostHce, Status = %r\n", Status));
1891 return Status;
1892 }
1893 }
1894
1895 return EFI_SUCCESS;
1896 }
1897
1898 /**
1899 Detect if a UFS device attached.
1900
1901 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1902
1903 @retval EFI_SUCCESS The UFS device detection was executed successfully.
1904 @retval EFI_NOT_FOUND Not found a UFS device attached.
1905 @retval EFI_DEVICE_ERROR A device error occurred while detecting the UFS device.
1906
1907 **/
1908 EFI_STATUS
1909 UfsDeviceDetection (
1910 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1911 )
1912 {
1913 UINTN Retry;
1914 EFI_STATUS Status;
1915 UINT32 Data;
1916 EDKII_UIC_COMMAND LinkStartupCommand;
1917
1918 if (mUfsHcPlatform != NULL && mUfsHcPlatform->Callback != NULL) {
1919 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPreLinkStartup, &Private->UfsHcDriverInterface);
1920 if (EFI_ERROR (Status)) {
1921 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreLinkStartup, Status = %r\n", Status));
1922 return Status;
1923 }
1924 }
1925
1926 //
1927 // Start UFS device detection.
1928 // Try up to 3 times for establishing data link with device.
1929 //
1930 for (Retry = 0; Retry < 3; Retry++) {
1931 LinkStartupCommand.Opcode = UfsUicDmeLinkStartup;
1932 LinkStartupCommand.Arg1 = 0;
1933 LinkStartupCommand.Arg2 = 0;
1934 LinkStartupCommand.Arg3 = 0;
1935 Status = UfsExecUicCommands (Private, &LinkStartupCommand);
1936 if (EFI_ERROR (Status)) {
1937 return EFI_DEVICE_ERROR;
1938 }
1939
1940 Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
1941 if (EFI_ERROR (Status)) {
1942 return EFI_DEVICE_ERROR;
1943 }
1944
1945 if ((Data & UFS_HC_HCS_DP) == 0) {
1946 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
1947 if (EFI_ERROR (Status)) {
1948 return EFI_DEVICE_ERROR;
1949 }
1950 } else {
1951 if (mUfsHcPlatform != NULL && mUfsHcPlatform->Callback != NULL) {
1952 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPostLinkStartup, &Private->UfsHcDriverInterface);
1953 if (EFI_ERROR (Status)) {
1954 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostLinkStartup, Status = %r\n", Status));
1955 return Status;
1956 }
1957 }
1958 return EFI_SUCCESS;
1959 }
1960 }
1961
1962 return EFI_NOT_FOUND;
1963 }
1964
1965 /**
1966 Initialize UFS task management request list related h/w context.
1967
1968 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1969
1970 @retval EFI_SUCCESS The UFS task management list was initialzed successfully.
1971 @retval EFI_DEVICE_ERROR The initialization fails.
1972
1973 **/
1974 EFI_STATUS
1975 UfsInitTaskManagementRequestList (
1976 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1977 )
1978 {
1979 UINT8 Nutmrs;
1980 VOID *CmdDescHost;
1981 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
1982 VOID *CmdDescMapping;
1983 EFI_STATUS Status;
1984
1985 //
1986 // Initial h/w and s/w context for future operations.
1987 //
1988 CmdDescHost = NULL;
1989 CmdDescMapping = NULL;
1990 CmdDescPhyAddr = 0;
1991
1992 //
1993 // Allocate and initialize UTP Task Management Request List.
1994 //
1995 Nutmrs = (UINT8) (RShiftU64 ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);
1996 Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
1997 if (EFI_ERROR (Status)) {
1998 return Status;
1999 }
2000
2001 //
2002 // Program the UTP Task Management Request List Base Address and UTP Task Management
2003 // Request List Base Address with a 64-bit address allocated at step 6.
2004 //
2005 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2006 if (EFI_ERROR (Status)) {
2007 return Status;
2008 }
2009
2010 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2011 if (EFI_ERROR (Status)) {
2012 return Status;
2013 }
2014 Private->UtpTmrlBase = CmdDescHost;
2015 Private->Nutmrs = Nutmrs;
2016 Private->TmrlMapping = CmdDescMapping;
2017
2018 //
2019 // Enable the UTP Task Management Request List by setting the UTP Task Management
2020 // Request List RunStop Register (UTMRLRSR) to '1'.
2021 //
2022 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
2023 if (EFI_ERROR (Status)) {
2024 return Status;
2025 }
2026
2027 return EFI_SUCCESS;
2028 }
2029
2030 /**
2031 Initialize UFS transfer request list related h/w context.
2032
2033 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2034
2035 @retval EFI_SUCCESS The UFS transfer list was initialzed successfully.
2036 @retval EFI_DEVICE_ERROR The initialization fails.
2037
2038 **/
2039 EFI_STATUS
2040 UfsInitTransferRequestList (
2041 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2042 )
2043 {
2044 UINT8 Nutrs;
2045 VOID *CmdDescHost;
2046 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
2047 VOID *CmdDescMapping;
2048 EFI_STATUS Status;
2049
2050 //
2051 // Initial h/w and s/w context for future operations.
2052 //
2053 CmdDescHost = NULL;
2054 CmdDescMapping = NULL;
2055 CmdDescPhyAddr = 0;
2056
2057 //
2058 // Allocate and initialize UTP Transfer Request List.
2059 //
2060 Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);
2061 Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
2062 if (EFI_ERROR (Status)) {
2063 return Status;
2064 }
2065
2066 //
2067 // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
2068 // Base Address with a 64-bit address allocated at step 8.
2069 //
2070 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2071 if (EFI_ERROR (Status)) {
2072 return Status;
2073 }
2074
2075 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2076 if (EFI_ERROR (Status)) {
2077 return Status;
2078 }
2079
2080 Private->UtpTrlBase = CmdDescHost;
2081 Private->Nutrs = Nutrs;
2082 Private->TrlMapping = CmdDescMapping;
2083
2084 //
2085 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2086 // RunStop Register (UTRLRSR) to '1'.
2087 //
2088 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
2089 if (EFI_ERROR (Status)) {
2090 return Status;
2091 }
2092
2093 return EFI_SUCCESS;
2094 }
2095
2096 /**
2097 Initialize the UFS host controller.
2098
2099 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2100
2101 @retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
2102 @retval Others A device error occurred while initializing the controller.
2103
2104 **/
2105 EFI_STATUS
2106 UfsControllerInit (
2107 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2108 )
2109 {
2110 EFI_STATUS Status;
2111
2112 Status = UfsEnableHostController (Private);
2113 if (EFI_ERROR (Status)) {
2114 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));
2115 return Status;
2116 }
2117
2118 Status = UfsDeviceDetection (Private);
2119 if (EFI_ERROR (Status)) {
2120 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));
2121 return Status;
2122 }
2123
2124 Status = UfsInitTaskManagementRequestList (Private);
2125 if (EFI_ERROR (Status)) {
2126 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));
2127 return Status;
2128 }
2129
2130 Status = UfsInitTransferRequestList (Private);
2131 if (EFI_ERROR (Status)) {
2132 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));
2133 return Status;
2134 }
2135
2136 DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));
2137 return EFI_SUCCESS;
2138 }
2139
2140 /**
2141 Stop the UFS host controller.
2142
2143 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2144
2145 @retval EFI_SUCCESS The Ufs Host Controller is stopped successfully.
2146 @retval Others A device error occurred while stopping the controller.
2147
2148 **/
2149 EFI_STATUS
2150 UfsControllerStop (
2151 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2152 )
2153 {
2154 EFI_STATUS Status;
2155 UINT32 Data;
2156
2157 //
2158 // Enable the UTP Task Management Request List by setting the UTP Task Management
2159 // Request List RunStop Register (UTMRLRSR) to '1'.
2160 //
2161 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
2162 if (EFI_ERROR (Status)) {
2163 return Status;
2164 }
2165
2166 //
2167 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2168 // RunStop Register (UTRLRSR) to '1'.
2169 //
2170 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
2171 if (EFI_ERROR (Status)) {
2172 return Status;
2173 }
2174
2175 //
2176 // Write a 0 to the HCE register in order to disable the host controller.
2177 //
2178 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
2179 if (EFI_ERROR (Status)) {
2180 return Status;
2181 }
2182 ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
2183
2184 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
2185 if (EFI_ERROR (Status)) {
2186 return Status;
2187 }
2188
2189 //
2190 // Wait until HCE is read as '0' before continuing.
2191 //
2192 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
2193 if (EFI_ERROR (Status)) {
2194 return EFI_DEVICE_ERROR;
2195 }
2196
2197 DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));
2198
2199 return EFI_SUCCESS;
2200 }
2201
2202 /**
2203 Internal helper function which will signal the caller event and clean up
2204 resources.
2205
2206 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data
2207 structure.
2208 @param[in] TransReq The pointer to the UFS_PASS_THRU_TRANS_REQ data
2209 structure.
2210
2211 **/
2212 VOID
2213 EFIAPI
2214 SignalCallerEvent (
2215 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
2216 IN UFS_PASS_THRU_TRANS_REQ *TransReq
2217 )
2218 {
2219 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
2220 EFI_EVENT CallerEvent;
2221
2222 ASSERT ((Private != NULL) && (TransReq != NULL));
2223
2224 UfsHc = Private->UfsHostController;
2225 CallerEvent = TransReq->CallerEvent;
2226
2227 RemoveEntryList (&TransReq->TransferList);
2228
2229 UfsHc->Flush (UfsHc);
2230
2231 UfsStopExecCmd (Private, TransReq->Slot);
2232
2233 UfsReconcileDataTransferBuffer (Private, TransReq);
2234
2235 if (TransReq->CmdDescMapping != NULL) {
2236 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
2237 }
2238 if (TransReq->CmdDescHost != NULL) {
2239 UfsHc->FreeBuffer (
2240 UfsHc,
2241 EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),
2242 TransReq->CmdDescHost
2243 );
2244 }
2245
2246 FreePool (TransReq);
2247
2248 gBS->SignalEvent (CallerEvent);
2249 return;
2250 }
2251
2252 /**
2253 Call back function when the timer event is signaled.
2254
2255 @param[in] Event The Event this notify function registered to.
2256 @param[in] Context Pointer to the context data registered to the Event.
2257
2258 **/
2259 VOID
2260 EFIAPI
2261 ProcessAsyncTaskList (
2262 IN EFI_EVENT Event,
2263 IN VOID *Context
2264 )
2265 {
2266 UFS_PASS_THRU_PRIVATE_DATA *Private;
2267 LIST_ENTRY *Entry;
2268 LIST_ENTRY *NextEntry;
2269 UFS_PASS_THRU_TRANS_REQ *TransReq;
2270 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet;
2271 UTP_RESPONSE_UPIU *Response;
2272 UINT16 SenseDataLen;
2273 UINT32 ResTranCount;
2274 UINT32 SlotsMap;
2275 UINT32 Value;
2276 EFI_STATUS Status;
2277
2278 Private = (UFS_PASS_THRU_PRIVATE_DATA*) Context;
2279 SlotsMap = 0;
2280
2281 //
2282 // Check the entries in the async I/O queue are done or not.
2283 //
2284 if (!IsListEmpty(&Private->Queue)) {
2285 EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
2286 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
2287 Packet = TransReq->Packet;
2288
2289 if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {
2290 return;
2291 }
2292 SlotsMap |= BIT0 << TransReq->Slot;
2293
2294 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);
2295 if (EFI_ERROR (Status)) {
2296 //
2297 // TODO: Should find/add a proper host adapter return status for this
2298 // case.
2299 //
2300 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
2301 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));
2302 SignalCallerEvent (Private, TransReq);
2303 continue;
2304 }
2305
2306 if ((Value & (BIT0 << TransReq->Slot)) != 0) {
2307 //
2308 // Scsi cmd not finished yet.
2309 //
2310 if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {
2311 TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;
2312 continue;
2313 } else {
2314 //
2315 // Timeout occurs.
2316 //
2317 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
2318 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));
2319 SignalCallerEvent (Private, TransReq);
2320 continue;
2321 }
2322 } else {
2323 //
2324 // Scsi cmd finished.
2325 //
2326 // Get sense data if exists
2327 //
2328 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
2329 ASSERT (Response != NULL);
2330 SenseDataLen = Response->SenseDataLen;
2331 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
2332
2333 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
2334 //
2335 // Make sure the hardware device does not return more data than expected.
2336 //
2337 if (SenseDataLen <= Packet->SenseDataLength) {
2338 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
2339 Packet->SenseDataLength = (UINT8)SenseDataLen;
2340 } else {
2341 Packet->SenseDataLength = 0;
2342 }
2343 }
2344
2345 //
2346 // Check the transfer request result.
2347 //
2348 Packet->TargetStatus = Response->Status;
2349 if (Response->Response != 0) {
2350 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));
2351 SignalCallerEvent (Private, TransReq);
2352 continue;
2353 }
2354
2355 if (TransReq->Trd->Ocs == 0) {
2356 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
2357 if ((Response->Flags & BIT5) == BIT5) {
2358 ResTranCount = Response->ResTranCount;
2359 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2360 Packet->InTransferLength -= ResTranCount;
2361 }
2362 } else {
2363 if ((Response->Flags & BIT5) == BIT5) {
2364 ResTranCount = Response->ResTranCount;
2365 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2366 Packet->OutTransferLength -= ResTranCount;
2367 }
2368 }
2369 } else {
2370 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));
2371 SignalCallerEvent (Private, TransReq);
2372 continue;
2373 }
2374
2375 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));
2376 SignalCallerEvent (Private, TransReq);
2377 }
2378 }
2379 }
2380 }
2381
2382 /**
2383 Execute UIC command.
2384
2385 @param[in] This Pointer to driver interface produced by the UFS controller.
2386 @param[in, out] UicCommand Descriptor of the command that will be executed.
2387
2388 @retval EFI_SUCCESS Command executed successfully.
2389 @retval EFI_INVALID_PARAMETER This or UicCommand is NULL.
2390 @retval Others Command failed to execute.
2391 **/
2392 EFI_STATUS
2393 EFIAPI
2394 UfsHcDriverInterfaceExecUicCommand (
2395 IN EDKII_UFS_HC_DRIVER_INTERFACE *This,
2396 IN OUT EDKII_UIC_COMMAND *UicCommand
2397 )
2398 {
2399 UFS_PASS_THRU_PRIVATE_DATA *Private;
2400
2401 if (This == NULL || UicCommand == NULL) {
2402 return EFI_INVALID_PARAMETER;
2403 }
2404
2405 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DRIVER_INTF (This);
2406
2407 return UfsExecUicCommands (Private, UicCommand);
2408 }
2409
2410 /**
2411 Initializes UfsHcInfo field in private data.
2412
2413 @param[in] Private Pointer to host controller private data.
2414
2415 @retval EFI_SUCCESS UfsHcInfo initialized successfully.
2416 @retval Others Failed to initalize UfsHcInfo.
2417 **/
2418 EFI_STATUS
2419 GetUfsHcInfo (
2420 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2421 )
2422 {
2423 UINT32 Data;
2424 EFI_STATUS Status;
2425
2426 Status = UfsMmioRead32 (Private, UFS_HC_VER_OFFSET, &Data);
2427 if (EFI_ERROR (Status)) {
2428 return Status;
2429 }
2430
2431 Private->UfsHcInfo.Version = Data;
2432
2433 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
2434 if (EFI_ERROR (Status)) {
2435 return Status;
2436 }
2437
2438 Private->UfsHcInfo.Capabilities = Data;
2439
2440 if (mUfsHcPlatform != NULL && mUfsHcPlatform->OverrideHcInfo != NULL) {
2441 Status = mUfsHcPlatform->OverrideHcInfo (Private->Handle, &Private->UfsHcInfo);
2442 if (EFI_ERROR (Status)) {
2443 DEBUG ((DEBUG_ERROR, "Failure from platform on OverrideHcInfo, Status = %r\n", Status));
2444 return Status;
2445 }
2446 }
2447
2448 return EFI_SUCCESS;
2449 }
2450