- Rearrange code inside ScsiPortStartIo() routine (some code for dma-support added...
authorAleksey Bragin <aleksey@reactos.org>
Wed, 28 Mar 2007 18:29:15 +0000 (18:29 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Wed, 28 Mar 2007 18:29:15 +0000 (18:29 +0000)
- Respective changes in ScsiPortStartPacket(), also some code is missing for rare kind of requests.
- Add flags check into ScsiPortIsr(), so that we skip unwanted interrupts (and change to usage of the new interrupt flags structure instead of a strange and unclear "IrpFlags" field).

svn path=/trunk/; revision=26196

reactos/drivers/storage/scsiport-new/scsiport.c
reactos/drivers/storage/scsiport-new/scsiport_int.h

index 955efb1..ce7c9f3 100644 (file)
@@ -885,6 +885,9 @@ ScsiPortInitialize(IN PVOID Argument1,
              goto ByeBye;
            }
 
+          /* Initialize counter of active requests (-1 means there are none) */
+          DeviceExtension->ActiveRequestCounter = -1;
+
          if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
            {
              DbgPrint("HwInitialize() failed!");
@@ -1642,152 +1645,253 @@ static VOID STDCALL
 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
                IN PIRP Irp)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  PSCSI_PORT_LUN_EXTENSION LunExtension;
-  PIO_STACK_LOCATION IrpStack;
-  PSCSI_REQUEST_BLOCK Srb;
-  KIRQL oldIrql;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PSCSI_PORT_LUN_EXTENSION LunExtension;
+    PIO_STACK_LOCATION IrpStack;
+    PSCSI_REQUEST_BLOCK Srb;
+    PSCSI_REQUEST_BLOCK_INFO SrbInfo;
+    LONG CounterResult;
 
-  DPRINT("ScsiPortStartIo() called!\n");
+    DPRINT("ScsiPortStartIo() called!\n");
 
-  DeviceExtension = DeviceObject->DeviceExtension;
-  IrpStack = IoGetCurrentIrpStackLocation(Irp);
+    DeviceExtension = DeviceObject->DeviceExtension;
+    IrpStack = IoGetCurrentIrpStackLocation(Irp);
 
-  DPRINT("DeviceExtension %p\n", DeviceExtension);
+    DPRINT("DeviceExtension %p\n", DeviceExtension);
+
+    Srb = IrpStack->Parameters.Scsi.Srb;
 
-  oldIrql = KeGetCurrentIrql();
+    /* FIXME: Apply standard flags to Srb->SrbFlags ? */
 
-  if (IrpStack->MajorFunction != IRP_MJ_SCSI)
+    /* Get LUN extension */
+    LunExtension = SpiGetLunExtension(DeviceExtension,
+                                      Srb->PathId,
+                                      Srb->TargetId,
+                                      Srb->Lun);
+
+    if (DeviceExtension->NeedSrbDataAlloc ||
+        DeviceExtension->NeedSrbExtensionAlloc)
     {
-      DPRINT("No IRP_MJ_SCSI!\n");
-      Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-      Irp->IoStatus.Information = 0;
-      IoCompleteRequest (Irp,
-                        IO_NO_INCREMENT);
-      if (oldIrql < DISPATCH_LEVEL)
-       {
-         KeRaiseIrql (DISPATCH_LEVEL,
-                      &oldIrql);
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-         KeLowerIrql (oldIrql);
-       }
-      else
-       {
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-       }
-      return;
+        /* TODO: Implement */
+        ASSERT(FALSE);
+        SrbInfo = NULL;
+    }
+    else
+    {
+        /* No allocations are needed */
+        SrbInfo = &LunExtension->SrbInfo;
+        Srb->SrbExtension = NULL;
+        Srb->QueueTag = SP_UNTAGGED;
     }
 
-  Srb = IrpStack->Parameters.Scsi.Srb;
+    /* FIXME: Increase sequence number here of SRB, if it's ever needed */
 
-  LunExtension = SpiGetLunExtension(DeviceExtension,
-                                   Srb->PathId,
-                                   Srb->TargetId,
-                                   Srb->Lun);
-  if (LunExtension == NULL)
+    /* Check some special SRBs */
+    if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
     {
-      DPRINT("Can't get LunExtension!\n");
-      Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
-      Irp->IoStatus.Information = 0;
-      IoCompleteRequest (Irp,
-                        IO_NO_INCREMENT);
-      if (oldIrql < DISPATCH_LEVEL)
-       {
-         KeRaiseIrql (DISPATCH_LEVEL,
-                      &oldIrql);
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-         KeLowerIrql (oldIrql);
-       }
-      else
-       {
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-       }
-      return;
+        /* Some special handling */
+        DPRINT1("Abort command! Unimplemented now\n");
+    }
+    else
+    {
+        SrbInfo->Srb = Srb;
     }
 
-  Irp->IoStatus.Status = STATUS_SUCCESS;
-  Irp->IoStatus.Information = Srb->DataTransferLength;
+    if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION)
+    {
+        // Store the MDL virtual address in SrbInfo structure
+        SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress);
 
-  DeviceExtension->CurrentIrp = Irp;
+        if (DeviceExtension->MapBuffers && Irp->MdlAddress)
+        {
+            /* Calculate offset within DataBuffer */
+            SrbInfo->DataOffset = MmGetSystemAddressForMdl(Irp->MdlAddress);
+            Srb->DataBuffer = SrbInfo->DataOffset +
+                (ULONG)((PUCHAR)Srb->DataBuffer -
+                (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress));
+        }
 
-  if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
-                             ScsiPortStartPacket,
-                             DeviceExtension))
-    {
-      DPRINT("Synchronization failed!\n");
+        if (DeviceExtension->AdapterObject)
+        {
+            /* Flush buffers */
+            KeFlushIoBuffers(Irp->MdlAddress,
+                             Srb->SrbFlags & SRB_FLAGS_DATA_IN ? TRUE : FALSE,
+                             TRUE);
+        }
 
-      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-      Irp->IoStatus.Information = 0;
-      IoCompleteRequest(Irp,
-                       IO_NO_INCREMENT);
-      if (oldIrql < DISPATCH_LEVEL)
-       {
-         KeRaiseIrql (DISPATCH_LEVEL,
-                      &oldIrql);
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-         KeLowerIrql (oldIrql);
-       }
-      else
-       {
-         IoStartNextPacket (DeviceObject,
-                            FALSE);
-       }
-    }
+        if (DeviceExtension->MapRegisters)
+        {
+#if 0
+            /* Calculate number of needed map registers */
+            SrbInfo->NumberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+                    Srb->DataBuffer,
+                    Srb->DataTransferLength);
+
+            /* Allocate adapter channel */
+            Status = IoAllocateAdapterChannel(DeviceExtension->AdapterObject,
+                                              DeviceExtension->DeviceObject,
+                                              SrbInfo->NumberOfMapRegisters,
+                                              SpiAdapterControl,
+                                              SrbInfo);
+
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("IoAllocateAdapterChannel() failed!\n");
 
