]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
6ea27e473cc72386c23fbeb971bade177ff93b62
[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->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
1207 /**
1208 Read specified flag from a UFS device.
1209
1210 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1211 @param[in] FlagId The ID of flag to be read.
1212 @param[out] Value The flag's value.
1213
1214 @retval EFI_SUCCESS The flag was read successfully.
1215 @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
1216 @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
1217
1218 **/
1219 EFI_STATUS
1220 UfsReadFlag (
1221 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1222 IN UINT8 FlagId,
1223 OUT UINT8 *Value
1224 )
1225 {
1226 EFI_STATUS Status;
1227
1228 Status = UfsRwFlags (Private, TRUE, FlagId, Value);
1229
1230 return Status;
1231 }
1232
1233 /**
1234 Sends NOP IN cmd to a UFS device for initialization process request.
1235 For more details, please refer to UFS 2.0 spec Figure 13.3.
1236
1237 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1238
1239 @retval EFI_SUCCESS The NOP IN command was sent by the host. The NOP OUT response was
1240 received successfully.
1241 @retval EFI_DEVICE_ERROR A device error occurred while attempting to execute NOP IN command.
1242 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1243 @retval EFI_TIMEOUT A timeout occurred while waiting for the NOP IN command to execute.
1244
1245 **/
1246 EFI_STATUS
1247 UfsExecNopCmds (
1248 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1249 )
1250 {
1251 EFI_STATUS Status;
1252 UINT8 Slot;
1253 UTP_TRD *Trd;
1254 UTP_NOP_IN_UPIU *NopInUpiu;
1255 UINT32 CmdDescSize;
1256 VOID *CmdDescHost;
1257 VOID *CmdDescMapping;
1258 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1259
1260 //
1261 // Find out which slot of transfer request list is available.
1262 //
1263 Status = UfsFindAvailableSlotInTrl (Private, &Slot);
1264 if (EFI_ERROR (Status)) {
1265 return Status;
1266 }
1267
1268 Trd = ((UTP_TRD*)Private->UtpTrlBase) + Slot;
1269 Status = UfsCreateNopCommandDesc (Private, Trd, &CmdDescHost, &CmdDescMapping);
1270 if (EFI_ERROR (Status)) {
1271 return Status;
1272 }
1273
1274 //
1275 // Check the transfer request result.
1276 //
1277 UfsHc = Private->UfsHostController;
1278 NopInUpiu = (UTP_NOP_IN_UPIU*)((UINT8*)CmdDescHost + Trd->RuO * sizeof (UINT32));
1279 ASSERT (NopInUpiu != NULL);
1280 CmdDescSize = Trd->RuO * sizeof (UINT32) + Trd->RuL * sizeof (UINT32);
1281
1282 //
1283 // Start to execute the transfer request.
1284 //
1285 UfsStartExecCmd (Private, Slot);
1286
1287 //
1288 // Wait for the completion of the transfer request.
1289 //
1290 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << Slot, 0, UFS_TIMEOUT);
1291 if (EFI_ERROR (Status)) {
1292 goto Exit;
1293 }
1294
1295 if (NopInUpiu->Resp != 0) {
1296 Status = EFI_DEVICE_ERROR;
1297 } else {
1298 Status = EFI_SUCCESS;
1299 }
1300
1301 Exit:
1302 UfsHc->Flush (UfsHc);
1303
1304 UfsStopExecCmd (Private, Slot);
1305
1306 if (CmdDescMapping != NULL) {
1307 UfsHc->Unmap (UfsHc, CmdDescMapping);
1308 }
1309 if (CmdDescHost != NULL) {
1310 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (CmdDescSize), CmdDescHost);
1311 }
1312
1313 return Status;
1314 }
1315
1316 /**
1317 Cleanup data buffers after data transfer. This function
1318 also takes care to copy all data to user memory pool for
1319 unaligned data transfers.
1320
1321 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1322 @param[in] TransReq Pointer to the transfer request
1323 **/
1324 VOID
1325 UfsReconcileDataTransferBuffer (
1326 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1327 IN UFS_PASS_THRU_TRANS_REQ *TransReq
1328 )
1329 {
1330 if (TransReq->DataBufMapping != NULL) {
1331 Private->UfsHostController->Unmap (
1332 Private->UfsHostController,
1333 TransReq->DataBufMapping
1334 );
1335 }
1336
1337 //
1338 // Check if unaligned transfer was performed. If it was and we read
1339 // data from device copy memory to user data buffers before cleanup.
1340 // The assumption is if auxiliary aligned data buffer is not NULL then
1341 // unaligned transfer has been performed.
1342 //
1343 if (TransReq->AlignedDataBuf != NULL) {
1344 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1345 CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);
1346 }
1347 //
1348 // Wipe out the transfer buffer in case it contains sensitive data.
1349 //
1350 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1351 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1352 TransReq->AlignedDataBuf = NULL;
1353 }
1354 }
1355
1356 /**
1357 Prepare data buffer for transfer.
1358
1359 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA
1360 @param[in, out] TransReq Pointer to the transfer request
1361
1362 @retval EFI_DEVICE_ERROR Failed to prepare buffer for transfer
1363 @retval EFI_SUCCESS Buffer ready for transfer
1364 **/
1365 EFI_STATUS
1366 UfsPrepareDataTransferBuffer (
1367 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1368 IN OUT UFS_PASS_THRU_TRANS_REQ *TransReq
1369 )
1370 {
1371 EFI_STATUS Status;
1372 VOID *DataBuf;
1373 UINT32 DataLen;
1374 UINTN MapLength;
1375 EFI_PHYSICAL_ADDRESS DataBufPhyAddr;
1376 EDKII_UFS_HOST_CONTROLLER_OPERATION Flag;
1377 UTP_TR_PRD *PrdtBase;
1378
1379 DataBufPhyAddr = 0;
1380 DataBuf = NULL;
1381
1382 //
1383 // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.
1384 // When command is finished auxiliary memory pool is copied into actual user memory.
1385 // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)
1386 //
1387 if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1388 if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {
1389 DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));
1390 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1391 if (DataBuf == NULL) {
1392 return EFI_DEVICE_ERROR;
1393 }
1394 ZeroMem (DataBuf, DataLen);
1395 TransReq->AlignedDataBuf = DataBuf;
1396 TransReq->AlignedDataBufSize = DataLen;
1397 } else {
1398 DataLen = TransReq->Packet->InTransferLength;
1399 DataBuf = TransReq->Packet->InDataBuffer;
1400 }
1401 Flag = EdkiiUfsHcOperationBusMasterWrite;
1402 } else {
1403 if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {
1404 DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));
1405 DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);
1406 if (DataBuf == NULL) {
1407 return EFI_DEVICE_ERROR;
1408 }
1409 CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);
1410 TransReq->AlignedDataBuf = DataBuf;
1411 TransReq->AlignedDataBufSize = DataLen;
1412 } else {
1413 DataLen = TransReq->Packet->OutTransferLength;
1414 DataBuf = TransReq->Packet->OutDataBuffer;
1415 }
1416 Flag = EdkiiUfsHcOperationBusMasterRead;
1417 }
1418
1419 if (DataLen != 0) {
1420 MapLength = DataLen;
1421 Status = Private->UfsHostController->Map (
1422 Private->UfsHostController,
1423 Flag,
1424 DataBuf,
1425 &MapLength,
1426 &DataBufPhyAddr,
1427 &TransReq->DataBufMapping
1428 );
1429
1430 if (EFI_ERROR (Status) || (DataLen != MapLength)) {
1431 if (TransReq->AlignedDataBuf != NULL) {
1432 //
1433 // Wipe out the transfer buffer in case it contains sensitive data.
1434 //
1435 ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);
1436 FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));
1437 TransReq->AlignedDataBuf = NULL;
1438 }
1439 return EFI_DEVICE_ERROR;
1440 }
1441 }
1442
1443 //
1444 // Fill PRDT table of Command UPIU for executed SCSI cmd.
1445 //
1446 PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));
1447 ASSERT (PrdtBase != NULL);
1448 UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);
1449
1450 return EFI_SUCCESS;
1451 }
1452
1453 /**
1454 Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
1455
1456 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1457 @param[in] Lun The LUN of the UFS device to send the SCSI Request Packet.
1458 @param[in, out] Packet A pointer to the SCSI Request Packet to send to a specified Lun of the
1459 UFS device.
1460 @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking
1461 I/O is performed. If Event is NULL, then blocking I/O is performed. If
1462 Event is not NULL and non blocking I/O is supported, then
1463 nonblocking I/O is performed, and Event will be signaled when the
1464 SCSI Request Packet completes.
1465
1466 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
1467 commands, InTransferLength bytes were transferred from
1468 InDataBuffer. For write and bi-directional commands,
1469 OutTransferLength bytes were transferred by
1470 OutDataBuffer.
1471 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
1472 Packet.
1473 @retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
1474 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
1475
1476 **/
1477 EFI_STATUS
1478 UfsExecScsiCmds (
1479 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1480 IN UINT8 Lun,
1481 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
1482 IN EFI_EVENT Event OPTIONAL
1483 )
1484 {
1485 EFI_STATUS Status;
1486 UTP_RESPONSE_UPIU *Response;
1487 UINT16 SenseDataLen;
1488 UINT32 ResTranCount;
1489 EFI_TPL OldTpl;
1490 UFS_PASS_THRU_TRANS_REQ *TransReq;
1491 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1492
1493 TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));
1494 if (TransReq == NULL) {
1495 return EFI_OUT_OF_RESOURCES;
1496 }
1497
1498 TransReq->Signature = UFS_PASS_THRU_TRANS_REQ_SIG;
1499 TransReq->TimeoutRemain = Packet->Timeout;
1500 TransReq->Packet = Packet;
1501
1502 UfsHc = Private->UfsHostController;
1503 //
1504 // Find out which slot of transfer request list is available.
1505 //
1506 Status = UfsFindAvailableSlotInTrl (Private, &TransReq->Slot);
1507 if (EFI_ERROR (Status)) {
1508 return Status;
1509 }
1510
1511 TransReq->Trd = ((UTP_TRD*)Private->UtpTrlBase) + TransReq->Slot;
1512
1513 //
1514 // Fill transfer request descriptor to this slot.
1515 //
1516 Status = UfsCreateScsiCommandDesc (
1517 Private,
1518 Lun,
1519 Packet,
1520 TransReq->Trd,
1521 &TransReq->CmdDescHost,
1522 &TransReq->CmdDescMapping
1523 );
1524 if (EFI_ERROR (Status)) {
1525 return Status;
1526 }
1527
1528 TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);
1529
1530 Status = UfsPrepareDataTransferBuffer (Private, TransReq);
1531 if (EFI_ERROR (Status)) {
1532 goto Exit1;
1533 }
1534
1535 //
1536 // Insert the async SCSI cmd to the Async I/O list
1537 //
1538 if (Event != NULL) {
1539 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1540 TransReq->CallerEvent = Event;
1541 InsertTailList (&Private->Queue, &TransReq->TransferList);
1542 gBS->RestoreTPL (OldTpl);
1543 }
1544
1545 //
1546 // Start to execute the transfer request.
1547 //
1548 UfsStartExecCmd (Private, TransReq->Slot);
1549
1550 //
1551 // Immediately return for async I/O.
1552 //
1553 if (Event != NULL) {
1554 return EFI_SUCCESS;
1555 }
1556
1557 //
1558 // Wait for the completion of the transfer request.
1559 //
1560 Status = UfsWaitMemSet (Private, UFS_HC_UTRLDBR_OFFSET, BIT0 << TransReq->Slot, 0, Packet->Timeout);
1561 if (EFI_ERROR (Status)) {
1562 goto Exit;
1563 }
1564
1565 //
1566 // Get sense data if exists
1567 //
1568 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
1569 ASSERT (Response != NULL);
1570 SenseDataLen = Response->SenseDataLen;
1571 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
1572
1573 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
1574 //
1575 // Make sure the hardware device does not return more data than expected.
1576 //
1577 if (SenseDataLen <= Packet->SenseDataLength) {
1578 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
1579 Packet->SenseDataLength = (UINT8)SenseDataLen;
1580 } else {
1581 Packet->SenseDataLength = 0;
1582 }
1583 }
1584
1585 //
1586 // Check the transfer request result.
1587 //
1588 Packet->TargetStatus = Response->Status;
1589 if (Response->Response != 0) {
1590 DEBUG ((DEBUG_ERROR, "UfsExecScsiCmds() fails with Target Failure\n"));
1591 Status = EFI_DEVICE_ERROR;
1592 goto Exit;
1593 }
1594
1595 if (TransReq->Trd->Ocs == 0) {
1596 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1597 if ((Response->Flags & BIT5) == BIT5) {
1598 ResTranCount = Response->ResTranCount;
1599 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1600 Packet->InTransferLength -= ResTranCount;
1601 }
1602 } else {
1603 if ((Response->Flags & BIT5) == BIT5) {
1604 ResTranCount = Response->ResTranCount;
1605 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
1606 Packet->OutTransferLength -= ResTranCount;
1607 }
1608 }
1609 } else {
1610 Status = EFI_DEVICE_ERROR;
1611 }
1612
1613 Exit:
1614 UfsHc->Flush (UfsHc);
1615
1616 UfsStopExecCmd (Private, TransReq->Slot);
1617
1618 UfsReconcileDataTransferBuffer (Private, TransReq);
1619
1620 Exit1:
1621 if (TransReq->CmdDescMapping != NULL) {
1622 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
1623 }
1624 if (TransReq->CmdDescHost != NULL) {
1625 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (TransReq->CmdDescSize), TransReq->CmdDescHost);
1626 }
1627 if (TransReq != NULL) {
1628 FreePool (TransReq);
1629 }
1630 return Status;
1631 }
1632
1633 /**
1634 Send UIC command.
1635
1636 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1637 @param[in, out] UicCommand UIC command descriptor. On exit contains UIC command results.
1638
1639 @return EFI_SUCCESS Successfully execute this UIC command and detect attached UFS device.
1640 @return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.
1641
1642 **/
1643 EFI_STATUS
1644 UfsExecUicCommands (
1645 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1646 IN OUT EDKII_UIC_COMMAND *UicCommand
1647 )
1648 {
1649 EFI_STATUS Status;
1650 UINT32 Data;
1651
1652 Status = UfsMmioRead32 (Private, UFS_HC_IS_OFFSET, &Data);
1653 if (EFI_ERROR (Status)) {
1654 return Status;
1655 }
1656
1657 if ((Data & UFS_HC_IS_UCCS) == UFS_HC_IS_UCCS) {
1658 //
1659 // Clear IS.BIT10 UIC Command Completion Status (UCCS) at first.
1660 //
1661 Status = UfsMmioWrite32 (Private, UFS_HC_IS_OFFSET, Data);
1662 if (EFI_ERROR (Status)) {
1663 return Status;
1664 }
1665 }
1666
1667 //
1668 // When programming UIC command registers, host software shall set the register UICCMD
1669 // only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)
1670 // are set.
1671 //
1672 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, UicCommand->Arg1);
1673 if (EFI_ERROR (Status)) {
1674 return Status;
1675 }
1676
1677 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, UicCommand->Arg2);
1678 if (EFI_ERROR (Status)) {
1679 return Status;
1680 }
1681
1682 Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, UicCommand->Arg3);
1683 if (EFI_ERROR (Status)) {
1684 return Status;
1685 }
1686
1687 //
1688 // Host software shall only set the UICCMD if HCS.UCRDY is set to 1.
1689 //
1690 Status = UfsWaitMemSet (Private, UFS_HC_STATUS_OFFSET, UFS_HC_HCS_UCRDY, UFS_HC_HCS_UCRDY, UFS_TIMEOUT);
1691 if (EFI_ERROR (Status)) {
1692 return Status;
1693 }
1694
1695 Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, UicCommand->Opcode);
1696 if (EFI_ERROR (Status)) {
1697 return Status;
1698 }
1699
1700 //
1701 // UFS 2.0 spec section 5.3.1 Offset:0x20 IS.Bit10 UIC Command Completion Status (UCCS)
1702 // This bit is set to '1' by the host controller upon completion of a UIC command.
1703 //
1704 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_UCCS, UFS_HC_IS_UCCS, UFS_TIMEOUT);
1705 if (EFI_ERROR (Status)) {
1706 return Status;
1707 }
1708
1709 if (UicCommand->Opcode != UfsUicDmeReset) {
1710 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &UicCommand->Arg2);
1711 if (EFI_ERROR (Status)) {
1712 return Status;
1713 }
1714 Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG3_OFFSET, &UicCommand->Arg3);
1715 if (EFI_ERROR (Status)) {
1716 return Status;
1717 }
1718 if ((UicCommand->Arg2 & 0xFF) != 0) {
1719 DEBUG_CODE_BEGIN();
1720 DumpUicCmdExecResult ((UINT8)UicCommand->Opcode, (UINT8)(UicCommand->Arg2 & 0xFF));
1721 DEBUG_CODE_END();
1722 return EFI_DEVICE_ERROR;
1723 }
1724 }
1725
1726 return EFI_SUCCESS;
1727 }
1728
1729 /**
1730 Allocate common buffer for host and UFS bus master access simultaneously.
1731
1732 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1733 @param[in] Size The length of buffer to be allocated.
1734 @param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
1735 @param[out] CmdDescPhyAddr The resulting map address for the UFS bus master to use to access the hosts CmdDescHost.
1736 @param[out] CmdDescMapping A resulting value to pass to Unmap().
1737
1738 @retval EFI_SUCCESS The common buffer was allocated successfully.
1739 @retval EFI_DEVICE_ERROR The allocation fails.
1740 @retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
1741
1742 **/
1743 EFI_STATUS
1744 UfsAllocateAlignCommonBuffer (
1745 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
1746 IN UINTN Size,
1747 OUT VOID **CmdDescHost,
1748 OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr,
1749 OUT VOID **CmdDescMapping
1750 )
1751 {
1752 EFI_STATUS Status;
1753 UINTN Bytes;
1754 BOOLEAN Is32BitAddr;
1755 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1756
1757 if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {
1758 Is32BitAddr = FALSE;
1759 } else {
1760 Is32BitAddr = TRUE;
1761 }
1762
1763 UfsHc = Private->UfsHostController;
1764 Status = UfsHc->AllocateBuffer (
1765 UfsHc,
1766 AllocateAnyPages,
1767 EfiBootServicesData,
1768 EFI_SIZE_TO_PAGES (Size),
1769 CmdDescHost,
1770 0
1771 );
1772 if (EFI_ERROR (Status)) {
1773 *CmdDescMapping = NULL;
1774 *CmdDescHost = NULL;
1775 *CmdDescPhyAddr = 0;
1776 return EFI_OUT_OF_RESOURCES;
1777 }
1778
1779 Bytes = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size));
1780 Status = UfsHc->Map (
1781 UfsHc,
1782 EdkiiUfsHcOperationBusMasterCommonBuffer,
1783 *CmdDescHost,
1784 &Bytes,
1785 CmdDescPhyAddr,
1786 CmdDescMapping
1787 );
1788
1789 if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
1790 UfsHc->FreeBuffer (
1791 UfsHc,
1792 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1793 *CmdDescHost
1794 );
1795 *CmdDescHost = NULL;
1796 return EFI_OUT_OF_RESOURCES;
1797 }
1798
1799 if (Is32BitAddr && ((*CmdDescPhyAddr) > 0x100000000ULL)) {
1800 //
1801 // The UFS host controller doesn't support 64bit addressing, so should not get a >4G UFS bus master address.
1802 //
1803 UfsHc->Unmap (
1804 UfsHc,
1805 *CmdDescMapping
1806 );
1807 UfsHc->FreeBuffer (
1808 UfsHc,
1809 EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
1810 *CmdDescHost
1811 );
1812 *CmdDescMapping = NULL;
1813 *CmdDescHost = NULL;
1814 return EFI_DEVICE_ERROR;
1815 }
1816
1817 ZeroMem (*CmdDescHost, EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)));
1818 return EFI_SUCCESS;
1819 }
1820
1821 /**
1822 Enable the UFS host controller for accessing.
1823
1824 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1825
1826 @retval EFI_SUCCESS The UFS host controller enabling was executed successfully.
1827 @retval EFI_DEVICE_ERROR A device error occurred while enabling the UFS host controller.
1828
1829 **/
1830 EFI_STATUS
1831 UfsEnableHostController (
1832 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1833 )
1834 {
1835 EFI_STATUS Status;
1836 UINT32 Data;
1837
1838 //
1839 // UFS 2.0 spec section 7.1.1 - Host Controller Initialization
1840 //
1841 // Reinitialize the UFS host controller if HCE bit of HC register is set.
1842 //
1843 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
1844 if (EFI_ERROR (Status)) {
1845 return Status;
1846 }
1847
1848 if ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN) {
1849 //
1850 // Write a 0 to the HCE register at first to disable the host controller.
1851 //
1852 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
1853 if (EFI_ERROR (Status)) {
1854 return Status;
1855 }
1856 //
1857 // Wait until HCE is read as '0' before continuing.
1858 //
1859 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
1860 if (EFI_ERROR (Status)) {
1861 return EFI_DEVICE_ERROR;
1862 }
1863 }
1864
1865 //
1866 // Write a 1 to the HCE register to enable the UFS host controller.
1867 //
1868 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN);
1869 if (EFI_ERROR (Status)) {
1870 return Status;
1871 }
1872
1873 //
1874 // Wait until HCE is read as '1' before continuing.
1875 //
1876 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, UFS_HC_HCE_EN, UFS_TIMEOUT);
1877 if (EFI_ERROR (Status)) {
1878 return EFI_DEVICE_ERROR;
1879 }
1880
1881 return EFI_SUCCESS;
1882 }
1883
1884 /**
1885 Detect if a UFS device attached.
1886
1887 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1888
1889 @retval EFI_SUCCESS The UFS device detection was executed successfully.
1890 @retval EFI_NOT_FOUND Not found a UFS device attached.
1891 @retval EFI_DEVICE_ERROR A device error occurred while detecting the UFS device.
1892
1893 **/
1894 EFI_STATUS
1895 UfsDeviceDetection (
1896 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1897 )
1898 {
1899 UINTN Retry;
1900 EFI_STATUS Status;
1901 UINT32 Data;
1902 EDKII_UIC_COMMAND LinkStartupCommand;
1903
1904 //
1905 // Start UFS device detection.
1906 // Try up to 3 times for establishing data link with device.
1907 //
1908 for (Retry = 0; Retry < 3; Retry++) {
1909 LinkStartupCommand.Opcode = UfsUicDmeLinkStartup;
1910 LinkStartupCommand.Arg1 = 0;
1911 LinkStartupCommand.Arg2 = 0;
1912 LinkStartupCommand.Arg3 = 0;
1913 Status = UfsExecUicCommands (Private, &LinkStartupCommand);
1914 if (EFI_ERROR (Status)) {
1915 return EFI_DEVICE_ERROR;
1916 }
1917
1918 Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);
1919 if (EFI_ERROR (Status)) {
1920 return EFI_DEVICE_ERROR;
1921 }
1922
1923 if ((Data & UFS_HC_HCS_DP) == 0) {
1924 Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);
1925 if (EFI_ERROR (Status)) {
1926 return EFI_DEVICE_ERROR;
1927 }
1928 } else {
1929 return EFI_SUCCESS;
1930 }
1931 }
1932
1933 return EFI_NOT_FOUND;
1934 }
1935
1936 /**
1937 Initialize UFS task management request list related h/w context.
1938
1939 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
1940
1941 @retval EFI_SUCCESS The UFS task management list was initialzed successfully.
1942 @retval EFI_DEVICE_ERROR The initialization fails.
1943
1944 **/
1945 EFI_STATUS
1946 UfsInitTaskManagementRequestList (
1947 IN UFS_PASS_THRU_PRIVATE_DATA *Private
1948 )
1949 {
1950 UINT32 Data;
1951 UINT8 Nutmrs;
1952 VOID *CmdDescHost;
1953 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
1954 VOID *CmdDescMapping;
1955 EFI_STATUS Status;
1956
1957 //
1958 // Initial h/w and s/w context for future operations.
1959 //
1960 CmdDescHost = NULL;
1961 CmdDescMapping = NULL;
1962 CmdDescPhyAddr = 0;
1963
1964 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
1965 if (EFI_ERROR (Status)) {
1966 return Status;
1967 }
1968
1969 Private->Capabilities = Data;
1970
1971 //
1972 // Allocate and initialize UTP Task Management Request List.
1973 //
1974 Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);
1975 Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
1976 if (EFI_ERROR (Status)) {
1977 return Status;
1978 }
1979
1980 //
1981 // Program the UTP Task Management Request List Base Address and UTP Task Management
1982 // Request List Base Address with a 64-bit address allocated at step 6.
1983 //
1984 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
1985 if (EFI_ERROR (Status)) {
1986 return Status;
1987 }
1988
1989 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
1990 if (EFI_ERROR (Status)) {
1991 return Status;
1992 }
1993 Private->UtpTmrlBase = CmdDescHost;
1994 Private->Nutmrs = Nutmrs;
1995 Private->TmrlMapping = CmdDescMapping;
1996
1997 //
1998 // Enable the UTP Task Management Request List by setting the UTP Task Management
1999 // Request List RunStop Register (UTMRLRSR) to '1'.
2000 //
2001 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, UFS_HC_UTMRLRSR);
2002 if (EFI_ERROR (Status)) {
2003 return Status;
2004 }
2005
2006 return EFI_SUCCESS;
2007 }
2008
2009 /**
2010 Initialize UFS transfer request list related h/w context.
2011
2012 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2013
2014 @retval EFI_SUCCESS The UFS transfer list was initialzed successfully.
2015 @retval EFI_DEVICE_ERROR The initialization fails.
2016
2017 **/
2018 EFI_STATUS
2019 UfsInitTransferRequestList (
2020 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2021 )
2022 {
2023 UINT32 Data;
2024 UINT8 Nutrs;
2025 VOID *CmdDescHost;
2026 EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;
2027 VOID *CmdDescMapping;
2028 EFI_STATUS Status;
2029
2030 //
2031 // Initial h/w and s/w context for future operations.
2032 //
2033 CmdDescHost = NULL;
2034 CmdDescMapping = NULL;
2035 CmdDescPhyAddr = 0;
2036
2037 Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);
2038 if (EFI_ERROR (Status)) {
2039 return Status;
2040 }
2041
2042 Private->Capabilities = Data;
2043
2044 //
2045 // Allocate and initialize UTP Transfer Request List.
2046 //
2047 Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);
2048 Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);
2049 if (EFI_ERROR (Status)) {
2050 return Status;
2051 }
2052
2053 //
2054 // Program the UTP Transfer Request List Base Address and UTP Transfer Request List
2055 // Base Address with a 64-bit address allocated at step 8.
2056 //
2057 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBA_OFFSET, (UINT32)(UINTN)CmdDescPhyAddr);
2058 if (EFI_ERROR (Status)) {
2059 return Status;
2060 }
2061
2062 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLBAU_OFFSET, (UINT32)RShiftU64 ((UINT64)CmdDescPhyAddr, 32));
2063 if (EFI_ERROR (Status)) {
2064 return Status;
2065 }
2066
2067 Private->UtpTrlBase = CmdDescHost;
2068 Private->Nutrs = Nutrs;
2069 Private->TrlMapping = CmdDescMapping;
2070
2071 //
2072 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2073 // RunStop Register (UTRLRSR) to '1'.
2074 //
2075 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, UFS_HC_UTRLRSR);
2076 if (EFI_ERROR (Status)) {
2077 return Status;
2078 }
2079
2080 return EFI_SUCCESS;
2081 }
2082
2083 /**
2084 Initialize the UFS host controller.
2085
2086 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2087
2088 @retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
2089 @retval Others A device error occurred while initializing the controller.
2090
2091 **/
2092 EFI_STATUS
2093 UfsControllerInit (
2094 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2095 )
2096 {
2097 EFI_STATUS Status;
2098
2099 Status = UfsEnableHostController (Private);
2100 if (EFI_ERROR (Status)) {
2101 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Enable Host Controller Fails, Status = %r\n", Status));
2102 return Status;
2103 }
2104
2105 Status = UfsDeviceDetection (Private);
2106 if (EFI_ERROR (Status)) {
2107 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Device Detection Fails, Status = %r\n", Status));
2108 return Status;
2109 }
2110
2111 Status = UfsInitTaskManagementRequestList (Private);
2112 if (EFI_ERROR (Status)) {
2113 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Task management list initialization Fails, Status = %r\n", Status));
2114 return Status;
2115 }
2116
2117 Status = UfsInitTransferRequestList (Private);
2118 if (EFI_ERROR (Status)) {
2119 DEBUG ((DEBUG_ERROR, "UfsControllerInit: Transfer list initialization Fails, Status = %r\n", Status));
2120 return Status;
2121 }
2122
2123 DEBUG ((DEBUG_INFO, "UfsControllerInit Finished\n"));
2124 return EFI_SUCCESS;
2125 }
2126
2127 /**
2128 Stop the UFS host controller.
2129
2130 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
2131
2132 @retval EFI_SUCCESS The Ufs Host Controller is stopped successfully.
2133 @retval Others A device error occurred while stopping the controller.
2134
2135 **/
2136 EFI_STATUS
2137 UfsControllerStop (
2138 IN UFS_PASS_THRU_PRIVATE_DATA *Private
2139 )
2140 {
2141 EFI_STATUS Status;
2142 UINT32 Data;
2143
2144 //
2145 // Enable the UTP Task Management Request List by setting the UTP Task Management
2146 // Request List RunStop Register (UTMRLRSR) to '1'.
2147 //
2148 Status = UfsMmioWrite32 (Private, UFS_HC_UTMRLRSR_OFFSET, 0);
2149 if (EFI_ERROR (Status)) {
2150 return Status;
2151 }
2152
2153 //
2154 // Enable the UTP Transfer Request List by setting the UTP Transfer Request List
2155 // RunStop Register (UTRLRSR) to '1'.
2156 //
2157 Status = UfsMmioWrite32 (Private, UFS_HC_UTRLRSR_OFFSET, 0);
2158 if (EFI_ERROR (Status)) {
2159 return Status;
2160 }
2161
2162 //
2163 // Write a 0 to the HCE register in order to disable the host controller.
2164 //
2165 Status = UfsMmioRead32 (Private, UFS_HC_ENABLE_OFFSET, &Data);
2166 if (EFI_ERROR (Status)) {
2167 return Status;
2168 }
2169 ASSERT ((Data & UFS_HC_HCE_EN) == UFS_HC_HCE_EN);
2170
2171 Status = UfsMmioWrite32 (Private, UFS_HC_ENABLE_OFFSET, 0);
2172 if (EFI_ERROR (Status)) {
2173 return Status;
2174 }
2175
2176 //
2177 // Wait until HCE is read as '0' before continuing.
2178 //
2179 Status = UfsWaitMemSet (Private, UFS_HC_ENABLE_OFFSET, UFS_HC_HCE_EN, 0, UFS_TIMEOUT);
2180 if (EFI_ERROR (Status)) {
2181 return EFI_DEVICE_ERROR;
2182 }
2183
2184 DEBUG ((DEBUG_INFO, "UfsController is stopped\n"));
2185
2186 return EFI_SUCCESS;
2187 }
2188
2189 /**
2190 Internal helper function which will signal the caller event and clean up
2191 resources.
2192
2193 @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data
2194 structure.
2195 @param[in] TransReq The pointer to the UFS_PASS_THRU_TRANS_REQ data
2196 structure.
2197
2198 **/
2199 VOID
2200 EFIAPI
2201 SignalCallerEvent (
2202 IN UFS_PASS_THRU_PRIVATE_DATA *Private,
2203 IN UFS_PASS_THRU_TRANS_REQ *TransReq
2204 )
2205 {
2206 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
2207 EFI_EVENT CallerEvent;
2208
2209 ASSERT ((Private != NULL) && (TransReq != NULL));
2210
2211 UfsHc = Private->UfsHostController;
2212 CallerEvent = TransReq->CallerEvent;
2213
2214 RemoveEntryList (&TransReq->TransferList);
2215
2216 UfsHc->Flush (UfsHc);
2217
2218 UfsStopExecCmd (Private, TransReq->Slot);
2219
2220 UfsReconcileDataTransferBuffer (Private, TransReq);
2221
2222 if (TransReq->CmdDescMapping != NULL) {
2223 UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);
2224 }
2225 if (TransReq->CmdDescHost != NULL) {
2226 UfsHc->FreeBuffer (
2227 UfsHc,
2228 EFI_SIZE_TO_PAGES (TransReq->CmdDescSize),
2229 TransReq->CmdDescHost
2230 );
2231 }
2232
2233 FreePool (TransReq);
2234
2235 gBS->SignalEvent (CallerEvent);
2236 return;
2237 }
2238
2239 /**
2240 Call back function when the timer event is signaled.
2241
2242 @param[in] Event The Event this notify function registered to.
2243 @param[in] Context Pointer to the context data registered to the Event.
2244
2245 **/
2246 VOID
2247 EFIAPI
2248 ProcessAsyncTaskList (
2249 IN EFI_EVENT Event,
2250 IN VOID *Context
2251 )
2252 {
2253 UFS_PASS_THRU_PRIVATE_DATA *Private;
2254 LIST_ENTRY *Entry;
2255 LIST_ENTRY *NextEntry;
2256 UFS_PASS_THRU_TRANS_REQ *TransReq;
2257 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet;
2258 UTP_RESPONSE_UPIU *Response;
2259 UINT16 SenseDataLen;
2260 UINT32 ResTranCount;
2261 UINT32 SlotsMap;
2262 UINT32 Value;
2263 EFI_STATUS Status;
2264
2265 Private = (UFS_PASS_THRU_PRIVATE_DATA*) Context;
2266 SlotsMap = 0;
2267
2268 //
2269 // Check the entries in the async I/O queue are done or not.
2270 //
2271 if (!IsListEmpty(&Private->Queue)) {
2272 EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
2273 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
2274 Packet = TransReq->Packet;
2275
2276 if ((SlotsMap & (BIT0 << TransReq->Slot)) != 0) {
2277 return;
2278 }
2279 SlotsMap |= BIT0 << TransReq->Slot;
2280
2281 Status = UfsMmioRead32 (Private, UFS_HC_UTRLDBR_OFFSET, &Value);
2282 if (EFI_ERROR (Status)) {
2283 //
2284 // TODO: Should find/add a proper host adapter return status for this
2285 // case.
2286 //
2287 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
2288 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p UfsMmioRead32() Error.\n", TransReq->CallerEvent));
2289 SignalCallerEvent (Private, TransReq);
2290 continue;
2291 }
2292
2293 if ((Value & (BIT0 << TransReq->Slot)) != 0) {
2294 //
2295 // Scsi cmd not finished yet.
2296 //
2297 if (TransReq->TimeoutRemain > UFS_HC_ASYNC_TIMER) {
2298 TransReq->TimeoutRemain -= UFS_HC_ASYNC_TIMER;
2299 continue;
2300 } else {
2301 //
2302 // Timeout occurs.
2303 //
2304 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
2305 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p EFI_TIMEOUT.\n", TransReq->CallerEvent));
2306 SignalCallerEvent (Private, TransReq);
2307 continue;
2308 }
2309 } else {
2310 //
2311 // Scsi cmd finished.
2312 //
2313 // Get sense data if exists
2314 //
2315 Response = (UTP_RESPONSE_UPIU*)((UINT8*)TransReq->CmdDescHost + TransReq->Trd->RuO * sizeof (UINT32));
2316 ASSERT (Response != NULL);
2317 SenseDataLen = Response->SenseDataLen;
2318 SwapLittleEndianToBigEndian ((UINT8*)&SenseDataLen, sizeof (UINT16));
2319
2320 if ((Packet->SenseDataLength != 0) && (Packet->SenseData != NULL)) {
2321 //
2322 // Make sure the hardware device does not return more data than expected.
2323 //
2324 if (SenseDataLen <= Packet->SenseDataLength) {
2325 CopyMem (Packet->SenseData, Response->SenseData, SenseDataLen);
2326 Packet->SenseDataLength = (UINT8)SenseDataLen;
2327 } else {
2328 Packet->SenseDataLength = 0;
2329 }
2330 }
2331
2332 //
2333 // Check the transfer request result.
2334 //
2335 Packet->TargetStatus = Response->Status;
2336 if (Response->Response != 0) {
2337 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Failure.\n", TransReq->CallerEvent));
2338 SignalCallerEvent (Private, TransReq);
2339 continue;
2340 }
2341
2342 if (TransReq->Trd->Ocs == 0) {
2343 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
2344 if ((Response->Flags & BIT5) == BIT5) {
2345 ResTranCount = Response->ResTranCount;
2346 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2347 Packet->InTransferLength -= ResTranCount;
2348 }
2349 } else {
2350 if ((Response->Flags & BIT5) == BIT5) {
2351 ResTranCount = Response->ResTranCount;
2352 SwapLittleEndianToBigEndian ((UINT8*)&ResTranCount, sizeof (UINT32));
2353 Packet->OutTransferLength -= ResTranCount;
2354 }
2355 }
2356 } else {
2357 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Target Device Error.\n", TransReq->CallerEvent));
2358 SignalCallerEvent (Private, TransReq);
2359 continue;
2360 }
2361
2362 DEBUG ((DEBUG_VERBOSE, "ProcessAsyncTaskList(): Signal Event %p Success.\n", TransReq->CallerEvent));
2363 SignalCallerEvent (Private, TransReq);
2364 }
2365 }
2366 }
2367 }
2368