68f3683bb632cfc0cda7f1a700511c883309fdff
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
1 /*++\r
2 \r
3 Copyright (c) 2006, Intel Corporation                                                         \r
4 All rights reserved. This program and the accompanying materials                          \r
5 are licensed and made available under the terms and conditions of the BSD License         \r
6 which accompanies this distribution.  The full text of the license may be found at        \r
7 http://opensource.org/licenses/bsd-license.php                                            \r
8                                                                                           \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
11 \r
12 Module Name:\r
13 \r
14     scsibus.c\r
15     \r
16 Abstract: \r
17     \r
18 \r
19 Revision 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
31 #include <Protocol/ScsiPassThruExt.h>\r
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
43 #include <Library/MemoryAllocationLib.h>\r
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
50 EFI_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
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
65 STATIC EFI_GUID  mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;\r
66 \r
67 STATIC VOID  *WorkingBuffer;\r
68 \r
69 STATIC\r
70 EFI_STATUS\r
71 EFIAPI\r
72 ScsiioToPassThruPacket (\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
79 STATIC\r
80 EFI_STATUS\r
81 EFIAPI\r
82 PassThruToScsiioPacket (\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
87 STATIC\r
88 VOID\r
89 EFIAPI\r
90 NotifyFunction (\r
91   EFI_EVENT  Event,\r
92   VOID       *Context\r
93   )\r
94 ;\r
95 \r
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
106 EFI_STATUS\r
107 EFIAPI\r
108 InitializeScsiBus(\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
133 EFI_STATUS\r
134 EFIAPI\r
135 SCSIBusDriverBindingSupported (\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
141 \r
142 Routine 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
147 Arguments:\r
148 \r
149   This                - Protocol instance pointer.\r
150   Controller          - Handle of device to test\r
151   RemainingDevicePath - Not used\r
152 \r
153 Returns:\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
158 --*/\r
159 \r
160 {\r
161   EFI_STATUS  Status;\r
162   EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
163   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\r
164   //\r
165   // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol\r
166   //\r
167   Status = gBS->OpenProtocol (\r
168                   Controller,\r
169                   &gEfiExtScsiPassThruProtocolGuid,\r
170                   (VOID **)&ExtPassThru,\r
171                   This->DriverBindingHandle,\r
172                   Controller,\r
173                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
174                   );\r
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
205   }\r
206   \r
207   gBS->CloseProtocol (\r
208     Controller,\r
209     &gEfiExtScsiPassThruProtocolGuid,\r
210     This->DriverBindingHandle,\r
211     Controller\r
212     );\r
213 \r
214   return EFI_SUCCESS;\r
215 }\r
216 \r
217 EFI_STATUS\r
218 EFIAPI\r
219 SCSIBusDriverBindingStart (\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
225 \r
226 Routine Description:\r
227   Starting the SCSI Bus Driver\r
228 \r
229 Arguments:\r
230   This                - Protocol instance pointer.\r
231   Controller          - Handle of device to test\r
232   RemainingDevicePath - Not used\r
233 \r
234 Returns:\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
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
245   UINT64                      Lun;\r
246   BOOLEAN                     ScanOtherPuns;\r
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
263 \r
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
272   Status = gBS->OpenProtocol (\r
273                   Controller,\r
274                   &gEfiDevicePathProtocolGuid,\r
275                   (VOID **) &(ScsiBusDev->DevicePath),\r
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
281     gBS->FreePool (ScsiBusDev);\r
282     return Status;\r
283   }\r
284 \r
285   //\r
286   // First consume Extended SCSI Pass Thru protocol, if fail, then consume\r
287   // SCSI Pass Thru protocol\r
288   //\r
289   Status = gBS->OpenProtocol (\r
290                   Controller,\r
291                   &gEfiExtScsiPassThruProtocolGuid,\r
292                   (VOID **) &(ScsiBusDev->ExtScsiInterface),\r
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
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
335     gBS->CloseProtocol (\r
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
357     return Status;\r
358   }\r
359 \r
360   if (RemainingDevicePath == NULL) {\r
361     SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);\r
362     Lun  = 0;\r
363     FromFirstTarget = TRUE;\r
364   } else {\r
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
370   }\r
371 \r
372   while(ScanOtherPuns) {\r
373     if (FromFirstTarget) {\r
374       //\r
375       // Remaining Device Path is NULL, scan all the possible Puns in the\r
376       // SCSI Channel.\r
377       //\r
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
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
390       ScanOtherPuns = FALSE;\r
391     }\r
392     //\r
393     // Avoid creating handle for the host adapter.\r
394     //\r
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
403     }\r
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
408     Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev);\r
409   }\r
410   return Status;\r
411 }\r
412 \r
413 EFI_STATUS\r
414 EFIAPI\r
415 SCSIBusDriverBindingStop (\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
443   VOID                        *ScsiPassThru;\r
444   EFI_SCSI_BUS_PROTOCOL       *Scsidentifier;\r
445   SCSI_BUS_DEVICE             *ScsiBusDev;\r
446 \r
447   if (NumberOfChildren == 0) {\r
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
475     //\r
476     // Close the bus driver\r
477     //\r
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
493 \r
494     gBS->CloseProtocol (\r
495            Controller,\r
496            &gEfiDevicePathProtocolGuid,\r
497            This->DriverBindingHandle,\r
498            Controller\r
499            );\r
500     gBS->FreePool (ScsiBusDev);\r
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
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
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
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
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
583 EFI_STATUS\r
584 EFIAPI\r
585 ScsiGetDeviceType (\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
615 EFI_STATUS\r
616 EFIAPI\r
617 ScsiGetDeviceLocation (\r
618   IN  EFI_SCSI_IO_PROTOCOL    *This,\r
619   IN OUT UINT8                **Target,\r
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
646   CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
647 \r
648   *Lun          = ScsiIoDevice->Lun;\r
649 \r
650   return EFI_SUCCESS;\r
651 }\r
652 \r
653 EFI_STATUS\r
654 EFIAPI\r
655 ScsiResetBus (\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
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
684 }\r
685 \r
686 EFI_STATUS\r
687 EFIAPI\r
688 ScsiResetDevice (\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
711   UINT8        Target[TARGET_MAX_BYTES];\r
712 \r
713   ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
714   CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
715 \r
716 \r
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
730 }\r
731 \r
732 EFI_STATUS\r
733 EFIAPI\r
734 ScsiExecuteSCSICommand (\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
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
796 \r
797   PacketEvent = NULL;\r
798   \r
799   if (Packet == NULL) {\r
800     return EFI_INVALID_PARAMETER;\r
801   }\r
802 \r
803   ScsiIoDevice  = SCSI_IO_DEV_FROM_THIS (This);\r
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
816 \r
817     Status = gBS->AllocatePool (\r
818                      EfiBootServicesData,\r
819                      sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),\r
820                      (VOID**)&WorkingBuffer\r
821                      );\r
822 \r
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
893   return Status;\r
894 }\r
895 \r
896 EFI_STATUS\r
897 EFIAPI    \r
898 ScsiScanCreateDevice (\r
899   EFI_DRIVER_BINDING_PROTOCOL   *This,\r
900   EFI_HANDLE                    Controller,\r
901   SCSI_TARGET_ID                *TargetId,\r
902   UINT64                        Lun,\r
903   SCSI_BUS_DEVICE               *ScsiBusDev\r
904   )\r
905 /*++\r
906 \r
907 Routine Description:\r
908 \r
909   Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\r
910 \r
911 Arguments:\r
912 \r
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
918 \r
919 Returns:\r
920 \r
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
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
942   CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);\r
943   ScsiIoDevice->Lun                       = Lun;\r
944 \r
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
956   ScsiIoDevice->ScsiIo.GetDeviceType      = ScsiGetDeviceType;\r
957   ScsiIoDevice->ScsiIo.GetDeviceLocation  = ScsiGetDeviceLocation;\r
958   ScsiIoDevice->ScsiIo.ResetBus           = ScsiResetBus;\r
959   ScsiIoDevice->ScsiIo.ResetDevice        = ScsiResetDevice;\r
960   ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
961 \r
962 \r
963   if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
964     gBS->FreePool (ScsiIoDevice);\r
965     return EFI_OUT_OF_RESOURCES;\r
966   }\r
967 \r
968   //\r
969   // Set Device Path\r
970   //\r
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
993   }\r
994   \r
995   ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
996                               ScsiBusDev->DevicePath,\r
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
1010   \r
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
1021     return EFI_OUT_OF_RESOURCES;\r
1022   } else {\r
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
1042   }\r
1043   return EFI_SUCCESS;\r
1044 }\r
1045 \r
1046 BOOLEAN\r
1047 EFIAPI    \r
1048 DiscoverScsiDevice (\r
1049   SCSI_IO_DEV   *ScsiIoDevice\r
1050   )\r
1051 /*++\r
1052 \r
1053 Routine Description:\r
1054 \r
1055   Discovery SCSI Device\r
1056 \r
1057 Arguments:\r
1058 \r
1059   ScsiIoDevice    - The pointer of SCSI_IO_DEV\r
1060 \r
1061 Returns:\r
1062 \r
1063   TRUE            - Find SCSI Device and verify it.\r
1064   FALSE           - Unable to find SCSI Device.  \r
1065 \r
1066 --*/\r
1067 {\r
1068   EFI_STATUS            Status;\r
1069   UINT32                InquiryDataLength;\r
1070   UINT8                 SenseDataLength;\r
1071   UINT8                 HostAdapterStatus;\r
1072   UINT8                 TargetStatus;\r
1073   EFI_SCSI_SENSE_DATA   SenseData;\r
1074   EFI_SCSI_INQUIRY_DATA InquiryData;\r
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
1115   if (0x1e >= InquiryData.Peripheral_Type >= 0xa) {\r
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
1135 \r
1136 \r
1137 STATIC\r
1138 EFI_STATUS\r
1139 EFIAPI\r
1140 ScsiioToPassThruPacket (\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
1146 Routine 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
1151 Arguments:\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
1156 Returns:\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
1191 STATIC\r
1192 EFI_STATUS\r
1193 EFIAPI\r
1194 PassThruToScsiioPacket (\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
1200 Routine 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
1205 Arguments:\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
1210 Returns:\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
1238 STATIC\r
1239 VOID\r
1240 EFIAPI\r
1241 NotifyFunction (\r
1242   EFI_EVENT  Event,\r
1243   VOID       *Context\r
1244   )\r
1245 /*++\r
1246 \r
1247 Routine 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
1252 Arguments:\r
1253 \r
1254   Event          - The instance of EFI_EVENT.\r
1255   Context        - The parameter passed in.\r
1256    \r
1257 Returns:\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