summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c202
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c2412
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h774
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.inf100
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa72
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc3
-rw-r--r--Nt32Pkg/Nt32.dsc3
7 files changed, 3564 insertions, 2 deletions
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ComponentName.c
new file mode 100644
index 0000000..24adbe9
--- /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 <PiDxe.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/ScsiIo.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DriverBinding.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ScsiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#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 0000000..e85f99b
--- /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 <PiDxe.h>
+
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/ScsiIo.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/DriverBinding.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ScsiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#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 0000000..675c643
--- /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 <IndustryStandard/scsi.h>
+
+#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 0000000..fa7cca0
--- /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 0000000..eb722a2
--- /dev/null
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.msa
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>ScsiDisk</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>0A66E322-3740-4cce-AD62-BD172CECCA35</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for Scsi Disk module.Revision History</Abstract>
+ <Description>Scsi Disk driver. This driver detected the Scsi disk media and export block io protocol</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
+ <License>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.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>ScsiDisk</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverModelLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>EdkScsiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>ScsiDisk.h</Filename>
+ <Filename>ScsiDisk.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiScsiIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00010010</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <DriverBinding>gScsiDiskDriverBinding</DriverBinding>
+ <ComponentName>gScsiDiskComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index baf274a..d7c468c 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 c9e2600..4fd7094 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