]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
f59116733e9fe1151a24724981260c80fea83b2a
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
1 /** @file
2 SCSI Bus driver that layers on every SCSI Pass Thru and
3 Extended SCSI Pass Thru protocol in the system.
4
5 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include <Uefi.h>
18
19
20 #include <Protocol/ScsiPassThru.h>
21 #include <Protocol/ScsiPassThruExt.h>
22 #include <Protocol/ScsiIo.h>
23 #include <Protocol/ComponentName.h>
24 #include <Protocol/DriverBinding.h>
25 #include <Protocol/DevicePath.h>
26
27 #include <Library/DebugLib.h>
28 #include <Library/UefiDriverEntryPoint.h>
29 #include <Library/UefiLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/ScsiLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/DevicePathLib.h>
35
36 #include "ScsiBus.h"
37
38 EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
39 SCSIBusDriverBindingSupported,
40 SCSIBusDriverBindingStart,
41 SCSIBusDriverBindingStop,
42 0xa,
43 NULL,
44 NULL
45 };
46
47
48 //
49 // The ScsiBusProtocol is just used to locate ScsiBusDev
50 // structure in the SCSIBusDriverBindingStop(). Then we can
51 // Close all opened protocols and release this structure.
52 //
53 STATIC EFI_GUID mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;
54
55 STATIC VOID *WorkingBuffer;
56
57 STATIC
58 EFI_STATUS
59 EFIAPI
60 ScsiioToPassThruPacket (
61 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
62 IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
63 );
64
65
66 STATIC
67 EFI_STATUS
68 EFIAPI
69 PassThruToScsiioPacket (
70 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
71 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
72 );
73 STATIC
74 VOID
75 EFIAPI
76 NotifyFunction (
77 EFI_EVENT Event,
78 VOID *Context
79 );
80
81 /**
82 The user Entry Point for module ScsiBus. The user code starts with this function.
83
84 @param[in] ImageHandle The firmware allocated handle for the EFI image.
85 @param[in] SystemTable A pointer to the EFI System Table.
86
87 @retval EFI_SUCCESS The entry point is executed successfully.
88 @retval other Some error occurs when executing this entry point.
89
90 **/
91 EFI_STATUS
92 EFIAPI
93 InitializeScsiBus(
94 IN EFI_HANDLE ImageHandle,
95 IN EFI_SYSTEM_TABLE *SystemTable
96 )
97 {
98 EFI_STATUS Status;
99
100 //
101 // Install driver model protocol(s).
102 //
103 Status = EfiLibInstallDriverBindingComponentName2 (
104 ImageHandle,
105 SystemTable,
106 &gSCSIBusDriverBinding,
107 ImageHandle,
108 &gScsiBusComponentName,
109 &gScsiBusComponentName2
110 );
111 ASSERT_EFI_ERROR (Status);
112
113 return Status;
114 }
115
116 EFI_STATUS
117 EFIAPI
118 SCSIBusDriverBindingSupported (
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,
120 IN EFI_HANDLE Controller,
121 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
122 )
123 /*++
124
125 Routine Description:
126
127 Test to see if this driver supports ControllerHandle. Any ControllerHandle
128 that has ExtScsiPassThruProtocol/ScsiPassThruProtocol installed will be supported.
129
130 Arguments:
131
132 This - Protocol instance pointer.
133 Controller - Handle of device to test
134 RemainingDevicePath - Not used
135
136 Returns:
137
138 EFI_SUCCESS - This driver supports this device.
139 EFI_UNSUPPORTED - This driver does not support this device.
140
141 --*/
142
143 {
144 EFI_STATUS Status;
145 EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;
146 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;
147 //
148 // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol
149 //
150 Status = gBS->OpenProtocol (
151 Controller,
152 &gEfiExtScsiPassThruProtocolGuid,
153 (VOID **)&ExtPassThru,
154 This->DriverBindingHandle,
155 Controller,
156 EFI_OPEN_PROTOCOL_BY_DRIVER
157 );
158
159 if (Status == EFI_ALREADY_STARTED) {
160 return EFI_SUCCESS;
161 }
162
163 if (EFI_ERROR (Status)) {
164 Status = gBS->OpenProtocol (
165 Controller,
166 &gEfiScsiPassThruProtocolGuid,
167 (VOID **)&PassThru,
168 This->DriverBindingHandle,
169 Controller,
170 EFI_OPEN_PROTOCOL_BY_DRIVER
171 );
172
173 if (Status == EFI_ALREADY_STARTED) {
174 return EFI_SUCCESS;
175 }
176
177 if (EFI_ERROR (Status)) {
178 return Status;
179 }
180
181 gBS->CloseProtocol (
182 Controller,
183 &gEfiScsiPassThruProtocolGuid,
184 This->DriverBindingHandle,
185 Controller
186 );
187 return EFI_SUCCESS;
188 }
189
190 gBS->CloseProtocol (
191 Controller,
192 &gEfiExtScsiPassThruProtocolGuid,
193 This->DriverBindingHandle,
194 Controller
195 );
196
197 return EFI_SUCCESS;
198 }
199
200 EFI_STATUS
201 EFIAPI
202 SCSIBusDriverBindingStart (
203 IN EFI_DRIVER_BINDING_PROTOCOL *This,
204 IN EFI_HANDLE Controller,
205 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
206 )
207 /*++
208
209 Routine Description:
210 Starting the SCSI Bus Driver
211
212 Arguments:
213 This - Protocol instance pointer.
214 Controller - Handle of device to test
215 RemainingDevicePath - Not used
216
217 Returns:
218 EFI_SUCCESS - This driver supports this device.
219 EFI_UNSUPPORTED - This driver does not support this device.
220 EFI_DEVICE_ERROR - This driver cannot be started due to device Error
221
222 --*/
223 {
224 UINT64 Lun;
225 UINT8 *TargetId;
226 BOOLEAN ScanOtherPuns;
227 BOOLEAN FromFirstTarget;
228 BOOLEAN ExtScsiSupport;
229 EFI_STATUS Status;
230 EFI_STATUS DevicePathStatus;
231 EFI_STATUS PassThruStatus;
232 SCSI_BUS_DEVICE *ScsiBusDev;
233 SCSI_TARGET_ID *ScsiTargetId;
234 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
235 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;
236 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;
237 EFI_SCSI_BUS_PROTOCOL *BusIdentify;
238
239 TargetId = NULL;
240 ScsiTargetId = NULL;
241 ScanOtherPuns = TRUE;
242 FromFirstTarget = FALSE;
243 ExtScsiSupport = FALSE;
244 PassThruStatus = EFI_SUCCESS;
245
246 ScsiTargetId = AllocateZeroPool(sizeof(SCSI_TARGET_ID));
247 if (ScsiTargetId == NULL) {
248 return EFI_OUT_OF_RESOURCES;
249 }
250
251 TargetId = &ScsiTargetId->ScsiId.ExtScsi[0];
252
253 DevicePathStatus = gBS->OpenProtocol (
254 Controller,
255 &gEfiDevicePathProtocolGuid,
256 (VOID **) &ParentDevicePath,
257 This->DriverBindingHandle,
258 Controller,
259 EFI_OPEN_PROTOCOL_BY_DRIVER
260 );
261 if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {
262 return DevicePathStatus;
263 }
264
265 //
266 // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
267 // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
268 // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
269 //
270 Status = gBS->OpenProtocol (
271 Controller,
272 &gEfiExtScsiPassThruProtocolGuid,
273 (VOID **) &ExtScsiInterface,
274 This->DriverBindingHandle,
275 Controller,
276 EFI_OPEN_PROTOCOL_BY_DRIVER
277 );
278 //
279 // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.
280 //
281 if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
282 Status = gBS->OpenProtocol (
283 Controller,
284 &gEfiScsiPassThruProtocolGuid,
285 (VOID **) &ScsiInterface,
286 This->DriverBindingHandle,
287 Controller,
288 EFI_OPEN_PROTOCOL_BY_DRIVER
289 );
290 //
291 // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.
292 //
293 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
294 if (!EFI_ERROR(DevicePathStatus)) {
295 gBS->CloseProtocol (
296 Controller,
297 &gEfiDevicePathProtocolGuid,
298 This->DriverBindingHandle,
299 Controller
300 );
301 }
302 return Status;
303 }
304 } else {
305 //
306 // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol
307 // with BY_DRIVER if it is also present on the handle. The intent is to prevent
308 // another SCSI Bus Driver to work on the same host handle.
309 //
310 ExtScsiSupport = TRUE;
311 PassThruStatus = gBS->OpenProtocol (
312 Controller,
313 &gEfiScsiPassThruProtocolGuid,
314 (VOID **) &ScsiInterface,
315 This->DriverBindingHandle,
316 Controller,
317 EFI_OPEN_PROTOCOL_BY_DRIVER
318 );
319 }
320
321 if (Status != EFI_ALREADY_STARTED) {
322 //
323 // Go through here means either ExtPassThru or PassThru Protocol is successfully opened
324 // on this handle for this time. Then construct Host controller private data.
325 //
326 ScsiBusDev = NULL;
327 ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE));
328 if (ScsiBusDev == NULL) {
329 Status = EFI_OUT_OF_RESOURCES;
330 goto ErrorExit;
331 }
332 ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
333 ScsiBusDev->ExtScsiSupport = ExtScsiSupport;
334 ScsiBusDev->DevicePath = ParentDevicePath;
335 if (ScsiBusDev->ExtScsiSupport) {
336 ScsiBusDev->ExtScsiInterface = ExtScsiInterface;
337 } else {
338 ScsiBusDev->ScsiInterface = ScsiInterface;
339 }
340
341 //
342 // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be
343 // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru
344 // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.
345 //
346 Status = gBS->InstallProtocolInterface (
347 &Controller,
348 &mScsiBusProtocolGuid,
349 EFI_NATIVE_INTERFACE,
350 &ScsiBusDev->BusIdentify
351 );
352 if (EFI_ERROR (Status)) {
353 goto ErrorExit;
354 }
355 } else {
356 //
357 // Go through here means Start() is re-invoked again, nothing special is required to do except
358 // picking up Host controller private information.
359 //
360 Status = gBS->OpenProtocol (
361 Controller,
362 &mScsiBusProtocolGuid,
363 (VOID **) &BusIdentify,
364 This->DriverBindingHandle,
365 Controller,
366 EFI_OPEN_PROTOCOL_GET_PROTOCOL
367 );
368
369 if (EFI_ERROR (Status)) {
370 return Status;
371 }
372 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);
373 }
374
375 if (RemainingDevicePath == NULL) {
376 SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);
377 Lun = 0;
378 FromFirstTarget = TRUE;
379 } else {
380 if (ScsiBusDev->ExtScsiSupport) {
381 ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);
382 } else {
383 ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);
384 }
385 }
386
387 while(ScanOtherPuns) {
388 if (FromFirstTarget) {
389 //
390 // Remaining Device Path is NULL, scan all the possible Puns in the
391 // SCSI Channel.
392 //
393 if (ScsiBusDev->ExtScsiSupport) {
394 Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);
395 } else {
396 Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId->ScsiId.Scsi, &Lun);
397 }
398 if (EFI_ERROR (Status)) {
399 //
400 // no legal Pun and Lun found any more
401 //
402 break;
403 }
404 } else {
405 ScanOtherPuns = FALSE;
406 }
407 //
408 // Avoid creating handle for the host adapter.
409 //
410 if (ScsiBusDev->ExtScsiSupport) {
411 if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {
412 continue;
413 }
414 } else {
415 if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {
416 continue;
417 }
418 }
419 //
420 // Scan for the scsi device, if it attaches to the scsi bus,
421 // then create handle and install scsi i/o protocol.
422 //
423 Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev);
424 }
425 gBS->FreePool (ScsiTargetId);
426 return EFI_SUCCESS;
427
428 ErrorExit:
429
430 if (ScsiBusDev != NULL) {
431 gBS->FreePool (ScsiBusDev);
432 }
433
434 if (ExtScsiSupport) {
435 gBS->CloseProtocol (
436 Controller,
437 &gEfiExtScsiPassThruProtocolGuid,
438 This->DriverBindingHandle,
439 Controller
440 );
441 if (!EFI_ERROR (PassThruStatus)) {
442 gBS->CloseProtocol (
443 Controller,
444 &gEfiScsiPassThruProtocolGuid,
445 This->DriverBindingHandle,
446 Controller
447 );
448 }
449 } else {
450 gBS->CloseProtocol (
451 Controller,
452 &gEfiScsiPassThruProtocolGuid,
453 This->DriverBindingHandle,
454 Controller
455 );
456 }
457 return Status;
458 }
459
460 EFI_STATUS
461 EFIAPI
462 SCSIBusDriverBindingStop (
463 IN EFI_DRIVER_BINDING_PROTOCOL *This,
464 IN EFI_HANDLE Controller,
465 IN UINTN NumberOfChildren,
466 IN EFI_HANDLE *ChildHandleBuffer
467 )
468 /*++
469
470 Routine Description:
471
472 Stop this driver on ControllerHandle. Support stoping any child handles
473 created by this driver.
474
475 Arguments:
476
477 This - Protocol instance pointer.
478 Controller - Handle of device to stop driver on
479 NumberOfChildren - Number of Children in the ChildHandleBuffer
480 ChildHandleBuffer - List of handles for the children we need to stop.
481
482 Returns:
483
484 EFI_SUCCESS
485 Others
486 --*/
487 {
488 EFI_STATUS Status;
489 BOOLEAN AllChildrenStopped;
490 UINTN Index;
491 EFI_SCSI_IO_PROTOCOL *ScsiIo;
492 SCSI_IO_DEV *ScsiIoDevice;
493 VOID *ScsiPassThru;
494 EFI_SCSI_BUS_PROTOCOL *Scsidentifier;
495 SCSI_BUS_DEVICE *ScsiBusDev;
496
497 if (NumberOfChildren == 0) {
498 //
499 // Get the SCSI_BUS_DEVICE
500 //
501 Status = gBS->OpenProtocol (
502 Controller,
503 &mScsiBusProtocolGuid,
504 (VOID **) &Scsidentifier,
505 This->DriverBindingHandle,
506 Controller,
507 EFI_OPEN_PROTOCOL_GET_PROTOCOL
508 );
509
510 if (EFI_ERROR (Status)) {
511 return EFI_DEVICE_ERROR;
512 }
513
514 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier);
515
516 //
517 // Uninstall SCSI Bus Protocol
518 //
519 gBS->UninstallProtocolInterface (
520 Controller,
521 &mScsiBusProtocolGuid,
522 &ScsiBusDev->BusIdentify
523 );
524
525 //
526 // Close the bus driver
527 //
528 if (ScsiBusDev->ExtScsiSupport) {
529 gBS->CloseProtocol (
530 Controller,
531 &gEfiExtScsiPassThruProtocolGuid,
532 This->DriverBindingHandle,
533 Controller
534 );
535 } else {
536 gBS->CloseProtocol (
537 Controller,
538 &gEfiScsiPassThruProtocolGuid,
539 This->DriverBindingHandle,
540 Controller
541 );
542 }
543
544 gBS->CloseProtocol (
545 Controller,
546 &gEfiDevicePathProtocolGuid,
547 This->DriverBindingHandle,
548 Controller
549 );
550 gBS->FreePool (ScsiBusDev);
551 return EFI_SUCCESS;
552 }
553
554 AllChildrenStopped = TRUE;
555
556 for (Index = 0; Index < NumberOfChildren; Index++) {
557
558 Status = gBS->OpenProtocol (
559 ChildHandleBuffer[Index],
560 &gEfiScsiIoProtocolGuid,
561 (VOID **) &ScsiIo,
562 This->DriverBindingHandle,
563 Controller,
564 EFI_OPEN_PROTOCOL_GET_PROTOCOL
565 );
566 if (EFI_ERROR (Status)) {
567 AllChildrenStopped = FALSE;
568 continue;
569 }
570
571 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);
572 //
573 // Close the child handle
574 //
575 if (ScsiIoDevice->ExtScsiSupport) {
576 Status = gBS->CloseProtocol (
577 Controller,
578 &gEfiExtScsiPassThruProtocolGuid,
579 This->DriverBindingHandle,
580 ChildHandleBuffer[Index]
581 );
582
583 } else {
584 Status = gBS->CloseProtocol (
585 Controller,
586 &gEfiScsiPassThruProtocolGuid,
587 This->DriverBindingHandle,
588 ChildHandleBuffer[Index]
589 );
590 }
591
592 Status = gBS->UninstallMultipleProtocolInterfaces (
593 ChildHandleBuffer[Index],
594 &gEfiDevicePathProtocolGuid,
595 ScsiIoDevice->DevicePath,
596 &gEfiScsiIoProtocolGuid,
597 &ScsiIoDevice->ScsiIo,
598 NULL
599 );
600 if (EFI_ERROR (Status)) {
601 AllChildrenStopped = FALSE;
602 if (ScsiIoDevice->ExtScsiSupport) {
603 gBS->OpenProtocol (
604 Controller,
605 &gEfiExtScsiPassThruProtocolGuid,
606 &ScsiPassThru,
607 This->DriverBindingHandle,
608 ChildHandleBuffer[Index],
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
610 );
611 } else {
612 gBS->OpenProtocol (
613 Controller,
614 &gEfiScsiPassThruProtocolGuid,
615 &ScsiPassThru,
616 This->DriverBindingHandle,
617 ChildHandleBuffer[Index],
618 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
619 );
620 }
621 } else {
622 gBS->FreePool (ScsiIoDevice);
623 }
624 }
625
626 if (!AllChildrenStopped) {
627 return EFI_DEVICE_ERROR;
628 }
629
630 return EFI_SUCCESS;
631 }
632
633 EFI_STATUS
634 EFIAPI
635 ScsiGetDeviceType (
636 IN EFI_SCSI_IO_PROTOCOL *This,
637 OUT UINT8 *DeviceType
638 )
639 /*++
640
641 Routine Description:
642
643 Retrieves the device type information of the SCSI Controller.
644
645 Arguments:
646
647 This - Protocol instance pointer.
648 DeviceType - A pointer to the device type information
649 retrieved from the SCSI Controller.
650
651 Returns:
652
653 EFI_SUCCESS - Retrieves the device type information successfully.
654 EFI_INVALID_PARAMETER - The DeviceType is NULL.
655
656 --*/
657 {
658 SCSI_IO_DEV *ScsiIoDevice;
659
660 if (DeviceType == NULL) {
661 return EFI_INVALID_PARAMETER;
662 }
663
664 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
665 *DeviceType = ScsiIoDevice->ScsiDeviceType;
666 return EFI_SUCCESS;
667 }
668
669 EFI_STATUS
670 EFIAPI
671 ScsiGetDeviceLocation (
672 IN EFI_SCSI_IO_PROTOCOL *This,
673 IN OUT UINT8 **Target,
674 OUT UINT64 *Lun
675 )
676 /*++
677
678 Routine Description:
679
680 Retrieves the device location in the SCSI channel.
681
682 Arguments:
683
684 This - Protocol instance pointer.
685 Target - A pointer to the Target Array which represents ID of a SCSI device
686 on the SCSI channel.
687 Lun - A pointer to the LUN of the SCSI device on
688 the SCSI channel.
689
690 Returns:
691
692 EFI_SUCCESS - Retrieves the device location successfully.
693 EFI_INVALID_PARAMETER - The Target or Lun is NULL.
694
695 --*/
696 {
697 SCSI_IO_DEV *ScsiIoDevice;
698
699 if (Target == NULL || Lun == NULL) {
700 return EFI_INVALID_PARAMETER;
701 }
702
703 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
704
705 CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
706
707 *Lun = ScsiIoDevice->Lun;
708
709 return EFI_SUCCESS;
710 }
711
712 EFI_STATUS
713 EFIAPI
714 ScsiResetBus (
715 IN EFI_SCSI_IO_PROTOCOL *This
716 )
717 /*++
718
719 Routine Description:
720
721 Resets the SCSI Bus that the SCSI Controller is attached to.
722
723 Arguments:
724
725 This - Protocol instance pointer.
726
727 Returns:
728
729 EFI_SUCCESS - The SCSI bus is reset successfully.
730 EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus.
731 EFI_UNSUPPORTED - The bus reset operation is not supported by the
732 SCSI Host Controller.
733 EFI_TIMEOUT - A timeout occurred while attempting to reset
734 the SCSI bus.
735 --*/
736 {
737 SCSI_IO_DEV *ScsiIoDevice;
738
739 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
740
741 if (ScsiIoDevice->ExtScsiSupport){
742 return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru);
743 } else {
744 return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);
745 }
746 }
747
748 EFI_STATUS
749 EFIAPI
750 ScsiResetDevice (
751 IN EFI_SCSI_IO_PROTOCOL *This
752 )
753 /*++
754
755 Routine Description:
756
757 Resets the SCSI Controller that the device handle specifies.
758
759 Arguments:
760
761 This - Protocol instance pointer.
762
763 Returns:
764
765 EFI_SUCCESS - Reset the SCSI controller successfully.
766 EFI_DEVICE_ERROR - Errors are encountered when resetting the
767 SCSI Controller.
768 EFI_UNSUPPORTED - The SCSI bus does not support a device
769 reset operation.
770 EFI_TIMEOUT - A timeout occurred while attempting to
771 reset the SCSI Controller.
772 --*/
773 {
774 SCSI_IO_DEV *ScsiIoDevice;
775 UINT8 Target[TARGET_MAX_BYTES];
776
777 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
778 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
779
780
781 if (ScsiIoDevice->ExtScsiSupport) {
782 return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (
783 ScsiIoDevice->ExtScsiPassThru,
784 Target,
785 ScsiIoDevice->Lun
786 );
787 } else {
788 return ScsiIoDevice->ScsiPassThru->ResetTarget (
789 ScsiIoDevice->ScsiPassThru,
790 ScsiIoDevice->Pun.ScsiId.Scsi,
791 ScsiIoDevice->Lun
792 );
793 }
794 }
795
796 EFI_STATUS
797 EFIAPI
798 ScsiExecuteSCSICommand (
799 IN EFI_SCSI_IO_PROTOCOL *This,
800 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
801 IN EFI_EVENT Event OPTIONAL
802 )
803 /*++
804
805 Routine Description:
806
807 Sends a SCSI Request Packet to the SCSI Controller for execution.
808
809 Arguments:
810
811 This - Protocol instance pointer.
812 Packet - The SCSI request packet to send to the SCSI
813 Controller specified by the device handle.
814 Event - If the SCSI bus where the SCSI device is attached
815 does not support non-blocking I/O, then Event is
816 ignored, and blocking I/O is performed.
817 If Event is NULL, then blocking I/O is performed.
818 If Event is not NULL and non-blocking I/O is
819 supported, then non-blocking I/O is performed,
820 and Event will be signaled when the SCSI Request
821 Packet completes.
822 Returns:
823
824 EFI_SUCCESS - The SCSI Request Packet was sent by the host
825 successfully, and TransferLength bytes were
826 transferred to/from DataBuffer.See
827 HostAdapterStatus, TargetStatus,
828 SenseDataLength, and SenseData in that order
829 for additional status information.
830 EFI_BAD_BUFFER_SIZE - The SCSI Request Packet was executed,
831 but the entire DataBuffer could not be transferred.
832 The actual number of bytes transferred is returned
833 in TransferLength. See HostAdapterStatus,
834 TargetStatus, SenseDataLength, and SenseData in
835 that order for additional status information.
836 EFI_NOT_READY - The SCSI Request Packet could not be sent because
837 there are too many SCSI Command Packets already
838 queued.The caller may retry again later.
839 EFI_DEVICE_ERROR - A device error occurred while attempting to send
840 the SCSI Request Packet. See HostAdapterStatus,
841 TargetStatus, SenseDataLength, and SenseData in
842 that order for additional status information.
843 EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
844 The SCSI Request Packet was not sent, so no
845 additional status information is available.
846 EFI_UNSUPPORTED - The command described by the SCSI Request Packet
847 is not supported by the SCSI initiator(i.e., SCSI
848 Host Controller). The SCSI Request Packet was not
849 sent, so no additional status information is
850 available.
851 EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
852 Request Packet to execute. See HostAdapterStatus,
853 TargetStatus, SenseDataLength, and SenseData in
854 that order for additional status information.
855 --*/
856 {
857 SCSI_IO_DEV *ScsiIoDevice;
858 EFI_STATUS Status;
859 UINT8 Target[TARGET_MAX_BYTES];
860 EFI_EVENT PacketEvent;
861 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;
862 SCSI_EVENT_DATA EventData;
863
864 PacketEvent = NULL;
865
866 if (Packet == NULL) {
867 return EFI_INVALID_PARAMETER;
868 }
869
870 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
871 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
872
873 if (ScsiIoDevice->ExtScsiSupport) {
874 ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;
875 Status = ScsiIoDevice->ExtScsiPassThru->PassThru (
876 ScsiIoDevice->ExtScsiPassThru,
877 Target,
878 ScsiIoDevice->Lun,
879 ExtRequestPacket,
880 Event
881 );
882 } else {
883
884 Status = gBS->AllocatePool (
885 EfiBootServicesData,
886 sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),
887 (VOID**)&WorkingBuffer
888 );
889
890 if (EFI_ERROR (Status)) {
891 return EFI_DEVICE_ERROR;
892 }
893
894 //
895 // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.
896 //
897 Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer);
898 if (EFI_ERROR(Status)) {
899 gBS->FreePool(WorkingBuffer);
900 return Status;
901 }
902
903 if ((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) && (Event != NULL)) {
904 EventData.Data1 = (VOID*)Packet;
905 EventData.Data2 = Event;
906 //
907 // Create Event
908 //
909 Status = gBS->CreateEvent (
910 EVT_NOTIFY_SIGNAL,
911 TPL_CALLBACK,
912 NotifyFunction,
913 &EventData,
914 &PacketEvent
915 );
916 if (EFI_ERROR(Status)) {
917 gBS->FreePool(WorkingBuffer);
918 return Status;
919 }
920
921 Status = ScsiIoDevice->ScsiPassThru->PassThru (
922 ScsiIoDevice->ScsiPassThru,
923 ScsiIoDevice->Pun.ScsiId.Scsi,
924 ScsiIoDevice->Lun,
925 WorkingBuffer,
926 PacketEvent
927 );
928
929 if (EFI_ERROR(Status)) {
930 gBS->FreePool(WorkingBuffer);
931 gBS->CloseEvent(PacketEvent);
932 return Status;
933 }
934
935 } else {
936 //
937 // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert
938 // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet.
939 //
940 Status = ScsiIoDevice->ScsiPassThru->PassThru (
941 ScsiIoDevice->ScsiPassThru,
942 ScsiIoDevice->Pun.ScsiId.Scsi,
943 ScsiIoDevice->Lun,
944 WorkingBuffer,
945 Event
946 );
947 if (EFI_ERROR(Status)) {
948 gBS->FreePool(WorkingBuffer);
949 return Status;
950 }
951
952 PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer,Packet);
953 //
954 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
955 // free WorkingBuffer.
956 //
957 gBS->FreePool(WorkingBuffer);
958 }
959 }
960 return Status;
961 }
962
963 EFI_STATUS
964 EFIAPI
965 ScsiScanCreateDevice (
966 EFI_DRIVER_BINDING_PROTOCOL *This,
967 EFI_HANDLE Controller,
968 SCSI_TARGET_ID *TargetId,
969 UINT64 Lun,
970 SCSI_BUS_DEVICE *ScsiBusDev
971 )
972 /*++
973
974 Routine Description:
975
976 Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.
977
978 Arguments:
979
980 This - Protocol instance pointer
981 Controller - Controller handle
982 Pun - The Pun of the SCSI device on the SCSI channel.
983 Lun - The Lun of the SCSI device on the SCSI channel.
984 ScsiBusDev - The pointer of SCSI_BUS_DEVICE
985
986 Returns:
987
988 EFI_SUCCESS - Successfully to discover the device and attach ScsiIoProtocol to it.
989 EFI_OUT_OF_RESOURCES - Fail to discover the device.
990
991 --*/
992 {
993 EFI_STATUS Status;
994 SCSI_IO_DEV *ScsiIoDevice;
995 EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
996
997 Status = gBS->AllocatePool (
998 EfiBootServicesData,
999 sizeof (SCSI_IO_DEV),
1000 (VOID **) &ScsiIoDevice
1001 );
1002 if (EFI_ERROR (Status)) {
1003 return Status;
1004 }
1005
1006 ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));
1007
1008 ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
1009 CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);
1010 ScsiIoDevice->Lun = Lun;
1011
1012 if (ScsiBusDev->ExtScsiSupport) {
1013 ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface;
1014 ScsiIoDevice->ExtScsiSupport = TRUE;
1015 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;
1016
1017 } else {
1018 ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface;
1019 ScsiIoDevice->ExtScsiSupport = FALSE;
1020 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;
1021 }
1022
1023 ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;
1024 ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;
1025 ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;
1026 ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
1027 ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
1028
1029
1030 if (!DiscoverScsiDevice (ScsiIoDevice)) {
1031 gBS->FreePool (ScsiIoDevice);
1032 return EFI_OUT_OF_RESOURCES;
1033 }
1034
1035 //
1036 // Set Device Path
1037 //
1038 if (ScsiIoDevice->ExtScsiSupport){
1039 Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (
1040 ScsiIoDevice->ExtScsiPassThru,
1041 &ScsiIoDevice->Pun.ScsiId.ExtScsi[0],
1042 ScsiIoDevice->Lun,
1043 &ScsiDevicePath
1044 );
1045 if (Status == EFI_OUT_OF_RESOURCES) {
1046 gBS->FreePool (ScsiIoDevice);
1047 return Status;
1048 }
1049 } else {
1050 Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
1051 ScsiIoDevice->ScsiPassThru,
1052 ScsiIoDevice->Pun.ScsiId.Scsi,
1053 ScsiIoDevice->Lun,
1054 &ScsiDevicePath
1055 );
1056 if (Status == EFI_OUT_OF_RESOURCES) {
1057 gBS->FreePool (ScsiIoDevice);
1058 return Status;
1059 }
1060 }
1061
1062 ScsiIoDevice->DevicePath = AppendDevicePathNode (
1063 ScsiBusDev->DevicePath,
1064 ScsiDevicePath
1065 );
1066 //
1067 // The memory space for ScsiDevicePath is allocated in
1068 // ScsiPassThru->BuildDevicePath() function; It is no longer used
1069 // after EfiAppendDevicePathNode,so free the memory it occupies.
1070 //
1071 gBS->FreePool (ScsiDevicePath);
1072
1073 if (ScsiIoDevice->DevicePath == NULL) {
1074 gBS->FreePool (ScsiIoDevice);
1075 return EFI_OUT_OF_RESOURCES;
1076 }
1077
1078 Status = gBS->InstallMultipleProtocolInterfaces (
1079 &ScsiIoDevice->Handle,
1080 &gEfiDevicePathProtocolGuid,
1081 ScsiIoDevice->DevicePath,
1082 &gEfiScsiIoProtocolGuid,
1083 &ScsiIoDevice->ScsiIo,
1084 NULL
1085 );
1086 if (EFI_ERROR (Status)) {
1087 gBS->FreePool (ScsiIoDevice);
1088 return EFI_OUT_OF_RESOURCES;
1089 } else {
1090 if (ScsiBusDev->ExtScsiSupport) {
1091 gBS->OpenProtocol (
1092 Controller,
1093 &gEfiExtScsiPassThruProtocolGuid,
1094 (VOID **) &(ScsiBusDev->ExtScsiInterface),
1095 This->DriverBindingHandle,
1096 ScsiIoDevice->Handle,
1097 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1098 );
1099 } else {
1100 gBS->OpenProtocol (
1101 Controller,
1102 &gEfiScsiPassThruProtocolGuid,
1103 (VOID **) &(ScsiBusDev->ScsiInterface),
1104 This->DriverBindingHandle,
1105 ScsiIoDevice->Handle,
1106 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1107 );
1108 }
1109 }
1110 return EFI_SUCCESS;
1111 }
1112
1113 BOOLEAN
1114 EFIAPI
1115 DiscoverScsiDevice (
1116 SCSI_IO_DEV *ScsiIoDevice
1117 )
1118 /*++
1119
1120 Routine Description:
1121
1122 Discovery SCSI Device
1123
1124 Arguments:
1125
1126 ScsiIoDevice - The pointer of SCSI_IO_DEV
1127
1128 Returns:
1129
1130 TRUE - Find SCSI Device and verify it.
1131 FALSE - Unable to find SCSI Device.
1132
1133 --*/
1134 {
1135 EFI_STATUS Status;
1136 UINT32 InquiryDataLength;
1137 UINT8 SenseDataLength;
1138 UINT8 HostAdapterStatus;
1139 UINT8 TargetStatus;
1140 EFI_SCSI_SENSE_DATA SenseData;
1141 EFI_SCSI_INQUIRY_DATA InquiryData;
1142
1143 HostAdapterStatus = 0;
1144 TargetStatus = 0;
1145 //
1146 // Using Inquiry command to scan for the device
1147 //
1148 InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
1149 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
1150
1151 Status = ScsiInquiryCommand (
1152 &ScsiIoDevice->ScsiIo,
1153 EfiScsiStallSeconds (1),
1154 (VOID *) &SenseData,
1155 &SenseDataLength,
1156 &HostAdapterStatus,
1157 &TargetStatus,
1158 (VOID *) &InquiryData,
1159 &InquiryDataLength,
1160 FALSE
1161 );
1162 if (EFI_ERROR (Status)) {
1163 //
1164 // ParseSenseData (&SenseData,SenseDataLength);
1165 //
1166 return FALSE;
1167 }
1168 //
1169 // Retrieved inquiry data successfully
1170 //
1171 if ((InquiryData.Peripheral_Qualifier != 0) &&
1172 (InquiryData.Peripheral_Qualifier != 3)) {
1173 return FALSE;
1174 }
1175
1176 if (InquiryData.Peripheral_Qualifier == 3) {
1177 if (InquiryData.Peripheral_Type != 0x1f) {
1178 return FALSE;
1179 }
1180 }
1181
1182 if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {
1183 return FALSE;
1184 }
1185
1186 //
1187 // valid device type and peripheral qualifier combination.
1188 //
1189 ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;
1190 ScsiIoDevice->RemovableDevice = InquiryData.RMB;
1191 if (InquiryData.Version == 0) {
1192 ScsiIoDevice->ScsiVersion = 0;
1193 } else {
1194 //
1195 // ANSI-approved version
1196 //
1197 ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);
1198 }
1199
1200 return TRUE;
1201 }
1202
1203
1204 STATIC
1205 EFI_STATUS
1206 EFIAPI
1207 ScsiioToPassThruPacket (
1208 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
1209 IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
1210 )
1211 /*++
1212
1213 Routine Description:
1214
1215 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to
1216 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet
1217
1218 Arguments:
1219
1220 Packet - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
1221 CommandPacket - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
1222
1223 Returns:
1224
1225 NONE
1226
1227 --*/
1228 {
1229 //
1230 //EFI 1.10 doesn't support Bi-Direction Command.
1231 //
1232 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {
1233 return EFI_UNSUPPORTED;
1234 }
1235
1236 ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
1237
1238 CommandPacket->Timeout = Packet->Timeout;
1239 CommandPacket->Cdb = Packet->Cdb;
1240 CommandPacket->CdbLength = Packet->CdbLength;
1241 CommandPacket->DataDirection = Packet->DataDirection;
1242 CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus;
1243 CommandPacket->TargetStatus = Packet->TargetStatus;
1244 CommandPacket->SenseData = Packet->SenseData;
1245 CommandPacket->SenseDataLength = Packet->SenseDataLength;
1246
1247 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
1248 CommandPacket->DataBuffer = Packet->InDataBuffer;
1249 CommandPacket->TransferLength = Packet->InTransferLength;
1250 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
1251 CommandPacket->DataBuffer = Packet->OutDataBuffer;
1252 CommandPacket->TransferLength = Packet->OutTransferLength;
1253 }
1254 return EFI_SUCCESS;
1255 }
1256
1257
1258 STATIC
1259 EFI_STATUS
1260 EFIAPI
1261 PassThruToScsiioPacket (
1262 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
1263 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
1264 )
1265 /*++
1266
1267 Routine Description:
1268
1269 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to
1270 EFI_SCSI_IO_SCSI_REQUEST_PACKET packet
1271
1272 Arguments:
1273
1274 ScsiPacket - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
1275 Packet - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
1276
1277 Returns:
1278
1279 NONE
1280
1281 --*/
1282 {
1283 Packet->Timeout = ScsiPacket->Timeout;
1284 Packet->Cdb = ScsiPacket->Cdb;
1285 Packet->CdbLength = ScsiPacket->CdbLength;
1286 Packet->DataDirection = ScsiPacket->DataDirection;
1287 Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus;
1288 Packet->TargetStatus = ScsiPacket->TargetStatus;
1289 Packet->SenseData = ScsiPacket->SenseData;
1290 Packet->SenseDataLength = ScsiPacket->SenseDataLength;
1291
1292 if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
1293 Packet->InDataBuffer = ScsiPacket->DataBuffer;
1294 Packet->InTransferLength = ScsiPacket->TransferLength;
1295 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
1296 Packet->OutDataBuffer = ScsiPacket->DataBuffer;
1297 Packet->OutTransferLength = ScsiPacket->TransferLength;
1298 }
1299
1300 return EFI_SUCCESS;
1301 }
1302
1303
1304
1305 STATIC
1306 VOID
1307 EFIAPI
1308 NotifyFunction (
1309 EFI_EVENT Event,
1310 VOID *Context
1311 )
1312 /*++
1313
1314 Routine Description:
1315
1316 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
1317 SCSI IO Packet.
1318
1319 Arguments:
1320
1321 Event - The instance of EFI_EVENT.
1322 Context - The parameter passed in.
1323
1324 Returns:
1325
1326 NONE
1327
1328 --*/
1329 {
1330 EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet;
1331 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket;
1332 EFI_EVENT CallerEvent;
1333 SCSI_EVENT_DATA *PassData;
1334
1335 PassData = (SCSI_EVENT_DATA*)Context;
1336 Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;
1337 ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer;
1338
1339 //
1340 // Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.
1341 //
1342 PassThruToScsiioPacket(ScsiPacket, Packet);
1343
1344 //
1345 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
1346 // free WorkingBuffer.
1347 //
1348 gBS->FreePool(WorkingBuffer);
1349
1350 //
1351 // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.
1352 //
1353 CallerEvent = PassData->Data2;
1354 gBS->CloseEvent(Event);
1355 gBS->SignalEvent(CallerEvent);
1356 }