]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
Porting R8's PI-enabled ScsiBus driver
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
index 0840cba5d88494a25e9716dc55035abed169c521..68f3683bb632cfc0cda7f1a700511c883309fdff 100644 (file)
@@ -28,6 +28,7 @@ Revision History
 // The protocols, PPI and GUID defintions for this module\r
 //\r
 #include <Protocol/ScsiPassThru.h>\r
+#include <Protocol/ScsiPassThruExt.h>\r
 #include <Protocol/ScsiIo.h>\r
 #include <Protocol/ComponentName.h>\r
 #include <Protocol/DriverBinding.h>\r
@@ -39,6 +40,7 @@ Revision History
 #include <Library/UefiDriverEntryPoint.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
 #include <Library/ScsiLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/DevicePathLib.h>\r
@@ -54,6 +56,43 @@ EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
   NULL\r
 };\r
 \r
+\r
+//\r
+// The ScsiBusProtocol is just used to locate ScsiBusDev\r
+// structure in the SCSIBusDriverBindingStop(). Then we can\r
+// Close all opened protocols and release this structure.\r
+//\r
+STATIC EFI_GUID  mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;\r
+\r
+STATIC VOID  *WorkingBuffer;\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiioToPassThruPacket (\r
+  IN      EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet,\r
+  IN OUT  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *CommandPacket\r
+  )\r
+;\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PassThruToScsiioPacket (\r
+  IN     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *ScsiPacket,\r
+  IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet\r
+  )\r
+;\r
+STATIC\r
+VOID\r
+EFIAPI\r
+NotifyFunction (\r
+  EFI_EVENT  Event,\r
+  VOID       *Context\r
+  )\r
+;\r
+\r
 /**\r
   The user Entry Point for module ScsiBus. The user code starts with this function.\r
 \r
@@ -99,48 +138,78 @@ SCSIBusDriverBindingSupported (
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 /*++\r
-  \r
-  Routine Description:\r
-  \r
-  Arguments:\r
-  \r
-  Returns:\r
-  \r
+\r
+Routine Description:\r
+\r
+  Test to see if this driver supports ControllerHandle. Any ControllerHandle\r
+  that has ExtScsiPassThruProtocol/ScsiPassThruProtocol installed will be supported.\r
+\r
+Arguments:\r
+\r
+  This                - Protocol instance pointer.\r
+  Controller          - Handle of device to test\r
+  RemainingDevicePath - Not used\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS         - This driver supports this device.\r
+  EFI_UNSUPPORTED     - This driver does not support this device.\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
 {\r
   EFI_STATUS  Status;\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
+  EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
+  EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\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
-    }\r
-  }\r
-  //\r
-  // check for the existence of SCSI Pass Thru Protocol\r
+  // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiScsiPassThruProtocolGuid,\r
-                  NULL,\r
+                  &gEfiExtScsiPassThruProtocolGuid,\r
+                  (VOID **)&ExtPassThru,\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
+  if (EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiScsiPassThruProtocolGuid,\r
+                    (VOID **)&PassThru,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+    \r
+    if (Status == EFI_ALREADY_STARTED) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    \r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    gBS->CloseProtocol (\r
+      Controller,\r
+      &gEfiScsiPassThruProtocolGuid,\r
+      This->DriverBindingHandle,\r
+      Controller\r
+      );\r
+    return EFI_SUCCESS;\r
   }\r
+  \r
+  gBS->CloseProtocol (\r
+    Controller,\r
+    &gEfiExtScsiPassThruProtocolGuid,\r
+    This->DriverBindingHandle,\r
+    Controller\r
+    );\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -153,77 +222,164 @@ SCSIBusDriverBindingStart (
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
   )\r
 /*++\r
-  \r
-  Routine Description:\r
-  \r
-  Arguments:\r
-  \r
-  Returns:\r
-  \r
+\r
+Routine Description:\r
+  Starting the SCSI Bus Driver\r
+\r
+Arguments:\r
+  This                - Protocol instance pointer.\r
+  Controller          - Handle of device to test\r
+  RemainingDevicePath - Not used\r
+\r
+Returns:\r
+  EFI_SUCCESS         - This driver supports this device.\r
+  EFI_UNSUPPORTED     - This driver does not support this device.\r
+  EFI_DEVICE_ERROR    - This driver cannot be started due to device Error\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
+  SCSI_BUS_DEVICE             *ScsiBusDev;\r
+  BOOLEAN                     FromFirstTarget;\r
+  SCSI_TARGET_ID              *ScsiTargetId;\r
+  UINT8                       *TargetId;\r
+\r
+  TargetId = NULL;\r
+  ScanOtherPuns = TRUE;\r
+  FromFirstTarget = FALSE;\r
+  //\r
+  // Allocate SCSI_BUS_DEVICE structure\r
+  //\r
+  ScsiBusDev = NULL;\r
+  ScsiBusDev = AllocateZeroPool (sizeof (SCSI_BUS_DEVICE));\r
+  if (ScsiBusDev == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
 \r
-  StartPun  = 0;\r
-  StartLun  = 0;\r
+  ScsiTargetId = NULL;\r
+  ScsiTargetId = AllocateZeroPool (sizeof (SCSI_TARGET_ID));\r
+  if (ScsiTargetId == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TargetId = &ScsiTargetId->ScsiId.ExtScsi[0];\r
+  \r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
                   &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
+                  (VOID **) &(ScsiBusDev->DevicePath),\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    gBS->FreePool (ScsiBusDev);\r
     return Status;\r
   }\r
 \r
   //\r
-  // Consume SCSI Pass Thru protocol.\r
+  // First consume Extended SCSI Pass Thru protocol, if fail, then consume\r
+  // SCSI Pass Thru protocol\r
   //\r
   Status = gBS->OpenProtocol (\r
                   Controller,\r
-                  &gEfiScsiPassThruProtocolGuid,\r
-                  (VOID **) &ScsiPassThru,\r
+                  &gEfiExtScsiPassThruProtocolGuid,\r
+                  (VOID **) &(ScsiBusDev->ExtScsiInterface),\r
                   This->DriverBindingHandle,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
                   );\r
   if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiScsiPassThruProtocolGuid,\r
+                    (VOID **) &(ScsiBusDev->ScsiInterface),\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
+      gBS->FreePool (ScsiBusDev);\r
+      return Status;\r
+    } \r
+    DEBUG ((EFI_D_INFO, "Open Scsi Pass Thrugh Protocol\n"));\r
+    ScsiBusDev->ExtScsiSupport  = FALSE;\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "Open Extended Scsi Pass Thrugh Protocol\n"));\r
+    ScsiBusDev->ExtScsiSupport  = TRUE;\r
+  }\r
+\r
+  ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;\r
+  //\r
+  // Attach EFI_SCSI_BUS_PROTOCOL to controller handle\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &mScsiBusProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &ScsiBusDev->BusIdentify\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
     gBS->CloseProtocol (\r
-          Controller,\r
-          &gEfiDevicePathProtocolGuid,\r
-          This->DriverBindingHandle,\r
-          Controller\r
-          );\r
+           Controller,\r
+           &gEfiDevicePathProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    } else {\r
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiScsiPassThruProtocolGuid,\r
+             This->DriverBindingHandle,\r
+             Controller\r
+             );\r
+    }\r
+    gBS->FreePool (ScsiBusDev);\r
     return Status;\r
   }\r
 \r
   if (RemainingDevicePath == NULL) {\r
-    StartPun  = 0xFFFFFFFF;\r
-    StartLun  = 0;\r
+    SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);\r
+    Lun  = 0;\r
+    FromFirstTarget = TRUE;\r
   } else {\r
-    ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun);\r
+    if (ScsiBusDev->ExtScsiSupport) {\r
+      ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);  \r
+    } else {\r
+      ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);\r
+    }\r
   }\r
 \r
-  for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) {\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,28 +387,26 @@ 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
-\r
   return Status;\r
 }\r
 \r
@@ -286,25 +440,64 @@ SCSIBusDriverBindingStop (
   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
+                    &mScsiBusProtocolGuid,\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
+           &mScsiBusProtocolGuid,\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
+      gBS->CloseProtocol (\r
+             Controller,\r
+             &gEfiExtScsiPassThruProtocolGuid,\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
+    gBS->FreePool (ScsiBusDev);\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -329,12 +522,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,14 +549,25 @@ 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
+               &(EFI_EXT_SCSI_PASS_THRU_PROTOCOL*)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
+               &(EFI_SCSI_PASS_THRU_PROTOCOL*)ScsiPassThru,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\r
+      }\r
     } else {\r
       gBS->FreePool (ScsiIoDevice);\r
     }\r
@@ -398,12 +612,11 @@ ScsiGetDeviceType (
   return EFI_SUCCESS;\r
 }\r
 \r
-STATIC\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
@@ -430,7 +643,8 @@ ScsiGetDeviceLocation (
 \r
   ScsiIoDevice  = SCSI_IO_DEV_FROM_THIS (This);\r
 \r
-  *Target       = ScsiIoDevice->Pun;\r
+  CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
+\r
   *Lun          = ScsiIoDevice->Lun;\r
 \r
   return EFI_SUCCESS;\r
@@ -462,8 +676,11 @@ ScsiResetBus (
 \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
 EFI_STATUS\r
@@ -491,14 +708,25 @@ ScsiResetDevice (
 --*/\r
 {\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
 EFI_STATUS\r
@@ -561,56 +789,137 @@ ScsiExecuteSCSICommand (
 {\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
-  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *RequestPacket;\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
+    Status = gBS->AllocatePool (\r
+                     EfiBootServicesData,\r
+                     sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),\r
+                     (VOID**)&WorkingBuffer\r
+                     );\r
 \r
-  Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
-                                        ScsiIoDevice->ScsiPassThru,\r
-                                        ScsiIoDevice->Pun,\r
-                                        ScsiIoDevice->Lun,\r
-                                        RequestPacket,\r
-                                        Event\r
-                                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_DEVICE_ERROR;\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*)WorkingBuffer);\r
+    if (EFI_ERROR(Status)) {\r
+      gBS->FreePool(WorkingBuffer);  \r
+      return Status;\r
+    }\r
+\r
+    if ((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) && (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
+        gBS->FreePool(WorkingBuffer);\r
+        return Status;\r
+      }\r
+    \r
+      Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
+                                          ScsiIoDevice->ScsiPassThru,\r
+                                          ScsiIoDevice->Pun.ScsiId.Scsi,\r
+                                          ScsiIoDevice->Lun,\r
+                                          WorkingBuffer,\r
+                                          PacketEvent\r
+                                          );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        gBS->FreePool(WorkingBuffer);\r
+        gBS->CloseEvent(PacketEvent);\r
+        return Status;\r
+      }\r
+      \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
+                                          WorkingBuffer,\r
+                                          Event\r
+                                          );\r
+      if (EFI_ERROR(Status)) {\r
+        gBS->FreePool(WorkingBuffer);\r
+        return Status;\r
+      }\r
+\r
+      PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer,Packet);\r
+      //\r
+      // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,\r
+      // free WorkingBuffer.\r
+      //\r
+      gBS->FreePool(WorkingBuffer);\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
 EFI_STATUS\r
