// 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
#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
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
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
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
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
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
//\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
);\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
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
\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
\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
--*/\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
{\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
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
gBS->FreePool (ScsiIoDevice);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
-\r
+ \r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&ScsiIoDevice->Handle,\r
&gEfiDevicePathProtocolGuid,\r
);\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
\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
}\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
\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