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