]> git.proxmox.com Git - mirror_edk2.git/blame - 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
3b2dbece 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
3a10d471 4\r
3b2dbece 5Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
c52fa98c 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
3a10d471 13\r
3b2dbece 14**/\r
3a10d471 15\r
ed7748fe 16\r
60c93673 17#include <Uefi.h>\r
3a10d471 18\r
ed7748fe 19\r
3a10d471 20#include <Protocol/ScsiPassThru.h>\r
70c94b3b 21#include <Protocol/ScsiPassThruExt.h>\r
3a10d471 22#include <Protocol/ScsiIo.h>\r
23#include <Protocol/ComponentName.h>\r
24#include <Protocol/DriverBinding.h>\r
25#include <Protocol/DevicePath.h>\r
ed7748fe 26\r
3a10d471 27#include <Library/DebugLib.h>\r
28#include <Library/UefiDriverEntryPoint.h>\r
29#include <Library/UefiLib.h>\r
30#include <Library/BaseMemoryLib.h>\r
70c94b3b 31#include <Library/MemoryAllocationLib.h>\r
3a10d471 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
70c94b3b 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
ed66e1bc 63 );\r
70c94b3b 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
ed66e1bc 72 );\r
70c94b3b 73STATIC\r
74VOID\r
75EFIAPI\r
76NotifyFunction (\r
77 EFI_EVENT Event,\r
78 VOID *Context\r
ed66e1bc 79 );\r
70c94b3b 80\r
3a10d471 81/**\r
82 The user Entry Point for module ScsiBus. The user code starts with this function.\r
83\r
c52fa98c 84 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
3a10d471 85 @param[in] SystemTable A pointer to the EFI System Table.\r
c52fa98c 86\r
3a10d471 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
70da5bc2 103 Status = EfiLibInstallDriverBindingComponentName2 (\r
3a10d471 104 ImageHandle,\r
105 SystemTable,\r
106 &gSCSIBusDriverBinding,\r
107 ImageHandle,\r
108 &gScsiBusComponentName,\r
70da5bc2 109 &gScsiBusComponentName2\r
3a10d471 110 );\r
111 ASSERT_EFI_ERROR (Status);\r
112\r
3a10d471 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
70c94b3b 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
3a10d471 141--*/\r
70c94b3b 142\r
3a10d471 143{\r
144 EFI_STATUS Status;\r
70c94b3b 145 EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
146 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\r
3a10d471 147 //\r
70c94b3b 148 // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol\r
3a10d471 149 //\r
150 Status = gBS->OpenProtocol (\r
151 Controller,\r
70c94b3b 152 &gEfiExtScsiPassThruProtocolGuid,\r
153 (VOID **)&ExtPassThru,\r
3a10d471 154 This->DriverBindingHandle,\r
155 Controller,\r
70c94b3b 156 EFI_OPEN_PROTOCOL_BY_DRIVER\r
3a10d471 157 );\r
c52fa98c 158\r
70c94b3b 159 if (Status == EFI_ALREADY_STARTED) {\r
160 return EFI_SUCCESS;\r
161 }\r
c52fa98c 162\r
70c94b3b 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
c52fa98c 172\r
70c94b3b 173 if (Status == EFI_ALREADY_STARTED) {\r
174 return EFI_SUCCESS;\r
175 }\r
c52fa98c 176\r
70c94b3b 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
3a10d471 188 }\r
c52fa98c 189\r
70c94b3b 190 gBS->CloseProtocol (\r
191 Controller,\r
192 &gEfiExtScsiPassThruProtocolGuid,\r
193 This->DriverBindingHandle,\r
194 Controller\r
195 );\r
3a10d471 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
70c94b3b 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
3a10d471 222--*/\r
3a10d471 223{\r
f36d6e66 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
70c94b3b 242 FromFirstTarget = FALSE;\r
f36d6e66 243 ExtScsiSupport = FALSE;\r
244 PassThruStatus = EFI_SUCCESS;\r
245 \r
246 ScsiTargetId = AllocateZeroPool(sizeof(SCSI_TARGET_ID));\r
70c94b3b 247 if (ScsiTargetId == NULL) {\r
248 return EFI_OUT_OF_RESOURCES;\r
249 }\r
250\r
251 TargetId = &ScsiTargetId->ScsiId.ExtScsi[0];\r
f36d6e66 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
3a10d471 263 }\r
264\r
265 //\r
f36d6e66 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
3a10d471 269 //\r
270 Status = gBS->OpenProtocol (\r
271 Controller,\r
70c94b3b 272 &gEfiExtScsiPassThruProtocolGuid,\r
f36d6e66 273 (VOID **) &ExtScsiInterface,\r
3a10d471 274 This->DriverBindingHandle,\r
275 Controller,\r
276 EFI_OPEN_PROTOCOL_BY_DRIVER\r
277 );\r
f36d6e66 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
70c94b3b 282 Status = gBS->OpenProtocol (\r
283 Controller,\r
284 &gEfiScsiPassThruProtocolGuid,\r
f36d6e66 285 (VOID **) &ScsiInterface,\r
70c94b3b 286 This->DriverBindingHandle,\r
287 Controller,\r
288 EFI_OPEN_PROTOCOL_BY_DRIVER\r
289 );\r
f36d6e66 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
70c94b3b 302 return Status;\r
f36d6e66 303 } \r
70c94b3b 304 } else {\r
f36d6e66 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
70c94b3b 319 }\r
f36d6e66 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
70c94b3b 335 if (ScsiBusDev->ExtScsiSupport) {\r
f36d6e66 336 ScsiBusDev->ExtScsiInterface = ExtScsiInterface;\r
70c94b3b 337 } else {\r
f36d6e66 338 ScsiBusDev->ScsiInterface = ScsiInterface; \r
70c94b3b 339 }\r
f36d6e66 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
3a10d471 373 }\r
374\r
375 if (RemainingDevicePath == NULL) {\r
70c94b3b 376 SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);\r
377 Lun = 0;\r
378 FromFirstTarget = TRUE;\r
3a10d471 379 } else {\r
70c94b3b 380 if (ScsiBusDev->ExtScsiSupport) {\r
f36d6e66 381 ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun); \r
70c94b3b 382 } else {\r
383 ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);\r
384 }\r
3a10d471 385 }\r
386\r
70c94b3b 387 while(ScanOtherPuns) {\r
388 if (FromFirstTarget) {\r
3a10d471 389 //\r
390 // Remaining Device Path is NULL, scan all the possible Puns in the\r
391 // SCSI Channel.\r
392 //\r
70c94b3b 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
3a10d471 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
3a10d471 405 ScanOtherPuns = FALSE;\r
406 }\r
3a10d471 407 //\r
408 // Avoid creating handle for the host adapter.\r
409 //\r
70c94b3b 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
3a10d471 418 }\r
3a10d471 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
70c94b3b 423 Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev);\r
3a10d471 424 }\r
f36d6e66 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
3a10d471 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
c52fa98c 469\r
f36d6e66 470Routine Description:\r
471\r
472 Stop this driver on ControllerHandle. Support stoping any child handles\r
473 created by this driver.\r
c52fa98c 474\r
f36d6e66 475Arguments:\r
c52fa98c 476\r
f36d6e66 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
c52fa98c 481\r
f36d6e66 482Returns:\r
483\r
484 EFI_SUCCESS\r
485 Others\r
3a10d471 486--*/\r
3a10d471 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
70c94b3b 493 VOID *ScsiPassThru;\r
494 EFI_SCSI_BUS_PROTOCOL *Scsidentifier;\r
495 SCSI_BUS_DEVICE *ScsiBusDev;\r
3a10d471 496\r
497 if (NumberOfChildren == 0) {\r
70c94b3b 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
c52fa98c 509\r
70c94b3b 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
c52fa98c 524\r
3a10d471 525 //\r
526 // Close the bus driver\r
527 //\r
70c94b3b 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
3a10d471 543\r
70c94b3b 544 gBS->CloseProtocol (\r
545 Controller,\r
546 &gEfiDevicePathProtocolGuid,\r
547 This->DriverBindingHandle,\r
548 Controller\r
549 );\r
550 gBS->FreePool (ScsiBusDev);\r
3a10d471 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
70c94b3b 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
3a10d471 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
70c94b3b 602 if (ScsiIoDevice->ExtScsiSupport) {\r
603 gBS->OpenProtocol (\r
604 Controller,\r
605 &gEfiExtScsiPassThruProtocolGuid,\r
84b5c78e 606 &ScsiPassThru,\r
70c94b3b 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
84b5c78e 615 &ScsiPassThru,\r
70c94b3b 616 This->DriverBindingHandle,\r
617 ChildHandleBuffer[Index],\r
618 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
619 );\r
620 }\r
3a10d471 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
f36d6e66 641Routine Description:\r
642\r
643 Retrieves the device type information of the SCSI Controller.\r
644 \r
645Arguments:\r
c52fa98c 646\r
f36d6e66 647 This - Protocol instance pointer.\r
648 DeviceType - A pointer to the device type information\r
649 retrieved from the SCSI Controller. \r
3a10d471 650\r
f36d6e66 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
3a10d471 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
3a10d471 669EFI_STATUS\r
670EFIAPI\r
671ScsiGetDeviceLocation (\r
672 IN EFI_SCSI_IO_PROTOCOL *This,\r
70c94b3b 673 IN OUT UINT8 **Target,\r
3a10d471 674 OUT UINT64 *Lun\r
675 )\r
676/*++\r
f36d6e66 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
3a10d471 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
f36d6e66 703 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
3a10d471 704\r
70c94b3b 705 CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
706\r
f36d6e66 707 *Lun = ScsiIoDevice->Lun;\r
3a10d471 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
f36d6e66 719Routine Description:\r
c52fa98c 720\r
f36d6e66 721 Resets the SCSI Bus that the SCSI Controller is attached to.\r
722 \r
723Arguments:\r
3a10d471 724\r
f36d6e66 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
3a10d471 735--*/\r
736{\r
737 SCSI_IO_DEV *ScsiIoDevice;\r
738\r
739 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
740\r
70c94b3b 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
3a10d471 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
f36d6e66 755Routine Description:\r
c52fa98c 756\r
f36d6e66 757 Resets the SCSI Controller that the device handle specifies.\r
758 \r
759Arguments:\r
c52fa98c 760\r
f36d6e66 761 This - Protocol instance pointer.\r
762 \r
763Returns:\r
3a10d471 764\r
f36d6e66 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
3a10d471 772--*/\r
773{\r
f36d6e66 774 SCSI_IO_DEV *ScsiIoDevice;\r
70c94b3b 775 UINT8 Target[TARGET_MAX_BYTES];\r
3a10d471 776\r
777 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
70c94b3b 778 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
779\r
3a10d471 780\r
70c94b3b 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
3a10d471 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
f36d6e66 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
3a10d471 855--*/\r
856{\r
f36d6e66 857 SCSI_IO_DEV *ScsiIoDevice;\r
858 EFI_STATUS Status;\r
70c94b3b 859 UINT8 Target[TARGET_MAX_BYTES];\r
860 EFI_EVENT PacketEvent;\r
861 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;\r
f36d6e66 862 SCSI_EVENT_DATA EventData; \r
3a10d471 863\r
70c94b3b 864 PacketEvent = NULL;\r
f36d6e66 865 \r
3a10d471 866 if (Packet == NULL) {\r
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869\r
870 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
70c94b3b 871 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
c52fa98c 872\r
70c94b3b 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
3a10d471 883\r
70c94b3b 884 Status = gBS->AllocatePool (\r
885 EfiBootServicesData,\r
886 sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),\r
887 (VOID**)&WorkingBuffer\r
888 );\r
3a10d471 889\r
70c94b3b 890 if (EFI_ERROR (Status)) {\r
891 return EFI_DEVICE_ERROR;\r
892 }\r
893\r
894 //\r
c52fa98c 895 // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.\r
70c94b3b 896 //\r
897 Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer);\r
898 if (EFI_ERROR(Status)) {\r
c52fa98c 899 gBS->FreePool(WorkingBuffer);\r
70c94b3b 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
c52fa98c 920\r
70c94b3b 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
c52fa98c 934\r
70c94b3b 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
3a10d471 960 return Status;\r
961}\r
962\r
963EFI_STATUS\r
c52fa98c 964EFIAPI\r
3a10d471 965ScsiScanCreateDevice (\r
966 EFI_DRIVER_BINDING_PROTOCOL *This,\r
967 EFI_HANDLE Controller,\r
70c94b3b 968 SCSI_TARGET_ID *TargetId,\r
3a10d471 969 UINT64 Lun,\r
70c94b3b 970 SCSI_BUS_DEVICE *ScsiBusDev\r
3a10d471 971 )\r
972/*++\r
973\r
974Routine Description:\r
975\r
70c94b3b 976 Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\r
3a10d471 977\r
978Arguments:\r
979\r
70c94b3b 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
3a10d471 985\r
986Returns:\r
987\r
70c94b3b 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
3a10d471 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
70c94b3b 1009 CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);\r
3a10d471 1010 ScsiIoDevice->Lun = Lun;\r
1011\r
70c94b3b 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
3a10d471 1023 ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;\r
70c94b3b 1024 ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;\r
3a10d471 1025 ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;\r
1026 ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;\r
24e734d2 1027 ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
3a10d471 1028\r
70c94b3b 1029\r
3a10d471 1030 if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
1031 gBS->FreePool (ScsiIoDevice);\r
70c94b3b 1032 return EFI_OUT_OF_RESOURCES;\r
3a10d471 1033 }\r
70c94b3b 1034\r
3a10d471 1035 //\r
1036 // Set Device Path\r
1037 //\r
70c94b3b 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
3a10d471 1060 }\r
c52fa98c 1061\r
3a10d471 1062 ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
70c94b3b 1063 ScsiBusDev->DevicePath,\r
3a10d471 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
c52fa98c 1077\r
3a10d471 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
70c94b3b 1088 return EFI_OUT_OF_RESOURCES;\r
3a10d471 1089 } else {\r
70c94b3b 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
3a10d471 1109 }\r
3a10d471 1110 return EFI_SUCCESS;\r
1111}\r
1112\r
1113BOOLEAN\r
c52fa98c 1114EFIAPI\r
3a10d471 1115DiscoverScsiDevice (\r
1116 SCSI_IO_DEV *ScsiIoDevice\r
1117 )\r
1118/*++\r
1119\r
1120Routine Description:\r
1121\r
70c94b3b 1122 Discovery SCSI Device\r
3a10d471 1123\r
1124Arguments:\r
1125\r
70c94b3b 1126 ScsiIoDevice - The pointer of SCSI_IO_DEV\r
3a10d471 1127\r
1128Returns:\r
1129\r
70c94b3b 1130 TRUE - Find SCSI Device and verify it.\r
c52fa98c 1131 FALSE - Unable to find SCSI Device.\r
3a10d471 1132\r
1133--*/\r
1134{\r
1135 EFI_STATUS Status;\r
3a10d471 1136 UINT32 InquiryDataLength;\r
3a10d471 1137 UINT8 SenseDataLength;\r
1138 UINT8 HostAdapterStatus;\r
1139 UINT8 TargetStatus;\r
70c94b3b 1140 EFI_SCSI_SENSE_DATA SenseData;\r
1141 EFI_SCSI_INQUIRY_DATA InquiryData;\r
3a10d471 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
d35be2a4 1151 Status = ScsiInquiryCommand (\r
3a10d471 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
67a58d0f 1182 if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {\r
3a10d471 1183 return FALSE;\r
1184 }\r
c52fa98c 1185\r
3a10d471 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
70c94b3b 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
c52fa98c 1215 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to\r
70c94b3b 1216 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet\r
c52fa98c 1217\r
70c94b3b 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
c52fa98c 1222\r
70c94b3b 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
c52fa98c 1235\r
70c94b3b 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
c52fa98c 1269 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to\r
70c94b3b 1270 EFI_SCSI_IO_SCSI_REQUEST_PACKET packet\r
c52fa98c 1271\r
70c94b3b 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
c52fa98c 1276\r
70c94b3b 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
c52fa98c 1299\r
70c94b3b 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
c52fa98c 1316 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0\r
70c94b3b 1317 SCSI IO Packet.\r
c52fa98c 1318\r
70c94b3b 1319Arguments:\r
1320\r
1321 Event - The instance of EFI_EVENT.\r
1322 Context - The parameter passed in.\r
c52fa98c 1323\r
70c94b3b 1324Returns:\r
1325\r
1326 NONE\r
1327\r
c52fa98c 1328--*/\r
70c94b3b 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
c52fa98c 1333 SCSI_EVENT_DATA *PassData;\r
70c94b3b 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
c52fa98c 1343\r
70c94b3b 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