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