From: Eric Kohl Date: Mon, 25 Mar 2002 21:56:19 +0000 (+0000) Subject: Started improving error handling and retries. X-Git-Tag: backups/mpw@12443~159 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=c773562024849aad4ac4f42b96e1f8968223aea6 Started improving error handling and retries. svn path=/trunk/; revision=2783 --- diff --git a/reactos/drivers/storage/atapi/atapi.c b/reactos/drivers/storage/atapi/atapi.c index 85fece9f474..33687c032e1 100644 --- a/reactos/drivers/storage/atapi/atapi.c +++ b/reactos/drivers/storage/atapi/atapi.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: atapi.c,v 1.17 2002/03/24 15:29:57 ekohl Exp $ +/* $Id: atapi.c,v 1.18 2002/03/25 21:54:41 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS ATAPI miniport driver @@ -203,6 +203,11 @@ static ULONG AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb); + +static UCHAR +AtapiErrorToScsi(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb); + // ---------------------------------------------------------------- Inlines void @@ -685,29 +690,10 @@ AtapiInterrupt(IN PVOID DeviceExtension) DeviceStatus = IDEReadStatus(CommandPortBase); - /* Handle error condition if it exists */ - if (DeviceStatus & IDE_SR_ERR) + if ((DeviceStatus & IDE_SR_ERR) && + (Srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) { - BYTE ErrorReg, SectorCount, SectorNum, CylinderLow, CylinderHigh; - BYTE DriveHead; - - /* Log the error */ - ErrorReg = IDEReadError(CommandPortBase); - CylinderLow = IDEReadCylinderLow(CommandPortBase); - CylinderHigh = IDEReadCylinderHigh(CommandPortBase); - DriveHead = IDEReadDriveHead(CommandPortBase); - SectorCount = IDEReadSectorCount(CommandPortBase); - SectorNum = IDEReadSectorNum(CommandPortBase); - - DPRINT1("ATAPI Error: STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", - DeviceStatus, - ErrorReg, - CylinderLow, - CylinderHigh, - SectorCount, - SectorNum); - - /* FIXME: set a useful status code */ + /* Report error condition */ Srb->SrbStatus = SRB_STATUS_ERROR; IsLastBlock = TRUE; } @@ -823,11 +809,19 @@ AtapiInterrupt(IN PVOID DeviceExtension) else { DPRINT1("Unspecified transfer direction!\n"); - Srb->SrbStatus = SRB_STATUS_ERROR; + Srb->SrbStatus = SRB_STATUS_SUCCESS; // SRB_STATUS_ERROR; IsLastBlock = TRUE; } } + + if (Srb->SrbStatus == SRB_STATUS_ERROR) + { + Srb->SrbStatus = AtapiErrorToScsi(DeviceExtension, + Srb); + } + + /* complete this packet */ if (IsLastBlock) { @@ -1664,8 +1658,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { PIDE_DRIVE_IDENTIFY DeviceParams; - - ULONG StartingSector,i; + ULONG StartingSector; ULONG SectorCount; UCHAR CylinderHigh; UCHAR CylinderLow; @@ -1675,7 +1668,6 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension, ULONG Retries; UCHAR Status; - DPRINT("AtapiReadWrite() called!\n"); if ((Srb->PathId != 0) || @@ -1914,4 +1906,130 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension, return(SRB_STATUS_PENDING); } + +static UCHAR +AtapiErrorToScsi(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PATAPI_MINIPORT_EXTENSION DevExt; + ULONG CommandPortBase; + ULONG ControlPortBase; + UCHAR ErrorReg; + UCHAR ScsiStatus; + UCHAR SrbStatus; + + DPRINT1("AtapiErrorToScsi() called\n"); + + DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension; + + CommandPortBase = DevExt->CommandPortBase; + ControlPortBase = DevExt->ControlPortBase; + + ErrorReg = IDEReadError(CommandPortBase); + + if (DevExt->DeviceAtapi[Srb->TargetId]) + { + switch (ErrorReg >> 4) + { + case SCSI_SENSE_NO_SENSE: + DPRINT1("ATAPI error: SCSI_SENSE_NO_SENSE\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_RECOVERED_ERROR: + DPRINT1("ATAPI error: SCSI_SENSE_RECOVERED_SENSE\n"); + ScsiStatus = 0; + SrbStatus = SRB_STATUS_SUCCESS; + break; + + case SCSI_SENSE_NOT_READY: + DPRINT1("ATAPI error: SCSI_SENSE_NOT_READY\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_MEDIUM_ERROR: + DPRINT1("ATAPI error: SCSI_SENSE_MEDIUM_ERROR\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_HARDWARE_ERROR: + DPRINT1("ATAPI error: SCSI_SENSE_HARDWARE_ERROR\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_ILLEGAL_REQUEST: + DPRINT1("ATAPI error: SCSI_SENSE_ILLEGAL_REQUEST\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_UNIT_ATTENTION: + DPRINT1("ATAPI error: SCSI_SENSE_UNIT_ATTENTION\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_DATA_PROTECT: + DPRINT1("ATAPI error: SCSI_SENSE_DATA_PROTECT\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_BLANK_CHECK: + DPRINT1("ATAPI error: SCSI_SENSE_BLANK_CHECK\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + case SCSI_SENSE_ABORTED_COMMAND: + DPRINT1("ATAPI error: SCSI_SENSE_ABORTED_COMMAND\n"); + ScsiStatus = SCSISTAT_CHECK_CONDITION; + SrbStatus = SRB_STATUS_ERROR; + break; + + default: + DPRINT1("ATAPI error: Invalid sense key\n"); + ScsiStatus = 0; + SrbStatus = SRB_STATUS_ERROR; + break; + } + } + else + { + DPRINT1("IDE error: %02x\n", ErrorReg); + + ScsiStatus = 0; + +#if 0 + UCHAR SectorCount, SectorNum, CylinderLow, CylinderHigh; + UCHAR DriveHead; + + CylinderLow = IDEReadCylinderLow(CommandPortBase); + CylinderHigh = IDEReadCylinderHigh(CommandPortBase); + DriveHead = IDEReadDriveHead(CommandPortBase); + SectorCount = IDEReadSectorCount(CommandPortBase); + SectorNum = IDEReadSectorNum(CommandPortBase); + + DPRINT1("IDE Error: ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", + ErrorReg, + CylinderLow, + CylinderHigh, + SectorCount, + SectorNum); +#endif + } + + + + Srb->ScsiStatus = ScsiStatus; + + DPRINT1("AtapiErrorToScsi() done\n"); + + return(SrbStatus); +} + /* EOF */ diff --git a/reactos/drivers/storage/cdrom/cdrom.c b/reactos/drivers/storage/cdrom/cdrom.c index 64031c36af3..05a7d431f16 100644 --- a/reactos/drivers/storage/cdrom/cdrom.c +++ b/reactos/drivers/storage/cdrom/cdrom.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: cdrom.c,v 1.6 2002/03/22 23:05:44 ekohl Exp $ +/* $Id: cdrom.c,v 1.7 2002/03/25 21:56:19 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -425,6 +425,23 @@ CdromClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, RtlZeroMemory(CdromData, sizeof(CDROM_DATA)); + DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool, + sizeof(SENSE_DATA)); + if (DiskDeviceExtension->SenseData == NULL) + { + DPRINT1("Failed to allocate sense data buffer!\n"); + + IoDeleteDevice(DiskDeviceObject); + + /* Release (unclaim) the disk */ + ScsiClassClaimDevice(PortDeviceObject, + InquiryData, + TRUE, + NULL); + + return(STATUS_INSUFFICIENT_RESOURCES); + } + /* Get disk geometry */ DiskDeviceExtension->DiskGeometry = ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY)); diff --git a/reactos/drivers/storage/class2/class2.c b/reactos/drivers/storage/class2/class2.c index 6815b416d68..43757f7b990 100644 --- a/reactos/drivers/storage/class2/class2.c +++ b/reactos/drivers/storage/class2/class2.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: class2.c,v 1.13 2002/03/22 23:06:58 ekohl Exp $ +/* $Id: class2.c,v 1.14 2002/03/25 21:55:51 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -145,13 +145,13 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject, NextIrpStack = IoGetNextIrpStackLocation(Irp); StartingOffset = CurrentIrpStack->Parameters.Read.ByteOffset; - /* calculate logical block address */ + /* Calculate logical block address */ StartingBlock.QuadPart = StartingOffset.QuadPart >> DeviceExtension->SectorShift; LogicalBlockAddress = (ULONG)StartingBlock.u.LowPart; DPRINT("Logical block address: %lu\n", LogicalBlockAddress); - /* allocate and initialize an SRB */ + /* Allocate and initialize an SRB */ /* FIXME: use lookaside list instead */ Srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK)); @@ -230,7 +230,7 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject, } #endif - /* or in the default flags from the device object. */ + /* Update srb flags */ Srb->SrbFlags |= DeviceExtension->SrbFlags; @@ -238,10 +238,8 @@ ScsiClassBuildRequest(PDEVICE_OBJECT DeviceObject, NextIrpStack->Parameters.Scsi.Srb = Srb; NextIrpStack->DeviceObject = DeviceObject; -#if 0 - /* save retry count in current IRP stack */ + /* Save retry count in current IRP stack */ CurrentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; -#endif DPRINT("IoSetCompletionRoutine (Irp %p Srb %p)\n", Irp, Srb); IoSetCompletionRoutine(Irp, @@ -724,7 +722,23 @@ ScsiClassInterpretSenseInfo(PDEVICE_OBJECT DeviceObject, ULONG RetryCount, NTSTATUS *Status) { - UNIMPLEMENTED; + + DPRINT1("ScsiClassInterpretSenseInfo() called\n"); + + DPRINT1("Srb->SrbStatus %lx\n", Srb->SrbStatus); + + if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING) + { + *Status = STATUS_SUCCESS; + } + else + { + *Status = STATUS_UNSUCCESSFUL; + } + + DPRINT1("ScsiClassInterpretSenseInfo() done\n"); + + return(FALSE); } @@ -736,6 +750,7 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, PDEVICE_EXTENSION DeviceExtension; PIO_STACK_LOCATION IrpStack; PSCSI_REQUEST_BLOCK Srb; + BOOLEAN Retry; NTSTATUS Status; DPRINT("ScsiClassIoComplete(DeviceObject %p Irp %p Context %p) called\n", @@ -747,30 +762,36 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, IrpStack = IoGetCurrentIrpStackLocation(Irp); -#if 0 if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS) { Status = STATUS_SUCCESS; } else { - /* FIXME: improve error handling */ - DPRINT1("Srb->SrbStatus %lx\n", Srb->SrbStatus); + Retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IrpStack->MajorFunction, + 0, + MAXIMUM_RETRIES - ((ULONG)IrpStack->Parameters.Others.Argument4), + &Status); +#if 0 + irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0, + +#endif - if (SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_PENDING) + if (Retry == TRUE) { - Status = STATUS_SUCCESS; + /* FIXME!! */ + DPRINT1("Should try again!\n"); + } - else - Status = STATUS_UNSUCCESSFUL; } -#endif /* FIXME: use lookaside list instead */ DPRINT("Freed SRB %p\n", IrpStack->Parameters.Scsi.Srb); ExFreePool(IrpStack->Parameters.Scsi.Srb); -// Irp->IoStatus.Status = Status; + Irp->IoStatus.Status = Status; #if 0 if (!NT_SUCCESS(Status) && IoIsErrorUserInduced(Status)) @@ -797,8 +818,7 @@ ScsiClassIoComplete(PDEVICE_OBJECT DeviceObject, DPRINT("ScsiClassIoComplete() done (Status %lx)\n", Status); -// return(Status); - return(STATUS_SUCCESS); + return(Status); } @@ -958,6 +978,8 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, IO_STATUS_BLOCK IoStatusBlock; PIO_STACK_LOCATION IoStack; ULONG RequestType; + BOOLEAN Retry; + ULONG RetryCount; KEVENT Event; PIRP Irp; NTSTATUS Status; @@ -965,8 +987,10 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, DPRINT("ScsiClassSendSrbSynchronous() called\n"); + RetryCount = MAXIMUM_RETRIES; DeviceExtension = DeviceObject->DeviceExtension; + Srb->Length = SCSI_REQUEST_BLOCK_SIZE; Srb->PathId = DeviceExtension->PathId; Srb->TargetId = DeviceExtension->TargetId; Srb->Lun = DeviceExtension->Lun; @@ -974,6 +998,11 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, /* FIXME: more srb initialization required? */ + Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; + Srb->SenseInfoBuffer = ExAllocatePool(NonPagedPool, + SENSE_BUFFER_SIZE); + if (Srb->SenseInfoBuffer == NULL) + return(STATUS_INSUFFICIENT_RESOURCES); if (BufferAddress == NULL) { @@ -1015,6 +1044,7 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, if (Irp == NULL) { DPRINT1("IoBuildDeviceIoControlRequest() failed\n"); + ExFreePool(Srb->SenseInfoBuffer); return(STATUS_INSUFFICIENT_RESOURCES); } @@ -1041,15 +1071,26 @@ ScsiClassSendSrbSynchronous(PDEVICE_OBJECT DeviceObject, if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) { - /* FIXME!! */ - DPRINT1("Fix return value!\n"); - Status = STATUS_UNSUCCESSFUL; + Retry = ScsiClassInterpretSenseInfo(DeviceObject, + Srb, + IRP_MJ_SCSI, + 0, + MAXIMUM_RETRIES - RetryCount, + &Status); + if (Retry == TRUE) + { + /* FIXME!! */ + DPRINT1("Should try again!\n"); + + } } else { Status = STATUS_SUCCESS; } + ExFreePool(Srb->SenseInfoBuffer); + DPRINT("ScsiClassSendSrbSynchronous() done\n"); return(Status); diff --git a/reactos/drivers/storage/include/class2.h b/reactos/drivers/storage/include/class2.h index 073d33af993..fc85ac04021 100644 --- a/reactos/drivers/storage/include/class2.h +++ b/reactos/drivers/storage/include/class2.h @@ -1,4 +1,4 @@ -/* $Id: class2.h,v 1.3 2002/01/31 14:58:34 ekohl Exp $ +/* $Id: class2.h,v 1.4 2002/03/25 21:54:06 ekohl Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -13,6 +13,8 @@ #include "ntddscsi.h" #include "srb.h" +#define MAXIMUM_RETRIES 4 + struct _CLASS_INIT_DATA; typedef VOID STDCALL diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index 46dfd75f4d0..8b314819db5 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -1,4 +1,4 @@ -/* $Id: iotypes.h,v 1.34 2002/03/17 17:53:34 hbirr Exp $ +/* $Id: iotypes.h,v 1.35 2002/03/25 21:53:27 ekohl Exp $ * */ @@ -305,6 +305,11 @@ typedef struct __attribute__((packed)) _IO_STACK_LOCATION struct _VPB* Vpb; struct _DEVICE_OBJECT* DeviceObject; } Mount; + struct + { + struct _VPB* Vpb; + struct _DEVICE_OBJECT* DeviceObject; + } VerifyVolume; struct { ULONG Length; @@ -415,12 +420,20 @@ typedef struct __attribute__((packed)) _IO_STACK_LOCATION PCM_RESOURCE_LIST AllocatedResourcesTranslated; } StartDevice; - // Parameters for IRP_MN_SCSI_CLASS + /* Parameters for IRP_MN_SCSI_CLASS */ struct { struct _SCSI_REQUEST_BLOCK *Srb; } Scsi; + /* Paramters for other calls */ + struct + { + PVOID Argument1; + PVOID Argument2; + PVOID Argument3; + PVOID Argument4; + } Others; } Parameters; struct _DEVICE_OBJECT* DeviceObject;