[ros-diffs] [fireball] 26192: - Start putting all data, needed for ISR into a dedicated structure. - Use DEVICE_QUEUEs. - Add a function to retrieve SRB information help structure (is a shared code between Notify(), and in future - ScsiPortGetSrb()). - Rework RequestComplete part of ScsiPortNotification(). - Rework ScsiPortDispatchScsi() a bit - shutdown/flush can share the same code as execute_scsi/ioctl requests, also added a few more DPRINTs in error conditions to help debugging.

fireball at svn.reactos.org fireball at svn.reactos.org
Wed Mar 28 12:41:04 CEST 2007


Author: fireball
Date: Wed Mar 28 14:41:03 2007
New Revision: 26192

URL: http://svn.reactos.org/svn/reactos?rev=26192&view=rev
Log:
- Start putting all data, needed for ISR into a dedicated structure.
- Use DEVICE_QUEUEs.
- Add a function to retrieve SRB information help structure (is a shared code between Notify(), and in future - ScsiPortGetSrb()).
- Rework RequestComplete part of ScsiPortNotification().
- Rework ScsiPortDispatchScsi() a bit - shutdown/flush can share the same code as execute_scsi/ioctl requests, also added a few more DPRINTs in error conditions to help debugging.

Modified:
    trunk/reactos/drivers/storage/scsiport-new/scsiport.c
    trunk/reactos/drivers/storage/scsiport-new/scsiport_int.h

Modified: trunk/reactos/drivers/storage/scsiport-new/scsiport.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/storage/scsiport-new/scsiport.c?rev=26192&r1=26191&r2=26192&view=diff
==============================================================================
--- trunk/reactos/drivers/storage/scsiport-new/scsiport.c (original)
+++ trunk/reactos/drivers/storage/scsiport-new/scsiport.c Wed Mar 28 14:41:03 2007
@@ -41,9 +41,6 @@
 
 #include "scsiport_int.h"
 
-
-/* #define USE_DEVICE_QUEUES */
-
 /* TYPES *********************************************************************/
 
 #define IRP_FLAG_COMPLETE	0x00000001
@@ -98,6 +95,13 @@
 static NTSTATUS
 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
 		   IN PIRP Irp);
+
+static PSCSI_REQUEST_BLOCK_INFO
+SpiGetSrbData(IN PVOID DeviceExtension,
+              IN UCHAR PathId,
+              IN UCHAR TargetId,
+              IN UCHAR Lun,
+              IN UCHAR QueueTag);
 
 static BOOLEAN STDCALL
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
@@ -1073,36 +1077,79 @@
 		     IN PVOID HwDeviceExtension,
 		     ...)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  va_list ap;
-
-  DPRINT("ScsiPortNotification() called\n");
-
-  DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
-				      SCSI_PORT_DEVICE_EXTENSION,
-				      MiniPortDeviceExtension);
-
-  DPRINT("DeviceExtension %p\n", DeviceExtension);
-
-  va_start(ap, HwDeviceExtension);
-
-  switch (NotificationType)
-    {
-      case RequestComplete:
-	{
-	  PSCSI_REQUEST_BLOCK Srb;
-
-	  Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
-
-	  DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
-	  DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
-	}
-	break;
-
-      case NextRequest:
-	DPRINT("Notify: NextRequest\n");
-	DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
-	break;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    va_list ap;
+
+    DPRINT("ScsiPortNotification() called\n");
+
+    DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
+        SCSI_PORT_DEVICE_EXTENSION,
+        MiniPortDeviceExtension);
+
+    DPRINT("DeviceExtension %p\n", DeviceExtension);
+
+    va_start(ap, HwDeviceExtension);
+
+    switch (NotificationType)
+    {
+    case RequestComplete:
+        {
+            PSCSI_REQUEST_BLOCK Srb;
+            PSCSI_REQUEST_BLOCK_INFO SrbData;
+
+            Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
+
+            DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
+            //	  DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
+
+            /* Make sure Srb is allright */
+            ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING);
+            ASSERT(Srb->Function != SRB_FUNCTION_EXECUTE_SCSI || Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD);
+
+            if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
+            {
+                /* It's been already completed */
+                va_end(ap);
+                return;
+            }
+
+            /* It's not active anymore */
+            Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
+
+            if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
+            {
+                /* TODO: Treat it specially */
+                ASSERT(FALSE);
+            }
+            else
+            {
+                /* Get the SRB data */
+                SrbData = SpiGetSrbData(DeviceExtension,
+                                        Srb->PathId,
+                                        Srb->TargetId,
+                                        Srb->Lun,
+                                        Srb->QueueTag);
+
+                /* Make sure there are no CompletedRequests and there is a Srb */
+                ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);
+
+                /* If it's a read/write request, make sure it has data inside it */
+                if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
+                    ((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE)))
+                {
+                        ASSERT(Srb->DataTransferLength);
+                }
+
+                SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests;
+                DeviceExtension->InterruptData.CompletedRequests = SrbData;
+            }
+        }
+        break;
+
+    case NextRequest:
+        DPRINT("Notify: NextRequest\n");
+        DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
+        break;
 
       case NextLuRequest:
 	{
@@ -1381,130 +1428,135 @@
 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
 		     IN PIRP Irp)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  PSCSI_PORT_LUN_EXTENSION LunExtension;
