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