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