]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
Clean up the private GUID definition in module Level.
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
index dc28be8dc67dd83387a134a79d9f0542fadc9def..b1c4d207f9de8bf415b3b7a157906391dcba334e 100644 (file)
@@ -1,50 +1,22 @@
-/*++\r
+/** @file\r
+  SCSI Bus driver that layers on every SCSI Pass Thru and\r
+  Extended SCSI Pass Thru protocol in the system.\r
 \r
-Copyright (c) 2006, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
 \r
-Module Name:\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-    scsibus.c\r
-    \r
-Abstract: \r
-    \r
+**/\r
 \r
-Revision History\r
---*/\r
-\r
-//\r
-// The package level header files this module uses\r
-//\r
-#include <PiDxe.h>\r
-\r
-//\r
-// The protocols, PPI and GUID defintions for this module\r
-//\r
-#include <Protocol/ScsiPassThru.h>\r
-#include <Protocol/ScsiIo.h>\r
-#include <Protocol/ComponentName.h>\r
-#include <Protocol/DriverBinding.h>\r
-#include <Protocol/DevicePath.h>\r
-//\r
-// The Library classes this module consumes\r
-//\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiDriverEntryPoint.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/ScsiLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/DevicePathLib.h>\r
 \r
 #include "ScsiBus.h"\r
 \r
+\r
 EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {\r
   SCSIBusDriverBindingSupported,\r
   SCSIBusDriverBindingStart,\r
@@ -54,14 +26,59 @@ EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
   NULL\r
 };\r
 \r
+VOID  *mWorkingBuffer;\r
+\r
+/**\r
+  Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.\r
+\r
+  @param  Packet         The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+  @param  CommandPacket  The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiioToPassThruPacket (\r
+  IN      EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet,\r
+  OUT     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *CommandPacket\r
+  );\r
+\r
+/**\r
+  Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.\r
+\r
+  @param  ScsiPacket  The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+  @param  Packet      The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PassThruToScsiioPacket (\r
+  IN     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *ScsiPacket,\r
+  OUT    EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet\r
+  );\r
+\r
+/**\r
+  Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0\r
+  SCSI IO Packet.\r
+\r
+  @param  Event    The instance of EFI_EVENT.\r
+  @param  Context  The parameter passed in.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NotifyFunction (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  );\r
+\r
 /**\r
   The user Entry Point for module ScsiBus. The user code starts with this function.\r
 \r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
-  @retval EFI_SUCCESS       The entry point is executed successfully.\r
-  @retval other             Some error occurs when executing this entry point.\r
+  @param  ImageHandle    The firmware allocated handle for the EFI image.\r
+  @param  SystemTable    A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS    The entry point is executed successfully.\r
+  @retval other          Some error occurs when executing this entry point.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -76,21 +93,39 @@ InitializeScsiBus(
   //\r
   // Install driver model protocol(s).\r
   //\r
-  Status = EfiLibInstallAllDriverProtocols (\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
              ImageHandle,\r
              SystemTable,\r
              &gSCSIBusDriverBinding,\r
              ImageHandle,\r
              &gScsiBusComponentName,\r
-             NULL,\r
-             NULL\r
+             &gScsiBusComponentName2\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-\r
   return Status;\r
 }\r
 \r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle.\r
+\r
+  This service is called by the EFI boot service ConnectController(). In order\r
+  to make drivers as small as possible, there are a few calling restrictions for\r
+  this service. ConnectController() must follow these calling restrictions. If\r
+  any other agent wishes to call Supported() it must also follow these calling\r
+  restrictions.\r
+\r
+  @param  This                Protocol instance pointer.\r
+  @param  ControllerHandle    Handle of device to test\r
+  @param  RemainingDevicePath Optional parameter use to pick a specific child\r
+                              device to start.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device\r
+  @retval EFI_ALREADY_STARTED This driver is already running on this device\r
+  @retval other               This driver does not support this device\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 SCSIBusDriverBindingSupported (\r
@@ -98,53 +133,127 @@ SCSIBusDriverBindingSupported (
   IN EFI_HANDLE                   Controller,\r
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
-/*++\r
-  \r
-  Routine Description:\r
-  \r
-  Arguments:\r
-  \r
-  Returns:\r
-  \r
---*/\r
-// TODO:    This - add argument and description to function comment\r
-// TODO:    Controller - add argument and description to function comment\r
-// TODO:    RemainingDevicePath - add argument and description to function comment\r
-// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS                      Status;\r
+  EFI_SCSI_PASS_THRU_PROTOCOL     *PassThru;\r
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\r
+  UINT64                          Lun;\r
+  UINT8                           *TargetId;\r
+  SCSI_TARGET_ID                  ScsiTargetId;\r
+\r
+  TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];\r
+  SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
 \r
   //\r
-  // If RemainingDevicePath is not NULL, it should verify that the first device\r
-  // path node in RemainingDevicePath is an ATAPI Device path node.\r
+  // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as \r
+  // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly\r
+  // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.\r
   //\r
