X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FScsi%2FScsiBusDxe%2FScsiBus.c;h=b1c4d207f9de8bf415b3b7a157906391dcba334e;hp=68f3683bb632cfc0cda7f1a700511c883309fdff;hb=c8ad2d7a296c851c2a91519f80dab479df0fdf46;hpb=70c94b3b6ddf1d84ddb20118d898fd7a85725386
diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
index 68f3683bb6..b1c4d207f9 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
@@ -1,52 +1,22 @@
-/*++
+/** @file
+ SCSI Bus driver that layers on every SCSI Pass Thru and
+ Extended SCSI Pass Thru protocol in the system.
-Copyright (c) 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
-Module Name:
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
- scsibus.c
-
-Abstract:
-
+**/
-Revision History
---*/
-
-//
-// The package level header files this module uses
-//
-#include
-
-//
-// The protocols, PPI and GUID defintions for this module
-//
-#include
-#include
-#include
-#include
-#include
-#include
-//
-// The Library classes this module consumes
-//
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include "ScsiBus.h"
+
EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
SCSIBusDriverBindingSupported,
SCSIBusDriverBindingStart,
@@ -56,51 +26,59 @@ EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
NULL
};
+VOID *mWorkingBuffer;
-//
-// The ScsiBusProtocol is just used to locate ScsiBusDev
-// structure in the SCSIBusDriverBindingStop(). Then we can
-// Close all opened protocols and release this structure.
-//
-STATIC EFI_GUID mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;
+/**
+ Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
-STATIC VOID *WorkingBuffer;
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+ @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
-STATIC
+**/
EFI_STATUS
EFIAPI
ScsiioToPassThruPacket (
IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
- IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
- )
-;
+ OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
+ );
+/**
+ Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
+
+ @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
-STATIC
+**/
EFI_STATUS
EFIAPI
PassThruToScsiioPacket (
IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
- IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
- )
-;
-STATIC
+ OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
+ );
+
+/**
+ Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
+ SCSI IO Packet.
+
+ @param Event The instance of EFI_EVENT.
+ @param Context The parameter passed in.
+
+**/
VOID
EFIAPI
NotifyFunction (
- EFI_EVENT Event,
- VOID *Context
- )
-;
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
/**
The user Entry Point for module ScsiBus. The user code starts with this function.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
**/
EFI_STATUS
@@ -115,21 +93,39 @@ InitializeScsiBus(
//
// Install driver model protocol(s).
//
- Status = EfiLibInstallAllDriverProtocols (
+ Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gSCSIBusDriverBinding,
ImageHandle,
&gScsiBusComponentName,
- NULL,
- NULL
+ &gScsiBusComponentName2
);
ASSERT_EFI_ERROR (Status);
-
return Status;
}
+
+/**
+ Test to see if this driver supports ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Supported() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver supports this device
+ @retval EFI_ALREADY_STARTED This driver is already running on this device
+ @retval other This driver does not support this device
+
+**/
EFI_STATUS
EFIAPI
SCSIBusDriverBindingSupported (
@@ -137,32 +133,21 @@ SCSIBusDriverBindingSupported (
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
-/*++
-
-Routine Description:
-
- Test to see if this driver supports ControllerHandle. Any ControllerHandle
- that has ExtScsiPassThruProtocol/ScsiPassThruProtocol installed will be supported.
-
-Arguments:
-
- This - Protocol instance pointer.
- Controller - Handle of device to test
- RemainingDevicePath - Not used
-
-Returns:
-
- EFI_SUCCESS - This driver supports this device.
- EFI_UNSUPPORTED - This driver does not support this device.
-
---*/
-
{
- EFI_STATUS Status;
- EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;
+ EFI_STATUS Status;
+ EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;
EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;
+ UINT64 Lun;
+ UINT8 *TargetId;
+ SCSI_TARGET_ID ScsiTargetId;
+
+ TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];
+ SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
+
//
- // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol
+ // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
+ // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
+ // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
//
Status = gBS->OpenProtocol (
Controller,
@@ -172,48 +157,103 @@ Returns:
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
-
+
if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiScsiPassThruProtocolGuid,
- (VOID **)&PassThru,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (Status == EFI_ALREADY_STARTED) {
+ } else if (!EFI_ERROR(Status)) {
+ //
+ // Check if RemainingDevicePath is NULL or the End of Device Path Node,
+ // if yes, return EFI_SUCCESS.
+ //
+ if ((RemainingDevicePath == NULL) || IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // Close protocol regardless of RemainingDevicePath validation
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
return EFI_SUCCESS;
+ } else {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node, check its validation
+ //
+ Status = ExtPassThru->GetTargetLun (ExtPassThru, RemainingDevicePath, &TargetId, &Lun);
+ //
+ // Close protocol regardless of RemainingDevicePath validation
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (!EFI_ERROR(Status)) {
+ return EFI_SUCCESS;
+ }
}
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
+ }
- gBS->CloseProtocol (
- Controller,
- &gEfiScsiPassThruProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ //
+ // Come here in 2 condition:
+ // 1. ExtPassThru doesn't exist.
+ // 2. ExtPassThru exists but RemainingDevicePath is invalid.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **)&PassThru,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
return EFI_SUCCESS;
}
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Test RemainingDevicePath is valid or not.
+ //
+ if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
+ Status = PassThru->GetTargetLun (PassThru, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);
+ }
+
gBS->CloseProtocol (
- Controller,
- &gEfiExtScsiPassThruProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
-
- return EFI_SUCCESS;
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
}
+
+/**
+ Start this driver on ControllerHandle.
+
+ This service is called by the EFI boot service ConnectController(). In order
+ to make drivers as small as possible, there are a few calling restrictions for
+ this service. ConnectController() must follow these calling restrictions. If
+ any other agent wishes to call Start() it must also follow these calling
+ restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to bind driver to
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCESS This driver is added to ControllerHandle
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
+ @retval other This driver does not support this device
+
+**/
EFI_STATUS
EFIAPI
SCSIBusDriverBindingStart (
@@ -221,152 +261,180 @@ SCSIBusDriverBindingStart (
IN EFI_HANDLE Controller,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
-/*++
-
-Routine Description:
- Starting the SCSI Bus Driver
-
-Arguments:
- This - Protocol instance pointer.
- Controller - Handle of device to test
- RemainingDevicePath - Not used
-
-Returns:
- EFI_SUCCESS - This driver supports this device.
- EFI_UNSUPPORTED - This driver does not support this device.
- EFI_DEVICE_ERROR - This driver cannot be started due to device Error
-
---*/
-// TODO: This - add argument and description to function comment
-// TODO: Controller - add argument and description to function comment
-// TODO: RemainingDevicePath - add argument and description to function comment
{
- EFI_STATUS Status;
- UINT64 Lun;
- BOOLEAN ScanOtherPuns;
- SCSI_BUS_DEVICE *ScsiBusDev;
- BOOLEAN FromFirstTarget;
- SCSI_TARGET_ID *ScsiTargetId;
- UINT8 *TargetId;
-
- TargetId = NULL;
- ScanOtherPuns = TRUE;
+ UINT64 Lun;
+ UINT8 *TargetId;
+ BOOLEAN ScanOtherPuns;
+ BOOLEAN FromFirstTarget;
+ BOOLEAN ExtScsiSupport;
+ EFI_STATUS Status;
+ EFI_STATUS DevicePathStatus;
+ EFI_STATUS PassThruStatus;
+ SCSI_BUS_DEVICE *ScsiBusDev;
+ SCSI_TARGET_ID ScsiTargetId;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;
+ EFI_SCSI_BUS_PROTOCOL *BusIdentify;
+
+ TargetId = NULL;
+ ScanOtherPuns = TRUE;
FromFirstTarget = FALSE;
- //
- // Allocate SCSI_BUS_DEVICE structure
- //
- ScsiBusDev = NULL;
- ScsiBusDev = AllocateZeroPool (sizeof (SCSI_BUS_DEVICE));
- if (ScsiBusDev == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- ScsiTargetId = NULL;
- ScsiTargetId = AllocateZeroPool (sizeof (SCSI_TARGET_ID));
- if (ScsiTargetId == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- TargetId = &ScsiTargetId->ScsiId.ExtScsi[0];
+ ExtScsiSupport = FALSE;
+ PassThruStatus = EFI_SUCCESS;
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &(ScsiBusDev->DevicePath),
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- gBS->FreePool (ScsiBusDev);
- return Status;
+ TargetId = &ScsiTargetId.ScsiId.ExtScsi[0];
+ SetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
+
+ DevicePathStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {
+ return DevicePathStatus;
}
//
- // First consume Extended SCSI Pass Thru protocol, if fail, then consume
- // SCSI Pass Thru protocol
+ // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
+ // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
+ // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
//
Status = gBS->OpenProtocol (
Controller,
&gEfiExtScsiPassThruProtocolGuid,
- (VOID **) &(ScsiBusDev->ExtScsiInterface),
+ (VOID **) &ExtScsiInterface,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ //
+ // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.
+ //
+ if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
Status = gBS->OpenProtocol (
Controller,
&gEfiScsiPassThruProtocolGuid,
- (VOID **) &(ScsiBusDev->ScsiInterface),
+ (VOID **) &ScsiInterface,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
- if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->FreePool (ScsiBusDev);
+ //
+ // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
+ if (!EFI_ERROR(DevicePathStatus)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
return Status;
}
- DEBUG ((EFI_D_INFO, "Open Scsi Pass Thrugh Protocol\n"));
- ScsiBusDev->ExtScsiSupport = FALSE;
} else {
- DEBUG ((EFI_D_INFO, "Open Extended Scsi Pass Thrugh Protocol\n"));
- ScsiBusDev->ExtScsiSupport = TRUE;
+ //
+ // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol
+ // with BY_DRIVER if it is also present on the handle. The intent is to prevent
+ // another SCSI Bus Driver to work on the same host handle.
+ //
+ ExtScsiSupport = TRUE;
+ PassThruStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &ScsiInterface,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
}
-
- ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
- //
- // Attach EFI_SCSI_BUS_PROTOCOL to controller handle
- //
- Status = gBS->InstallProtocolInterface (
- &Controller,
- &mScsiBusProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &ScsiBusDev->BusIdentify
- );
-
- if (EFI_ERROR (Status)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+
+ if (Status != EFI_ALREADY_STARTED) {
+ //
+ // Go through here means either ExtPassThru or PassThru Protocol is successfully opened
+ // on this handle for this time. Then construct Host controller private data.
+ //
+ ScsiBusDev = NULL;
+ ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE));
+ if (ScsiBusDev == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+ ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
+ ScsiBusDev->ExtScsiSupport = ExtScsiSupport;
+ ScsiBusDev->DevicePath = ParentDevicePath;
if (ScsiBusDev->ExtScsiSupport) {
- gBS->CloseProtocol (
- Controller,
- &gEfiExtScsiPassThruProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ ScsiBusDev->ExtScsiInterface = ExtScsiInterface;
} else {
- gBS->CloseProtocol (
- Controller,
- &gEfiScsiPassThruProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ ScsiBusDev->ScsiInterface = ScsiInterface;
}
- gBS->FreePool (ScsiBusDev);
- return Status;
+
+ //
+ // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be
+ // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru
+ // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &ScsiBusDev->BusIdentify
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+ } else {
+ //
+ // Go through here means Start() is re-invoked again, nothing special is required to do except
+ // picking up Host controller private information.
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &BusIdentify,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);
}
+ Lun = 0;
if (RemainingDevicePath == NULL) {
- SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);
- Lun = 0;
+ //
+ // If RemainingDevicePath is NULL,
+ // must enumerate all SCSI devices anyway
+ //
FromFirstTarget = TRUE;
- } else {
+ } else if (!IsDevicePathEnd (RemainingDevicePath)) {
+ //
+ // If RemainingDevicePath isn't the End of Device Path Node,
+ // only scan the specified device by RemainingDevicePath
+ //
if (ScsiBusDev->ExtScsiSupport) {
- ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);
+ Status = ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);
} else {
- ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);
+ Status = ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId.ScsiId.Scsi, &Lun);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+ } else {
+ //
+ // If RemainingDevicePath is the End of Device Path Node,
+ // skip enumerate any device and return EFI_SUCESSS
+ //
+ ScanOtherPuns = FALSE;
}
while(ScanOtherPuns) {
@@ -378,7 +446,7 @@ Returns:
if (ScsiBusDev->ExtScsiSupport) {
Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);
} else {
- Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId->ScsiId.Scsi, &Lun);
+ Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId.ScsiId.Scsi, &Lun);
}
if (EFI_ERROR (Status)) {
//
@@ -393,11 +461,11 @@ Returns:
// Avoid creating handle for the host adapter.
//
if (ScsiBusDev->ExtScsiSupport) {
- if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {
+ if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {
continue;
}
} else {
- if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {
+ if ((ScsiTargetId.ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {
continue;
}
}
@@ -405,11 +473,61 @@ Returns:
// Scan for the scsi device, if it attaches to the scsi bus,
// then create handle and install scsi i/o protocol.
//
- Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev);
+ Status = ScsiScanCreateDevice (This, Controller, &ScsiTargetId, Lun, ScsiBusDev);
+ }
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ if (ScsiBusDev != NULL) {
+ FreePool (ScsiBusDev);
+ }
+
+ if (ExtScsiSupport) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (!EFI_ERROR (PassThruStatus)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ } else {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
}
return Status;
}
+/**
+ Stop this driver on ControllerHandle.
+
+ This service is called by the EFI boot service DisconnectController().
+ In order to make drivers as small as possible, there are a few calling
+ restrictions for this service. DisconnectController() must follow these
+ calling restrictions. If any other agent wishes to call Stop() it must also
+ follow these calling restrictions.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
+ children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCESS This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
EFI_STATUS
EFIAPI
SCSIBusDriverBindingStop (
@@ -418,22 +536,6 @@ SCSIBusDriverBindingStop (
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
-/*++
-
- Routine Description:
-
- Arguments:
-
- Returns:
-
---*/
-// TODO: This - add argument and description to function comment
-// TODO: Controller - add argument and description to function comment
-// TODO: NumberOfChildren - add argument and description to function comment
-// TODO: ChildHandleBuffer - add argument and description to function comment
-// TODO: EFI_SUCCESS - add return value to function comment
-// TODO: EFI_DEVICE_ERROR - add return value to function comment
-// TODO: EFI_SUCCESS - add return value to function comment
{
EFI_STATUS Status;
BOOLEAN AllChildrenStopped;
@@ -450,13 +552,13 @@ SCSIBusDriverBindingStop (
//
Status = gBS->OpenProtocol (
Controller,
- &mScsiBusProtocolGuid,
+ &gEfiCallerIdGuid,
(VOID **) &Scsidentifier,
This->DriverBindingHandle,
Controller,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
-
+
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
@@ -468,20 +570,34 @@ SCSIBusDriverBindingStop (
//
gBS->UninstallProtocolInterface (
Controller,
- &mScsiBusProtocolGuid,
+ &gEfiCallerIdGuid,
&ScsiBusDev->BusIdentify
);
-
+
//
// Close the bus driver
//
if (ScsiBusDev->ExtScsiSupport) {
+ //
+ // Close ExtPassThru Protocol from this controller handle
+ //
gBS->CloseProtocol (
Controller,
&gEfiExtScsiPassThruProtocolGuid,
This->DriverBindingHandle,
Controller
);
+ //
+ // When Start() succeeds to open ExtPassThru, it always tries to open PassThru BY_DRIVER.
+ // Its intent is to prevent another SCSI Bus Driver from woking on the same host handle.
+ // So Stop() needs to try to close PassThru if present here.
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
} else {
gBS->CloseProtocol (
Controller,
@@ -497,7 +613,7 @@ SCSIBusDriverBindingStop (
This->DriverBindingHandle,
Controller
);
- gBS->FreePool (ScsiBusDev);
+ FreePool (ScsiBusDev);
return EFI_SUCCESS;
}
@@ -553,7 +669,7 @@ SCSIBusDriverBindingStop (
gBS->OpenProtocol (
Controller,
&gEfiExtScsiPassThruProtocolGuid,
- &(EFI_EXT_SCSI_PASS_THRU_PROTOCOL*)ScsiPassThru,
+ &ScsiPassThru,
This->DriverBindingHandle,
ChildHandleBuffer[Index],
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
@@ -562,14 +678,14 @@ SCSIBusDriverBindingStop (
gBS->OpenProtocol (
Controller,
&gEfiScsiPassThruProtocolGuid,
- &(EFI_SCSI_PASS_THRU_PROTOCOL*)ScsiPassThru,
+ &ScsiPassThru,
This->DriverBindingHandle,
ChildHandleBuffer[Index],
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
}
} else {
- gBS->FreePool (ScsiIoDevice);
+ FreePool (ScsiIoDevice);
}
}
@@ -580,26 +696,24 @@ SCSIBusDriverBindingStop (
return EFI_SUCCESS;
}
+
+/**
+ Retrieves the device type information of the SCSI Controller.
+
+ @param This Protocol instance pointer.
+ @param DeviceType A pointer to the device type information retrieved from
+ the SCSI Controller.
+
+ @retval EFI_SUCCESS Retrieves the device type information successfully.
+ @retval EFI_INVALID_PARAMETER The DeviceType is NULL.
+
+**/
EFI_STATUS
EFIAPI
ScsiGetDeviceType (
IN EFI_SCSI_IO_PROTOCOL *This,
OUT UINT8 *DeviceType
)
-/*++
-
- Routine Description:
- Retrieves the device type information of the SCSI Controller.
-
- Arguments:
- This - Protocol instance pointer.
- DeviceType - A pointer to the device type information
- retrieved from the SCSI Controller.
-
- Returns:
- EFI_SUCCESS - Retrieves the device type information successfully.
- EFI_INVALID_PARAMETER - The DeviceType is NULL.
---*/
{
SCSI_IO_DEV *ScsiIoDevice;
@@ -612,6 +726,20 @@ ScsiGetDeviceType (
return EFI_SUCCESS;
}
+
+/**
+ Retrieves the device location in the SCSI channel.
+
+ @param This Protocol instance pointer.
+ @param Target A pointer to the Target ID of a SCSI device
+ on the SCSI channel.
+ @param Lun A pointer to the LUN of the SCSI device on
+ the SCSI channel.
+
+ @retval EFI_SUCCESS Retrieves the device location successfully.
+ @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.
+
+**/
EFI_STATUS
EFIAPI
ScsiGetDeviceLocation (
@@ -619,21 +747,6 @@ ScsiGetDeviceLocation (
IN OUT UINT8 **Target,
OUT UINT64 *Lun
)
-/*++
- Routine Description:
- Retrieves the device location in the SCSI channel.
-
- Arguments:
- This - Protocol instance pointer.
- Target - A pointer to the Target ID of a SCSI device
- on the SCSI channel.
- Lun - A pointer to the LUN of the SCSI device on
- the SCSI channel.
-
- Returns:
- EFI_SUCCESS - Retrieves the device location successfully.
- EFI_INVALID_PARAMETER - The Target or Lun is NULL.
---*/
{
SCSI_IO_DEV *ScsiIoDevice;
@@ -641,36 +754,32 @@ ScsiGetDeviceLocation (
return EFI_INVALID_PARAMETER;
}
- ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
+ ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
- *Lun = ScsiIoDevice->Lun;
+ *Lun = ScsiIoDevice->Lun;
return EFI_SUCCESS;
}
+/**
+ Resets the SCSI Bus that the SCSI Controller is attached to.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The SCSI bus is reset successfully.
+ @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus.
+ @retval EFI_UNSUPPORTED The bus reset operation is not supported by the
+ SCSI Host Controller.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset
+ the SCSI bus.
+**/
EFI_STATUS
EFIAPI
ScsiResetBus (
IN EFI_SCSI_IO_PROTOCOL *This
)
-/*++
-
- Routine Description:
- Resets the SCSI Bus that the SCSI Controller is attached to.
-
- Arguments:
- This - Protocol instance pointer.
-
- Returns:
- EFI_SUCCESS - The SCSI bus is reset successfully.
- EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus.
- EFI_UNSUPPORTED - The bus reset operation is not supported by the
- SCSI Host Controller.
- EFI_TIMEOUT - A timeout occurred while attempting to reset
- the SCSI bus.
---*/
{
SCSI_IO_DEV *ScsiIoDevice;
@@ -683,31 +792,25 @@ ScsiResetBus (
}
}
+
+/**
+ Resets the SCSI Controller that the device handle specifies.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Reset the SCSI controller successfully.
+ @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller.
+ @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation.
+ @retval EFI_TIMEOUT A timeout occurred while attempting to reset the
+ SCSI Controller.
+**/
EFI_STATUS
EFIAPI
ScsiResetDevice (
IN EFI_SCSI_IO_PROTOCOL *This
)
-/*++
-
- Routine Description:
- Resets the SCSI Controller that the device handle specifies.
-
- Arguments:
- This - Protocol instance pointer.
-
-
- Returns:
- EFI_SUCCESS - Reset the SCSI controller successfully.
- EFI_DEVICE_ERROR - Errors are encountered when resetting the
- SCSI Controller.
- EFI_UNSUPPORTED - The SCSI bus does not support a device
- reset operation.
- EFI_TIMEOUT - A timeout occurred while attempting to
- reset the SCSI Controller.
---*/
{
- SCSI_IO_DEV *ScsiIoDevice;
+ SCSI_IO_DEV *ScsiIoDevice;
UINT8 Target[TARGET_MAX_BYTES];
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
@@ -729,66 +832,64 @@ ScsiResetDevice (
}
}
+
+/**
+ Sends a SCSI Request Packet to the SCSI Controller for execution.
+
+ @param This Protocol instance pointer.
+ @param CommandPacket The SCSI request packet to send to the SCSI
+ Controller specified by the device handle.
+ @param Event If the SCSI bus where the SCSI device is attached
+ does not support non-blocking I/O, then Event is
+ ignored, and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed.
+ If Event is not NULL and non-blocking I/O is
+ supported, then non-blocking I/O is performed,
+ and Event will be signaled when the SCSI Request
+ Packet completes.
+
+ @retval EFI_SUCCESS The SCSI Request Packet was sent by the host
+ successfully, and TransferLength bytes were
+ transferred to/from DataBuffer.See
+ HostAdapterStatus, TargetStatus,
+ SenseDataLength, and SenseData in that order
+ for additional status information.
+ @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
+ but the entire DataBuffer could not be transferred.
+ The actual number of bytes transferred is returned
+ in TransferLength. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
+ there are too many SCSI Command Packets already
+ queued.The caller may retry again later.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
+ the SCSI Request Packet. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+ @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.
+ The SCSI Request Packet was not sent, so no
+ additional status information is available.
+ @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
+ is not supported by the SCSI initiator(i.e., SCSI
+ Host Controller). The SCSI Request Packet was not
+ sent, so no additional status information is
+ available.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
+ Request Packet to execute. See HostAdapterStatus,
+ TargetStatus, SenseDataLength, and SenseData in
+ that order for additional status information.
+**/
EFI_STATUS
EFIAPI
ScsiExecuteSCSICommand (
- IN EFI_SCSI_IO_PROTOCOL *This,
- IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
- IN EFI_EVENT Event OPTIONAL
+ IN EFI_SCSI_IO_PROTOCOL *This,
+ IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
)
-/*++
-
- Routine Description:
- Sends a SCSI Request Packet to the SCSI Controller for execution.
-
- Arguments:
- This - Protocol instance pointer.
- Packet - The SCSI request packet to send to the SCSI
- Controller specified by the device handle.
- Event - If the SCSI bus where the SCSI device is attached
- does not support non-blocking I/O, then Event is
- ignored, and blocking I/O is performed.
- If Event is NULL, then blocking I/O is performed.
- If Event is not NULL and non-blocking I/O is
- supported, then non-blocking I/O is performed,
- and Event will be signaled when the SCSI Request
- Packet completes.
- Returns:
- EFI_SUCCESS - The SCSI Request Packet was sent by the host
- successfully, and TransferLength bytes were
- transferred to/from DataBuffer.See
- HostAdapterStatus, TargetStatus,
- SenseDataLength, and SenseData in that order
- for additional status information.
- EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed,
- but the entire DataBuffer could not be transferred.
- The actual number of bytes transferred is returned
- in TransferLength. See HostAdapterStatus,
- TargetStatus, SenseDataLength, and SenseData in
- that order for additional status information.
- EFI_NOT_READY - The SCSI Request Packet could not be sent because
- there are too many SCSI Command Packets already
- queued.The caller may retry again later.
- EFI_DEVICE_ERROR - A device error occurred while attempting to send
- the SCSI Request Packet. See HostAdapterStatus,
- TargetStatus, SenseDataLength, and SenseData in
- that order for additional status information.
- EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid.
- The SCSI Request Packet was not sent, so no
- additional status information is available.
- EFI_UNSUPPORTED - The command described by the SCSI Request Packet
- is not supported by the SCSI initiator(i.e., SCSI
- Host Controller). The SCSI Request Packet was not
- sent, so no additional status information is
- available.
- EFI_TIMEOUT - A timeout occurred while waiting for the SCSI
- Request Packet to execute. See HostAdapterStatus,
- TargetStatus, SenseDataLength, and SenseData in
- that order for additional status information.
---*/
{
- SCSI_IO_DEV *ScsiIoDevice;
- EFI_STATUS Status;
+ SCSI_IO_DEV *ScsiIoDevice;
+ EFI_STATUS Status;
UINT8 Target[TARGET_MAX_BYTES];
EFI_EVENT PacketEvent;
EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;
@@ -802,7 +903,7 @@ ScsiExecuteSCSICommand (
ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
-
+
if (ScsiIoDevice->ExtScsiSupport) {
ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;
Status = ScsiIoDevice->ExtScsiPassThru->PassThru (
@@ -814,26 +915,22 @@ ScsiExecuteSCSICommand (
);
} else {
- Status = gBS->AllocatePool (
- EfiBootServicesData,
- sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),
- (VOID**)&WorkingBuffer
- );
+ mWorkingBuffer = AllocatePool (sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
- if (EFI_ERROR (Status)) {
+ if (mWorkingBuffer == NULL) {
return EFI_DEVICE_ERROR;
}
//
- // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.
+ // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.
//
- Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer);
+ Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer);
if (EFI_ERROR(Status)) {
- gBS->FreePool(WorkingBuffer);
+ FreePool(mWorkingBuffer);
return Status;
}
- if ((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) && (Event != NULL)) {
+ if (((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) != 0) && (Event != NULL)) {
EventData.Data1 = (VOID*)Packet;
EventData.Data2 = Event;
//
@@ -847,24 +944,24 @@ ScsiExecuteSCSICommand (
&PacketEvent
);
if (EFI_ERROR(Status)) {
- gBS->FreePool(WorkingBuffer);
+ FreePool(mWorkingBuffer);
return Status;
}
-
+
Status = ScsiIoDevice->ScsiPassThru->PassThru (
ScsiIoDevice->ScsiPassThru,
ScsiIoDevice->Pun.ScsiId.Scsi,
ScsiIoDevice->Lun,
- WorkingBuffer,
+ mWorkingBuffer,
PacketEvent
);
if (EFI_ERROR(Status)) {
- gBS->FreePool(WorkingBuffer);
+ FreePool(mWorkingBuffer);
gBS->CloseEvent(PacketEvent);
return Status;
}
-
+
} else {
//
// If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert
@@ -874,69 +971,111 @@ ScsiExecuteSCSICommand (
ScsiIoDevice->ScsiPassThru,
ScsiIoDevice->Pun.ScsiId.Scsi,
ScsiIoDevice->Lun,
- WorkingBuffer,
+ mWorkingBuffer,
Event
);
if (EFI_ERROR(Status)) {
- gBS->FreePool(WorkingBuffer);
+ FreePool(mWorkingBuffer);
return Status;
}
- PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer,Packet);
+ PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer,Packet);
//
// After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
- // free WorkingBuffer.
+ // free mWorkingBuffer.
//
- gBS->FreePool(WorkingBuffer);
+ FreePool(mWorkingBuffer);
}
}
return Status;
}
-EFI_STATUS
-EFIAPI
-ScsiScanCreateDevice (
- EFI_DRIVER_BINDING_PROTOCOL *This,
- EFI_HANDLE Controller,
- SCSI_TARGET_ID *TargetId,
- UINT64 Lun,
- SCSI_BUS_DEVICE *ScsiBusDev
- )
-/*++
-
-Routine Description:
+/**
Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.
-Arguments:
-
- This - Protocol instance pointer
- Controller - Controller handle
- Pun - The Pun of the SCSI device on the SCSI channel.
- Lun - The Lun of the SCSI device on the SCSI channel.
- ScsiBusDev - The pointer of SCSI_BUS_DEVICE
-
-Returns:
+ @param This Protocol instance pointer
+ @param Controller Controller handle
+ @param TargetId Tartget to be scanned
+ @param Lun The Lun of the SCSI device on the SCSI channel.
+ @param ScsiBusDev The pointer of SCSI_BUS_DEVICE
- EFI_SUCCESS - Successfully to discover the device and attach ScsiIoProtocol to it.
- EFI_OUT_OF_RESOURCES - Fail to discover the device.
+ @retval EFI_SUCCESS Successfully to discover the device and attach
+ ScsiIoProtocol to it.
+ @retval EFI_OUT_OF_RESOURCES Fail to discover the device.
---*/
+**/
+EFI_STATUS
+EFIAPI
+ScsiScanCreateDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN SCSI_TARGET_ID *TargetId,
+ IN UINT64 Lun,
+ IN OUT SCSI_BUS_DEVICE *ScsiBusDev
+ )
{
EFI_STATUS Status;
SCSI_IO_DEV *ScsiIoDevice;
EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_HANDLE DeviceHandle;
- Status = gBS->AllocatePool (
- EfiBootServicesData,
- sizeof (SCSI_IO_DEV),
- (VOID **) &ScsiIoDevice
- );
- if (EFI_ERROR (Status)) {
+ DevicePath = NULL;
+ RemainingDevicePath = NULL;
+ ScsiDevicePath = NULL;
+ ScsiIoDevice = NULL;
+
+ //
+ // Build Device Path
+ //
+ if (ScsiBusDev->ExtScsiSupport){
+ Status = ScsiBusDev->ExtScsiInterface->BuildDevicePath (
+ ScsiBusDev->ExtScsiInterface,
+ &TargetId->ScsiId.ExtScsi[0],
+ Lun,
+ &ScsiDevicePath
+ );
+ } else {
+ Status = ScsiBusDev->ScsiInterface->BuildDevicePath (
+ ScsiBusDev->ScsiInterface,
+ TargetId->ScsiId.Scsi,
+ Lun,
+ &ScsiDevicePath
+ );
+ }
+
+ if (EFI_ERROR(Status)) {
return Status;
}
- ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV));
+ DevicePath = AppendDevicePathNode (
+ ScsiBusDev->DevicePath,
+ ScsiDevicePath
+ );
+
+ if (DevicePath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ DeviceHandle = NULL;
+ RemainingDevicePath = DevicePath;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
+ if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
+ //
+ // The device has been started, directly return to fast boot.
+ //
+ Status = EFI_ALREADY_STARTED;
+ goto ErrorExit;
+ }
+
+ ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));
+ if (ScsiIoDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);
@@ -959,55 +1098,13 @@ Returns:
ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
-
if (!DiscoverScsiDevice (ScsiIoDevice)) {
- gBS->FreePool (ScsiIoDevice);
- return EFI_OUT_OF_RESOURCES;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
}
- //
- // Set Device Path
- //
- if (ScsiIoDevice->ExtScsiSupport){
- Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (
- ScsiIoDevice->ExtScsiPassThru,
- &ScsiIoDevice->Pun.ScsiId.ExtScsi[0],
- ScsiIoDevice->Lun,
- &ScsiDevicePath
- );
- if (Status == EFI_OUT_OF_RESOURCES) {
- gBS->FreePool (ScsiIoDevice);
- return Status;
- }
- } else {
- Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
- ScsiIoDevice->ScsiPassThru,
- ScsiIoDevice->Pun.ScsiId.Scsi,
- ScsiIoDevice->Lun,
- &ScsiDevicePath
- );
- if (Status == EFI_OUT_OF_RESOURCES) {
- gBS->FreePool (ScsiIoDevice);
- return Status;
- }
- }
-
- ScsiIoDevice->DevicePath = AppendDevicePathNode (
- ScsiBusDev->DevicePath,
- ScsiDevicePath
- );
- //
- // The memory space for ScsiDevicePath is allocated in
- // ScsiPassThru->BuildDevicePath() function; It is no longer used
- // after EfiAppendDevicePathNode,so free the memory it occupies.
- //
- gBS->FreePool (ScsiDevicePath);
+ ScsiIoDevice->DevicePath = DevicePath;
- if (ScsiIoDevice->DevicePath == NULL) {
- gBS->FreePool (ScsiIoDevice);
- return EFI_OUT_OF_RESOURCES;
- }
-
Status = gBS->InstallMultipleProtocolInterfaces (
&ScsiIoDevice->Handle,
&gEfiDevicePathProtocolGuid,
@@ -1017,53 +1114,64 @@ Returns:
NULL
);
if (EFI_ERROR (Status)) {
- gBS->FreePool (ScsiIoDevice);
- return EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
} else {
if (ScsiBusDev->ExtScsiSupport) {
gBS->OpenProtocol (
- Controller,
- &gEfiExtScsiPassThruProtocolGuid,
- (VOID **) &(ScsiBusDev->ExtScsiInterface),
- This->DriverBindingHandle,
- ScsiIoDevice->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
+ Controller,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **) &(ScsiBusDev->ExtScsiInterface),
+ This->DriverBindingHandle,
+ ScsiIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
} else {
gBS->OpenProtocol (
- Controller,
- &gEfiScsiPassThruProtocolGuid,
- (VOID **) &(ScsiBusDev->ScsiInterface),
- This->DriverBindingHandle,
- ScsiIoDevice->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &(ScsiBusDev->ScsiInterface),
+ This->DriverBindingHandle,
+ ScsiIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
}
}
return EFI_SUCCESS;
-}
-BOOLEAN
-EFIAPI
-DiscoverScsiDevice (
- SCSI_IO_DEV *ScsiIoDevice
- )
-/*++
+ErrorExit:
+
+ //
+ // The memory space for ScsiDevicePath is allocated in
+ // ScsiPassThru->BuildDevicePath() function; It is no longer used
+ // after AppendDevicePathNode,so free the memory it occupies.
+ //
+ FreePool (ScsiDevicePath);
-Routine Description:
+ if (DevicePath != NULL) {
+ FreePool (DevicePath);
+ }
- Discovery SCSI Device
+ if (ScsiIoDevice != NULL) {
+ FreePool (ScsiIoDevice);
+ }
-Arguments:
+ return Status;
+}
- ScsiIoDevice - The pointer of SCSI_IO_DEV
-Returns:
+/**
+ Discovery SCSI Device
+
+ @param ScsiIoDevice The pointer of SCSI_IO_DEV
- TRUE - Find SCSI Device and verify it.
- FALSE - Unable to find SCSI Device.
+ @retval TRUE Find SCSI Device and verify it.
+ @retval FALSE Unable to find SCSI Device.
---*/
+**/
+BOOLEAN
+DiscoverScsiDevice (
+ IN OUT SCSI_IO_DEV *ScsiIoDevice
+ )
{
EFI_STATUS Status;
UINT32 InquiryDataLength;
@@ -1072,6 +1180,8 @@ Returns:
UINT8 TargetStatus;
EFI_SCSI_SENSE_DATA SenseData;
EFI_SCSI_INQUIRY_DATA InquiryData;
+ UINT8 MaxRetry;
+ UINT8 Index;
HostAdapterStatus = 0;
TargetStatus = 0;
@@ -1079,25 +1189,35 @@ Returns:
// Using Inquiry command to scan for the device
//
InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
- SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
-
- Status = SubmitInquiryCommand (
- &ScsiIoDevice->ScsiIo,
- EfiScsiStallSeconds (1),
- (VOID *) &SenseData,
- &SenseDataLength,
- &HostAdapterStatus,
- &TargetStatus,
- (VOID *) &InquiryData,
- &InquiryDataLength,
- FALSE
- );
- if (EFI_ERROR (Status)) {
- //
- // ParseSenseData (&SenseData,SenseDataLength);
- //
+ SenseDataLength = (UINT8) sizeof (EFI_SCSI_SENSE_DATA);
+ ZeroMem (&InquiryData, InquiryDataLength);
+
+ MaxRetry = 2;
+ for (Index = 0; Index < MaxRetry; Index++) {
+ Status = ScsiInquiryCommand (
+ &ScsiIoDevice->ScsiIo,
+ EFI_TIMER_PERIOD_SECONDS (1),
+ (VOID *) &SenseData,
+ &SenseDataLength,
+ &HostAdapterStatus,
+ &TargetStatus,
+ (VOID *) &InquiryData,
+ &InquiryDataLength,
+ FALSE
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ } else if ((Status == EFI_BAD_BUFFER_SIZE) ||
+ (Status == EFI_INVALID_PARAMETER) ||
+ (Status == EFI_UNSUPPORTED)) {
+ return FALSE;
+ }
+ }
+
+ if (Index == MaxRetry) {
return FALSE;
}
+
//
// Retrieved inquiry data successfully
//
@@ -1112,52 +1232,41 @@ Returns:
}
}
- if (0x1e >= InquiryData.Peripheral_Type >= 0xa) {
+ if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {
return FALSE;
}
-
+
//
// valid device type and peripheral qualifier combination.
//
ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;
- ScsiIoDevice->RemovableDevice = InquiryData.RMB;
+ ScsiIoDevice->RemovableDevice = InquiryData.Rmb;
if (InquiryData.Version == 0) {
ScsiIoDevice->ScsiVersion = 0;
} else {
//
// ANSI-approved version
//
- ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);
+ ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x07);
}
return TRUE;
}
-STATIC
+/**
+ Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
+
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+ @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+
+**/
EFI_STATUS
EFIAPI
ScsiioToPassThruPacket (
IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
- IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
+ OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
)
-/*++
-
-Routine Description:
-
- Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to
- EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet
-
-Arguments:
-
- Packet - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
- CommandPacket - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
-
-Returns:
-
- NONE
-
---*/
{
//
//EFI 1.10 doesn't support Bi-Direction Command.
@@ -1165,7 +1274,7 @@ Returns:
if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {
return EFI_UNSUPPORTED;
}
-
+
ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
CommandPacket->Timeout = Packet->Timeout;
@@ -1188,30 +1297,19 @@ Returns:
}
-STATIC
+/**
+ Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
+
+ @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
+ @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
+
+**/
EFI_STATUS
EFIAPI
PassThruToScsiioPacket (
IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
- IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
+ OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
)
-/*++
-
-Routine Description:
-
- Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to
- EFI_SCSI_IO_SCSI_REQUEST_PACKET packet
-
-Arguments:
-
- ScsiPacket - The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
- Packet - The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
-
-Returns:
-
- NONE
-
---*/
{
Packet->Timeout = ScsiPacket->Timeout;
Packet->Cdb = ScsiPacket->Cdb;
@@ -1229,56 +1327,44 @@ Returns:
Packet->OutDataBuffer = ScsiPacket->DataBuffer;
Packet->OutTransferLength = ScsiPacket->TransferLength;
}
-
+
return EFI_SUCCESS;
}
+/**
+ Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
+ SCSI IO Packet.
+ @param Event The instance of EFI_EVENT.
+ @param Context The parameter passed in.
-STATIC
+**/
VOID
EFIAPI
NotifyFunction (
- EFI_EVENT Event,
- VOID *Context
+ IN EFI_EVENT Event,
+ IN VOID *Context
)
-/*++
-
-Routine Description:
-
- Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
- SCSI IO Packet.
-
-Arguments:
-
- Event - The instance of EFI_EVENT.
- Context - The parameter passed in.
-
-Returns:
-
- NONE
-
---*/
{
EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet;
EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket;
EFI_EVENT CallerEvent;
- SCSI_EVENT_DATA *PassData;
+ SCSI_EVENT_DATA *PassData;
PassData = (SCSI_EVENT_DATA*)Context;
Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;
- ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer;
+ ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer;
//
// Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.
//
PassThruToScsiioPacket(ScsiPacket, Packet);
-
+
//
// After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
- // free WorkingBuffer.
+ // free mWorkingBuffer.
//
- gBS->FreePool(WorkingBuffer);
+ gBS->FreePool(mWorkingBuffer);
//
// Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.
@@ -1287,3 +1373,4 @@ Returns:
gBS->CloseEvent(Event);
gBS->SignalEvent(CallerEvent);
}
+