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