]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsPassThruDxe / UfsPassThru.c
1 /** @file
2
3 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 **/
13
14 #include "UfsPassThru.h"
15
16 //
17 // Template for Ufs Pass Thru private data.
18 //
19 UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
20 UFS_PASS_THRU_SIG, // Signature
21 NULL, // Handle
22 { // ExtScsiPassThruMode
23 0xFFFFFFFF,
24 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
25 sizeof (UINTN)
26 },
27 { // ExtScsiPassThru
28 NULL,
29 UfsPassThruPassThru,
30 UfsPassThruGetNextTargetLun,
31 UfsPassThruBuildDevicePath,
32 UfsPassThruGetTargetLun,
33 UfsPassThruResetChannel,
34 UfsPassThruResetTargetLun,
35 UfsPassThruGetNextTarget
36 },
37 { // UfsDevConfig
38 UfsRwUfsDescriptor,
39 UfsRwUfsFlag,
40 UfsRwUfsAttribute
41 },
42 0, // UfsHostController
43 0, // UfsHcBase
44 0, // Capabilities
45 0, // TaskTag
46 0, // UtpTrlBase
47 0, // Nutrs
48 0, // TrlMapping
49 0, // UtpTmrlBase
50 0, // Nutmrs
51 0, // TmrlMapping
52 { // Luns
53 {
54 UFS_LUN_0, // Ufs Common Lun 0
55 UFS_LUN_1, // Ufs Common Lun 1
56 UFS_LUN_2, // Ufs Common Lun 2
57 UFS_LUN_3, // Ufs Common Lun 3
58 UFS_LUN_4, // Ufs Common Lun 4
59 UFS_LUN_5, // Ufs Common Lun 5
60 UFS_LUN_6, // Ufs Common Lun 6
61 UFS_LUN_7, // Ufs Common Lun 7
62 UFS_WLUN_REPORT_LUNS, // Ufs Reports Luns Well Known Lun
63 UFS_WLUN_UFS_DEV, // Ufs Device Well Known Lun
64 UFS_WLUN_BOOT, // Ufs Boot Well Known Lun
65 UFS_WLUN_RPMB // RPMB Well Known Lun
66 },
67 0x0000, // By default don't expose any Luns.
68 0x0
69 },
70 NULL, // TimerEvent
71 { // Queue
72 NULL,
73 NULL
74 }
75 };
76
77 EFI_DRIVER_BINDING_PROTOCOL gUfsPassThruDriverBinding = {
78 UfsPassThruDriverBindingSupported,
79 UfsPassThruDriverBindingStart,
80 UfsPassThruDriverBindingStop,
81 0x10,
82 NULL,
83 NULL
84 };
85
86 UFS_DEVICE_PATH mUfsDevicePathTemplate = {
87 {
88 MESSAGING_DEVICE_PATH,
89 MSG_UFS_DP,
90 {
91 (UINT8) (sizeof (UFS_DEVICE_PATH)),
92 (UINT8) ((sizeof (UFS_DEVICE_PATH)) >> 8)
93 }
94 },
95 0,
96 0
97 };
98
99 UINT8 mUfsTargetId[TARGET_MAX_BYTES];
100
101 /**
102 Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
103 supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
104 nonblocking I/O functionality is optional.
105
106 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
107 @param Target The Target is an array of size TARGET_MAX_BYTES and it represents
108 the id of the SCSI device to send the SCSI Request Packet. Each
109 transport driver may choose to utilize a subset of this size to suit the needs
110 of transport target representation. For example, a Fibre Channel driver
111 may use only 8 bytes (WWN) to represent an FC target.
112 @param Lun The LUN of the SCSI device to send the SCSI Request Packet.
113 @param Packet A pointer to the SCSI Request Packet to send to the SCSI device
114 specified by Target and Lun.
115 @param Event If nonblocking I/O is not supported then Event is ignored, and blocking
116 I/O is performed. If Event is NULL, then blocking I/O is performed. If
117 Event is not NULL and non blocking I/O is supported, then
118 nonblocking I/O is performed, and Event will be signaled when the
119 SCSI Request Packet completes.
120
121 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
122 commands, InTransferLength bytes were transferred from
123 InDataBuffer. For write and bi-directional commands,
124 OutTransferLength bytes were transferred by
125 OutDataBuffer.
126 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that
127 could be transferred is returned in InTransferLength. For write
128 and bi-directional commands, OutTransferLength bytes were
129 transferred by OutDataBuffer.
130 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
131 SCSI Request Packets already queued. The caller may retry again later.
132 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
133 Packet.
134 @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.
135 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported
136 by the host adapter. This includes the case of Bi-directional SCSI
137 commands not supported by the implementation. The SCSI Request
138 Packet was not sent, so no additional status information is available.
139 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
140
141 **/
142 EFI_STATUS
143 EFIAPI
144 UfsPassThruPassThru (
145 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
146 IN UINT8 *Target,
147 IN UINT64 Lun,
148 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
149 IN EFI_EVENT Event OPTIONAL
150 )
151 {
152 EFI_STATUS Status;
153 UFS_PASS_THRU_PRIVATE_DATA *Private;
154 UINT8 UfsLun;
155 UINT16 Index;
156
157 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
158
159 if ((Packet == NULL) || (Packet->Cdb == NULL)) {
160 return EFI_INVALID_PARAMETER;
161 }
162
163 //
164 // Don't support variable length CDB
165 //
166 if ((Packet->CdbLength != 6) && (Packet->CdbLength != 10) &&
167 (Packet->CdbLength != 12) && (Packet->CdbLength != 16)) {
168 return EFI_INVALID_PARAMETER;
169 }
170
171 if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {
172 return EFI_INVALID_PARAMETER;
173 }
174
175 if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {
176 return EFI_INVALID_PARAMETER;
177 }
178
179 if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->OutDataBuffer, This->Mode->IoAlign)) {
180 return EFI_INVALID_PARAMETER;
181 }
182
183 if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->SenseData, This->Mode->IoAlign)) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 //
188 // For UFS 2.0 compatible device, 0 is always used to represent the location of the UFS device.
189 //
190 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
191 if ((Target == NULL) || (CompareMem(Target, mUfsTargetId, TARGET_MAX_BYTES) != 0)) {
192 return EFI_INVALID_PARAMETER;
193 }
194
195 //
196 // UFS 2.0 spec Section 10.6.7 - Translation of 8-bit UFS LUN to 64-bit SCSI LUN Address
197 // 0xC1 in the first 8 bits of the 64-bit address indicates a well known LUN address in the SAM SCSI format.
198 // The second 8 bits of the 64-bit address saves the corresponding 8-bit UFS LUN.
199 //
200 if ((UINT8)Lun == UFS_WLUN_PREFIX) {
201 UfsLun = BIT7 | (((UINT8*)&Lun)[1] & 0xFF);
202 } else if ((UINT8)Lun == 0) {
203 UfsLun = ((UINT8*)&Lun)[1] & 0xFF;
204 } else {
205 return EFI_INVALID_PARAMETER;
206 }
207
208 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
209 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
210 continue;
211 }
212
213 if (Private->Luns.Lun[Index] == UfsLun) {
214 break;
215 }
216 }
217
218 if (Index == UFS_MAX_LUNS) {
219 return EFI_INVALID_PARAMETER;
220 }
221
222 Status = UfsExecScsiCmds (Private, UfsLun, Packet, Event);
223
224 return Status;
225 }
226
227 /**
228 Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
229 can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
230 Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
231 Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
232 channel.
233
234 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
235 @param Target On input, a pointer to the Target ID (an array of size
236 TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
237 On output, a pointer to the Target ID (an array of
238 TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
239 channel. An input value of 0xF(all bytes in the array are 0xF) in the
240 Target array retrieves the Target ID of the first SCSI device present on a
241 SCSI channel.
242 @param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI
243 channel. On output, a pointer to the LUN of the next SCSI device present
244 on a SCSI channel.
245
246 @retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI
247 channel was returned in Target and Lun.
248 @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
249 not returned on a previous call to GetNextTargetLun().
250 @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
251
252 **/
253 EFI_STATUS
254 EFIAPI
255 UfsPassThruGetNextTargetLun (
256 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
257 IN OUT UINT8 **Target,
258 IN OUT UINT64 *Lun
259 )
260 {
261 UFS_PASS_THRU_PRIVATE_DATA *Private;
262 UINT8 UfsLun;
263 UINT16 Index;
264 UINT16 Next;
265
266 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
267
268 if (Target == NULL || Lun == NULL) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 if (*Target == NULL) {
273 return EFI_INVALID_PARAMETER;
274 }
275
276 UfsLun = 0;
277 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
278 if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
279 //
280 // If the array is all 0xFF's, return the first exposed Lun to caller.
281 //
282 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
283 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
284 if ((Private->Luns.BitMask & (BIT0 << Index)) != 0) {
285 UfsLun = Private->Luns.Lun[Index];
286 break;
287 }
288 }
289 if (Index != UFS_MAX_LUNS) {
290 *Lun = 0;
291 if ((UfsLun & BIT7) == BIT7) {
292 ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
293 ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
294 } else {
295 ((UINT8*)Lun)[1] = UfsLun;
296 }
297 return EFI_SUCCESS;
298 } else {
299 return EFI_NOT_FOUND;
300 }
301 }
302
303 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
304 if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
305 if (((UINT8*)Lun)[0] == UFS_WLUN_PREFIX) {
306 UfsLun = BIT7 | (((UINT8*)Lun)[1] & 0xFF);
307 } else if (((UINT8*)Lun)[0] == 0) {
308 UfsLun = ((UINT8*)Lun)[1] & 0xFF;
309 } else {
310 return EFI_NOT_FOUND;
311 }
312
313 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
314 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
315 continue;
316 }
317
318 if (Private->Luns.Lun[Index] != UfsLun) {
319 continue;
320 }
321
322 for (Next = Index + 1; Next < UFS_MAX_LUNS; Next++) {
323 if ((Private->Luns.BitMask & (BIT0 << Next)) != 0) {
324 UfsLun = Private->Luns.Lun[Next];
325 break;
326 }
327 }
328
329 if (Next == UFS_MAX_LUNS) {
330 return EFI_NOT_FOUND;
331 } else {
332 break;
333 }
334 }
335
336 if (Index != UFS_MAX_LUNS) {
337 *Lun = 0;
338 if ((UfsLun & BIT7) == BIT7) {
339 ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
340 ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
341 } else {
342 ((UINT8*)Lun)[1] = UfsLun;
343 }
344 return EFI_SUCCESS;
345 } else {
346 return EFI_NOT_FOUND;
347 }
348 }
349
350 return EFI_NOT_FOUND;
351 }
352
353 /**
354 Used to allocate and build a device path node for a SCSI device on a SCSI channel.
355
356 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
357 @param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the
358 Target ID of the SCSI device for which a device path node is to be
359 allocated and built. Transport drivers may chose to utilize a subset of
360 this size to suit the representation of targets. For example, a Fibre
361 Channel driver may use only 8 bytes (WWN) in the array to represent a
362 FC target.
363 @param Lun The LUN of the SCSI device for which a device path node is to be
364 allocated and built.
365 @param DevicePath A pointer to a single device path node that describes the SCSI device
366 specified by Target and Lun. This function is responsible for
367 allocating the buffer DevicePath with the boot service
368 AllocatePool(). It is the caller's responsibility to free
369 DevicePath when the caller is finished with DevicePath.
370
371 @retval EFI_SUCCESS The device path node that describes the SCSI device specified by
372 Target and Lun was allocated and returned in
373 DevicePath.
374 @retval EFI_INVALID_PARAMETER DevicePath is NULL.
375 @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist
376 on the SCSI channel.
377 @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
378
379 **/
380 EFI_STATUS
381 EFIAPI
382 UfsPassThruBuildDevicePath (
383 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
384 IN UINT8 *Target,
385 IN UINT64 Lun,
386 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
387 )
388 {
389 UFS_PASS_THRU_PRIVATE_DATA *Private;
390 EFI_DEV_PATH *DevicePathNode;
391 UINT8 UfsLun;
392 UINT16 Index;
393
394 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
395
396 //
397 // Validate parameters passed in.
398 //
399 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
400 if (CompareMem (Target, mUfsTargetId, TARGET_MAX_BYTES) != 0) {
401 return EFI_INVALID_PARAMETER;
402 }
403
404 if ((UINT8)Lun == UFS_WLUN_PREFIX) {
405 UfsLun = BIT7 | (((UINT8*)&Lun)[1] & 0xFF);
406 } else if ((UINT8)Lun == 0) {
407 UfsLun = ((UINT8*)&Lun)[1] & 0xFF;
408 } else {
409 return EFI_NOT_FOUND;
410 }
411
412 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
413 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
414 continue;
415 }
416
417 if (Private->Luns.Lun[Index] == UfsLun) {
418 break;
419 }
420 }
421
422 if (Index == UFS_MAX_LUNS) {
423 return EFI_NOT_FOUND;
424 }
425
426 DevicePathNode = AllocateCopyPool (sizeof (UFS_DEVICE_PATH), &mUfsDevicePathTemplate);
427 if (DevicePathNode == NULL) {
428 return EFI_OUT_OF_RESOURCES;
429 }
430
431 DevicePathNode->Ufs.Pun = 0;
432 DevicePathNode->Ufs.Lun = UfsLun;
433
434 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathNode;
435
436 return EFI_SUCCESS;
437 }
438
439 /**
440 Used to translate a device path node to a Target ID and LUN.
441
442 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
443 @param DevicePath A pointer to a single device path node that describes the SCSI device
444 on the SCSI channel.
445 @param Target A pointer to the Target Array which represents the ID of a SCSI device
446 on the SCSI channel.
447 @param Lun A pointer to the LUN of a SCSI device on the SCSI channel.
448
449 @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and
450 LUN, and they were returned in Target and Lun.
451 @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.
452 @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN
453 does not exist.
454 @retval EFI_UNSUPPORTED This driver does not support the device path node type in
455 DevicePath.
456
457 **/
458 EFI_STATUS
459 EFIAPI
460 UfsPassThruGetTargetLun (
461 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
462 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
463 OUT UINT8 **Target,
464 OUT UINT64 *Lun
465 )
466 {
467 UFS_PASS_THRU_PRIVATE_DATA *Private;
468 EFI_DEV_PATH *DevicePathNode;
469 UINT8 Pun;
470 UINT8 UfsLun;
471 UINT16 Index;
472
473 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
474
475 //
476 // Validate parameters passed in.
477 //
478 if (DevicePath == NULL || Target == NULL || Lun == NULL) {
479 return EFI_INVALID_PARAMETER;
480 }
481
482 if (*Target == NULL) {
483 return EFI_INVALID_PARAMETER;
484 }
485
486 //
487 // Check whether the DevicePath belongs to UFS_DEVICE_PATH
488 //
489 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || (DevicePath->SubType != MSG_UFS_DP) ||
490 (DevicePathNodeLength(DevicePath) != sizeof(UFS_DEVICE_PATH))) {
491 return EFI_UNSUPPORTED;
492 }
493
494 DevicePathNode = (EFI_DEV_PATH *) DevicePath;
495
496 Pun = (UINT8) DevicePathNode->Ufs.Pun;
497 UfsLun = (UINT8) DevicePathNode->Ufs.Lun;
498
499 if (Pun != 0) {
500 return EFI_NOT_FOUND;
501 }
502
503 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
504 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
505 continue;
506 }
507
508 if (Private->Luns.Lun[Index] == UfsLun) {
509 break;
510 }
511 }
512
513 if (Index == UFS_MAX_LUNS) {
514 return EFI_NOT_FOUND;
515 }
516
517 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
518 *Lun = 0;
519 if ((UfsLun & BIT7) == BIT7) {
520 ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
521 ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
522 } else {
523 ((UINT8*)Lun)[1] = UfsLun;
524 }
525 return EFI_SUCCESS;
526 }
527
528 /**
529 Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.
530
531 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
532
533 @retval EFI_SUCCESS The SCSI channel was reset.
534 @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.
535 @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel.
536 @retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation.
537
538 **/
539 EFI_STATUS
540 EFIAPI
541 UfsPassThruResetChannel (
542 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
543 )
544 {
545 //
546 // Return success directly then upper layer driver could think reset channel operation is done.
547 //
548 return EFI_SUCCESS;
549 }
550
551 /**
552 Resets a SCSI logical unit that is connected to a SCSI channel.
553
554 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
555 @param Target The Target is an array of size TARGET_MAX_BYTE and it represents the
556 target port ID of the SCSI device containing the SCSI logical unit to
557 reset. Transport drivers may chose to utilize a subset of this array to suit
558 the representation of their targets.
559 @param Lun The LUN of the SCSI device to reset.
560
561 @retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset.
562 @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
563 @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device
564 specified by Target and Lun.
565 @retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation.
566 @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device
567 specified by Target and Lun.
568
569 **/
570 EFI_STATUS
571 EFIAPI
572 UfsPassThruResetTargetLun (
573 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
574 IN UINT8 *Target,
575 IN UINT64 Lun
576 )
577 {
578 //
579 // Return success directly then upper layer driver could think reset target LUN operation is done.
580 //
581 return EFI_SUCCESS;
582 }
583
584 /**
585 Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
586 be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs
587 for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to
588 see if a SCSI device is actually present at that location on the SCSI channel.
589
590 @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
591 @param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
592 On output, a pointer to the Target ID (an array of
593 TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
594 channel. An input value of 0xF(all bytes in the array are 0xF) in the
595 Target array retrieves the Target ID of the first SCSI device present on a
596 SCSI channel.
597
598 @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI
599 channel was returned in Target.
600 @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
601 @retval EFI_TIMEOUT Target array is not all 0xF, and Target was not
602 returned on a previous call to GetNextTarget().
603 @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
604
605 **/
606 EFI_STATUS
607 EFIAPI
608 UfsPassThruGetNextTarget (
609 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
610 IN OUT UINT8 **Target
611 )
612 {
613 if (Target == NULL || *Target == NULL) {
614 return EFI_INVALID_PARAMETER;
615 }
616
617 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
618 if (CompareMem(*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
619 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
620 return EFI_SUCCESS;
621 }
622
623 return EFI_NOT_FOUND;
624 }
625
626 /**
627 Tests to see if this driver supports a given controller. If a child device is provided,
628 it further tests to see if this driver supports creating a handle for the specified child device.
629
630 This function checks to see if the driver specified by This supports the device specified by
631 ControllerHandle. Drivers will typically use the device path attached to
632 ControllerHandle and/or the services from the bus I/O abstraction attached to
633 ControllerHandle to determine if the driver supports ControllerHandle. This function
634 may be called many times during platform initialization. In order to reduce boot times, the tests
635 performed by this function must be very small, and take as little time as possible to execute. This
636 function must not change the state of any hardware devices, and this function must be aware that the
637 device specified by ControllerHandle may already be managed by the same driver or a
638 different driver. This function must match its calls to AllocatePages() with FreePages(),
639 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
640 Since ControllerHandle may have been previously started by the same driver, if a protocol is
641 already in the opened state, then it must not be closed with CloseProtocol(). This is required
642 to guarantee the state of ControllerHandle is not modified by this function.
643
644 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
645 @param[in] ControllerHandle The handle of the controller to test. This handle
646 must support a protocol interface that supplies
647 an I/O abstraction to the driver.
648 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
649 parameter is ignored by device drivers, and is optional for bus
650 drivers. For bus drivers, if this parameter is not NULL, then
651 the bus driver must determine if the bus controller specified
652 by ControllerHandle and the child controller specified
653 by RemainingDevicePath are both supported by this
654 bus driver.
655
656 @retval EFI_SUCCESS The device specified by ControllerHandle and
657 RemainingDevicePath is supported by the driver specified by This.
658 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
659 RemainingDevicePath is already being managed by the driver
660 specified by This.
661 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
662 RemainingDevicePath is already being managed by a different
663 driver or an application that requires exclusive access.
664 Currently not implemented.
665 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
666 RemainingDevicePath is not supported by the driver specified by This.
667 **/
668 EFI_STATUS
669 EFIAPI
670 UfsPassThruDriverBindingSupported (
671 IN EFI_DRIVER_BINDING_PROTOCOL *This,
672 IN EFI_HANDLE Controller,
673 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
674 )
675 {
676 EFI_STATUS Status;
677 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
678 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHostController;
679
680 //
681 // Ufs Pass Thru driver is a device driver, and should ingore the
682 // "RemainingDevicePath" according to UEFI spec
683 //
684 Status = gBS->OpenProtocol (
685 Controller,
686 &gEfiDevicePathProtocolGuid,
687 (VOID *) &ParentDevicePath,
688 This->DriverBindingHandle,
689 Controller,
690 EFI_OPEN_PROTOCOL_BY_DRIVER
691 );
692 if (EFI_ERROR (Status)) {
693 //
694 // EFI_ALREADY_STARTED is also an error
695 //
696 return Status;
697 }
698 //
699 // Close the protocol because we don't use it here
700 //
701 gBS->CloseProtocol (
702 Controller,
703 &gEfiDevicePathProtocolGuid,
704 This->DriverBindingHandle,
705 Controller
706 );
707
708 Status = gBS->OpenProtocol (
709 Controller,
710 &gEdkiiUfsHostControllerProtocolGuid,
711 (VOID **) &UfsHostController,
712 This->DriverBindingHandle,
713 Controller,
714 EFI_OPEN_PROTOCOL_BY_DRIVER
715 );
716
717 if (EFI_ERROR (Status)) {
718 //
719 // EFI_ALREADY_STARTED is also an error
720 //
721 return Status;
722 }
723
724 //
725 // Close the I/O Abstraction(s) used to perform the supported test
726 //
727 gBS->CloseProtocol (
728 Controller,
729 &gEdkiiUfsHostControllerProtocolGuid,
730 This->DriverBindingHandle,
731 Controller
732 );
733
734 return EFI_SUCCESS;
735 }
736
737 /**
738 Finishes device initialization by setting fDeviceInit flag and waiting untill device responds by
739 clearing it.
740
741 @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA.
742
743 @retval EFI_SUCCESS The operation succeeds.
744 @retval Others The operation fails.
745
746 **/
747 EFI_STATUS
748 UfsFinishDeviceInitialization (
749 IN UFS_PASS_THRU_PRIVATE_DATA *Private
750 )
751 {
752 EFI_STATUS Status;
753 UINT8 DeviceInitStatus;
754 UINT8 Timeout;
755
756 DeviceInitStatus = 0xFF;
757
758 //
759 // The host enables the device initialization completion by setting fDeviceInit flag.
760 //
761 Status = UfsSetFlag (Private, UfsFlagDevInit);
762 if (EFI_ERROR (Status)) {
763 return Status;
764 }
765
766 Timeout = 5;
767 do {
768 Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
769 if (EFI_ERROR (Status)) {
770 return Status;
771 }
772 MicroSecondDelay (1);
773 Timeout--;
774 } while (DeviceInitStatus != 0 && Timeout != 0);
775
776 return EFI_SUCCESS;
777 }
778
779 /**
780 Starts a device controller or a bus controller.
781
782 The Start() function is designed to be invoked from the EFI boot service ConnectController().
783 As a result, much of the error checking on the parameters to Start() has been moved into this
784 common boot service. It is legal to call Start() from other locations,
785 but the following calling restrictions must be followed or the system behavior will not be deterministic.
786 1. ControllerHandle must be a valid EFI_HANDLE.
787 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
788 EFI_DEVICE_PATH_PROTOCOL.
789 3. Prior to calling Start(), the Supported() function for the driver specified by This must
790 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
791
792 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
793 @param[in] ControllerHandle The handle of the controller to start. This handle
794 must support a protocol interface that supplies
795 an I/O abstraction to the driver.
796 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
797 parameter is ignored by device drivers, and is optional for bus
798 drivers. For a bus driver, if this parameter is NULL, then handles
799 for all the children of Controller are created by this driver.
800 If this parameter is not NULL and the first Device Path Node is
801 not the End of Device Path Node, then only the handle for the
802 child device specified by the first Device Path Node of
803 RemainingDevicePath is created by this driver.
804 If the first Device Path Node of RemainingDevicePath is
805 the End of Device Path Node, no child handle is created by this
806 driver.
807
808 @retval EFI_SUCCESS The device was started.
809 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
810 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
811 @retval Others The driver failded to start the device.
812
813 **/
814 EFI_STATUS
815 EFIAPI
816 UfsPassThruDriverBindingStart (
817 IN EFI_DRIVER_BINDING_PROTOCOL *This,
818 IN EFI_HANDLE Controller,
819 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
820 )
821 {
822 EFI_STATUS Status;
823 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
824 UFS_PASS_THRU_PRIVATE_DATA *Private;
825 UINTN UfsHcBase;
826 UINT32 Index;
827 UFS_UNIT_DESC UnitDescriptor;
828 UINT32 UnitDescriptorSize;
829
830 Status = EFI_SUCCESS;
831 UfsHc = NULL;
832 Private = NULL;
833 UfsHcBase = 0;
834
835 DEBUG ((DEBUG_INFO, "==UfsPassThru Start== Controller = %x\n", Controller));
836
837 Status = gBS->OpenProtocol (
838 Controller,
839 &gEdkiiUfsHostControllerProtocolGuid,
840 (VOID **) &UfsHc,
841 This->DriverBindingHandle,
842 Controller,
843 EFI_OPEN_PROTOCOL_BY_DRIVER
844 );
845
846 if (EFI_ERROR (Status)) {
847 DEBUG ((DEBUG_ERROR, "Open Ufs Host Controller Protocol Error, Status = %r\n", Status));
848 goto Error;
849 }
850
851 //
852 // Get the UFS Host Controller MMIO Bar Base Address.
853 //
854 Status = UfsHc->GetUfsHcMmioBar (UfsHc, &UfsHcBase);
855 if (EFI_ERROR (Status)) {
856 DEBUG ((DEBUG_ERROR, "Get Ufs Host Controller Mmio Bar Error, Status = %r\n", Status));
857 goto Error;
858 }
859
860 //
861 // Initialize Ufs Pass Thru private data for managed UFS Host Controller.
862 //
863 Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
864 if (Private == NULL) {
865 DEBUG ((DEBUG_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
866 Status = EFI_OUT_OF_RESOURCES;
867 goto Error;
868 }
869
870 Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
871 Private->UfsHostController = UfsHc;
872 Private->UfsHcBase = UfsHcBase;
873 InitializeListHead (&Private->Queue);
874
875 //
876 // Initialize UFS Host Controller H/W.
877 //
878 Status = UfsControllerInit (Private);
879 if (EFI_ERROR (Status)) {
880 DEBUG ((DEBUG_ERROR, "Ufs Host Controller Initialization Error, Status = %r\n", Status));
881 goto Error;
882 }
883
884 //
885 // UFS 2.0 spec Section 13.1.3.3:
886 // At the end of the UFS Interconnect Layer initialization on both host and device side,
887 // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
888 //
889 Status = UfsExecNopCmds (Private);
890 if (EFI_ERROR (Status)) {
891 DEBUG ((DEBUG_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
892 goto Error;
893 }
894
895 Status = UfsFinishDeviceInitialization (Private);
896 if (EFI_ERROR (Status)) {
897 DEBUG ((DEBUG_ERROR, "Device failed to finish initialization, Status = %r\n", Status));
898 goto Error;
899 }
900
901 //
902 // Check if 8 common luns are active and set corresponding bit mask.
903 // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.
904 //
905 UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
906 for (Index = 0; Index < 8; Index++) {
907 Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8) Index, 0, &UnitDescriptor, &UnitDescriptorSize);
908 if (EFI_ERROR (Status)) {
909 DEBUG ((DEBUG_ERROR, "Failed to read unit descriptor, index = %X, status = %r\n", Index, Status));
910 continue;
911 }
912 if (UnitDescriptor.LunEn == 0x1) {
913 DEBUG ((DEBUG_INFO, "UFS LUN %X is enabled\n", Index));
914 Private->Luns.BitMask |= (BIT0 << Index);
915 }
916 }
917
918 //
919 // Start the asynchronous interrupt monitor
920 //
921 Status = gBS->CreateEvent (
922 EVT_TIMER | EVT_NOTIFY_SIGNAL,
923 TPL_NOTIFY,
924 ProcessAsyncTaskList,
925 Private,
926 &Private->TimerEvent
927 );
928 if (EFI_ERROR (Status)) {
929 DEBUG ((DEBUG_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
930 goto Error;
931 }
932
933 Status = gBS->SetTimer (
934 Private->TimerEvent,
935 TimerPeriodic,
936 UFS_HC_ASYNC_TIMER
937 );
938 if (EFI_ERROR (Status)) {
939 DEBUG ((DEBUG_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
940 goto Error;
941 }
942
943 Status = gBS->InstallMultipleProtocolInterfaces (
944 &Controller,
945 &gEfiExtScsiPassThruProtocolGuid,
946 &(Private->ExtScsiPassThru),
947 &gEfiUfsDeviceConfigProtocolGuid,
948 &(Private->UfsDevConfig),
949 NULL
950 );
951 ASSERT_EFI_ERROR (Status);
952
953 return EFI_SUCCESS;
954
955 Error:
956 if (Private != NULL) {
957 if (Private->TmrlMapping != NULL) {
958 UfsHc->Unmap (UfsHc, Private->TmrlMapping);
959 }
960 if (Private->UtpTmrlBase != NULL) {
961 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
962 }
963
964 if (Private->TrlMapping != NULL) {
965 UfsHc->Unmap (UfsHc, Private->TrlMapping);
966 }
967 if (Private->UtpTrlBase != NULL) {
968 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
969 }
970
971 if (Private->TimerEvent != NULL) {
972 gBS->CloseEvent (Private->TimerEvent);
973 }
974
975 FreePool (Private);
976 }
977
978 if (UfsHc != NULL) {
979 gBS->CloseProtocol (
980 Controller,
981 &gEdkiiUfsHostControllerProtocolGuid,
982 This->DriverBindingHandle,
983 Controller
984 );
985 }
986
987 return Status;
988 }
989
990 /**
991 Stops a device controller or a bus controller.
992
993 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
994 As a result, much of the error checking on the parameters to Stop() has been moved
995 into this common boot service. It is legal to call Stop() from other locations,
996 but the following calling restrictions must be followed or the system behavior will not be deterministic.
997 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
998 same driver's Start() function.
999 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1000 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1001 Start() function, and the Start() function must have called OpenProtocol() on
1002 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1003
1004 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1005 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1006 support a bus specific I/O protocol for the driver
1007 to use to stop the device.
1008 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1009 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1010 if NumberOfChildren is 0.
1011
1012 @retval EFI_SUCCESS The device was stopped.
1013 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1014
1015 **/
1016 EFI_STATUS
1017 EFIAPI
1018 UfsPassThruDriverBindingStop (
1019 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1020 IN EFI_HANDLE Controller,
1021 IN UINTN NumberOfChildren,
1022 IN EFI_HANDLE *ChildHandleBuffer
1023 )
1024 {
1025 EFI_STATUS Status;
1026 UFS_PASS_THRU_PRIVATE_DATA *Private;
1027 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
1028 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
1029 UFS_PASS_THRU_TRANS_REQ *TransReq;
1030 LIST_ENTRY *Entry;
1031 LIST_ENTRY *NextEntry;
1032
1033 DEBUG ((DEBUG_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
1034
1035 Status = gBS->OpenProtocol (
1036 Controller,
1037 &gEfiExtScsiPassThruProtocolGuid,
1038 (VOID **) &ExtScsiPassThru,
1039 This->DriverBindingHandle,
1040 Controller,
1041 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1042 );
1043
1044 if (EFI_ERROR (Status)) {
1045 return EFI_DEVICE_ERROR;
1046 }
1047
1048 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
1049 UfsHc = Private->UfsHostController;
1050
1051 //
1052 // Cleanup the resources of I/O requests in the async I/O queue
1053 //
1054 if (!IsListEmpty(&Private->Queue)) {
1055 EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
1056 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
1057
1058 //
1059 // TODO: Should find/add a proper host adapter return status for this
1060 // case.
1061 //
1062 TransReq->Packet->HostAdapterStatus =
1063 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
1064
1065 SignalCallerEvent (Private, TransReq);
1066 }
1067 }
1068
1069 Status = gBS->UninstallMultipleProtocolInterfaces (
1070 Controller,
1071 &gEfiExtScsiPassThruProtocolGuid,
1072 &(Private->ExtScsiPassThru),
1073 &gEfiUfsDeviceConfigProtocolGuid,
1074 &(Private->UfsDevConfig),
1075 NULL
1076 );
1077
1078 if (EFI_ERROR (Status)) {
1079 return EFI_DEVICE_ERROR;
1080 }
1081
1082 //
1083 // Stop Ufs Host Controller
1084 //
1085 Status = UfsControllerStop (Private);
1086 ASSERT_EFI_ERROR (Status);
1087
1088 if (Private->TmrlMapping != NULL) {
1089 UfsHc->Unmap (UfsHc, Private->TmrlMapping);
1090 }
1091 if (Private->UtpTmrlBase != NULL) {
1092 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
1093 }
1094
1095 if (Private->TrlMapping != NULL) {
1096 UfsHc->Unmap (UfsHc, Private->TrlMapping);
1097 }
1098 if (Private->UtpTrlBase != NULL) {
1099 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
1100 }
1101
1102 if (Private->TimerEvent != NULL) {
1103 gBS->CloseEvent (Private->TimerEvent);
1104 }
1105
1106 FreePool (Private);
1107
1108 //
1109 // Close protocols opened by UfsPassThru controller driver
1110 //
1111 gBS->CloseProtocol (
1112 Controller,
1113 &gEdkiiUfsHostControllerProtocolGuid,
1114 This->DriverBindingHandle,
1115 Controller
1116 );
1117
1118 return Status;
1119 }
1120
1121
1122 /**
1123 The user Entry Point for module UfsPassThru. The user code starts with this function.
1124
1125 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1126 @param[in] SystemTable A pointer to the EFI System Table.
1127
1128 @retval EFI_SUCCESS The entry point is executed successfully.
1129 @retval other Some error occurs when executing this entry point.
1130
1131 **/
1132 EFI_STATUS
1133 EFIAPI
1134 InitializeUfsPassThru (
1135 IN EFI_HANDLE ImageHandle,
1136 IN EFI_SYSTEM_TABLE *SystemTable
1137 )
1138 {
1139 EFI_STATUS Status;
1140
1141 //
1142 // Install driver model protocol(s).
1143 //
1144 Status = EfiLibInstallDriverBindingComponentName2 (
1145 ImageHandle,
1146 SystemTable,
1147 &gUfsPassThruDriverBinding,
1148 ImageHandle,
1149 &gUfsPassThruComponentName,
1150 &gUfsPassThruComponentName2
1151 );
1152 ASSERT_EFI_ERROR (Status);
1153
1154 return Status;
1155 }