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-n…
==============================================================================
--- 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-n…
==============================================================================
--- 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;