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