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