X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FBus%2FScsi%2FScsiBusDxe%2FScsiBus.c;h=f59116733e9fe1151a24724981260c80fea83b2a;hp=0840cba5d88494a25e9716dc55035abed169c521;hb=ed66e1bc0d2be0a185fc47adab4930c3b7e2767f;hpb=24e734d2100cd93f62ef66523277d3315dfa3712 diff --git a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c index 0840cba5d8..f59116733e 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c +++ b/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c @@ -1,44 +1,34 @@ -/*++ +/** @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 - 2008, 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 +#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 @@ -54,12 +44,46 @@ EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = { NULL }; + +// +// 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; + +STATIC VOID *WorkingBuffer; + +STATIC +EFI_STATUS +EFIAPI +ScsiioToPassThruPacket ( + IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket + ); + + +STATIC +EFI_STATUS +EFIAPI +PassThruToScsiioPacket ( + IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet + ); +STATIC +VOID +EFIAPI +NotifyFunction ( + EFI_EVENT Event, + 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] 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. @@ -76,18 +100,16 @@ InitializeScsiBus( // // Install driver model protocol(s). // - Status = EfiLibInstallAllDriverProtocols ( + Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &gSCSIBusDriverBinding, ImageHandle, &gScsiBusComponentName, - NULL, - NULL + &gScsiBusComponentName2 ); ASSERT_EFI_ERROR (Status); - return Status; } @@ -99,49 +121,79 @@ SCSIBusDriverBindingSupported ( IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ - - Routine Description: - - Arguments: - - Returns: - + +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. + --*/ -// 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 -// TODO: EFI_UNSUPPORTED - add return value to function comment -// TODO: EFI_UNSUPPORTED - add return value to function comment -// TODO: EFI_SUCCESS - add return value to function comment + { EFI_STATUS Status; - - // - // If RemainingDevicePath is not NULL, it should verify that the first device - // path node in RemainingDevicePath is an ATAPI Device path node. - // - if (RemainingDevicePath != NULL) { - if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) || - (RemainingDevicePath->SubType != MSG_ATAPI_DP) || - (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) { - return EFI_UNSUPPORTED; - } - } + EFI_SCSI_PASS_THRU_PROTOCOL *PassThru; + EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru; // - // check for the existence of SCSI Pass Thru Protocol + // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol // Status = gBS->OpenProtocol ( Controller, - &gEfiScsiPassThruProtocolGuid, - NULL, + &gEfiExtScsiPassThruProtocolGuid, + (VOID **)&ExtPassThru, This->DriverBindingHandle, Controller, - EFI_OPEN_PROTOCOL_TEST_PROTOCOL + EFI_OPEN_PROTOCOL_BY_DRIVER ); - if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { - return EFI_UNSUPPORTED; + + 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) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + gBS->CloseProtocol ( + Controller, + &gEfiExtScsiPassThruProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; } @@ -153,77 +205,196 @@ SCSIBusDriverBindingStart ( IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ - - Routine Description: - - Arguments: - - Returns: - + +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; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; - UINT32 StartPun; - UINT64 StartLun; - UINT32 Pun; - UINT64 Lun; - BOOLEAN ScanOtherPuns; - - StartPun = 0; - StartLun = 0; - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - return Status; + 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; + ScsiTargetId = NULL; + ScanOtherPuns = TRUE; + FromFirstTarget = FALSE; + ExtScsiSupport = FALSE; + PassThruStatus = EFI_SUCCESS; + + ScsiTargetId = AllocateZeroPool(sizeof(SCSI_TARGET_ID)); + if (ScsiTargetId == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TargetId = &ScsiTargetId->ScsiId.ExtScsi[0]; + + 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; } // - // 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, - &gEfiScsiPassThruProtocolGuid, - (VOID **) &ScsiPassThru, + &gEfiExtScsiPassThruProtocolGuid, + (VOID **) &ExtScsiInterface, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - return Status; + // + // 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 **) &ScsiInterface, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + // + // 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; + } + } else { + // + // 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 + ); } + + 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) { + ScsiBusDev->ExtScsiInterface = ExtScsiInterface; + } else { + ScsiBusDev->ScsiInterface = ScsiInterface; + } - if (RemainingDevicePath == NULL) { - StartPun = 0xFFFFFFFF; - StartLun = 0; + // + // 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, + &mScsiBusProtocolGuid, + EFI_NATIVE_INTERFACE, + &ScsiBusDev->BusIdentify + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } } else { - ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun); + // + // 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, + &mScsiBusProtocolGuid, + (VOID **) &BusIdentify, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify); } - for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) { + if (RemainingDevicePath == NULL) { + SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF); + Lun = 0; + FromFirstTarget = TRUE; + } else { + if (ScsiBusDev->ExtScsiSupport) { + ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun); + } else { + ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun); + } + } - if (StartPun == 0xFFFFFFFF) { + while(ScanOtherPuns) { + if (FromFirstTarget) { // // Remaining Device Path is NULL, scan all the possible Puns in the // SCSI Channel. // - Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun); + if (ScsiBusDev->ExtScsiSupport) { + Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun); + } else { + Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId->ScsiId.Scsi, &Lun); + } if (EFI_ERROR (Status)) { // // no legal Pun and Lun found any more @@ -231,28 +402,58 @@ SCSIBusDriverBindingStart ( break; } } else { - // - // Remaining Device Path is not NULL, only scan the specified Pun. - // - Pun = StartPun; - Lun = StartLun; ScanOtherPuns = FALSE; } - // // Avoid creating handle for the host adapter. // - if (Pun == ScsiPassThru->Mode->AdapterId) { - continue; + if (ScsiBusDev->ExtScsiSupport) { + if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) { + continue; + } + } else { + if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) { + continue; + } } - // // 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, Pun, Lun, ScsiPassThru, ParentDevicePath); + Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev); + } + gBS->FreePool (ScsiTargetId); + return EFI_SUCCESS; + +ErrorExit: + + if (ScsiBusDev != NULL) { + gBS->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; } @@ -265,46 +466,88 @@ SCSIBusDriverBindingStop ( IN EFI_HANDLE *ChildHandleBuffer ) /*++ - - Routine Description: - - Arguments: - - Returns: - + +Routine Description: + + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + +Arguments: + + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + +Returns: + + EFI_SUCCESS + Others --*/ -// 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; UINTN Index; EFI_SCSI_IO_PROTOCOL *ScsiIo; SCSI_IO_DEV *ScsiIoDevice; - EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + VOID *ScsiPassThru; + EFI_SCSI_BUS_PROTOCOL *Scsidentifier; + SCSI_BUS_DEVICE *ScsiBusDev; if (NumberOfChildren == 0) { + // + // Get the SCSI_BUS_DEVICE + // + Status = gBS->OpenProtocol ( + Controller, + &mScsiBusProtocolGuid, + (VOID **) &Scsidentifier, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier); + + // + // Uninstall SCSI Bus Protocol + // + gBS->UninstallProtocolInterface ( + Controller, + &mScsiBusProtocolGuid, + &ScsiBusDev->BusIdentify + ); + // // Close the bus driver // - gBS->CloseProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); + if (ScsiBusDev->ExtScsiSupport) { + gBS->CloseProtocol ( + Controller, + &gEfiExtScsiPassThruProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiBusDev); return EFI_SUCCESS; } @@ -329,12 +572,22 @@ SCSIBusDriverBindingStop ( // // Close the child handle // - Status = gBS->CloseProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - This->DriverBindingHandle, - ChildHandleBuffer[Index] - ); + if (ScsiIoDevice->ExtScsiSupport) { + Status = gBS->CloseProtocol ( + Controller, + &gEfiExtScsiPassThruProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + } else { + Status = gBS->CloseProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + } Status = gBS->UninstallMultipleProtocolInterfaces ( ChildHandleBuffer[Index], @@ -346,14 +599,25 @@ SCSIBusDriverBindingStop ( ); if (EFI_ERROR (Status)) { AllChildrenStopped = FALSE; - gBS->OpenProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - (VOID **) &ScsiPassThru, - This->DriverBindingHandle, - ChildHandleBuffer[Index], - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); + if (ScsiIoDevice->ExtScsiSupport) { + gBS->OpenProtocol ( + Controller, + &gEfiExtScsiPassThruProtocolGuid, + &ScsiPassThru, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + &ScsiPassThru, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } } else { gBS->FreePool (ScsiIoDevice); } @@ -374,17 +638,21 @@ ScsiGetDeviceType ( ) /*++ - Routine Description: - Retrieves the device type information of the SCSI Controller. +Routine Description: + + Retrieves the device type information of the SCSI Controller. - Arguments: - This - Protocol instance pointer. - DeviceType - A pointer to the device type information +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. +Returns: + + EFI_SUCCESS - Retrieves the device type information successfully. + EFI_INVALID_PARAMETER - The DeviceType is NULL. + --*/ { SCSI_IO_DEV *ScsiIoDevice; @@ -398,28 +666,32 @@ ScsiGetDeviceType ( return EFI_SUCCESS; } -STATIC EFI_STATUS EFIAPI ScsiGetDeviceLocation ( IN EFI_SCSI_IO_PROTOCOL *This, - OUT UINT32 *Target, + IN OUT UINT8 **Target, OUT UINT64 *Lun ) /*++ - Routine Description: - Retrieves the device location in the SCSI channel. + +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. +Arguments: + + This - Protocol instance pointer. + Target - A pointer to the Target Array which represents 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; @@ -428,10 +700,11 @@ 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); - *Target = ScsiIoDevice->Pun; - *Lun = ScsiIoDevice->Lun; + *Lun = ScsiIoDevice->Lun; return EFI_SUCCESS; } @@ -443,27 +716,33 @@ ScsiResetBus ( ) /*++ - Routine Description: - Resets the SCSI Bus that the SCSI Controller is attached to. +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. +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; ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); - return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru); - + if (ScsiIoDevice->ExtScsiSupport){ + return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru); + } else { + return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru); + } } EFI_STATUS @@ -473,32 +752,45 @@ ScsiResetDevice ( ) /*++ - Routine Description: - Resets the SCSI Controller that the device handle specifies. +Routine Description: + + Resets the SCSI Controller that the device handle specifies. - Arguments: - This - Protocol instance pointer. +Arguments: + + This - Protocol instance pointer. +Returns: - 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. + 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); + CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES); + - return ScsiIoDevice->ScsiPassThru->ResetTarget ( - ScsiIoDevice->ScsiPassThru, - ScsiIoDevice->Pun, - ScsiIoDevice->Lun - ); + if (ScsiIoDevice->ExtScsiSupport) { + return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun ( + ScsiIoDevice->ExtScsiPassThru, + Target, + ScsiIoDevice->Lun + ); + } else { + return ScsiIoDevice->ScsiPassThru->ResetTarget ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun.ScsiId.Scsi, + ScsiIoDevice->Lun + ); + } } EFI_STATUS @@ -510,107 +802,191 @@ ScsiExecuteSCSICommand ( ) /*++ - Routine Description: - Sends a SCSI Request Packet to the SCSI Controller for execution. +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; +Arguments: - EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *RequestPacket; + 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_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. + 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; + UINT8 Target[TARGET_MAX_BYTES]; + EFI_EVENT PacketEvent; + EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket; + SCSI_EVENT_DATA EventData; + + PacketEvent = NULL; + if (Packet == NULL) { return EFI_INVALID_PARAMETER; } 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 ( + ScsiIoDevice->ExtScsiPassThru, + Target, + ScsiIoDevice->Lun, + ExtRequestPacket, + Event + ); + } else { + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET), + (VOID**)&WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET. + // + Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer); + if (EFI_ERROR(Status)) { + gBS->FreePool(WorkingBuffer); + return Status; + } + + if ((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) && (Event != NULL)) { + EventData.Data1 = (VOID*)Packet; + EventData.Data2 = Event; + // + // Create Event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + NotifyFunction, + &EventData, + &PacketEvent + ); + if (EFI_ERROR(Status)) { + gBS->FreePool(WorkingBuffer); + return Status; + } + + Status = ScsiIoDevice->ScsiPassThru->PassThru ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun.ScsiId.Scsi, + ScsiIoDevice->Lun, + WorkingBuffer, + PacketEvent + ); + + if (EFI_ERROR(Status)) { + gBS->FreePool(WorkingBuffer); + gBS->CloseEvent(PacketEvent); + return Status; + } - RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet; + } else { + // + // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert + // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet. + // + Status = ScsiIoDevice->ScsiPassThru->PassThru ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun.ScsiId.Scsi, + ScsiIoDevice->Lun, + WorkingBuffer, + Event + ); + if (EFI_ERROR(Status)) { + gBS->FreePool(WorkingBuffer); + return Status; + } - Status = ScsiIoDevice->ScsiPassThru->PassThru ( - ScsiIoDevice->ScsiPassThru, - ScsiIoDevice->Pun, - ScsiIoDevice->Lun, - RequestPacket, - Event - ); + PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer,Packet); + // + // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet, + // free WorkingBuffer. + // + gBS->FreePool(WorkingBuffer); + } + } return Status; } EFI_STATUS +EFIAPI ScsiScanCreateDevice ( EFI_DRIVER_BINDING_PROTOCOL *This, EFI_HANDLE Controller, - UINT32 Pun, + SCSI_TARGET_ID *TargetId, UINT64 Lun, - EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + SCSI_BUS_DEVICE *ScsiBusDev ) /*++ Routine Description: - TODO: Add function description + Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it. Arguments: - This - TODO: add argument description - Controller - TODO: add argument description - Pun - TODO: add argument description - Lun - TODO: add argument description - ScsiPassThru - TODO: add argument description - ParentDevicePath - TODO: add argument description + 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: - EFI_SUCCESS - TODO: Add description for return value - EFI_OUT_OF_RESOURCES - TODO: Add description for return value - EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - Successfully to discover the device and attach ScsiIoProtocol to it. + EFI_OUT_OF_RESOURCES - Fail to discover the device. --*/ { @@ -630,37 +1006,61 @@ Returns: ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV)); ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; - ScsiIoDevice->ScsiPassThru = ScsiPassThru; - ScsiIoDevice->Pun = Pun; + CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES); ScsiIoDevice->Lun = Lun; + if (ScsiBusDev->ExtScsiSupport) { + ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface; + ScsiIoDevice->ExtScsiSupport = TRUE; + ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign; + + } else { + ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface; + ScsiIoDevice->ExtScsiSupport = FALSE; + ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign; + } + ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType; - // ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation; + ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation; ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus; ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand; + if (!DiscoverScsiDevice (ScsiIoDevice)) { gBS->FreePool (ScsiIoDevice); - return EFI_SUCCESS; + return EFI_OUT_OF_RESOURCES; } - + // // Set Device Path // - Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath ( - ScsiIoDevice->ScsiPassThru, - ScsiIoDevice->Pun, - ScsiIoDevice->Lun, - &ScsiDevicePath - ); - if (Status == EFI_OUT_OF_RESOURCES) { - gBS->FreePool (ScsiIoDevice); - return Status; + 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 ( - ParentDevicePath, + ScsiBusDev->DevicePath, ScsiDevicePath ); // @@ -685,21 +1085,33 @@ Returns: ); if (EFI_ERROR (Status)) { gBS->FreePool (ScsiIoDevice); + return EFI_OUT_OF_RESOURCES; } else { - gBS->OpenProtocol ( - Controller, - &gEfiScsiPassThruProtocolGuid, - (VOID **) &ScsiPassThru, - This->DriverBindingHandle, - ScsiIoDevice->Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); + if (ScsiBusDev->ExtScsiSupport) { + gBS->OpenProtocol ( + 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 + ); + } } - return EFI_SUCCESS; } BOOLEAN +EFIAPI DiscoverScsiDevice ( SCSI_IO_DEV *ScsiIoDevice ) @@ -707,25 +1119,26 @@ DiscoverScsiDevice ( Routine Description: - TODO: Add function description + Discovery SCSI Device Arguments: - ScsiIoDevice - TODO: add argument description + ScsiIoDevice - The pointer of SCSI_IO_DEV Returns: - TODO: add return values + TRUE - Find SCSI Device and verify it. + FALSE - Unable to find SCSI Device. --*/ { EFI_STATUS Status; - EFI_SCSI_INQUIRY_DATA InquiryData; UINT32 InquiryDataLength; - EFI_SCSI_SENSE_DATA SenseData; UINT8 SenseDataLength; UINT8 HostAdapterStatus; UINT8 TargetStatus; + EFI_SCSI_SENSE_DATA SenseData; + EFI_SCSI_INQUIRY_DATA InquiryData; HostAdapterStatus = 0; TargetStatus = 0; @@ -735,7 +1148,7 @@ Returns: InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA); - Status = SubmitInquiryCommand ( + Status = ScsiInquiryCommand ( &ScsiIoDevice->ScsiIo, EfiScsiStallSeconds (1), (VOID *) &SenseData, @@ -766,10 +1179,10 @@ Returns: } } - if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) { + if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) { return FALSE; } - + // // valid device type and peripheral qualifier combination. // @@ -786,3 +1199,158 @@ Returns: return TRUE; } + + +STATIC +EFI_STATUS +EFIAPI +ScsiioToPassThruPacket ( + IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN 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. + // + 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; + CommandPacket->Cdb = Packet->Cdb; + CommandPacket->CdbLength = Packet->CdbLength; + CommandPacket->DataDirection = Packet->DataDirection; + CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus; + CommandPacket->TargetStatus = Packet->TargetStatus; + CommandPacket->SenseData = Packet->SenseData; + CommandPacket->SenseDataLength = Packet->SenseDataLength; + + if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) { + CommandPacket->DataBuffer = Packet->InDataBuffer; + CommandPacket->TransferLength = Packet->InTransferLength; + } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) { + CommandPacket->DataBuffer = Packet->OutDataBuffer; + CommandPacket->TransferLength = Packet->OutTransferLength; + } + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +EFIAPI +PassThruToScsiioPacket ( + IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket, + IN 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; + Packet->CdbLength = ScsiPacket->CdbLength; + Packet->DataDirection = ScsiPacket->DataDirection; + Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus; + Packet->TargetStatus = ScsiPacket->TargetStatus; + Packet->SenseData = ScsiPacket->SenseData; + Packet->SenseDataLength = ScsiPacket->SenseDataLength; + + if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) { + Packet->InDataBuffer = ScsiPacket->DataBuffer; + Packet->InTransferLength = ScsiPacket->TransferLength; + } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) { + Packet->OutDataBuffer = ScsiPacket->DataBuffer; + Packet->OutTransferLength = ScsiPacket->TransferLength; + } + + return EFI_SUCCESS; +} + + + +STATIC +VOID +EFIAPI +NotifyFunction ( + EFI_EVENT Event, + 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; + + PassData = (SCSI_EVENT_DATA*)Context; + Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1; + ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)WorkingBuffer; + + // + // 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. + // + gBS->FreePool(WorkingBuffer); + + // + // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet. + // + CallerEvent = PassData->Data2; + gBS->CloseEvent(Event); + gBS->SignalEvent(CallerEvent); +}