-  PIO_STACK_LOCATION Stack;
-  PSCSI_REQUEST_BLOCK Srb;
-  NTSTATUS Status = STATUS_SUCCESS;
-  ULONG DataSize = 0;
-
-  DPRINT("ScsiPortDispatchScsi(DeviceObject %p  Irp %p)\n",
-	 DeviceObject, Irp);
-
-  DeviceExtension = DeviceObject->DeviceExtension;
-  Stack = IoGetCurrentIrpStackLocation(Irp);
-
-  Srb = Stack->Parameters.Scsi.Srb;
-  if (Srb == NULL)
-    {
-      Status = STATUS_UNSUCCESSFUL;
-
-      Irp->IoStatus.Status = Status;
-      Irp->IoStatus.Information = 0;
-
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-      return(Status);
-    }
-
-  DPRINT("Srb: %p\n", Srb);
-  DPRINT("Srb->Function: %lu\n", Srb->Function);
-  DPRINT("PathId: %lu  TargetId: %lu  Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
-
-  LunExtension = SpiGetLunExtension(DeviceExtension,
-				    Srb->PathId,
-				    Srb->TargetId,
-				    Srb->Lun);
-  if (LunExtension == NULL)
-    {
-      Status = STATUS_NO_SUCH_DEVICE;
-
-      Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
-      Irp->IoStatus.Status = Status;
-      Irp->IoStatus.Information = 0;
-
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-      return(Status);
-    }
-
-  switch (Srb->Function)
-    {
-      case SRB_FUNCTION_EXECUTE_SCSI:
-      case SRB_FUNCTION_IO_CONTROL:
-#ifdef USE_DEVICE_QUEUES
-	if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
-	  {
-	    IoMarkIrpPending(Irp);
-	    IoStartPacket (DeviceObject, Irp, NULL, NULL);
-	  }
-	else
-	  {
-	    KIRQL oldIrql;
-
-	    KeRaiseIrql (DISPATCH_LEVEL,
-			 &oldIrql);
-
-	    if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
-					   &Irp->Tail.Overlay.DeviceQueueEntry,
-					   Srb->QueueSortKey))
-	      {
-		Srb->SrbStatus = SRB_STATUS_SUCCESS;
-		IoMarkIrpPending(Irp);
-		IoStartPacket (DeviceObject, Irp, NULL, NULL);
-	      }
-
-	    KeLowerIrql (oldIrql);
-	  }
-#else
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PSCSI_PORT_LUN_EXTENSION LunExtension;
+    PIO_STACK_LOCATION Stack;
+    PSCSI_REQUEST_BLOCK Srb;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("ScsiPortDispatchScsi(DeviceObject %p  Irp %p)\n",
+        DeviceObject, Irp);
+
+    DeviceExtension = DeviceObject->DeviceExtension;
+    Stack = IoGetCurrentIrpStackLocation(Irp);
+
+    Srb = Stack->Parameters.Scsi.Srb;
+    if (Srb == NULL)
+    {
+        DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
+        Status = STATUS_UNSUCCESSFUL;
+
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return(Status);
+    }
+
+    DPRINT("Srb: %p\n", Srb);
+    DPRINT("Srb->Function: %lu\n", Srb->Function);
+    DPRINT("PathId: %lu  TargetId: %lu  Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
+
+    LunExtension = SpiGetLunExtension(DeviceExtension,
+        Srb->PathId,
+        Srb->TargetId,
+        Srb->Lun);
+    if (LunExtension == NULL)
+    {
+        DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
+        Status = STATUS_NO_SUCH_DEVICE;
+
+        Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+        Irp->IoStatus.Status = Status;
+        Irp->IoStatus.Information = 0;
+
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+        return(Status);
+    }
+
+    switch (Srb->Function)
+    {
+    case SRB_FUNCTION_SHUTDOWN:
+    case SRB_FUNCTION_FLUSH:
+        DPRINT ("  SRB_FUNCTION_SHUTDOWN or FLUSH\n");
+        if (DeviceExtension->PortConfig->CachesData == FALSE)
+        {
+            /* All success here */
+            Srb->SrbStatus = SRB_STATUS_SUCCESS;
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_SUCCESS;
+        }
+        /* Fall through to a usual execute operation */
+
+    case SRB_FUNCTION_EXECUTE_SCSI:
+    case SRB_FUNCTION_IO_CONTROL:
+        /* Mark IRP as pending in all cases */
         IoMarkIrpPending(Irp);
-        IoStartPacket (DeviceObject, Irp, NULL, NULL);
-#endif
-	return(STATUS_PENDING);
-
-      case SRB_FUNCTION_SHUTDOWN:
-      case SRB_FUNCTION_FLUSH:
-	if (DeviceExtension->PortConfig->CachesData == TRUE)
-	  {
-            IoMarkIrpPending(Irp);
-	    IoStartPacket(DeviceObject, Irp, NULL, NULL);
-	    return(STATUS_PENDING);
-	  }
-	break;
-
-      case SRB_FUNCTION_CLAIM_DEVICE:
-	DPRINT ("  SRB_FUNCTION_CLAIM_DEVICE\n");
-
-	/* Reference device object and keep the device object */
-	ObReferenceObject(DeviceObject);
-	LunExtension->DeviceObject = DeviceObject;
-	LunExtension->DeviceClaimed = TRUE;
-	Srb->DataBuffer = DeviceObject;
-	break;
-
-      case SRB_FUNCTION_RELEASE_DEVICE:
-	DPRINT ("  SRB_FUNCTION_RELEASE_DEVICE\n");
-	DPRINT ("PathId: %lu  TargetId: %lu  Lun: %lu\n",
-		Srb->PathId, Srb->TargetId, Srb->Lun);
-
-	/* Dereference device object and clear the device object */
-	ObDereferenceObject(LunExtension->DeviceObject);
-	LunExtension->DeviceObject = NULL;
-	LunExtension->DeviceClaimed = FALSE;
-	break;
-
-      default:
-	DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
-	Status = STATUS_NOT_IMPLEMENTED;
-	break;
-    }
-
-  Irp->IoStatus.Status = Status;
-  Irp->IoStatus.Information = DataSize;
-
-  IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-  return(Status);
+
+        if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
+        {
+            /* Start IO directly */
+            IoStartPacket(DeviceObject, Irp, NULL, NULL);
+        }
+        else
+        {
+            KIRQL oldIrql;
+
+            /* We need to be at DISPATCH_LEVEL */
+            KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
+
+            /* Insert IRP into the queue */
+            if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
+                &Irp->Tail.Overlay.DeviceQueueEntry,
+                Srb->QueueSortKey))
+            {
+                /* It means queue is empty, and we just start this request */
+                IoStartPacket(DeviceObject, Irp, NULL, NULL);
+            }
+
+            /* Back to the old IRQL */
+            KeLowerIrql (oldIrql);
+        }
+        return STATUS_PENDING;
+
+    case SRB_FUNCTION_CLAIM_DEVICE:
+    case SRB_FUNCTION_ATTACH_DEVICE:
+        DPRINT ("  SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
+
+        /* Reference device object and keep the device object */
+        /* TODO: Check if it's OK */
+        ObReferenceObject(DeviceObject);
+        LunExtension->DeviceObject = DeviceObject;
+        LunExtension->DeviceClaimed = TRUE;
+        Srb->DataBuffer = DeviceObject;
+        break;
+
+    case SRB_FUNCTION_RELEASE_DEVICE:
+        DPRINT ("  SRB_FUNCTION_RELEASE_DEVICE\n");
+        /* TODO: Check if it's OK */
+        DPRINT ("PathId: %lu  TargetId: %lu  Lun: %lu\n",
+            Srb->PathId, Srb->TargetId, Srb->Lun);
+
+        /* Dereference device object and clear the device object */
+        ObDereferenceObject(LunExtension->DeviceObject);
+        LunExtension->DeviceObject = NULL;
+        LunExtension->DeviceClaimed = FALSE;
+        break;
+
+    default:
+        DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
+        Status = STATUS_NOT_IMPLEMENTED;
+        break;
+    }
+
+    Irp->IoStatus.Status = Status;
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return(Status);
 }
 
 