-  KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
-  if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
-    {
-      DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
-      IoCompleteRequest(Irp,
-                       IO_NO_INCREMENT);
+                Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+                ScsiPortNotification(RequestComplete,
+                                     DeviceExtension + 1,
+                                     Srb);
+
+                ScsiPortNotification(NextRequest,
+                                     DeviceExtension + 1);
+
+                /* Request DPC for that work */
+                IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
+            }
+
+            /* Control goes to SpiAdapterControl */
+            return;
+#else
+            ASSERT(FALSE);
+#endif
+        }
     }
 
-  if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
+    /* Increase active request counter */
+    CounterResult = InterlockedIncrement(&DeviceExtension->ActiveRequestCounter);
+
+    if (CounterResult == 0 &&
+        DeviceExtension->AdapterObject != NULL &&
+        !DeviceExtension->MapRegisters)
     {
-      DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
-      KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
-      IoStartNextPacket(DeviceObject,
-                       FALSE);
-      KeLowerIrql(oldIrql);
+#if 0
+        IoAllocateAdapterChannel(
+            DeviceExtension->AdapterObject,
+            DeviceObject,
+            DeviceExtension->PortCapabilities.MaximumPhysicalPages,
+            ScsiPortAllocationRoutine,
+            LunExtension
+            );
+
+        return;
+#else
+        /* TODO: DMA is not implemented yet */
+        ASSERT(FALSE);
+#endif
     }