+EFIAPI    \r
 ScsiScanCreateDevice (\r
   EFI_DRIVER_BINDING_PROTOCOL   *This,\r
   EFI_HANDLE                    Controller,\r
-  UINT32                        Pun,\r
+  SCSI_TARGET_ID                *TargetId,\r
   UINT64                        Lun,\r
-  EFI_SCSI_PASS_THRU_PROTOCOL   *ScsiPassThru,\r
-  EFI_DEVICE_PATH_PROTOCOL      *ParentDevicePath\r
+  SCSI_BUS_DEVICE               *ScsiBusDev\r
   )\r
 /*++\r
 \r
 Routine Description:\r
 \r
-  TODO: Add function description\r
+  Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\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
+  This              - Protocol instance pointer\r
+  Controller        - Controller handle\r
+  Pun               - The Pun of the SCSI device on the SCSI channel.\r
+  Lun               - The Lun of the SCSI device on the SCSI channel.\r
+  ScsiBusDev        - The pointer of SCSI_BUS_DEVICE\r
 \r
 Returns:\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
+  EFI_SUCCESS       - Successfully to discover the device and attach ScsiIoProtocol to it.\r
+  EFI_OUT_OF_RESOURCES - Fail to discover the device.\r
 \r
 --*/\r
 {\r
@@ -630,37 +939,61 @@ Returns:
   ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));\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.GetDeviceLocation  = ScsiGetDeviceLocation;\r
   ScsiIoDevice->ScsiIo.ResetBus           = ScsiResetBus;\r
   ScsiIoDevice->ScsiIo.ResetDevice        = ScsiResetDevice;\r
   ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
 \r