@@ -2304,6 +2356,37 @@
     return STATUS_SUCCESS;
 }
 
+static PSCSI_REQUEST_BLOCK_INFO
+SpiGetSrbData(IN PVOID DeviceExtension,
+              IN UCHAR PathId,
+              IN UCHAR TargetId,
+              IN UCHAR Lun,
+              IN UCHAR QueueTag)
+{
+    PSCSI_PORT_LUN_EXTENSION LunExtension;
+
+    if (QueueTag == SP_UNTAGGED)
+    {
+        /* Untagged request, get LU and return pointer to SrbInfo */
+        LunExtension = SpiGetLunExtension(DeviceExtension,
+                                          PathId,
+                                          TargetId,
+                                          Lun);
+
+        /* Return NULL in case of error */
+        if (!LunExtension)
+            return(NULL);
+
+        /* Return the pointer to SrbInfo */
+        return &LunExtension->SrbInfo;
+    }
+    else
+    {
+        /* TODO: Implement when we have it */
+        ASSERT(FALSE);
+        return NULL;
+    }
+}
 
 static BOOLEAN STDCALL
 ScsiPortIsr(IN PKINTERRUPT Interrupt,

Modified: trunk/reactos/drivers/storage/scsiport-new/scsiport_int.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/storage/scsiport-new/scsiport_int.h?rev=26192&r1=26191&r2=26192&view=diff
==============================================================================
--- trunk/reactos/drivers/storage/scsiport-new/scsiport_int.h (original)
+++ trunk/reactos/drivers/storage/scsiport-new/scsiport_int.h Wed Mar 28 14:41:03 2007
@@ -20,7 +20,8 @@
 #define LUS_NUMBER 8
 
 /* Flags */
-#define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
+#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
+#define SCSI_PORT_SCAN_IN_PROGRESS   0x8000
 
 typedef enum _SCSI_PORT_TIMER_STATES
 {
@@ -44,6 +45,8 @@
 typedef struct _SCSI_REQUEST_BLOCK_INFO
 {
     LIST_ENTRY Requests;
+    PSCSI_REQUEST_BLOCK Srb;
+    struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
 } SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
 
 typedef struct _SCSI_PORT_LUN_EXTENSION
@@ -97,6 +100,15 @@
     PSCSI_BUS_SCAN_INFO BusScanInfo[1];
 } BUSES_CONFIGURATION_INFORMATION, *PBUSES_CONFIGURATION_INFORMATION;
 
+
+typedef struct _SCSI_PORT_INTERRUPT_DATA
+{
+    ULONG Flags; /* Interrupt-time flags */
+    PSCSI_REQUEST_BLOCK_INFO CompletedRequests; /* Linked list of Srb info data */
+
+} SCSI_PORT_INTERRUPT_DATA, *PSCSI_PORT_INTERRUPT_DATA;
+
+
 /*
  * SCSI_PORT_DEVICE_EXTENSION
  *
@@ -127,6 +139,8 @@
   ULONG LunExtensionSize;
   PSCSI_PORT_LUN_EXTENSION LunExtensionList[LUS_NUMBER];
 
+  SCSI_PORT_INTERRUPT_DATA InterruptData;
+
   ULONG SrbExtensionSize;
 
   PIO_SCSI_CAPABILITIES PortCapabilities;




More information about the Ros-diffs mailing list