-  else
+
+
+    KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
+
+    if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
+                                ScsiPortStartPacket,
+                                DeviceObject))
     {
-      KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
+        DPRINT("Synchronization failed!\n");
+
+        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+        Irp->IoStatus.Information = 0;
+        KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
+
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
-  DPRINT("ScsiPortStartIo() done\n");
+    KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
+
+    DPRINT("ScsiPortStartIo() done\n");
 }
 
 
 static BOOLEAN STDCALL
 ScsiPortStartPacket(IN OUT PVOID Context)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  PIO_STACK_LOCATION IrpStack;
-  PSCSI_REQUEST_BLOCK Srb;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    PIO_STACK_LOCATION IrpStack;
+    PSCSI_REQUEST_BLOCK Srb;
+    PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)Context;
+    PSCSI_PORT_LUN_EXTENSION LunExtension;
+    BOOLEAN Result;
+    BOOLEAN StartTimer;
+
+    DPRINT("ScsiPortStartPacket() called\n");
 
-  DPRINT("ScsiPortStartPacket() called\n");
+    DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-  DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
+    IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
+    Srb = IrpStack->Parameters.Scsi.Srb;
 
-  IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
-  Srb = IrpStack->Parameters.Scsi.Srb;
+    /* Get LUN extension */
+    LunExtension = SpiGetLunExtension(DeviceExtension,
+                                      Srb->PathId,
+                                      Srb->TargetId,
+                                      Srb->Lun);
 
-  /* Allocte SRB extension */
-  if (DeviceExtension->SrbExtensionSize != 0)
+    /* Check if we are in a reset state */
+    if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
     {
-      Srb->SrbExtension = DeviceExtension->VirtualAddress;
+        /* Mark the we've got requests while being in the reset state */
+        DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET_REQUEST;
+        return TRUE;
     }
 
-  return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
-                                   Srb));
-}
+    /* Set the time out value */
+    DeviceExtension->TimeOutCount = Srb->TimeOutValue;
 
+    /* We are busy */
+    DeviceExtension->Flags |= SCSI_PORT_DEVICE_BUSY;
+
+    if (LunExtension->RequestTimeout != -1)
+    {
+        /* Timer already active */
+        StartTimer = FALSE;
+    }
+    else
+    {
+        /* It hasn't been initialized yet */
+        LunExtension->RequestTimeout = Srb->TimeOutValue;
+        StartTimer = TRUE;
+    }
+
+    if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
+    {
+        /* TODO: Handle bypass-requests */
+        ASSERT(FALSE);
+    }
+    else
+    {
+        if (Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT)
+        {
+            /* It's a disconnect, so no more requests can go */
+            DeviceExtension->Flags &= ~SCSI_PORT_DISCONNECT_IN_PROGRESS;
+        }
+
+        LunExtension->Flags |= SCSI_PORT_LU_ACTIVE;
+
+        /* Increment queue count */
+        LunExtension->QueueCount++;
+
+        /* If it's tagged - special thing */
+        if (Srb->QueueTag != SP_UNTAGGED)
+        {
+            /* TODO: Support tagged requests */
+            ASSERT(FALSE);
+        }
+    }
+
+    /* Mark this Srb active */
+    Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE;
+
+    /* Call HwStartIo routine */
+    Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
+                                             Srb);
+
+    /* If notification is needed, then request a DPC */
+    if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
+        IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
+
+    return Result;
+}
 
 static PSCSI_PORT_LUN_EXTENSION
 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
@@ -1818,6 +1922,9 @@ SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
     /* Initialize a list of requests */
     InitializeListHead(&LunExtension->SrbInfo.Requests);
 
+    /* Initialize timeout counter */
+    LunExtension->RequestTimeout = -1;
+
     /* TODO: Initialize other fields */
 
     /* Initialize request queue */