+\r
   if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
     gBS->FreePool (ScsiIoDevice);\r
-    return EFI_SUCCESS;\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\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
+  if (ScsiIoDevice->ExtScsiSupport){\r
+    Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (\r
+                                          ScsiIoDevice->ExtScsiPassThru,\r
+                                          &ScsiIoDevice->Pun.ScsiId.ExtScsi[0],\r
+                                          ScsiIoDevice->Lun,\r
+                                          &ScsiDevicePath\r
+                                          );\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      gBS->FreePool (ScsiIoDevice);\r
+      return Status;\r
+    }\r
+  } else {\r
+    Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r
+                                          ScsiIoDevice->ScsiPassThru,\r
+                                          ScsiIoDevice->Pun.ScsiId.Scsi,\r
+                                          ScsiIoDevice->Lun,\r
+                                          &ScsiDevicePath\r
+                                          );\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      gBS->FreePool (ScsiIoDevice);\r
+      return Status;\r
+    }\r
   }\r
-\r
+  \r
   ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
-                              ParentDevicePath,\r
+                              ScsiBusDev->DevicePath,\r
                               ScsiDevicePath\r
                               );\r
   //\r
@@ -674,7 +1007,7 @@ Returns:
     gBS->FreePool (ScsiIoDevice);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-\r
+  \r
   Status = gBS->InstallMultipleProtocolInterfaces (\r
                   &ScsiIoDevice->Handle,\r
                   &gEfiDevicePathProtocolGuid,\r
@@ -685,21 +1018,33 @@ Returns:
                   );\r
   if (EFI_ERROR (Status)) {\r
     gBS->FreePool (ScsiIoDevice);\r
+    return EFI_OUT_OF_RESOURCES;\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
+EFIAPI    \r
 DiscoverScsiDevice (\r
   SCSI_IO_DEV   *ScsiIoDevice\r
   )\r
@@ -707,25 +1052,26 @@ DiscoverScsiDevice (
 \r
 Routine Description:\r
 \r
-  TODO: Add function description\r
+  Discovery SCSI Device\r
 \r
 Arguments:\r
 \r
-  ScsiIoDevice  - TODO: add argument description\r
+  ScsiIoDevice    - The pointer of SCSI_IO_DEV\r
 \r
 Returns:\r
 \r
-  TODO: add return values\r
+  TRUE            - Find SCSI Device and verify it.\r
+  FALSE           - Unable to find SCSI Device.  \r
 \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
 \r
   HostAdapterStatus = 0;\r
   TargetStatus      = 0;\r
@@ -766,7 +1112,7 @@ Returns:
     }\r
   }\r
 \r