-  if (RemainingDevicePath != NULL) {\r
-    if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
-        (RemainingDevicePath->SubType != MSG_ATAPI_DP) ||\r
-        (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) {\r
-      return EFI_UNSUPPORTED;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiExtScsiPassThruProtocolGuid,\r
+                  (VOID **)&ExtPassThru,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  } else if (!EFI_ERROR(Status)) {\r
+    //\r
+    // Check if RemainingDevicePath is NULL or the End of Device Path Node,\r
+    // if yes, return EFI_SUCCESS.\r
+    //\r
+    if ((RemainingDevicePath == NULL) || IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // Close protocol regardless of RemainingDevicePath validation\r
+      //\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );      \r
+      return EFI_SUCCESS;\r
+    } else {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node, check its validation\r
+      //\r
+      Status = ExtPassThru->GetTargetLun (ExtPassThru, RemainingDevicePath, &TargetId, &Lun);\r
+      //\r
+      // Close protocol regardless of RemainingDevicePath validation\r
+      //\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );      \r
+      if (!EFI_ERROR(Status)) {\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
   }\r
+\r
   //\r
-  // check for the existence of SCSI Pass Thru Protocol\r
+  // Come here in 2 condition: \r
+  // 1. ExtPassThru doesn't exist.\r
+  // 2. ExtPassThru exists but RemainingDevicePath is invalid.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiScsiPassThruProtocolGuid,\r
-                  NULL,\r
+                  (VOID **)&PassThru,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
-    return EFI_UNSUPPORTED;\r
+  \r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
   }\r
-\r
-  return EFI_SUCCESS;\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
+  //\r
+  // Test RemainingDevicePath is valid or not.\r
+  //\r
+  if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
+    Status = PassThru->GetTargetLun (PassThru, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
+  }\r
+  \r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiScsiPassThruProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+  return Status;\r
 }\r
 \r
+\r
+/**\r
+  Start this driver on ControllerHandle.\r
+\r
+  This service is called by the EFI boot service ConnectController(). In order\r
+  to make drivers as small as possible, there are a few calling restrictions for\r
+  this service. ConnectController() must follow these calling restrictions. If\r
+  any other agent wishes to call Start() it must also follow these calling\r
+  restrictions.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to bind driver to\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                               device to start.\r
+\r
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
+  @retval other                This driver does not support this device\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 SCSIBusDriverBindingStart (\r
@@ -152,78 +261,193 @@ SCSIBusDriverBindingStart (
   IN EFI_HANDLE                   Controller,\r
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
-/*++\r
-  \r
-  Routine Description:\r
-  \r
-  Arguments:\r
+{\r
+  UINT64                                Lun;\r
+  UINT8                                 *TargetId;\r
+  BOOLEAN                               ScanOtherPuns;\r
+  BOOLEAN                               FromFirstTarget;\r
+  BOOLEAN                               ExtScsiSupport;\r
+  EFI_STATUS                            Status;\r
+  EFI_STATUS                            DevicePathStatus;\r
+  EFI_STATUS                            PassThruStatus;\r
+  SCSI_BUS_DEVICE                       *ScsiBusDev;\r
+  SCSI_TARGET_ID                        ScsiTargetId;\r
+  EFI_DEVICE_PATH_PROTOCOL              *ParentDevicePath;\r
+  EFI_SCSI_PASS_THRU_PROTOCOL           *ScsiInterface;\r
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL       *ExtScsiInterface;\r
+  EFI_SCSI_BUS_PROTOCOL                 *BusIdentify;\r
+\r
+  TargetId        = NULL;\r
+  ScanOtherPuns   = TRUE;\r
+  FromFirstTarget = FALSE;\r
+  ExtScsiSupport  = FALSE;\r
+  PassThruStatus  = EFI_SUCCESS;\r
   \r
-  Returns:\r
+  TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];\r
+  SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
   \r
---*/\r
-// TODO:    This - add argument and description to function comment\r
-// TODO:    Controller - add argument and description to function comment\r
-// TODO:    RemainingDevicePath - add argument and description to function comment\r
-{\r
-  EFI_STATUS                  Status;\r
-  EFI_DEVICE_PATH_PROTOCOL    *ParentDevicePath;\r
-  EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r
-  UINT32                      StartPun;\r
-  UINT64                      StartLun;\r
-  UINT32                      Pun;\r
-  UINT64                      Lun;\r
-  BOOLEAN                     ScanOtherPuns;\r
-\r
-  StartPun  = 0;\r
-  StartLun  = 0;\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  This->DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
-    return Status;\r
+  DevicePathStatus = gBS->OpenProtocol (\r
+                            Controller,\r
+                            &gEfiDevicePathProtocolGuid,\r
+                            (VOID **) &ParentDevicePath,\r
+                            This->DriverBindingHandle,\r
+                            Controller,\r
+                            EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                            );\r
+  if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {\r
+    return DevicePathStatus;\r
   }\r
 \r
   //\r
-  // Consume SCSI Pass Thru protocol.\r
+  // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as \r
+  // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly\r
+  // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiScsiPassThruProtocolGuid,\r
-                  (VOID **) &ScsiPassThru,\r
+                  &gEfiExtScsiPassThruProtocolGuid,\r
+                  (VOID **) &ExtScsiInterface,\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
-  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiDevicePathProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-    return Status;\r
+  //\r
+  // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.\r
+  //\r
+  if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiScsiPassThruProtocolGuid,\r
+                    (VOID **) &ScsiInterface,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+    //\r
+    // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.\r
+    //\r
+    if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+      if (!EFI_ERROR(DevicePathStatus)) {\r
+        gBS->CloseProtocol (\r
+               Controller,\r
+               &gEfiDevicePathProtocolGuid,\r
+               This->DriverBindingHandle,\r
+               Controller\r
+               );\r
+      } \r
+      return Status;\r
+    } \r
+  } else {\r
+    //\r
+    // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol \r
+    // with BY_DRIVER if it is also present on the handle. The intent is to prevent \r
+    // another SCSI Bus Driver to work on the same host handle.\r
+    //\r
+    ExtScsiSupport = TRUE;\r
+    PassThruStatus = gBS->OpenProtocol (\r
+                            Controller,\r
+                            &gEfiScsiPassThruProtocolGuid,\r
+                            (VOID **) &ScsiInterface,\r
+                            This->DriverBindingHandle,\r
+                            Controller,\r
+                            EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                            );\r
   }\r
+    \r
+  if (Status != EFI_ALREADY_STARTED) {\r
+    //\r
+    // Go through here means either ExtPassThru or PassThru Protocol is successfully opened\r
+    // on this handle for this time. Then construct Host controller private data.\r
+    //\r
+    ScsiBusDev = NULL;\r
+    ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE));\r
+    if (ScsiBusDev == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ErrorExit;\r
+    }\r
+    ScsiBusDev->Signature        = SCSI_BUS_DEVICE_SIGNATURE;\r
+    ScsiBusDev->ExtScsiSupport   = ExtScsiSupport;\r
+    ScsiBusDev->DevicePath       = ParentDevicePath;\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      ScsiBusDev->ExtScsiInterface = ExtScsiInterface;\r
+    } else {\r
+      ScsiBusDev->ScsiInterface    = ScsiInterface;    \r
+    }\r
 \r
-  if (RemainingDevicePath == NULL) {\r
-    StartPun  = 0xFFFFFFFF;\r
-    StartLun  = 0;\r
+    //\r
+    // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be\r
+    // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru\r
+    // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.\r
+    // \r
+    Status = gBS->InstallProtocolInterface (\r
+                    &Controller,\r
+                    &gEfiCallerIdGuid,\r
+                    EFI_NATIVE_INTERFACE,\r
+                    &ScsiBusDev->BusIdentify\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ErrorExit;\r
+    }\r
   } else {\r
-    ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun);\r
+    //\r
+    // Go through here means Start() is re-invoked again, nothing special is required to do except\r
+    // picking up Host controller private information.\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiCallerIdGuid,\r
+                    (VOID **) &BusIdentify,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);\r
   }\r
 \r
-  for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) {\r
+  Lun  = 0;\r
+  if (RemainingDevicePath == NULL) {\r
+    //\r
+    // If RemainingDevicePath is NULL, \r
+    // must enumerate all SCSI devices anyway\r
+    //\r
+    FromFirstTarget = TRUE;\r
+  } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+    //\r
+    // If RemainingDevicePath isn't the End of Device Path Node, \r
+    // only scan the specified device by RemainingDevicePath\r
+    //\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);  \r
+    } else {\r
+      Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+    //\r
+    // If RemainingDevicePath is the End of Device Path Node,\r
+    // skip enumerate any device and return EFI_SUCESSS\r
+    // \r
+    ScanOtherPuns = FALSE;\r
+  }\r
 \r
