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 - 2008, Intel Corporation. <BR>\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 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include "ScsiBus.h"\r
\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {\r
SCSIBusDriverBindingSupported,\r
SCSIBusDriverBindingStart,\r
SCSIBusDriverBindingStop,\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
-EFI_GUID mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;\r
-\r
VOID *mWorkingBuffer;\r
\r
/**\r
IN VOID *Context\r
);\r
\r
+/**\r
+ Allocates an aligned buffer for SCSI device.\r
+\r
+ This function allocates an aligned buffer for the SCSI device to perform\r
+ SCSI pass through operations. The alignment requirement is from SCSI pass\r
+ through interface.\r
+\r
+ @param ScsiIoDevice The SCSI child device involved for the operation.\r
+ @param BufferSize The request buffer size.\r
+\r
+ @return A pointer to the aligned buffer or NULL if the allocation fails.\r
+\r
+**/\r
+VOID *\r
+AllocateAlignedBuffer (\r
+ IN SCSI_IO_DEV *ScsiIoDevice,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ return AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), ScsiIoDevice->ScsiIo.IoAlign);\r
+}\r
+\r
+/**\r
+ Frees an aligned buffer for SCSI device.\r
+\r
+ This function frees an aligned buffer for the SCSI device to perform\r
+ SCSI pass through operations.\r
+\r
+ @param Buffer The aligned buffer to be freed.\r
+ @param BufferSize The request buffer size.\r
+\r
+**/\r
+VOID\r
+FreeAlignedBuffer (\r
+ IN VOID *Buffer,\r
+ IN UINTN BufferSize\r
+ )\r
+{\r
+ if (Buffer != NULL) {\r
+ FreeAlignedPages (Buffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+ }\r
+}\r
+\r
/**\r
The user Entry Point for module ScsiBus. The user code starts with this function.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-InitializeScsiBus(\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+InitializeScsiBus (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
//\r
// Install driver model protocol(s).\r
return Status;\r
}\r
\r
-\r
/**\r
Test to see if this driver supports ControllerHandle.\r
\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;\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
- // Check for the existence of Extended SCSI Pass Thru Protocol and 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
\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
+ } 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
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ //\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
+ (VOID **)&PassThru,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiScsiPassThruProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ if (Status == EFI_ALREADY_STARTED) {\r
return EFI_SUCCESS;\r
}\r
\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiExtScsiPassThruProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
- return EFI_SUCCESS;\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
Start this driver on ControllerHandle.\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\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
+ 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
- ScsiTargetId = NULL;\r
ScanOtherPuns = TRUE;\r
FromFirstTarget = FALSE;\r
ExtScsiSupport = FALSE;\r
PassThruStatus = EFI_SUCCESS;\r
- \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
+ TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];\r
+ SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);\r
+\r
DevicePathStatus = gBS->OpenProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
- (VOID **) &ParentDevicePath,\r
+ (VOID **)&ParentDevicePath,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
}\r
\r
//\r
- // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as \r
+ // Report Status Code to indicate SCSI bus starts\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_INIT),\r
+ ParentDevicePath\r
+ );\r
+\r
+ //\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
&gEfiExtScsiPassThruProtocolGuid,\r
- (VOID **) &ExtScsiInterface,\r
+ (VOID **)&ExtScsiInterface,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\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
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiScsiPassThruProtocolGuid,\r
- (VOID **) &ScsiInterface,\r
+ (VOID **)&ScsiInterface,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\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
+ if (!EFI_ERROR (DevicePathStatus)) {\r
gBS->CloseProtocol (\r
Controller,\r
&gEfiDevicePathProtocolGuid,\r
This->DriverBindingHandle,\r
Controller\r
);\r
- } \r
+ }\r
+\r
return Status;\r
- } \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
+ // 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
+ (VOID **)&ScsiInterface,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\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
+ 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
+\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
+ ScsiBusDev->ScsiInterface = ScsiInterface;\r
}\r
\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
+ //\r
Status = gBS->InstallProtocolInterface (\r
&Controller,\r
- &mScsiBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
EFI_NATIVE_INTERFACE,\r
&ScsiBusDev->BusIdentify\r
);\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &mScsiBusProtocolGuid,\r
- (VOID **) &BusIdentify,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **)&BusIdentify,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
+\r
ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);\r
}\r
\r
+ //\r
+ // Report Status Code to indicate detecting devices on bus\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_DETECT),\r
+ ParentDevicePath\r
+ );\r
+\r
+ Lun = 0;\r
if (RemainingDevicePath == NULL) {\r
- SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);\r
- Lun = 0;\r
+ //\r
+ // If RemainingDevicePath is NULL,\r
+ // must enumerate all SCSI devices anyway\r
+ //\r
FromFirstTarget = TRUE;\r
- } else {\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
- ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun); \r
+ Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);\r
} else {\r
- ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);\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_SUCCESS\r
+ //\r
+ ScanOtherPuns = FALSE;\r
}\r
\r
- while(ScanOtherPuns) {\r
+ while (ScanOtherPuns) {\r
if (FromFirstTarget) {\r
//\r
// Remaining Device Path is NULL, scan all the possible Puns in the\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
+ Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun);\r
}\r
+\r
if (EFI_ERROR (Status)) {\r
//\r
// no legal Pun and Lun found any more\r
} else {\r
ScanOtherPuns = FALSE;\r
}\r
+\r
//\r
// Avoid creating handle for the host adapter.\r
//\r
if (ScsiBusDev->ExtScsiSupport) {\r
- if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {\r
+ if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {\r
continue;\r
}\r
} else {\r
- if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {\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, ScsiTargetId, Lun, ScsiBusDev);\r
+ Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev);\r
}\r
- FreePool (ScsiTargetId);\r
+\r
return EFI_SUCCESS;\r
\r
ErrorExit:\r
- \r
+\r
if (ScsiBusDev != NULL) {\r
FreePool (ScsiBusDev);\r
}\r
- \r
+\r
if (ExtScsiSupport) {\r
gBS->CloseProtocol (\r
Controller,\r
Controller\r
);\r
}\r
+\r
return Status;\r
}\r
\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
+\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
EFI_STATUS\r
EFIAPI\r
SCSIBusDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE Controller,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- EFI_STATUS Status;\r
- BOOLEAN AllChildrenStopped;\r
- UINTN Index;\r
- EFI_SCSI_IO_PROTOCOL *ScsiIo;\r
- SCSI_IO_DEV *ScsiIoDevice;\r
- VOID *ScsiPassThru;\r
- EFI_SCSI_BUS_PROTOCOL *Scsidentifier;\r
- SCSI_BUS_DEVICE *ScsiBusDev;\r
+ EFI_STATUS Status;\r
+ BOOLEAN AllChildrenStopped;\r
+ UINTN Index;\r
+ EFI_SCSI_IO_PROTOCOL *ScsiIo;\r
+ SCSI_IO_DEV *ScsiIoDevice;\r
+ VOID *ScsiPassThru;\r
+ EFI_SCSI_BUS_PROTOCOL *Scsidentifier;\r
+ SCSI_BUS_DEVICE *ScsiBusDev;\r
\r
if (NumberOfChildren == 0) {\r
//\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
- &mScsiBusProtocolGuid,\r
- (VOID **) &Scsidentifier,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **)&Scsidentifier,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
//\r
gBS->UninstallProtocolInterface (\r
Controller,\r
- &mScsiBusProtocolGuid,\r
+ &gEfiCallerIdGuid,\r
&ScsiBusDev->BusIdentify\r
);\r
\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
+ // Its intent is to prevent another SCSI Bus Driver from working on the same host handle.\r
// So Stop() needs to try to close PassThru if present here.\r
//\r
gBS->CloseProtocol (\r
AllChildrenStopped = TRUE;\r
\r
for (Index = 0; Index < NumberOfChildren; Index++) {\r
-\r
Status = gBS->OpenProtocol (\r
ChildHandleBuffer[Index],\r
&gEfiScsiIoProtocolGuid,\r
- (VOID **) &ScsiIo,\r
+ (VOID **)&ScsiIo,\r
This->DriverBindingHandle,\r
Controller,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
This->DriverBindingHandle,\r
ChildHandleBuffer[Index]\r
);\r
-\r
} else {\r
Status = gBS->CloseProtocol (\r
Controller,\r
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
+ 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
**/\r
EFI_STATUS\r
EFIAPI\r
ScsiGetDeviceType (\r
- IN EFI_SCSI_IO_PROTOCOL *This,\r
- OUT UINT8 *DeviceType\r
+ IN EFI_SCSI_IO_PROTOCOL *This,\r
+ OUT UINT8 *DeviceType\r
)\r
{\r
- SCSI_IO_DEV *ScsiIoDevice;\r
+ SCSI_IO_DEV *ScsiIoDevice;\r
\r
if (DeviceType == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
- *DeviceType = ScsiIoDevice->ScsiDeviceType;\r
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
+ *DeviceType = ScsiIoDevice->ScsiDeviceType;\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Retrieves the device location in the SCSI channel.\r
\r
EFI_STATUS\r
EFIAPI\r
ScsiGetDeviceLocation (\r
- IN EFI_SCSI_IO_PROTOCOL *This,\r
- IN OUT UINT8 **Target,\r
- OUT UINT64 *Lun\r
+ IN EFI_SCSI_IO_PROTOCOL *This,\r
+ IN OUT UINT8 **Target,\r
+ OUT UINT64 *Lun\r
)\r
{\r
- SCSI_IO_DEV *ScsiIoDevice;\r
+ SCSI_IO_DEV *ScsiIoDevice;\r
\r
- if (Target == NULL || Lun == NULL) {\r
+ if ((Target == NULL) || (Lun == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
\r
- CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
+ CopyMem (*Target, &ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
\r
- *Lun = ScsiIoDevice->Lun;\r
+ *Lun = ScsiIoDevice->Lun;\r
\r
return EFI_SUCCESS;\r
}\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
+ @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
+ IN EFI_SCSI_IO_PROTOCOL *This\r
)\r
{\r
- SCSI_IO_DEV *ScsiIoDevice;\r
+ SCSI_IO_DEV *ScsiIoDevice;\r
\r
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);\r
\r
- if (ScsiIoDevice->ExtScsiSupport){\r
+ //\r
+ // Report Status Code to indicate reset happens\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
+ ScsiIoDevice->ScsiBusDeviceData->DevicePath\r
+ );\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
EFI_STATUS\r
EFIAPI\r
ScsiResetDevice (\r
- IN EFI_SCSI_IO_PROTOCOL *This\r
+ IN EFI_SCSI_IO_PROTOCOL *This\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
+ // Report Status Code to indicate reset happens\r
+ //\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),\r
+ ScsiIoDevice->ScsiBusDeviceData->DevicePath\r
+ );\r
+\r
+ CopyMem (Target, &ScsiIoDevice->Pun, TARGET_MAX_BYTES);\r
\r
if (ScsiIoDevice->ExtScsiSupport) {\r
return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (\r
- ScsiIoDevice->ExtScsiPassThru,\r
- Target,\r
- ScsiIoDevice->Lun\r
- );\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
+ 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
+ @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
+ 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
+ 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
+ @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
+ @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
+ 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
+ @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
+ @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
+ @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
+ 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
+ sent, so no additional status information is\r
available.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI \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
+ 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
SCSI_IO_DEV *ScsiIoDevice;\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
+ SCSI_EVENT_DATA EventData;\r
\r
PacketEvent = NULL;\r
- \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
+ 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
+ ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *)Packet;\r
+\r
+ if (((ScsiIoDevice->ExtScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {\r
+ Status = ScsiIoDevice->ExtScsiPassThru->PassThru (\r
+ ScsiIoDevice->ExtScsiPassThru,\r
+ Target,\r
+ ScsiIoDevice->Lun,\r
+ ExtRequestPacket,\r
+ Event\r
+ );\r
+ } else {\r
+ //\r
+ // If there's no event or the SCSI Device doesn't support NON-BLOCKING,\r
+ // let the 'Event' parameter for PassThru() be NULL.\r
+ //\r
+ Status = ScsiIoDevice->ExtScsiPassThru->PassThru (\r
+ ScsiIoDevice->ExtScsiPassThru,\r
+ Target,\r
+ ScsiIoDevice->Lun,\r
+ ExtRequestPacket,\r
+ NULL\r
+ );\r
+ if ((!EFI_ERROR (Status)) && (Event != NULL)) {\r
+ //\r
+ // Signal Event to tell caller to pick up the SCSI IO packet if the\r
+ // PassThru() succeeds.\r
+ //\r
+ gBS->SignalEvent (Event);\r
+ }\r
+ }\r
} else {\r
-\r
- mWorkingBuffer = AllocatePool (sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
+ mWorkingBuffer = AllocatePool (sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));\r
\r
if (mWorkingBuffer == NULL) {\r
return EFI_DEVICE_ERROR;\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
+ 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.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
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ NotifyFunction,\r
+ &EventData,\r
+ &PacketEvent\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (mWorkingBuffer);\r
return Status;\r
}\r
\r
Status = ScsiIoDevice->ScsiPassThru->PassThru (\r
- ScsiIoDevice->ScsiPassThru,\r
- ScsiIoDevice->Pun.ScsiId.Scsi,\r
- ScsiIoDevice->Lun,\r
- mWorkingBuffer,\r
- PacketEvent\r
- );\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
+ if (EFI_ERROR (Status)) {\r
+ FreePool (mWorkingBuffer);\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
- mWorkingBuffer,\r
- Event\r
- );\r
- if (EFI_ERROR(Status)) {\r
- FreePool(mWorkingBuffer);\r
+ ScsiIoDevice->ScsiPassThru,\r
+ ScsiIoDevice->Pun.ScsiId.Scsi,\r
+ ScsiIoDevice->Lun,\r
+ mWorkingBuffer,\r
+ NULL\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
+ 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
+ FreePool (mWorkingBuffer);\r
+\r
+ //\r
+ // Signal Event to tell caller to pick up the SCSI IO Packet.\r
+ //\r
+ if (Event != NULL) {\r
+ gBS->SignalEvent (Event);\r
+ }\r
}\r
}\r
+\r
return Status;\r
}\r
\r
-\r
/**\r
Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.\r
\r
@param This Protocol instance pointer\r
@param Controller Controller handle\r
- @param TargetId Tartget to be scanned\r
+ @param TargetId Target 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_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
+ 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
+ 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
+ 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
- return EFI_OUT_OF_RESOURCES;\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
}\r
\r
- ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;\r
- CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);\r
- ScsiIoDevice->Lun = Lun;\r
+ ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;\r
+ ScsiIoDevice->ScsiBusDeviceData = ScsiBusDev;\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
+ ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface;\r
+ ScsiIoDevice->ExtScsiSupport = TRUE;\r
+ ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;\r
} else {\r
- ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface;\r
- ScsiIoDevice->ExtScsiSupport = FALSE;\r
- ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;\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.ResetDevice = ScsiResetDevice;\r
ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;\r
\r
-\r
- if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
//\r
- // Set Device Path\r
+ // Report Status Code here since the new SCSI device will be discovered\r
//\r
- ScsiDevicePath = NULL;\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
- } else {\r
- Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (\r
- ScsiIoDevice->ScsiPassThru,\r
- ScsiIoDevice->Pun.ScsiId.Scsi,\r
- ScsiIoDevice->Lun,\r
- &ScsiDevicePath\r
- );\r
- }\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_IO_BUS_SCSI | EFI_IOB_PC_ENABLE),\r
+ ScsiBusDev->DevicePath\r
+ );\r
\r
- if (Status == EFI_OUT_OF_RESOURCES) {\r
- FreePool (ScsiIoDevice);\r
- return Status;\r
+ if (!DiscoverScsiDevice (ScsiIoDevice)) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
}\r
\r
- ScsiIoDevice->DevicePath = AppendDevicePathNode (\r
- ScsiBusDev->DevicePath,\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
- FreePool (ScsiDevicePath);\r
-\r
- if (ScsiIoDevice->DevicePath == NULL) {\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ ScsiIoDevice->DevicePath = DevicePath;\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&ScsiIoDevice->Handle,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- FreePool (ScsiIoDevice->DevicePath);\r
- FreePool (ScsiIoDevice);\r
- return EFI_OUT_OF_RESOURCES;\r
+ goto ErrorExit;\r
} else {\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
+ 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
+ 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
+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
+ if (DevicePath != NULL) {\r
+ FreePool (DevicePath);\r
+ }\r
+\r
+ if (ScsiIoDevice != NULL) {\r
+ FreePool (ScsiIoDevice);\r
+ }\r
+\r
+ return Status;\r
+}\r
\r
/**\r
Discovery SCSI Device\r
**/\r
BOOLEAN\r
DiscoverScsiDevice (\r
- IN OUT SCSI_IO_DEV *ScsiIoDevice\r
+ IN OUT SCSI_IO_DEV *ScsiIoDevice\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 InquiryDataLength;\r
- UINT8 SenseDataLength;\r
- UINT8 HostAdapterStatus;\r
- UINT8 TargetStatus;\r
- EFI_SCSI_SENSE_DATA SenseData;\r
- EFI_SCSI_INQUIRY_DATA InquiryData;\r
+ EFI_STATUS Status;\r
+ UINT32 InquiryDataLength;\r
+ UINT8 SenseDataLength;\r
+ UINT8 HostAdapterStatus;\r
+ UINT8 TargetStatus;\r
+ EFI_SCSI_INQUIRY_DATA *InquiryData;\r
+ EFI_SCSI_SENSE_DATA *SenseData;\r
+ UINT8 MaxRetry;\r
+ UINT8 Index;\r
+ BOOLEAN ScsiDeviceFound;\r
\r
HostAdapterStatus = 0;\r
TargetStatus = 0;\r
+ SenseData = NULL;\r
+\r
+ InquiryData = AllocateAlignedBuffer (ScsiIoDevice, sizeof (EFI_SCSI_INQUIRY_DATA));\r
+ if (InquiryData == NULL) {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
+ }\r
+\r
+ SenseData = AllocateAlignedBuffer (\r
+ ScsiIoDevice,\r
+ sizeof (EFI_SCSI_SENSE_DATA)\r
+ );\r
+ if (SenseData == NULL) {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
+ }\r
+\r
//\r
// Using Inquiry command to scan for the device\r
//\r
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);\r
SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);\r
+ ZeroMem (InquiryData, InquiryDataLength);\r
+ ZeroMem (SenseData, SenseDataLength);\r
+\r
+ MaxRetry = 2;\r
+ for (Index = 0; Index < MaxRetry; Index++) {\r
+ Status = ScsiInquiryCommand (\r
+ &ScsiIoDevice->ScsiIo,\r
+ SCSI_BUS_TIMEOUT,\r
+ SenseData,\r
+ &SenseDataLength,\r
+ &HostAdapterStatus,\r
+ &TargetStatus,\r
+ (VOID *)InquiryData,\r
+ &InquiryDataLength,\r
+ FALSE\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if ((HostAdapterStatus == EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK) &&\r
+ (TargetStatus == EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION) &&\r
+ (SenseData->Error_Code == 0x70) &&\r
+ (SenseData->Sense_Key == EFI_SCSI_SK_ILLEGAL_REQUEST))\r
+ {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
+ }\r
\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
- return FALSE;\r
+ break;\r
+ }\r
+\r
+ if ((Status == EFI_BAD_BUFFER_SIZE) ||\r
+ (Status == EFI_INVALID_PARAMETER) ||\r
+ (Status == EFI_UNSUPPORTED))\r
+ {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
+ }\r
}\r
+\r
+ if (Index == MaxRetry) {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
+ }\r
+\r
//\r
// Retrieved inquiry data successfully\r
//\r
- if ((InquiryData.Peripheral_Qualifier != 0) &&\r
- (InquiryData.Peripheral_Qualifier != 3)) {\r
- return FALSE;\r
+ if (InquiryData->Peripheral_Qualifier != 0) {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
}\r
\r
- if (InquiryData.Peripheral_Qualifier == 3) {\r
- if (InquiryData.Peripheral_Type != 0x1f) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {\r
- return FALSE;\r
+ if ((InquiryData->Peripheral_Type >= EFI_SCSI_TYPE_RESERVED_LOW) &&\r
+ (InquiryData->Peripheral_Type <= EFI_SCSI_TYPE_RESERVED_HIGH))\r
+ {\r
+ ScsiDeviceFound = FALSE;\r
+ goto Done;\r
}\r
\r
//\r
// valid device type and peripheral qualifier combination.\r
//\r
- ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;\r
- ScsiIoDevice->RemovableDevice = InquiryData.Rmb;\r
- if (InquiryData.Version == 0) {\r
+ ScsiIoDevice->ScsiDeviceType = InquiryData->Peripheral_Type;\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
+ ScsiDeviceFound = TRUE;\r
+\r
+Done:\r
+ FreeAlignedBuffer (SenseData, sizeof (EFI_SCSI_SENSE_DATA));\r
+ FreeAlignedBuffer (InquiryData, sizeof (EFI_SCSI_INQUIRY_DATA));\r
\r
+ return ScsiDeviceFound;\r
+}\r
\r
/**\r
Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.\r
)\r
{\r
//\r
- //EFI 1.10 doesn't support Bi-Direction Command.\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
CommandPacket->SenseDataLength = Packet->SenseDataLength;\r
\r
if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
- CommandPacket->DataBuffer = Packet->InDataBuffer;\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->DataBuffer = Packet->OutDataBuffer;\r
CommandPacket->TransferLength = Packet->OutTransferLength;\r
}\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
Packet->SenseDataLength = ScsiPacket->SenseDataLength;\r
\r
if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {\r
- Packet->InDataBuffer = ScsiPacket->DataBuffer;\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->OutDataBuffer = ScsiPacket->DataBuffer;\r
Packet->OutTransferLength = ScsiPacket->TransferLength;\r
}\r
\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
+ 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
+ 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
+ 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
+ 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
+ gBS->CloseEvent (Event);\r
+ gBS->SignalEvent (CallerEvent);\r
}\r
-\r