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