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