Started improving error handling and retries.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 25 Mar 2002 21:56:19 +0000 (21:56 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 25 Mar 2002 21:56:19 +0000 (21:56 +0000)
svn path=/trunk/; revision=2783

reactos/drivers/storage/atapi/atapi.c
reactos/drivers/storage/cdrom/cdrom.c
reactos/drivers/storage/class2/class2.c
reactos/drivers/storage/include/class2.h
reactos/include/ddk/iotypes.h

index 85fece9..33687c0 100644 (file)
@@ -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 */
index 64031c3..05a7d43 100644 (file)
@@ -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));
index 6815b41..43757f7 100644 (file)
@@ -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);
index 073d33a..fc85ac0 100644 (file)
@@ -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
index 46dfd75..8b31481 100644 (file)
@@ -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;