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