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