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