-    if (StartPun == 0xFFFFFFFF) {\r
+  while(ScanOtherPuns) {\r
+    if (FromFirstTarget) {\r
       //\r
       // Remaining Device Path is NULL, scan all the possible Puns in the\r
       // SCSI Channel.\r
       //\r
-      Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun);\r
+      if (ScsiBusDev->ExtScsiSupport) {\r
+        Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);\r
+      } else {\r
+        Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
+      }\r
       if (EFI_ERROR (Status)) {\r
         //\r
         // no legal Pun and Lun found any more\r
@@ -231,31 +455,79 @@ SCSIBusDriverBindingStart (
         break;\r
       }\r
     } else {\r
-      //\r
-      // Remaining Device Path is not NULL, only scan the specified Pun.\r
-      //\r
-      Pun           = StartPun;\r
-      Lun           = StartLun;\r
       ScanOtherPuns = FALSE;\r
     }\r
-    \r
     //\r
     // Avoid creating handle for the host adapter.\r
     //\r
-    if (Pun == ScsiPassThru->Mode->AdapterId) {\r
-      continue;\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {\r
+        continue;\r
+      }\r
+    } else {\r
+      if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {\r
+        continue;\r
+      }\r
     }\r
-    \r
     //\r
     // Scan for the scsi device, if it attaches to the scsi bus,\r
     // then create handle and install scsi i/o protocol.\r
     //\r
-    Status = ScsiScanCreateDevice (This, Controller, Pun, Lun, ScsiPassThru, ParentDevicePath);\r
+    Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev);\r
   }\r
+  return EFI_SUCCESS;\r
 \r
+ErrorExit:\r
+  \r
+  if (ScsiBusDev != NULL) {\r
+    FreePool (ScsiBusDev);\r
+  }\r
+  \r
+  if (ExtScsiSupport) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiExtScsiPassThruProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+    if (!EFI_ERROR (PassThruStatus)) {\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    }\r
+  } else {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiScsiPassThruProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+  }\r
   return Status;\r
 }\r
 \r
