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