@@ -2390,29 +2497,31 @@ SpiGetSrbData(IN PVOID DeviceExtension,
 
 static BOOLEAN STDCALL
 ScsiPortIsr(IN PKINTERRUPT Interrupt,
-           IN PVOID ServiceContext)
+            IN PVOID ServiceContext)
 {
-  PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
-  BOOLEAN Result;
+    PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+    BOOLEAN Result;
 
-  DPRINT("ScsiPortIsr() called!\n");
+    DPRINT("ScsiPortIsr() called!\n");
 
-  DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
+    DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
 
-  Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
-  if (Result == FALSE)
-    {
-      return(FALSE);
-    }
+    /* If interrupts are disabled - we don't expect any */
+    if (DeviceExtension->InterruptData.Flags & SCSI_PORT_DISABLE_INTERRUPTS)
+        return FALSE;
 
-  if (DeviceExtension->IrpFlags)
+    /* Call miniport's HwInterrupt routine */
+    Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
+
+    /* If flag of notification is set - queue a DPC */
+    if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
     {
-      IoRequestDpc(DeviceExtension->DeviceObject,
-                  DeviceExtension->CurrentIrp,
-                  DeviceExtension);
+        IoRequestDpc(DeviceExtension->DeviceObject,
+                     DeviceExtension->CurrentIrp,
+                     DeviceExtension);
     }
 
-  return(TRUE);
+    return TRUE;
 }
 
 
@@ -2483,7 +2592,7 @@ ScsiPortDpcForIsr(IN PKDPC Dpc,
          KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
          if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
                                      ScsiPortStartPacket,
-                                     DeviceExtension))
+                                     DpcDeviceObject))
            {
              DPRINT1("Synchronization failed!\n");
 
index e94828c..604f7c4 100644 (file)
 #define LUS_NUMBER 8
 
 /* Flags */
-#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
-#define SCSI_PORT_SCAN_IN_PROGRESS   0x8000
+#define SCSI_PORT_DEVICE_BUSY         0x0001
+#define SCSI_PORT_LU_ACTIVE           0x0002
+#define SCSI_PORT_NOTIFICATION_NEEDED 0x0004
+#define SCSI_PORT_NEXT_REQUEST_READY  0x0008
+#define SCSI_PORT_RESET               0x0080
+#define SCSI_PORT_RESET_REQUEST       0x0100
+#define SCSI_PORT_DISCONNECT_IN_PROGRESS 0x1000
+#define SCSI_PORT_DISABLE_INTERRUPTS  0x4000
+#define SCSI_PORT_SCAN_IN_PROGRESS    0x8000
+
+
+
+
 
 typedef enum _SCSI_PORT_TIMER_STATES
 {
@@ -46,6 +57,7 @@ typedef struct _SCSI_REQUEST_BLOCK_INFO
 {
     LIST_ENTRY Requests;
     PSCSI_REQUEST_BLOCK Srb;
+    PCHAR DataOffset;
     struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
 } SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
 
@@ -65,6 +77,9 @@ typedef struct _SCSI_PORT_LUN_EXTENSION
   INQUIRYDATA InquiryData;
 
   KDEVICE_QUEUE DeviceQueue;
+  ULONG QueueCount;
+
+  LONG RequestTimeout;
 
   SCSI_REQUEST_BLOCK_INFO SrbInfo;
 
@@ -125,6 +140,10 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
   PBUSES_CONFIGURATION_INFORMATION BusesConfig;
   ULONG PortNumber;
 
+  LONG ActiveRequestCounter;
+  ULONG Flags;
+  LONG TimeOutCount;
+
   KSPIN_LOCK IrpLock;
   KSPIN_LOCK SpinLock;
   PKINTERRUPT Interrupt;
@@ -158,10 +177,15 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
   /* DMA related stuff */
   PADAPTER_OBJECT AdapterObject;
   ULONG MapRegisterCount;
+  BOOLEAN MapBuffers;
+  BOOLEAN MapRegisters;
 
   PHYSICAL_ADDRESS PhysicalAddress;
   PVOID VirtualAddress;
   ULONG CommonBufferLength;
 
+  BOOLEAN NeedSrbExtensionAlloc;
+  BOOLEAN NeedSrbDataAlloc;
+
   UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
 } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;