+/**\r
+  Stop this driver on ControllerHandle.\r
+\r
+  This service is called by the EFI boot service DisconnectController().\r
+  In order to make drivers as small as possible, there are a few calling\r
+  restrictions for this service. DisconnectController() must follow these\r
+  calling restrictions. If any other agent wishes to call Stop() it must also\r
+  follow these calling restrictions.\r
+  \r
+  @param  This              Protocol instance pointer.\r
+  @param  ControllerHandle  Handle of device to stop driver on\r
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                            children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
+  @retval other             This driver was not removed from this device\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 SCSIBusDriverBindingStop (\r
@@ -264,47 +536,84 @@ SCSIBusDriverBindingStop (
   IN  UINTN                           NumberOfChildren,\r
   IN  EFI_HANDLE                      *ChildHandleBuffer\r
   )\r
-/*++\r
-  \r
-  Routine Description:\r
-  \r
-  Arguments:\r
-  \r
-  Returns:\r
-  \r
---*/\r
-// TODO:    This - add argument and description to function comment\r
-// TODO:    Controller - add argument and description to function comment\r
-// TODO:    NumberOfChildren - add argument and description to function comment\r
-// TODO:    ChildHandleBuffer - add argument and description to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
-// TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
-// TODO:    EFI_SUCCESS - add return value to function comment\r
 {\r
   EFI_STATUS                  Status;\r
   BOOLEAN                     AllChildrenStopped;\r
   UINTN                       Index;\r
   EFI_SCSI_IO_PROTOCOL        *ScsiIo;\r
   SCSI_IO_DEV                 *ScsiIoDevice;\r
-  EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;\r
+  VOID                        *ScsiPassThru;\r
+  EFI_SCSI_BUS_PROTOCOL       *Scsidentifier;\r
+  SCSI_BUS_DEVICE             *ScsiBusDev;\r
 \r
   if (NumberOfChildren == 0) {\r
+    //\r
+    // Get the SCSI_BUS_DEVICE\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiCallerIdGuid,\r
+                    (VOID **) &Scsidentifier,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier);\r
+\r
+    //\r
+    // Uninstall SCSI Bus Protocol\r
+    //\r
+    gBS->UninstallProtocolInterface (\r
+           Controller,\r
+           &gEfiCallerIdGuid,\r
+           &ScsiBusDev->BusIdentify\r
+           );\r
+\r
     //\r
     // Close the bus driver\r
     //\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiScsiPassThruProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
-    gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiDevicePathProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      //\r
+      // Close ExtPassThru Protocol from this controller handle\r
+      //\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+      //\r
+      // When Start() succeeds to open ExtPassThru, it always tries to open PassThru BY_DRIVER.\r
+      // Its intent is to prevent another SCSI Bus Driver from woking on the same host handle. \r
+      // So Stop() needs to try to close PassThru if present here.\r
+      //\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    } else {\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    }\r
 \r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiDevicePathProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+    FreePool (ScsiBusDev);\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -329,12 +638,22 @@ SCSIBusDriverBindingStop (
     //\r
     // Close the child handle\r
     //\r
-    Status = gBS->CloseProtocol (\r
-                    Controller,\r
-                    &gEfiScsiPassThruProtocolGuid,\r
-                    This->DriverBindingHandle,\r
-                    ChildHandleBuffer[Index]\r
-                    );\r
+    if (ScsiIoDevice->ExtScsiSupport) {\r
+      Status = gBS->CloseProtocol (\r
+                      Controller,\r
+                      &gEfiExtScsiPassThruProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      ChildHandleBuffer[Index]\r
+                      );\r
+\r
+    } else {\r
+      Status = gBS->CloseProtocol (\r
+                      Controller,\r
+                      &gEfiScsiPassThruProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      ChildHandleBuffer[Index]\r
+                      );\r
+    }\r
 \r
     Status = gBS->UninstallMultipleProtocolInterfaces (\r
                     ChildHandleBuffer[Index],\r
@@ -346,16 +665,27 @@ SCSIBusDriverBindingStop (
                     );\r
     if (EFI_ERROR (Status)) {\r
       AllChildrenStopped = FALSE;\r
-      gBS->OpenProtocol (\r
-            Controller,\r
-            &gEfiScsiPassThruProtocolGuid,\r
-            (VOID **) &ScsiPassThru,\r
-            This->DriverBindingHandle,\r
-            ChildHandleBuffer[Index],\r
-            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-            );\r
+      if (ScsiIoDevice->ExtScsiSupport) {\r
+        gBS->OpenProtocol (\r
+               Controller,\r
+               &gEfiExtScsiPassThruProtocolGuid,\r
+               &ScsiPassThru,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\r
+      } else {\r
+        gBS->OpenProtocol (\r
+               Controller,\r
+               &gEfiScsiPassThruProtocolGuid,\r
+               &ScsiPassThru,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\r
+      }\r
     } else {\r
-      gBS->FreePool (ScsiIoDevice);\r
+      FreePool (ScsiIoDevice);\r
     }\r
   }\r
 \r
@@ -366,26 +696,24 @@ SCSIBusDriverBindingStop (
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+/**\r
+  Retrieves the device type information of the SCSI Controller.\r
+\r
+  @param  This          Protocol instance pointer.\r
+  @param  DeviceType    A pointer to the device type information retrieved from\r
+                        the SCSI Controller. \r
+\r
+  @retval EFI_SUCCESS             Retrieves the device type information successfully.\r
+  @retval EFI_INVALID_PARAMETER   The DeviceType is NULL.\r
+  \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 ScsiGetDeviceType (\r
   IN  EFI_SCSI_IO_PROTOCOL     *This,\r
   OUT UINT8                    *DeviceType\r
   )\r
-/*++\r
-\r
-  Routine Description:\r
-    Retrieves the device type information of the SCSI Controller.\r
-    \r
-  Arguments:\r
-    This                  - Protocol instance pointer.\r
-    DeviceType            - A pointer to the device type information\r
-                            retrieved from the SCSI Controller. \r
-\r
-  Returns:\r
-    EFI_SUCCESS           - Retrieves the device type information successfully.\r
-    EFI_INVALID_PARAMETER - The DeviceType is NULL.\r
---*/\r
 {\r
   SCSI_IO_DEV *ScsiIoDevice;\r
 \r
@@ -398,29 +726,27 @@ ScsiGetDeviceType (
   return EFI_SUCCESS;\r
 }\r
 \r
-STATIC\r
+\r
+/**\r
+  Retrieves the device location in the SCSI channel.\r
+\r
+  @param  This   Protocol instance pointer.\r
+  @param  Target A pointer to the Target ID of a SCSI device\r
+                 on the SCSI channel.\r
+  @param  Lun    A pointer to the LUN of the SCSI device on\r
+                 the SCSI channel.\r
+\r
+  @retval EFI_SUCCESS           Retrieves the device location successfully.\r
+  @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 ScsiGetDeviceLocation (\r
   IN  EFI_SCSI_IO_PROTOCOL    *This,\r
-  OUT UINT32                  *Target,\r
+  IN OUT UINT8                **Target,\r
   OUT UINT64                  *Lun\r
   )\r
-/*++\r
-  Routine Description:\r
-    Retrieves the device location in the SCSI channel.\r
-    \r
-  Arguments:\r
-    This                  - Protocol instance pointer.\r
-    Target                - A pointer to the Target ID of a SCSI device \r
-                            on the SCSI channel. \r
-    Lun                   - A pointer to the LUN of the SCSI device on \r
-                            the SCSI channel.\r
-\r
-  Returns:\r
-    EFI_SUCCESS           - Retrieves the device location successfully.\r
-    EFI_INVALID_PARAMETER - The Target or Lun is NULL.\r
---*/\r
 {\r
   SCSI_IO_DEV *ScsiIoDevice;\r
 \r
@@ -428,252 +754,356 @@ ScsiGetDeviceLocation (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  ScsiIoDevice  = SCSI_IO_DEV_FROM_THIS (This);\r
+  ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
+\r
+  CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
 \r
-  *Target       = ScsiIoDevice->Pun;\r
-  *Lun          = ScsiIoDevice->Lun;\r
+  *Lun         = ScsiIoDevice->Lun;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Resets the SCSI Bus that the SCSI Controller is attached to.\r
+\r
+  @param  This  Protocol instance pointer.\r
+\r
+  @retval  EFI_SUCCESS       The SCSI bus is reset successfully.\r
+  @retval  EFI_DEVICE_ERROR  Errors encountered when resetting the SCSI bus.\r
+  @retval  EFI_UNSUPPORTED   The bus reset operation is not supported by the\r
+                             SCSI Host Controller.\r
+  @retval  EFI_TIMEOUT       A timeout occurred while attempting to reset \r
+                             the SCSI bus.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 ScsiResetBus (\r
   IN  EFI_SCSI_IO_PROTOCOL     *This\r
   )\r
-/*++\r
-\r
-  Routine Description:\r
-    Resets the SCSI Bus that the SCSI Controller is attached to.\r
-    \r
-  Arguments:\r
-    This                  - Protocol instance pointer.\r
-\r
-  Returns:\r
-    EFI_SUCCESS           - The SCSI bus is reset successfully.\r
-    EFI_DEVICE_ERROR      - Errors encountered when resetting the SCSI bus.\r
-    EFI_UNSUPPORTED       - The bus reset operation is not supported by the\r
-                            SCSI Host Controller.\r
-    EFI_TIMEOUT           - A timeout occurred while attempting to reset \r
-                            the SCSI bus.\r
---*/\r
 {\r
   SCSI_IO_DEV *ScsiIoDevice;\r
 \r
   ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
 \r
-  return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);\r
-\r
+  if (ScsiIoDevice->ExtScsiSupport){\r
+    return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru);\r
+  } else {\r
+    return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);\r
+  }\r
 }\r
 \r
+\r
+/**\r
+  Resets the SCSI Controller that the device handle specifies.\r
+\r
+  @param  This  Protocol instance pointer.\r
+\r
+  @retval  EFI_SUCCESS       Reset the SCSI controller successfully.\r
+  @retval  EFI_DEVICE_ERROR  Errors are encountered when resetting the SCSI Controller.\r
+  @retval  EFI_UNSUPPORTED   The SCSI bus does not support a device reset operation.\r
+  @retval  EFI_TIMEOUT       A timeout occurred while attempting to reset the\r
+                             SCSI Controller.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 ScsiResetDevice (\r
   IN  EFI_SCSI_IO_PROTOCOL     *This\r
   )\r
-/*++\r
-\r
-  Routine Description:\r
-    Resets the SCSI Controller that the device handle specifies.\r
-    \r
-  Arguments:\r
-    This                  - Protocol instance pointer.\r
-    \r
-\r
-  Returns:\r
-    EFI_SUCCESS           - Reset the SCSI controller successfully.\r
-    EFI_DEVICE_ERROR      - Errors are encountered when resetting the\r
-                            SCSI Controller.\r
-    EFI_UNSUPPORTED       - The SCSI bus does not support a device \r
-                            reset operation.\r
-    EFI_TIMEOUT           - A timeout occurred while attempting to \r
-                            reset the SCSI Controller.\r
---*/\r
 {\r
-  SCSI_IO_DEV *ScsiIoDevice;\r
+  SCSI_IO_DEV  *ScsiIoDevice;\r
+  UINT8        Target[TARGET_MAX_BYTES];\r
 \r
   ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
+  CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
+\r
 \r
-  return ScsiIoDevice->ScsiPassThru->ResetTarget (\r
-                                      ScsiIoDevice->ScsiPassThru,\r
-                                      ScsiIoDevice->Pun,\r
-                                      ScsiIoDevice->Lun\r
-                                      );\r
+  if (ScsiIoDevice->ExtScsiSupport) {\r
+    return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (\r
+                                        ScsiIoDevice->ExtScsiPassThru,\r
+                                        Target,\r
+                                        ScsiIoDevice->Lun\r
+                                          );\r
+  } else {\r
+    return ScsiIoDevice->ScsiPassThru->ResetTarget (\r
+                                          ScsiIoDevice->ScsiPassThru,\r
+                                          ScsiIoDevice->Pun.ScsiId.Scsi,\r
+                                          ScsiIoDevice->Lun\r
+                                            );\r
+  }\r
 }\r
 \r
+\r
+/**\r
+  Sends a SCSI Request Packet to the SCSI Controller for execution.\r
+\r
+  @param  This            Protocol instance pointer.\r
+  @param  CommandPacket   The SCSI request packet to send to the SCSI \r
+                          Controller specified by the device handle.\r
+  @param  Event           If the SCSI bus where the SCSI device is attached\r
+                          does not support non-blocking I/O, then Event is \r
+                          ignored, and blocking I/O is performed.  \r
+                          If Event is NULL, then blocking I/O is performed.\r
+                          If Event is not NULL and non-blocking I/O is \r
+                          supported, then non-blocking I/O is performed,\r
+                          and Event will be signaled when the SCSI Request\r
+                          Packet completes.\r
+\r
+  @retval EFI_SUCCESS         The SCSI Request Packet was sent by the host \r
+                              successfully, and TransferLength bytes were \r
+                              transferred to/from DataBuffer.See \r
+                              HostAdapterStatus, TargetStatus, \r
+                              SenseDataLength, and SenseData in that order\r
+                              for additional status information.\r
+  @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed, \r
+                              but the entire DataBuffer could not be transferred.\r
+                              The actual number of bytes transferred is returned\r
+                              in TransferLength. See HostAdapterStatus, \r
+                              TargetStatus, SenseDataLength, and SenseData in \r
+                              that order for additional status information.\r
+  @retval EFI_NOT_READY       The SCSI Request Packet could not be sent because \r
+                              there are too many SCSI Command Packets already \r
+                              queued.The caller may retry again later.\r
+  @retval EFI_DEVICE_ERROR    A device error occurred while attempting to send \r
+                              the SCSI Request Packet. See HostAdapterStatus, \r
+                              TargetStatus, SenseDataLength, and SenseData in \r
+                              that order for additional status information.\r
+  @retval EFI_INVALID_PARAMETER  The contents of CommandPacket are invalid.  \r
+                                 The SCSI Request Packet was not sent, so no \r
+                                 additional status information is available.\r
+  @retval EFI_UNSUPPORTED     The command described by the SCSI Request Packet\r
+                              is not supported by the SCSI initiator(i.e., SCSI \r
+                              Host Controller). The SCSI Request Packet was not\r
+                              sent, so no additional status information is \r
+                              available.\r
+  @retval EFI_TIMEOUT         A timeout occurred while waiting for the SCSI \r
+                              Request Packet to execute. See HostAdapterStatus,\r
+                              TargetStatus, SenseDataLength, and SenseData in \r
+                              that order for additional status information.\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 ScsiExecuteSCSICommand (\r
-  IN  EFI_SCSI_IO_PROTOCOL                         *This,\r
-  IN OUT  EFI_SCSI_IO_SCSI_REQUEST_PACKET          *Packet,\r
-  IN EFI_EVENT                                     Event  OPTIONAL\r
+  IN     EFI_SCSI_IO_PROTOCOL                     *This,\r
+  IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET          *Packet,\r
+  IN     EFI_EVENT                                Event  OPTIONAL\r
   )\r
-/*++\r
-\r
-  Routine Description:\r
-    Sends a SCSI Request Packet to the SCSI Controller for execution.\r
-    \r
-  Arguments:\r
-    This                  - Protocol instance pointer.\r
-    Packet                - The SCSI request packet to send to the SCSI \r
-                            Controller specified by the device handle.\r
-    Event                 - If the SCSI bus where the SCSI device is attached\r
-                            does not support non-blocking I/O, then Event is \r
-                            ignored, and blocking I/O is performed.  \r
-                            If Event is NULL, then blocking I/O is performed.\r
-                            If Event is not NULL and non-blocking I/O is \r
-                            supported, then non-blocking I/O is performed,\r
-                            and Event will be signaled when the SCSI Request\r
-                            Packet completes.\r
-  Returns:\r
-    EFI_SUCCESS           - The SCSI Request Packet was sent by the host \r
-                            successfully, and TransferLength bytes were \r
-                            transferred to/from DataBuffer.See \r
-                            HostAdapterStatus, TargetStatus, \r
-                            SenseDataLength, and SenseData in that order\r
-                            for additional status information.\r
-    EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, \r
-                            but the entire DataBuffer could not be transferred.\r
-                            The actual number of bytes transferred is returned\r
-                            in TransferLength. See HostAdapterStatus, \r
-                            TargetStatus, SenseDataLength, and SenseData in \r
-                            that order for additional status information.\r
-    EFI_NOT_READY         - The SCSI Request Packet could not be sent because \r
-                            there are too many SCSI Command Packets already \r
-                            queued.The caller may retry again later.\r
-    EFI_DEVICE_ERROR      - A device error occurred while attempting to send \r
-                            the SCSI Request Packet. See HostAdapterStatus, \r
-                            TargetStatus, SenseDataLength, and SenseData in \r
-                            that order for additional status information.\r
-    EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.  \r
-                            The SCSI Request Packet was not sent, so no \r
-                            additional status information is available.\r
-    EFI_UNSUPPORTED       - The command described by the SCSI Request Packet\r
-                            is not supported by the SCSI initiator(i.e., SCSI \r
-                            Host Controller). The SCSI Request Packet was not\r
-                            sent, so no additional status information is \r
-                            available.\r
-    EFI_TIMEOUT           - A timeout occurred while waiting for the SCSI \r
-                            Request Packet to execute. See HostAdapterStatus,\r
-                            TargetStatus, SenseDataLength, and SenseData in \r
-                            that order for additional status information.\r
---*/\r
 {\r
-  SCSI_IO_DEV                             *ScsiIoDevice;\r
-  EFI_STATUS                              Status;\r
-\r
-  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *RequestPacket;\r
-\r
+  SCSI_IO_DEV                                 *ScsiIoDevice;\r
+  EFI_STATUS                                  Status;\r
+  UINT8                                       Target[TARGET_MAX_BYTES];\r
+  EFI_EVENT                                   PacketEvent;\r
+  EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *ExtRequestPacket;\r
+  SCSI_EVENT_DATA                             EventData;                                     \r
+\r
+  PacketEvent = NULL;\r
+  \r
   if (Packet == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   ScsiIoDevice  = SCSI_IO_DEV_FROM_THIS (This);\r
+  CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
+\r
+  if (ScsiIoDevice->ExtScsiSupport) {\r
+    ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;\r
+    Status = ScsiIoDevice->ExtScsiPassThru->PassThru (\r
+                                          ScsiIoDevice->ExtScsiPassThru,\r
+                                          Target,\r
+                                          ScsiIoDevice->Lun,\r
+                                          ExtRequestPacket,\r
+                                          Event\r
+                                          );\r
+  } else {\r
 \r
-  RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;\r
+    mWorkingBuffer = AllocatePool (sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
 \r
-  Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
-                                        ScsiIoDevice->ScsiPassThru,\r
-                                        ScsiIoDevice->Pun,\r
-                                        ScsiIoDevice->Lun,\r
-                                        RequestPacket,\r
-                                        Event\r
-                                        );\r
-  return Status;\r
-}\r
+    if (mWorkingBuffer == NULL) {\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
 \r
-EFI_STATUS\r
-ScsiScanCreateDevice (\r
-  EFI_DRIVER_BINDING_PROTOCOL   *This,\r
-  EFI_HANDLE                    Controller,\r
-  UINT32                        Pun,\r
-  UINT64                        Lun,\r
-  EFI_SCSI_PASS_THRU_PROTOCOL   *ScsiPassThru,\r
-  EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath\r
-  )\r
-/*++\r
+    //\r
+    // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.\r
+    //\r
+    Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      FreePool(mWorkingBuffer);\r
+      return Status;\r
+    }\r
+\r
+    if (((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event !=  NULL)) {\r
+      EventData.Data1 = (VOID*)Packet;\r
+      EventData.Data2 = Event;\r
+      //\r
+      // Create Event\r
+      //\r
+      Status = gBS->CreateEvent (\r
+                       EVT_NOTIFY_SIGNAL,\r
+                       TPL_CALLBACK,\r
+                       NotifyFunction,\r
+                       &EventData,\r
+                       &PacketEvent\r
+                       );\r
+      if (EFI_ERROR(Status)) {\r
+        FreePool(mWorkingBuffer);\r
+        return Status;\r
+      }\r
 \r
-Routine Description:\r
+      Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
+                                          ScsiIoDevice->ScsiPassThru,\r
+                                          ScsiIoDevice->Pun.ScsiId.Scsi,\r
+                                          ScsiIoDevice->Lun,\r
+                                          mWorkingBuffer,\r
+                                          PacketEvent\r
+                                          );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        FreePool(mWorkingBuffer);\r
+        gBS->CloseEvent(PacketEvent);\r
+        return Status;\r
+      }\r
 \r
-  TODO: Add function description\r
+    } else {\r
+      //\r
+      // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert\r
+      // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet.\r
+      //\r
+      Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
+                                          ScsiIoDevice->ScsiPassThru,\r
+                                          ScsiIoDevice->Pun.ScsiId.Scsi,\r
+                                          ScsiIoDevice->Lun,\r
+                                          mWorkingBuffer,\r
+                                          Event\r
+                                          );\r
+      if (EFI_ERROR(Status)) {\r
+        FreePool(mWorkingBuffer);\r
+        return Status;\r
+      }\r
+\r
+      PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer,Packet);\r
+      //\r
+      // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,\r
+      // free mWorkingBuffer.\r
+      //\r
+      FreePool(mWorkingBuffer);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
 \r
-Arguments:\r
 \r
-  This              - TODO: add argument description\r
-  Controller        - TODO: add argument description\r
-  Pun               - TODO: add argument description\r
-  Lun               - TODO: add argument description\r
-  ScsiPassThru      - TODO: add argument description\r
-  ParentDevicePath  - TODO: add argument description\r
+/**\r
+  Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\r
 \r
-Returns:\r
+  @param  This           Protocol instance pointer\r
+  @param  Controller     Controller handle\r
+  @param  TargetId       Tartget to be scanned\r
+  @param  Lun            The Lun of the SCSI device on the SCSI channel.\r
+  @param  ScsiBusDev     The pointer of SCSI_BUS_DEVICE\r
 \r
-  EFI_SUCCESS - TODO: Add description for return value\r
-  EFI_OUT_OF_RESOURCES - TODO: Add description for return value\r
-  EFI_SUCCESS - TODO: Add description for return value\r
+  @retval EFI_SUCCESS           Successfully to discover the device and attach\r
+                                ScsiIoProtocol to it.\r
+  @retval EFI_OUT_OF_RESOURCES  Fail to discover the device.\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiScanCreateDevice (\r
+  IN     EFI_DRIVER_BINDING_PROTOCOL   *This,\r
+  IN     EFI_HANDLE                    Controller,\r
+  IN     SCSI_TARGET_ID                *TargetId,\r
+  IN     UINT64                        Lun,\r
+  IN OUT SCSI_BUS_DEVICE               *ScsiBusDev\r
+  )\r
 {\r
   EFI_STATUS                Status;\r
   SCSI_IO_DEV               *ScsiIoDevice;\r
   EFI_DEVICE_PATH_PROTOCOL  *ScsiDevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;\r
+  EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;\r
+  EFI_HANDLE                 DeviceHandle;\r
 \r
-  Status = gBS->AllocatePool (\r
-                  EfiBootServicesData,\r
-                  sizeof (SCSI_IO_DEV),\r
-                  (VOID **) &ScsiIoDevice\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
+  DevicePath          = NULL;\r
+  RemainingDevicePath = NULL;\r
+  ScsiDevicePath      = NULL;\r
+  ScsiIoDevice        = NULL;\r
+\r
+  //\r
+  // Build Device Path\r
+  //\r
+  if (ScsiBusDev->ExtScsiSupport){\r
+    Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (\r
+                                             ScsiBusDev->ExtScsiInterface,\r
+                                             &TargetId->ScsiId.ExtScsi[0],\r
+                                             Lun,\r
+                                             &ScsiDevicePath\r
+                                             );\r
+  } else {\r
+    Status = ScsiBusDev->ScsiInterface->BuildDevicePath (\r
+                                          ScsiBusDev->ScsiInterface,\r
+                                          TargetId->ScsiId.Scsi,\r
+                                          Lun,\r
+                                          &ScsiDevicePath\r
+                                          );\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
     return Status;\r
   }\r
 \r
-  ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));\r
+  DevicePath = AppendDevicePathNode (\r
+                 ScsiBusDev->DevicePath,\r
+                 ScsiDevicePath\r
+                 );\r
+\r
+  if (DevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
+  }\r
+\r
+  DeviceHandle = NULL;\r
+  RemainingDevicePath = DevicePath;\r
+  Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
+  if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
+    //\r
+    // The device has been started, directly return to fast boot.\r
+    //\r
+    Status = EFI_ALREADY_STARTED;\r
+    goto ErrorExit;\r
+  }\r
+\r
+  ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));\r
+  if (ScsiIoDevice == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
+  }\r
 \r
   ScsiIoDevice->Signature                 = SCSI_IO_DEV_SIGNATURE;\r
-  ScsiIoDevice->ScsiPassThru              = ScsiPassThru;\r
-  ScsiIoDevice->Pun                       = Pun;\r
+  CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);\r
   ScsiIoDevice->Lun                       = Lun;\r
 \r
+  if (ScsiBusDev->ExtScsiSupport) {\r
+    ScsiIoDevice->ExtScsiPassThru         = ScsiBusDev->ExtScsiInterface;\r
+    ScsiIoDevice->ExtScsiSupport          = TRUE;\r
+    ScsiIoDevice->ScsiIo.IoAlign          = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;\r
+\r
+  } else {\r
+    ScsiIoDevice->ScsiPassThru            = ScsiBusDev->ScsiInterface;\r
+    ScsiIoDevice->ExtScsiSupport          = FALSE;\r
+    ScsiIoDevice->ScsiIo.IoAlign          = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;\r
+  }\r
+\r
   ScsiIoDevice->ScsiIo.GetDeviceType      = ScsiGetDeviceType;\r
   ScsiIoDevice->ScsiIo.GetDeviceLocation  = ScsiGetDeviceLocation;\r
   ScsiIoDevice->ScsiIo.ResetBus           = ScsiResetBus;\r
   ScsiIoDevice->ScsiIo.ResetDevice        = ScsiResetDevice;\r
-  ScsiIoDevice->ScsiIo.ExecuteSCSICommand = ScsiExecuteSCSICommand;\r
+  ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
 \r
   if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
-    gBS->FreePool (ScsiIoDevice);\r
-    return EFI_SUCCESS;\r
-  }\r
-  \r
-  //\r
-  // Set Device Path\r
-  //\r
-  Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r
-                                        ScsiIoDevice->ScsiPassThru,\r
-                                        ScsiIoDevice->Pun,\r
-                                        ScsiIoDevice->Lun,\r
-                                        &ScsiDevicePath\r
-                                        );\r
-  if (Status == EFI_OUT_OF_RESOURCES) {\r
-    gBS->FreePool (ScsiIoDevice);\r
-    return Status;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ErrorExit;\r
   }\r
 \r
-  ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
-                              ParentDevicePath,\r
-                              ScsiDevicePath\r
-                              );\r
-  //\r
-  // The memory space for ScsiDevicePath is allocated in\r
-  // ScsiPassThru->BuildDevicePath() function; It is no longer used\r
-  // after EfiAppendDevicePathNode,so free the memory it occupies.\r
-  //\r
-  gBS->FreePool (ScsiDevicePath);\r
-\r
-  if (ScsiIoDevice->DevicePath == NULL) {\r
-    gBS->FreePool (ScsiIoDevice);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
+  ScsiIoDevice->DevicePath = DevicePath;\r
 \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &ScsiIoDevice->Handle,\r
@@ -684,48 +1114,74 @@ Returns:
                   NULL\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (ScsiIoDevice);\r
+    goto ErrorExit;\r
   } else {\r
-    gBS->OpenProtocol (\r
-          Controller,\r
-          &gEfiScsiPassThruProtocolGuid,\r
-          (VOID **) &ScsiPassThru,\r
-          This->DriverBindingHandle,\r
-          ScsiIoDevice->Handle,\r
-          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-          );\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      gBS->OpenProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\r
+             (VOID **) &(ScsiBusDev->ExtScsiInterface),\r
+             This->DriverBindingHandle,\r
+             ScsiIoDevice->Handle,\r
+             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+             );\r
+     } else {\r
+      gBS->OpenProtocol (\r
+             Controller,\r
+             &gEfiScsiPassThruProtocolGuid,\r
+             (VOID **) &(ScsiBusDev->ScsiInterface),\r
+             This->DriverBindingHandle,\r
+             ScsiIoDevice->Handle,\r
+             EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+             );\r
+     }\r
   }\r
-\r
   return EFI_SUCCESS;\r
-}\r
 \r
-BOOLEAN\r
-DiscoverScsiDevice (\r
-  SCSI_IO_DEV   *ScsiIoDevice\r
-  )\r
-/*++\r
+ErrorExit:\r
+  \r
+  //\r
+  // The memory space for ScsiDevicePath is allocated in\r
+  // ScsiPassThru->BuildDevicePath() function; It is no longer used\r
+  // after AppendDevicePathNode,so free the memory it occupies.\r
+  //\r
+  FreePool (ScsiDevicePath);\r
 \r
-Routine Description:\r
+  if (DevicePath != NULL) {\r
+    FreePool (DevicePath);\r
+  }\r
 \r
-  TODO: Add function description\r
+  if (ScsiIoDevice != NULL) {\r
+    FreePool (ScsiIoDevice);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
-Arguments:\r
 \r
-  ScsiIoDevice  - TODO: add argument description\r
+/**\r
+  Discovery SCSI Device\r
 \r
-Returns:\r
+  @param  ScsiIoDevice    The pointer of SCSI_IO_DEV\r
 \r
-  TODO: add return values\r
+  @retval  TRUE   Find SCSI Device and verify it.\r
+  @retval  FALSE  Unable to find SCSI Device.\r
 \r
---*/\r
+**/\r
+BOOLEAN\r
+DiscoverScsiDevice (\r
+  IN OUT  SCSI_IO_DEV   *ScsiIoDevice\r
+  )\r
 {\r
   EFI_STATUS            Status;\r
-  EFI_SCSI_INQUIRY_DATA InquiryData;\r
   UINT32                InquiryDataLength;\r
-  EFI_SCSI_SENSE_DATA   SenseData;\r
   UINT8                 SenseDataLength;\r
   UINT8                 HostAdapterStatus;\r
   UINT8                 TargetStatus;\r
+  EFI_SCSI_SENSE_DATA   SenseData;\r
+  EFI_SCSI_INQUIRY_DATA InquiryData;\r
+  UINT8                 MaxRetry;\r
+  UINT8                 Index;\r
 \r
   HostAdapterStatus = 0;\r
   TargetStatus      = 0;\r
@@ -733,25 +1189,35 @@ Returns:
   // Using Inquiry command to scan for the device\r
   //\r
   InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);\r
-  SenseDataLength   = sizeof (EFI_SCSI_SENSE_DATA);\r
-\r
-  Status = SubmitInquiryCommand (\r
-            &ScsiIoDevice->ScsiIo,\r
-            EfiScsiStallSeconds (1),\r
-            (VOID *) &SenseData,\r
-            &SenseDataLength,\r
-            &HostAdapterStatus,\r
-            &TargetStatus,\r
-            (VOID *) &InquiryData,\r
-            &InquiryDataLength,\r
-            FALSE\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    //    ParseSenseData (&SenseData,SenseDataLength);\r
-    //\r
+  SenseDataLength   = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);\r
+  ZeroMem (&InquiryData, InquiryDataLength);\r
+\r
+  MaxRetry = 2;\r
+  for (Index = 0; Index < MaxRetry; Index++) {\r
+    Status = ScsiInquiryCommand (\r
+              &ScsiIoDevice->ScsiIo,\r
+              EFI_TIMER_PERIOD_SECONDS (1),\r
+              (VOID *) &SenseData,\r
+              &SenseDataLength,\r
+              &HostAdapterStatus,\r
+              &TargetStatus,\r
+              (VOID *) &InquiryData,\r
+              &InquiryDataLength,\r
+              FALSE\r
+              );\r
+    if (!EFI_ERROR (Status)) {\r
+      break;\r
+    } else if ((Status == EFI_BAD_BUFFER_SIZE) || \r
+               (Status == EFI_INVALID_PARAMETER) ||\r
+               (Status == EFI_UNSUPPORTED)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  if (Index == MaxRetry) {\r
     return FALSE;\r
   }\r
+  \r
   //\r
   // Retrieved inquiry data successfully\r
   //\r
@@ -766,23 +1232,145 @@ Returns:
     }\r
   }\r
 \r
-  if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) {\r
+  if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {\r
     return FALSE;\r
   }\r
-  \r
+\r
   //\r
   // valid device type and peripheral qualifier combination.\r
   //\r
   ScsiIoDevice->ScsiDeviceType  = InquiryData.Peripheral_Type;\r
-  ScsiIoDevice->RemovableDevice = InquiryData.RMB;\r
+  ScsiIoDevice->RemovableDevice = InquiryData.Rmb;\r
   if (InquiryData.Version == 0) {\r
     ScsiIoDevice->ScsiVersion = 0;\r
   } else {\r
     //\r
     // ANSI-approved version\r
     //\r
-    ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);\r
+    ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x07);\r
   }\r
 \r
   return TRUE;\r
 }\r
+\r
+\r
+/**\r
+  Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.\r
+\r
+  @param  Packet         The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+  @param  CommandPacket  The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiioToPassThruPacket (\r
+  IN      EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet,\r
+  OUT     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *CommandPacket\r
+  )\r
+{\r
+  //\r
+  //EFI 1.10 doesn't support Bi-Direction Command.\r
+  //\r
+  if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
+\r
+  CommandPacket->Timeout           = Packet->Timeout;\r
+  CommandPacket->Cdb               = Packet->Cdb;\r
+  CommandPacket->CdbLength         = Packet->CdbLength;\r
+  CommandPacket->DataDirection     = Packet->DataDirection;\r
+  CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus;\r
+  CommandPacket->TargetStatus      = Packet->TargetStatus;\r
+  CommandPacket->SenseData         = Packet->SenseData;\r
+  CommandPacket->SenseDataLength   = Packet->SenseDataLength;\r
+\r
+  if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
+    CommandPacket->DataBuffer = Packet->InDataBuffer;\r
+    CommandPacket->TransferLength = Packet->InTransferLength;\r
+  } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {\r
+    CommandPacket->DataBuffer = Packet->OutDataBuffer;\r
+    CommandPacket->TransferLength = Packet->OutTransferLength;\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.\r
+\r
+  @param  ScsiPacket  The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+  @param  Packet      The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PassThruToScsiioPacket (\r
+  IN     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *ScsiPacket,\r
+  OUT    EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet\r
+  )\r
+{\r
+  Packet->Timeout           = ScsiPacket->Timeout;\r
+  Packet->Cdb               = ScsiPacket->Cdb;\r
+  Packet->CdbLength         = ScsiPacket->CdbLength;\r
+  Packet->DataDirection     = ScsiPacket->DataDirection;\r
+  Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus;\r
+  Packet->TargetStatus      = ScsiPacket->TargetStatus;\r
+  Packet->SenseData         = ScsiPacket->SenseData;\r
+  Packet->SenseDataLength   = ScsiPacket->SenseDataLength;\r
+\r
+  if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
+    Packet->InDataBuffer = ScsiPacket->DataBuffer;\r
+    Packet->InTransferLength = ScsiPacket->TransferLength;\r
+  } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {\r
+    Packet->OutDataBuffer = ScsiPacket->DataBuffer;\r
+    Packet->OutTransferLength = ScsiPacket->TransferLength;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0\r
+  SCSI IO Packet.\r
+\r
+  @param  Event    The instance of EFI_EVENT.\r
+  @param  Context  The parameter passed in.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+NotifyFunction (\r
+  IN  EFI_EVENT  Event,\r
+  IN  VOID       *Context\r
+  )\r
+{\r
+  EFI_SCSI_IO_SCSI_REQUEST_PACKET          *Packet;\r
+  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET   *ScsiPacket;\r
+  EFI_EVENT                                CallerEvent;\r
+  SCSI_EVENT_DATA                          *PassData;\r
+\r
+  PassData = (SCSI_EVENT_DATA*)Context;\r
+  Packet  = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;\r
+  ScsiPacket =  (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer;\r
+\r
+  //\r
+  // Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.\r
+  //\r
+  PassThruToScsiioPacket(ScsiPacket, Packet);\r
+\r
+  //\r
+  // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,\r
+  // free mWorkingBuffer.\r
+  //\r
+  gBS->FreePool(mWorkingBuffer);\r
+\r
+  //\r
+  // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.\r
+  //\r
+  CallerEvent = PassData->Data2;\r
+  gBS->CloseEvent(Event);\r
+  gBS->SignalEvent(CallerEvent);\r
+}\r
+\r