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