-  if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) {\r
+  if (0x1e >= InquiryData.Peripheral_Type >= 0xa) {\r
     return FALSE;\r
   }\r
   \r
@@ -786,3 +1132,158 @@ Returns:
 \r
   return TRUE;\r
 }\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ScsiioToPassThruPacket (\r
+  IN      EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet,\r
+  IN OUT  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *CommandPacket\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to \r
+  EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet\r
+  \r
+Arguments:\r
+\r
+  Packet            - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+  CommandPacket     - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+   \r
+Returns:\r
+\r
+  NONE\r
+\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
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+PassThruToScsiioPacket (\r
+  IN     EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET  *ScsiPacket,\r
+  IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET         *Packet\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to \r
+  EFI_SCSI_IO_SCSI_REQUEST_PACKET packet\r
+  \r
+Arguments:\r
+\r
+  ScsiPacket        - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET\r
+  Packet            - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET\r
+   \r
+Returns:\r
+\r
+  NONE\r
+\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
+\r
+STATIC\r
+VOID\r
+EFIAPI\r
+NotifyFunction (\r
+  EFI_EVENT  Event,\r
+  VOID       *Context\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0 \r
+  SCSI IO Packet.\r
+  \r
+Arguments:\r
+\r
+  Event          - The instance of EFI_EVENT.\r
+  Context        - The parameter passed in.\r
+   \r
+Returns:\r
+\r
+  NONE\r
+\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*)WorkingBuffer;\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 WorkingBuffer.\r
+  //\r
+  gBS->FreePool(WorkingBuffer);\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