From 6ad55b150b92910b7fa3f11a2b966c028cc4e1e7 Mon Sep 17 00:00:00 2001 From: klu2 Date: Fri, 29 Jun 2007 03:44:58 +0000 Subject: [PATCH] Add ScsiDiskDxe driver for Nt32Pkg git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2879 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Bus/Scsi/ScsiDiskDxe/ComponentName.c | 202 ++ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 2412 +++++++++++++++++ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h | 774 ++++++ .../Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf | 100 + .../Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa | 72 + MdeModulePkg/MdeModulePkg.dsc | 3 +- Nt32Pkg/Nt32.dsc | 3 +- 7 files changed, 3564 insertions(+), 2 deletions(-) create mode 100644 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c create mode 100644 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c create mode 100644 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h create mode 100644 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf create mode 100644 MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c new file mode 100644 index 0000000000..24adbe9800 --- /dev/null +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c @@ -0,0 +1,202 @@ +/*++ + +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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +// +// The package level header files this module uses +// +#include + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include + +#include "ScsiDisk.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gScsiDiskComponentName = { + ScsiDiskComponentNameGetDriverName, + ScsiDiskComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mScsiDiskDriverNameTable[] = { + { "eng", (CHAR16 *) L"Scsi Disk Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gScsiDiskComponentName.SupportedLanguages, + mScsiDiskDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure this driver is currently managing ControllerHandle + // + Status = EfiTestManagedDevice ( + ControllerHandle, + gScsiDiskDriverBinding.DriverBindingHandle, + &gEfiScsiIoProtocolGuid + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gScsiDiskDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlockIo); + + return LookupUnicodeString ( + Language, + gScsiDiskComponentName.SupportedLanguages, + ScsiDiskDevice->ControllerNameTable, + ControllerName + ); + +} diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c new file mode 100644 index 0000000000..e85f99ba94 --- /dev/null +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -0,0 +1,2412 @@ +/*++ + +Copyright (c) 2006 - 2007, 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. + +Module Name: + + ScsiDisk.c + +Abstract: + +--*/ +// +// The package level header files this module uses +// +#include + +// +// The protocols, PPI and GUID defintions for this module +// +#include +#include +#include +#include +// +// The Library classes this module consumes +// +#include +#include +#include +#include +#include +#include + +#include "ScsiDisk.h" + +EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding = { + ScsiDiskDriverBindingSupported, + ScsiDiskDriverBindingStart, + ScsiDiskDriverBindingStop, + 0xa, + NULL, + NULL +}; + +/** + The user Entry Point for module ScsiDisk. 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. + +**/ +EFI_STATUS +EFIAPI +InitializeScsiDisk( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallAllDriverProtocols ( + ImageHandle, + SystemTable, + &gScsiDiskDriverBinding, + ImageHandle, + &gScsiDiskComponentName, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// 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_SCSI_IO_PROTOCOL *ScsiIo; + UINT8 DeviceType; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + (VOID **) &ScsiIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType); + if (!EFI_ERROR (Status)) { + if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType == EFI_SCSI_TYPE_CDROM)) { + Status = EFI_SUCCESS; + } else { + Status = EFI_UNSUPPORTED; + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// 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_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + SCSI_DISK_DEV *ScsiDiskDevice; + BOOLEAN Temp; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (SCSI_DISK_DEV), + (VOID **) &ScsiDiskDevice + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (ScsiDiskDevice, sizeof (SCSI_DISK_DEV)); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + (VOID **) &ScsiIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ScsiDiskDevice->Signature = SCSI_DISK_DEV_SIGNATURE; + ScsiDiskDevice->ScsiIo = ScsiIo; + ScsiDiskDevice->BlkIo.Media = &ScsiDiskDevice->BlkIoMedia; + ScsiDiskDevice->BlkIo.Reset = ScsiDiskReset; + ScsiDiskDevice->BlkIo.ReadBlocks = ScsiDiskReadBlocks; + ScsiDiskDevice->BlkIo.WriteBlocks = ScsiDiskWriteBlocks; + ScsiDiskDevice->BlkIo.FlushBlocks = ScsiDiskFlushBlocks; + ScsiDiskDevice->Handle = Controller; + + ScsiIo->GetDeviceType (ScsiIo, &(ScsiDiskDevice->DeviceType)); + switch (ScsiDiskDevice->DeviceType) { + case EFI_SCSI_TYPE_DISK: + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200; + break; + + case EFI_SCSI_TYPE_CDROM: + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800; + break; + } + // + // The Sense Data Array's initial size is 6 + // + ScsiDiskDevice->SenseDataNumber = 6; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber, + (VOID **) &(ScsiDiskDevice->SenseData) + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ZeroMem ( + ScsiDiskDevice->SenseData, + sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber + ); + + // + // Retrive device information + // + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskInquiryDevice (ScsiDiskDevice, &NeedRetry); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + gBS->FreePool (ScsiDiskDevice->SenseData); + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return EFI_DEVICE_ERROR; + } + } + // + // The second parameter "TRUE" means must + // retrieve media capacity + // + Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + NULL + ); + } + + if (EFI_ERROR (Status)) { + gBS->FreePool (ScsiDiskDevice->SenseData); + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ScsiDiskDevice->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gScsiDiskComponentName.SupportedLanguages, + &ScsiDiskDevice->ControllerNameTable, + (CHAR16 *) L"SCSI Disk Device" + ); + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + 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 +{ + EFI_BLOCK_IO_PROTOCOL *BlkIo; + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlkIo); + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + ReleaseScsiDiskDeviceResources (ScsiDiskDevice); + + return EFI_SUCCESS; + } + // + // errors met + // + return Status; +} + +// +// Block I/O Protocol Interface +// + +EFI_STATUS +EFIAPI +ScsiDiskReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_STATUS Status; + EFI_TPL OldTpl; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + Status = ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + + if (!ExtendedVerification) { + goto Done; + } + + Status = ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_NO_MEDIA - TODO: Add description for return value + EFI_MEDIA_CHANGED - TODO: Add description for return value + EFI_BAD_BUFFER_SIZE - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + EFI_TPL OldTpl; + + MediaChange = FALSE; + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + if (!IsDeviceFixed (ScsiDiskDevice)) { + + Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (MediaChange) { + gBS->ReinstallProtocolInterface ( + ScsiDiskDevice->Handle, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + &ScsiDiskDevice->BlkIo + ); + } + } + // + // Get the intrinsic block size + // + Media = ScsiDiskDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + Status = EFI_NO_MEDIA; + goto Done; + } + + if (MediaId != Media->MediaId) { + Status = EFI_MEDIA_CHANGED; + goto Done; + } + + if (BufferSize % BlockSize != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + if (LBA > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks); + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_NO_MEDIA - TODO: Add description for return value + EFI_MEDIA_CHANGED - TODO: Add description for return value + EFI_BAD_BUFFER_SIZE - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + EFI_TPL OldTpl; + + MediaChange = FALSE; + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + if (!IsDeviceFixed (ScsiDiskDevice)) { + + Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange); + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (MediaChange) { + gBS->ReinstallProtocolInterface ( + ScsiDiskDevice->Handle, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + &ScsiDiskDevice->BlkIo + ); + } + } + // + // Get the intrinsic block size + // + Media = ScsiDiskDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + Status = EFI_NO_MEDIA; + goto Done; + } + + if (MediaId != Media->MediaId) { + Status = EFI_MEDIA_CHANGED; + goto Done; + } + + if (BufferSize % BlockSize != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + if (LBA > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks); + +Done: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + // + // return directly + // + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskDetectMedia ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN MustReadCapacity, + BOOLEAN *MediaChange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + MustReadCapacity - TODO: add argument description + MediaChange - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReadCapacityStatus; + EFI_SCSI_SENSE_DATA *SenseData; + UINTN NumberOfSenseKeys; + BOOLEAN NeedRetry; + BOOLEAN NeedReadCapacity; + UINT8 Index; + UINT8 MaxRetry; + EFI_BLOCK_IO_MEDIA OldMedia; + UINTN Action; + + Status = EFI_SUCCESS; + ReadCapacityStatus = EFI_SUCCESS; + SenseData = NULL; + NumberOfSenseKeys = 0; + NeedReadCapacity = FALSE; + CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia)); + // OldMedia = *(ScsiDiskDevice->BlkIo.Media); + + *MediaChange = FALSE; + + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskTestUnitReady ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return Status; + } + } + + if ((Index == MaxRetry) && EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = DetectMediaParsingSenseKeys ( + ScsiDiskDevice, + SenseData, + NumberOfSenseKeys, + &Action + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // ACTION_NO_ACTION: need not read capacity + // other action code: need read capacity + // + if (Action == ACTION_NO_ACTION) { + NeedReadCapacity = FALSE; + } else { + NeedReadCapacity = TRUE; + } + + // + // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE, + // retrieve capacity via Read Capacity command + // + if (NeedReadCapacity || MustReadCapacity) { + + // + // retrieve media information + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + ReadCapacityStatus = ScsiDiskReadCapacity ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys + ); + if (EFI_ERROR (ReadCapacityStatus) && !NeedRetry) { + return EFI_DEVICE_ERROR; + } + // + // analyze sense key to action + // + Status = DetectMediaParsingSenseKeys ( + ScsiDiskDevice, + SenseData, + NumberOfSenseKeys, + &Action + ); + // + // if Status is error, it may indicate crisis error, + // so return without retry. + // + if (EFI_ERROR (Status)) { + return Status; + } + + switch (Action) { + case ACTION_NO_ACTION: + // + // no retry + // + Index = MaxRetry; + break; + + case ACTION_RETRY_COMMAND_LATER: + // + // retry the ReadCapacity later and continuously, until the condition + // no longer emerges. + // stall time is 100000us, or say 0.1 second. + // + gBS->Stall (100000); + Index = 0; + break; + + default: + // + // other cases, just retry the command + // + break; + } + } + + if ((Index == MaxRetry) && EFI_ERROR (ReadCapacityStatus)) { + return EFI_DEVICE_ERROR; + } + } + + if (ScsiDiskDevice->BlkIo.Media->MediaId != OldMedia.MediaId) { + // + // Media change information got from the device + // + *MediaChange = TRUE; + } + + if (ScsiDiskDevice->BlkIo.Media->ReadOnly != OldMedia.ReadOnly) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->BlockSize != OldMedia.BlockSize) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->LastBlock != OldMedia.LastBlock) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->MediaPresent != OldMedia.MediaPresent) { + if (ScsiDiskDevice->BlkIo.Media->MediaPresent) { + // + // when change from no media to media present, reset the MediaId to 1. + // + ScsiDiskDevice->BlkIo.Media->MediaId = 1; + } else { + // + // when no media, reset the MediaId to zero. + // + ScsiDiskDevice->BlkIo.Media->MediaId = 0; + } + + *MediaChange = TRUE; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskInquiryDevice ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + +--*/ +{ + UINT32 InquiryDataLength; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + EFI_SCSI_SENSE_DATA *SenseDataArray; + UINTN NumberOfSenseKeys; + EFI_STATUS Status; + UINT8 MaxRetry; + UINT8 Index; + + InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); + SenseDataLength = 0; + + Status = SubmitInquiryCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &(ScsiDiskDevice->InquiryData), + &InquiryDataLength, + FALSE + ); + if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) { + // + // no need to check HostAdapterStatus and TargetStatus + // + ParseInquiryData (ScsiDiskDevice); + return EFI_SUCCESS; + } else if (Status == EFI_NOT_READY) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + // + // go ahead to check HostAdapterStatus and TargetStatus + // (EFI_TIMEOUT, EFI_DEVICE_ERROR) + // + Status = CheckHostAdapterStatus (HostAdapterStatus); + if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + if (Status == EFI_NOT_READY) { + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + // + // if goes here, meant SubmitInquiryCommand() failed. + // if ScsiDiskRequestSenseKeys() succeeds at last, + // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE) + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + &SenseDataArray, + &NumberOfSenseKeys, + TRUE + ); + if (!EFI_ERROR (Status)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +ScsiDiskTestUnitReady ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +// TODO: function comment should start with '/*++' +/* + When Test Unit Ready command succeeds, + retrieve Sense Keys via Request Sense; + When Test Unit Ready command encounters any error caused by host adapter or + target, return error without retrieving Sense Keys. +*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: ScsiDiskDevice - add argument and description to function comment +// TODO: NeedRetry - add argument and description to function comment +// TODO: SenseDataArray - add argument and description to function comment +// TODO: NumberOfSenseKeys - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - 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 +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + EFI_STATUS Status; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 Index; + UINT8 MaxRetry; + + SenseDataLength = 0; + *NumberOfSenseKeys = 0; + + // + // Parameter 3 and 4: do not require sense data, retrieve it when needed. + // + Status = SubmitTestUnitReadyCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus + ); + if (Status == EFI_NOT_READY) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + // + // go ahead to check HostAdapterStatus and TargetStatus + // + Status = CheckHostAdapterStatus (HostAdapterStatus); + if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + if (Status == EFI_NOT_READY) { + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + SenseDataArray, + NumberOfSenseKeys, + FALSE + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +DetectMediaParsingSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_SENSE_DATA *SenseData, + UINTN NumberOfSenseKeys, + UINTN *Action + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + SenseData - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Action - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + BOOLEAN RetryLater; + + // + // Default is to read capacity, unless.. + // + *Action = ACTION_READ_CAPACITY; + + if (NumberOfSenseKeys == 0) { + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) { + // + // No Sense Key returned from last submitted command + // + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; + ScsiDiskDevice->BlkIo.Media->LastBlock = 0; + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaId++; + return EFI_SUCCESS; + } + + if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; + ScsiDiskDevice->BlkIo.Media->LastBlock = 0; + return EFI_DEVICE_ERROR; + } + + if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) { + return EFI_DEVICE_ERROR; + } + + if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) { + if (RetryLater) { + *Action = ACTION_RETRY_COMMAND_LATER; + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskReadCapacity ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + +--*/ +{ + EFI_SCSI_DISK_CAPACITY_DATA CapacityData; + UINT32 DataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + EFI_STATUS CommandStatus; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + UINT8 SenseDataLength; + + SenseDataLength = 0; + ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA)); + DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA); + + *NumberOfSenseKeys = 0; + *NeedRetry = FALSE; + // + // submit Read Capacity Command. in this call,not request sense data + // + CommandStatus = SubmitReadCapacityCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &CapacityData, + &DataLength, + FALSE + ); + if (CommandStatus == EFI_SUCCESS) { + // + // no need to check HostAdapterStatus and TargetStatus + // + GetMediaInfo (ScsiDiskDevice, &CapacityData); + return EFI_SUCCESS; + } else if (CommandStatus == EFI_NOT_READY) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if ((CommandStatus == EFI_INVALID_PARAMETER) || (CommandStatus == EFI_UNSUPPORTED)) { + // + // no need to check HostAdapterStatus and TargetStatus + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + // + // go ahead to check HostAdapterStatus and TargetStatus + // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL) + // + + Status = CheckHostAdapterStatus (HostAdapterStatus); + if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + if (Status == EFI_NOT_READY) { + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + // + // if goes here, meant SubmitReadCapacityCommand() failed. + // if ScsiDiskRequestSenseKeys() succeeds at last, + // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE) + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + SenseDataArray, + NumberOfSenseKeys, + TRUE + ); + if (!EFI_ERROR (Status)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +CheckHostAdapterStatus ( + UINT8 HostAdapterStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HostAdapterStatus - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_TIMEOUT - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + switch (HostAdapterStatus) { + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK: + return EFI_SUCCESS; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND: + return EFI_TIMEOUT; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET: + return EFI_NOT_READY; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR: + return EFI_DEVICE_ERROR; + + default: + return EFI_SUCCESS; + } +} + +EFI_STATUS +CheckTargetStatus ( + UINT8 TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + TargetStatus - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + switch (TargetStatus) { + case EFI_SCSI_IO_STATUS_TARGET_GOOD: + case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION: + case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET: + return EFI_SUCCESS; + + case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE: + case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET: + case EFI_SCSI_IO_STATUS_TARGET_BUSY: + case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED: + case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL: + return EFI_NOT_READY; + + case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT: + return EFI_DEVICE_ERROR; + break; + + default: + return EFI_SUCCESS; + } +} + +EFI_STATUS +ScsiDiskRequestSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + BOOLEAN AskResetIfError + ) +// TODO: function comment should start with '/*++' +/* + Retrieve all sense keys from the device. + When encountering error during the process, + if retrieve sense keys before error encounterred, + return the sense keys with return status set to EFI_SUCCESS, + and NeedRetry set to FALSE; otherwize, return the proper return + status. +*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: ScsiDiskDevice - add argument and description to function comment +// TODO: NeedRetry - add argument and description to function comment +// TODO: SenseDataArray - add argument and description to function comment +// TODO: NumberOfSenseKeys - add argument and description to function comment +// TODO: AskResetIfError - 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_SCSI_SENSE_DATA *PtrSenseData; + UINT8 SenseDataLength; + BOOLEAN SenseReq; + EFI_STATUS Status; + EFI_STATUS FallStatus; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + FallStatus = EFI_SUCCESS; + SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA); + + ZeroMem ( + ScsiDiskDevice->SenseData, + sizeof (EFI_SCSI_SENSE_DATA) * (ScsiDiskDevice->SenseDataNumber) + ); + + *NumberOfSenseKeys = 0; + *SenseDataArray = ScsiDiskDevice->SenseData; + PtrSenseData = ScsiDiskDevice->SenseData; + + for (SenseReq = TRUE; SenseReq;) { + + Status = SubmitRequestSenseCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (2), + PtrSenseData, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus + ); + if ((Status == EFI_SUCCESS) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) { + FallStatus = EFI_SUCCESS; + } else if ((Status == EFI_TIMEOUT) || (Status == EFI_NOT_READY)) { + *NeedRetry = TRUE; + FallStatus = EFI_DEVICE_ERROR; + } else if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED)) { + *NeedRetry = FALSE; + FallStatus = EFI_DEVICE_ERROR; + } else if (Status == EFI_DEVICE_ERROR) { + if (AskResetIfError) { + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + } + + FallStatus = EFI_DEVICE_ERROR; + } + + if (EFI_ERROR (FallStatus)) { + if (*NumberOfSenseKeys != 0) { + *NeedRetry = FALSE; + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + } + + (*NumberOfSenseKeys) += 1; + + // + // no more sense key or number of sense keys exceeds predefined, + // skip the loop. + // + if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) || + (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) { + SenseReq = FALSE; + } + + PtrSenseData += 1; + + } + + return EFI_SUCCESS; +} + +VOID +GetMediaInfo ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_DISK_CAPACITY_DATA *Capacity + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Capacity - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) | + (Capacity->LastLba2 << 16) | + (Capacity->LastLba1 << 8) | + Capacity->LastLba0; + + ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE; + ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) | + (Capacity->BlockSize2 << 16) | + (Capacity->BlockSize1 << 8) | + Capacity->BlockSize0; + if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) { + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200; + } + + if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_CDROM) { + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800; + } +} + +VOID +ParseInquiryData ( + SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + ScsiDiskDevice->FixedDevice = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1); + ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice); +} + +EFI_STATUS +ScsiDiskReadSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 *PtrBuffer; + UINT32 BlockSize; + UINT32 ByteCount; + UINT32 MaxBlock; + UINT32 SectorCount; + UINT64 Timeout; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + EFI_SCSI_SENSE_DATA *SenseData; + UINTN NumberOfSenseKeys; + + SenseData = NULL; + NumberOfSenseKeys = 0; + + Status = EFI_SUCCESS; + + BlocksRemaining = NumberOfBlocks; + BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize; + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = 65536; + + PtrBuffer = Buffer; + Lba32 = (UINT32) Lba; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + ByteCount = SectorCount * BlockSize; + Timeout = EfiScsiStallSeconds (2); + + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRead10 ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys, + Timeout, + PtrBuffer, + &ByteCount, + Lba32, + SectorCount + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return EFI_DEVICE_ERROR; + } + + } + + if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) { + return EFI_DEVICE_ERROR; + } + + // + // actual transferred sectors + // + SectorCount = ByteCount / BlockSize; + + Lba32 += SectorCount; + PtrBuffer = PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskWriteSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 *PtrBuffer; + UINT32 BlockSize; + UINT32 ByteCount; + UINT32 MaxBlock; + UINT32 SectorCount; + UINT64 Timeout; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + EFI_SCSI_SENSE_DATA *SenseData; + UINTN NumberOfSenseKeys; + + SenseData = NULL; + NumberOfSenseKeys = 0; + + Status = EFI_SUCCESS; + + BlocksRemaining = NumberOfBlocks; + BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize; + // + // limit the data bytes that can be transferred by one Write(10) Command + // + MaxBlock = 65536; + + PtrBuffer = Buffer; + Lba32 = (UINT32) Lba; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + ByteCount = SectorCount * BlockSize; + Timeout = EfiScsiStallSeconds (2); + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskWrite10 ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys, + Timeout, + PtrBuffer, + &ByteCount, + Lba32, + SectorCount + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + + if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) { + return EFI_DEVICE_ERROR; + } + // + // actual transferred sectors + // + SectorCount = ByteCount / BlockSize; + + Lba32 += SectorCount; + PtrBuffer = PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskRead10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 SenseDataLength; + EFI_STATUS Status; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + *NeedRetry = FALSE; + *NumberOfSenseKeys = 0; + SenseDataLength = 0; + Status = SubmitRead10Command ( + ScsiDiskDevice->ScsiIo, + Timeout, + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + return Status; +} + +EFI_STATUS +ScsiDiskWrite10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + *NeedRetry = FALSE; + *NumberOfSenseKeys = 0; + SenseDataLength = 0; + Status = SubmitWrite10Command ( + ScsiDiskDevice->ScsiIo, + Timeout, + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + return Status; +} + +BOOLEAN +ScsiDiskIsNoMedia ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsNoMedia; + + IsNoMedia = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2), + // Additional Sense Code is ASC_NO_MEDIA (0x3A) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) { + IsNoMedia = TRUE; + } + + SensePtr++; + } + + return IsNoMedia; +} + +BOOLEAN +ScsiDiskIsMediaError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePtr->Sense_Key) { + + case EFI_SCSI_SK_MEDIUM_ERROR: + // + // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3) + // + switch (SensePtr->Addnl_Sense_Code) { + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR1: + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR2: + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR3: + case EFI_SCSI_ASC_MEDIA_ERR4: + IsError = TRUE; + break; + + default: + break; + } + + break; + + case EFI_SCSI_SK_NOT_READY: + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2) + // + switch (SensePtr->Addnl_Sense_Code) { + // + // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6) + // + case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN: + IsError = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } + + SensePtr++; + } + + return IsError; +} + +BOOLEAN +ScsiDiskIsHardwareError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4) + // + if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) { + IsError = TRUE; + } + + SensePtr++; + } + + return IsError; +} + +BOOLEAN +ScsiDiskIsMediaChange ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsMediaChanged; + + IsMediaChanged = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + // + // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6), + // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) { + IsMediaChanged = TRUE; + } + + SensePtr++; + } + + return IsMediaChanged; +} + +BOOLEAN +ScsiDiskIsResetBefore ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsResetBefore; + + IsResetBefore = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6) + // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) { + IsResetBefore = TRUE; + } + + SensePtr++; + } + + return IsResetBefore; +} + +BOOLEAN +ScsiDiskIsDriveReady ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *RetryLater + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + RetryLater - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsReady; + + IsReady = TRUE; + *RetryLater = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePtr->Sense_Key) { + + case EFI_SCSI_SK_NOT_READY: + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2) + // + switch (SensePtr->Addnl_Sense_Code) { + case EFI_SCSI_ASC_NOT_READY: + // + // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4) + // + switch (SensePtr->Addnl_Sense_Code_Qualifier) { + case EFI_SCSI_ASCQ_IN_PROGRESS: + // + // Additional Sense Code Qualifier is + // EFI_SCSI_ASCQ_IN_PROGRESS (0x1) + // + IsReady = FALSE; + *RetryLater = TRUE; + break; + + default: + IsReady = FALSE; + *RetryLater = FALSE; + break; + } + break; + + default: + break; + } + break; + + default: + break; + } + + SensePtr++; + } + + return IsReady; +} + +BOOLEAN +ScsiDiskHaveSenseKey ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN HaveSenseKey; + + if (SenseCounts == 0) { + HaveSenseKey = FALSE; + } else { + HaveSenseKey = TRUE; + } + + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is SK_NO_SENSE (0x0) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) && + (Index == 0)) { + HaveSenseKey = FALSE; + } + + SensePtr++; + } + + return HaveSenseKey; +} + +VOID +ReleaseScsiDiskDeviceResources ( + IN SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (ScsiDiskDevice == NULL) { + return ; + } + + if (ScsiDiskDevice->SenseData != NULL) { + gBS->FreePool (ScsiDiskDevice->SenseData); + ScsiDiskDevice->SenseData = NULL; + } + + if (ScsiDiskDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable); + ScsiDiskDevice->ControllerNameTable = NULL; + } + + gBS->FreePool (ScsiDiskDevice); + + ScsiDiskDevice = NULL; +} diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h new file mode 100644 index 0000000000..675c643eff --- /dev/null +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h @@ -0,0 +1,774 @@ +/*++ + +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. + +Module Name: + + ScsiDisk.h + +Abstract: + + Header file for SCSI Disk Driver. + +--*/ + +#ifndef _SCSI_DISK_H +#define _SCSI_DISK_H + + +#include + +#define IsDeviceFixed(a) (a)->FixedDevice ? 1 : 0 + +#define SCSI_DISK_DEV_SIGNATURE EFI_SIGNATURE_32 ('s', 'c', 'd', 'k') + +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkIoMedia; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + UINT8 DeviceType; + BOOLEAN FixedDevice; + UINT16 Reserved; + + EFI_SCSI_SENSE_DATA *SenseData; + UINTN SenseDataNumber; + EFI_SCSI_INQUIRY_DATA InquiryData; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} SCSI_DISK_DEV; + +#define SCSI_DISK_DEV_FROM_THIS(a) CR (a, SCSI_DISK_DEV, BlkIo, SCSI_DISK_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gScsiDiskComponentName; +// +// action code used in detect media process +// +#define ACTION_NO_ACTION 0x00 +#define ACTION_READ_CAPACITY 0x01 +#define ACTION_RETRY_COMMAND_LATER 0x02 + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ScsiDiskReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskDetectMedia ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN MustReadCap, + BOOLEAN *MediaChange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + MustReadCap - TODO: add argument description + MediaChange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskTestUnitReady ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DetectMediaParsingSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_SENSE_DATA *SenseData, + UINTN NumberOfSenseKeys, + UINTN *Action + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + SenseData - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Action - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskReadCapacity ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckHostAdapterStatus ( + UINT8 HostAdapterStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HostAdapterStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckTargetStatus ( + UINT8 TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + TargetStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskRequestSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + BOOLEAN AskResetIfError + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + AskResetIfError - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskInquiryDevice ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +ParseInquiryData ( + SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskReadSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskWriteSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskRead10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskWrite10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +GetMediaInfo ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_DISK_CAPACITY_DATA *Capacity + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Capacity - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsNoMedia ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsMediaError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsHardwareError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsMediaChange ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsResetBefore ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsDriveReady ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskHaveSenseKey ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +ReleaseScsiDiskDeviceResources ( + IN SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf new file mode 100644 index 0000000000..fa7cca0765 --- /dev/null +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf @@ -0,0 +1,100 @@ +#/** @file +# Component description file for Scsi Disk module.Revision History +# +# Scsi Disk driver. This driver detected the Scsi disk media and export block io protocol +# Copyright (c) 2006 - 2007, 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. +# +# +#**/ + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ScsiDisk + FILE_GUID = 0A66E322-3740-4cce-AD62-BD172CECCA35 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + EDK_RELEASE_VERSION = 0x00020000 + EFI_SPECIFICATION_VERSION = 0x00010010 + + ENTRY_POINT = InitializeScsiDisk + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# +# DRIVER_BINDING = gScsiDiskDriverBinding +# COMPONENT_NAME = gScsiDiskComponentName +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources.common] + ComponentName.c + ScsiDisk.c + ScsiDisk.h + +################################################################################ +# +# Includes Section - list of Include locations that are required for +# this module. +# +################################################################################ + +[Includes] + $(WORKSPACE)/MdePkg/Include/Library + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + + +################################################################################ +# +# Library Class Section - list of Library Classes that are required for +# this module. +# +################################################################################ + +[LibraryClasses] + UefiBootServicesTableLib + ScsiLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DebugLib + + +################################################################################ +# +# Protocol C Name Section - list of Protocol and Protocol Notify C Names +# that this module uses or produces. +# +################################################################################ + +[Protocols] + gEfiBlockIoProtocolGuid # PROTOCOL BY_START + gEfiScsiIoProtocolGuid # PROTOCOL TO_START + diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa new file mode 100644 index 0000000000..eb722a2116 --- /dev/null +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa @@ -0,0 +1,72 @@ + + + + ScsiDisk + DXE_DRIVER + 0A66E322-3740-4cce-AD62-BD172CECCA35 + 1.0 + Component description file for Scsi Disk module.Revision History + Scsi Disk driver. This driver detected the Scsi disk media and export block io protocol + Copyright (c) 2006 - 2007, 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + ScsiDisk + + + + DebugLib + + + UefiDriverModelLib + + + UefiDriverEntryPoint + + + UefiLib + + + BaseMemoryLib + + + EdkScsiLib + + + UefiBootServicesTableLib + + + + ScsiDisk.h + ScsiDisk.c + ComponentName.c + + + + + + + + gEfiScsiIoProtocolGuid + + + gEfiBlockIoProtocolGuid + + + + EFI_SPECIFICATION_VERSION 0x00010010 + EDK_RELEASE_VERSION 0x00020000 + + gScsiDiskDriverBinding + gScsiDiskComponentName + + + \ No newline at end of file diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index baf274aeae..d7c468c2e6 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -344,4 +344,5 @@ ${WORKSPACE}/MdeModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.inf ${WORKSPACE}/MdeModulePkg/Universal/WatchDogTimerDxe/WatchDogTimer.inf ${WORKSPACE}/MdeModulePkg/Universal/VariablePei/Variable.inf - ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.inf \ No newline at end of file + ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.inf + ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf \ No newline at end of file diff --git a/Nt32Pkg/Nt32.dsc b/Nt32Pkg/Nt32.dsc index c9e2600065..4fd709495b 100644 --- a/Nt32Pkg/Nt32.dsc +++ b/Nt32Pkg/Nt32.dsc @@ -425,4 +425,5 @@ $(WORKSPACE)/IntelFrameworkModulePkg/Bus/Pci/IdeBus/Dxe/IdeBus.inf $(WORKSPACE)/IntelFrameworkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.inf $(WORKSPACE)/IntelFrameworkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.inf - ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.inf \ No newline at end of file + ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.inf ##This driver follows UEFI specification definition + ${WORKSPACE}/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf ##This driver follows UEFI specification definition \ No newline at end of file -- 2.39.2