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