Implemented command retries.

Improved error handling.

svn path=/trunk/; revision=2984
This commit is contained in:
Eric Kohl 2002-05-26 20:24:42 +00:00
parent af5a948adf
commit f193742266

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: class2.c,v 1.18 2002/05/25 13:30:12 ekohl Exp $ /* $Id: class2.c,v 1.19 2002/05/26 20:24:42 ekohl Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -27,7 +27,7 @@
/* /*
* TODO: * TODO:
* - a lot ;-) * - finish ScsiClassDeviceControl().
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -39,7 +39,6 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
// #define ENABLE_RETRIES
#define VERSION "0.0.1" #define VERSION "0.0.1"
@ -71,26 +70,30 @@ ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
static VOID static VOID
ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject, ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
PIRP Irp, PIRP Irp,
PSCSI_REQUEST_BLOCK Srb); PSCSI_REQUEST_BLOCK Srb,
BOOLEAN Associated);
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
// DriverEntry /**********************************************************************
// * NAME EXPORTED
// DESCRIPTION: * DriverEntry
// This function initializes the driver. *
// * DESCRIPTION
// RUN LEVEL: * This function initializes the driver.
// PASSIVE_LEVEL *
// * RUN LEVEL
// ARGUMENTS: * PASSIVE_LEVEL
// IN PDRIVER_OBJECT DriverObject System allocated Driver Object *
// for this driver * ARGUMENTS
// IN PUNICODE_STRING RegistryPath Name of registry driver service * DriverObject
// key * System allocated Driver Object for this driver.
// * RegistryPath
// RETURNS: * Name of registry driver service key.
// NTSTATUS *
* RETURNS
* Status
*/
NTSTATUS STDCALL NTSTATUS STDCALL
DriverEntry(IN PDRIVER_OBJECT DriverObject, DriverEntry(IN PDRIVER_OBJECT DriverObject,
@ -295,7 +298,7 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
&IoStatusBlock); &IoStatusBlock);
if (Irp == NULL) if (Irp == NULL)
{ {
DPRINT1("Failed to allocate Irp!\n"); DPRINT("Failed to allocate Irp!\n");
return(STATUS_INSUFFICIENT_RESOURCES); return(STATUS_INSUFFICIENT_RESOURCES);
} }
@ -786,9 +789,9 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
PSENSE_DATA SenseData; PSENSE_DATA SenseData;
BOOLEAN Retry; BOOLEAN Retry;
DPRINT1("ScsiClassInterpretSenseInfo() called\n"); DPRINT("ScsiClassInterpretSenseInfo() called\n");
DPRINT1("Srb->SrbStatus %lx\n", Srb->SrbStatus); DPRINT("Srb->SrbStatus %lx\n", Srb->SrbStatus);
if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING) if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING)
{ {
@ -805,21 +808,21 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
{ {
/* Got valid sense data, interpret them */ /* Got valid sense data, interpret them */
DPRINT1("ErrorCode: %x\n", SenseData->ErrorCode); DPRINT("ErrorCode: %x\n", SenseData->ErrorCode);
DPRINT1("SenseKey: %x\n", SenseData->SenseKey); DPRINT("SenseKey: %x\n", SenseData->SenseKey);
DPRINT1("SenseCode: %x\n", SenseData->AdditionalSenseCode); DPRINT("SenseCode: %x\n", SenseData->AdditionalSenseCode);
switch (SenseData->SenseKey & 0xf) switch (SenseData->SenseKey & 0xf)
{ {
/* FIXME: add more sense key codes */ /* FIXME: add more sense key codes */
case SCSI_SENSE_NOT_READY: case SCSI_SENSE_NOT_READY:
DPRINT1("SCSI_SENSE_NOT_READY\n"); DPRINT("SCSI_SENSE_NOT_READY\n");
*Status = STATUS_DEVICE_NOT_READY; *Status = STATUS_DEVICE_NOT_READY;
break; break;
case SCSI_SENSE_UNIT_ATTENTION: case SCSI_SENSE_UNIT_ATTENTION:
DPRINT1("SCSI_SENSE_UNIT_ATTENTION\n"); DPRINT("SCSI_SENSE_UNIT_ATTENTION\n");
if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) && if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
(DeviceObject->Vpb->Flags & VPB_MOUNTED)) (DeviceObject->Vpb->Flags & VPB_MOUNTED))
{ {
@ -834,7 +837,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
break; break;
case SCSI_SENSE_ILLEGAL_REQUEST: case SCSI_SENSE_ILLEGAL_REQUEST:
DPRINT1("SCSI_SENSE_ILLEGAL_REQUEST\n"); DPRINT("SCSI_SENSE_ILLEGAL_REQUEST\n");
*Status = STATUS_INVALID_DEVICE_REQUEST; *Status = STATUS_INVALID_DEVICE_REQUEST;
Retry = FALSE; Retry = FALSE;
break; break;
@ -849,17 +852,33 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
} }
else else
{ {
/* Got no/invalid sense data, return generic error codes */ /* Got no or invalid sense data, return generic error codes */
switch (SRB_STATUS(Srb->SrbStatus)) switch (SRB_STATUS(Srb->SrbStatus))
{ {
/* FIXME: add more srb status codes */ /* FIXME: add more srb status codes */
case SRB_STATUS_INVALID_PATH_ID:
case SRB_STATUS_INVALID_TARGET_ID:
case SRB_STATUS_INVALID_LUN:
case SRB_STATUS_NO_DEVICE:
case SRB_STATUS_NO_HBA:
*Status = STATUS_NO_SUCH_DEVICE;
Retry = FALSE;
break;
case SRB_STATUS_BUSY:
*Status = STATUS_DEVICE_BUSY;
Retry = TRUE;
break;
case SRB_STATUS_DATA_OVERRUN: case SRB_STATUS_DATA_OVERRUN:
*Status = STATUS_DATA_OVERRUN; *Status = STATUS_DATA_OVERRUN;
Retry = FALSE; Retry = FALSE;
break; break;
default: default:
DPRINT1("SCSI error (SRB status: %x)\n",
SRB_STATUS(Srb->SrbStatus));
*Status = STATUS_IO_DEVICE_ERROR; *Status = STATUS_IO_DEVICE_ERROR;
break; break;
} }
@ -876,7 +895,7 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject,
/* FIXME: log severe errors */ /* FIXME: log severe errors */
DPRINT1("ScsiClassInterpretSenseInfo() done\n"); DPRINT("ScsiClassInterpretSenseInfo() done\n");
return(Retry); return(Retry);
} }
@ -914,24 +933,16 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
0, 0,
MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4), MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4),
&Status); &Status);
DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
if ((Retry == TRUE) && if ((Retry == TRUE) &&
((ULONG)IrpStack->Parameters.Others.Argument4 > 0)) ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
{ {
((ULONG)IrpStack->Parameters.Others.Argument4)--; ((ULONG)IrpStack->Parameters.Others.Argument4)--;
DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
DPRINT1("Should try again!\n");
#ifdef ENABLE_RETRY
ScsiClassRetryRequest(DeviceObject, ScsiClassRetryRequest(DeviceObject,
Irp, Irp,
Srb); Srb,
FALSE);
return(STATUS_MORE_PROCESSING_REQUIRED); return(STATUS_MORE_PROCESSING_REQUIRED);
#else
return(Status);
#endif
} }
} }
@ -949,7 +960,6 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
ExFreePool(IrpStack->Parameters.Scsi.Srb); ExFreePool(IrpStack->Parameters.Scsi.Srb);
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
//#if 0
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
@ -959,13 +969,6 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject,
DeviceObject); DeviceObject);
} }
} }
//#endif
#if 0
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
#endif
if (DeviceExtension->ClassStartIo != NULL) if (DeviceExtension->ClassStartIo != NULL)
{ {
@ -1025,17 +1028,12 @@ ScsiClassIoCompleteAssociated(PDEVICE_OBJECT DeviceObject,
((ULONG)IrpStack->Parameters.Others.Argument4 > 0)) ((ULONG)IrpStack->Parameters.Others.Argument4 > 0))
{ {
((ULONG)IrpStack->Parameters.Others.Argument4)--; ((ULONG)IrpStack->Parameters.Others.Argument4)--;
DPRINT1("Retry count: %lu\n", (ULONG)IrpStack->Parameters.Others.Argument4);
DPRINT1("Should try again!\n");
#ifdef ENABLE_RETRY
ScsiClassRetryRequest(DeviceObject, ScsiClassRetryRequest(DeviceObject,
Irp, Irp,
Srb); Srb,
TRUE);
return(STATUS_MORE_PROCESSING_REQUIRED); return(STATUS_MORE_PROCESSING_REQUIRED);
#else
return(Status);
#endif
} }
} }
@ -1174,7 +1172,7 @@ ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
else else
{ {
/* Use default values if disk geometry cannot be read */ /* Use default values if disk geometry cannot be read */
RtlZeroMemory(&DeviceExtension->DiskGeometry, RtlZeroMemory(DeviceExtension->DiskGeometry,
sizeof(DISK_GEOMETRY)); sizeof(DISK_GEOMETRY));
DeviceExtension->DiskGeometry->BytesPerSector = 512; DeviceExtension->DiskGeometry->BytesPerSector = 512;
DeviceExtension->SectorShift = 9; DeviceExtension->SectorShift = 9;
@ -1188,6 +1186,8 @@ ScsiClassReadDriveCapacity(IN PDEVICE_OBJECT DeviceObject)
{ {
DeviceExtension->DiskGeometry->MediaType = FixedMedia; DeviceExtension->DiskGeometry->MediaType = FixedMedia;
} }
DPRINT("SectorSize: 512 SectorCount: 0\n");
} }
ExFreePool(CapacityBuffer); ExFreePool(CapacityBuffer);
@ -1226,7 +1226,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
{ {
PDEVICE_EXTENSION DeviceExtension; PDEVICE_EXTENSION DeviceExtension;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IrpStack;
ULONG RequestType; ULONG RequestType;
BOOLEAN Retry; BOOLEAN Retry;
ULONG RetryCount; ULONG RetryCount;
@ -1245,8 +1245,6 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
Srb->Lun = DeviceExtension->Lun; Srb->Lun = DeviceExtension->Lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
/* FIXME: more srb initialization required? */
Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool, Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool,
SENSE_BUFFER_SIZE); SENSE_BUFFER_SIZE);
@ -1278,6 +1276,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
Event = ExAllocatePool(NonPagedPool, Event = ExAllocatePool(NonPagedPool,
sizeof(KEVENT)); sizeof(KEVENT));
TryAgain:
KeInitializeEvent(Event, KeInitializeEvent(Event,
NotificationEvent, NotificationEvent,
FALSE); FALSE);
@ -1293,21 +1292,17 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
&IoStatusBlock); &IoStatusBlock);
if (Irp == NULL) if (Irp == NULL)
{ {
DPRINT1("IoBuildDeviceIoControlRequest() failed\n"); DPRINT("IoBuildDeviceIoControlRequest() failed\n");
ExFreePool(Srb->SenseInfoBuffer); ExFreePool(Srb->SenseInfoBuffer);
ExFreePool(Event); ExFreePool(Event);
return(STATUS_INSUFFICIENT_RESOURCES); return(STATUS_INSUFFICIENT_RESOURCES);
} }
/* FIXME: more irp initialization required? */
/* Attach Srb to the Irp */ /* Attach Srb to the Irp */
IoStack = IoGetNextIrpStackLocation(Irp); IrpStack = IoGetNextIrpStackLocation(Irp);
IoStack->Parameters.Scsi.Srb = Srb; IrpStack->Parameters.Scsi.Srb = Srb;
Srb->OriginalRequest = Irp; Srb->OriginalRequest = Irp;
/* Call the SCSI port driver */ /* Call the SCSI port driver */
Status = IoCallDriver(DeviceExtension->PortDeviceObject, Status = IoCallDriver(DeviceExtension->PortDeviceObject,
Irp); Irp);
@ -1330,9 +1325,12 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject,
&Status); &Status);
if (Retry == TRUE) if (Retry == TRUE)
{ {
/* FIXME!! */ DPRINT("Try again (RetryCount %lu)\n", RetryCount);
DPRINT1("Should try again!\n");
/* FIXME: Wait a little if we got a timeout error */
if (RetryCount--)
goto TryAgain;
} }
} }
else else
@ -1650,14 +1648,15 @@ ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
static VOID static VOID
ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject, ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
PIRP Irp, PIRP Irp,
PSCSI_REQUEST_BLOCK Srb) PSCSI_REQUEST_BLOCK Srb,
BOOLEAN Associated)
{ {
PDEVICE_EXTENSION DeviceExtension; PDEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION CurrentIrpStack; PIO_STACK_LOCATION CurrentIrpStack;
PIO_STACK_LOCATION NextIrpStack; PIO_STACK_LOCATION NextIrpStack;
ULONG TransferLength; ULONG TransferLength;
DPRINT1("ScsiPortRetryRequest() called\n"); DPRINT("ScsiPortRetryRequest() called\n");
DeviceExtension = DeviceObject->DeviceExtension; DeviceExtension = DeviceObject->DeviceExtension;
CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp); CurrentIrpStack = IoGetCurrentIrpStackLocation(Irp);
@ -1680,32 +1679,37 @@ ScsiClassRetryRequest(PDEVICE_OBJECT DeviceObject,
Srb->DataTransferLength = TransferLength; Srb->DataTransferLength = TransferLength;
Srb->SrbStatus = 0; Srb->SrbStatus = 0;
Srb->ScsiStatus = 0; Srb->ScsiStatus = 0;
// Srb->QueueTag = SP_UNTAGGED;
/* Don't modify the flags */ /* Don't modify the flags */
// Srb->Flags = // Srb->Flags =
// Srb->QueueTag = SP_UNTAGGED;
// CurrentIrpStack->MajorFunction = IRP_MJ_SCSI;
// CurrentIrpStack->Parameters.Scsi.Srb = Srb;
// IoSkipCurrentIrpStackLocation(Irp);
*NextIrpStack = *CurrentIrpStack;
NextIrpStack->MajorFunction = IRP_MJ_SCSI; NextIrpStack->MajorFunction = IRP_MJ_SCSI;
NextIrpStack->Parameters.Scsi.Srb = Srb; NextIrpStack->Parameters.Scsi.Srb = Srb;
if (Associated == FALSE)
IoSetCompletionRoutine(Irp, {
ScsiClassIoComplete, IoSetCompletionRoutine(Irp,
Srb, ScsiClassIoComplete,
TRUE, Srb,
TRUE, TRUE,
TRUE); TRUE,
TRUE);
DPRINT1("ScsiPortRetryRequest() done\n"); }
else
{
IoSetCompletionRoutine(Irp,
ScsiClassIoCompleteAssociated,
Srb,
TRUE,
TRUE,
TRUE);
}
IoCallDriver(DeviceExtension->PortDeviceObject, IoCallDriver(DeviceExtension->PortDeviceObject,
Irp); Irp);
DPRINT("ScsiPortRetryRequest() done\n");
} }
/* EOF */ /* EOF */