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