Author: fireball
Date: Wed Mar 28 22:29:15 2007
New Revision: 26196
URL:
http://svn.reactos.org/svn/reactos?rev=26196&view=rev
Log:
- Rearrange code inside ScsiPortStartIo() routine (some code for dma-support added, but
currently disabled), also change time when spinlock is being held.
- 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).
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 22:29:15 2007
@@ -885,6 +885,9 @@
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 @@
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;
-
- DPRINT("ScsiPortStartIo() called!\n");
-
- DeviceExtension = DeviceObject->DeviceExtension;
- IrpStack = IoGetCurrentIrpStackLocation(Irp);
-
- DPRINT("DeviceExtension %p\n", DeviceExtension);
-
- oldIrql = KeGetCurrentIrql();
-
- if (IrpStack->MajorFunction != IRP_MJ_SCSI)
- {
- 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;
- }
-
- Srb = IrpStack->Parameters.Scsi.Srb;
-
- LunExtension = SpiGetLunExtension(DeviceExtension,
- Srb->PathId,
- Srb->TargetId,
- Srb->Lun);
- if (LunExtension == NULL)
- {
- 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;
- }
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Srb->DataTransferLength;
-
- DeviceExtension->CurrentIrp = Irp;
-
- if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
- ScsiPortStartPacket,
- DeviceExtension))
- {
- DPRINT("Synchronization failed!\n");
-
- 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);
- }
- }
-
- KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
- if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
- IoCompleteRequest(Irp,
- IO_NO_INCREMENT);
- }
-
- if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
- {
- DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
- KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
- IoStartNextPacket(DeviceObject,
- FALSE);
- KeLowerIrql(oldIrql);
- }
- else
- {
- KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
- }
-
- DPRINT("ScsiPortStartIo() done\n");
+ 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");
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+ IrpStack = IoGetCurrentIrpStackLocation(Irp);
+
+ DPRINT("DeviceExtension %p\n", DeviceExtension);
+
+ Srb = IrpStack->Parameters.Scsi.Srb;
+
+ /* FIXME: Apply standard flags to Srb->SrbFlags ? */
+
+ /* Get LUN extension */
+ LunExtension = SpiGetLunExtension(DeviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun);
+
+ if (DeviceExtension->NeedSrbDataAlloc ||
+ DeviceExtension->NeedSrbExtensionAlloc)
+ {
+ /* TODO: Implement */
+ ASSERT(FALSE);
+ SrbInfo = NULL;
+ }
+ else
+ {
+ /* No allocations are needed */
+ SrbInfo = &LunExtension->SrbInfo;
+ Srb->SrbExtension = NULL;
+ Srb->QueueTag = SP_UNTAGGED;
+ }
+
+ /* FIXME: Increase sequence number here of SRB, if it's ever needed */
+
+ /* Check some special SRBs */
+ if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
+ {
+ /* Some special handling */
+ DPRINT1("Abort command! Unimplemented now\n");
+ }
+ else
+ {
+ SrbInfo->Srb = Srb;
+ }
+
+ if (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION)
+ {
+ // Store the MDL virtual address in SrbInfo structure
+ SrbInfo->DataOffset = MmGetMdlVirtualAddress(Irp->MdlAddress);
+
+ 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 (DeviceExtension->AdapterObject)
+ {
+ /* Flush buffers */
+ KeFlushIoBuffers(Irp->MdlAddress,
+ Srb->SrbFlags & SRB_FLAGS_DATA_IN ? TRUE : FALSE,
+ TRUE);
+ }
+
+ 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");
+
+ 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
+ }
+ }
+
+ /* Increase active request counter */
+ CounterResult = InterlockedIncrement(&DeviceExtension->ActiveRequestCounter);
+
+ if (CounterResult == 0 &&
+ DeviceExtension->AdapterObject != NULL &&
+ !DeviceExtension->MapRegisters)
+ {
+#if 0
+ IoAllocateAdapterChannel(
+ DeviceExtension->AdapterObject,
+ DeviceObject,
+ DeviceExtension->PortCapabilities.MaximumPhysicalPages,
+ ScsiPortAllocationRoutine,
+ LunExtension
+ );
+
+ return;
+#else
+ /* TODO: DMA is not implemented yet */
+ ASSERT(FALSE);
+#endif
+ }
+
+
+ KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
+
+ if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
+ ScsiPortStartPacket,
+ DeviceObject))
+ {
+ DPRINT("Synchronization failed!\n");
+
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+ Irp->IoStatus.Information = 0;
+ KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ 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;
-
- DPRINT("ScsiPortStartPacket() called\n");
-
- DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
-
- IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
- Srb = IrpStack->Parameters.Scsi.Srb;
-
- /* Allocte SRB extension */
- if (DeviceExtension->SrbExtensionSize != 0)
- {
- Srb->SrbExtension = DeviceExtension->VirtualAddress;
- }
-
- return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
- 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");
+
+ DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ IrpStack = IoGetCurrentIrpStackLocation(DeviceObject->CurrentIrp);
+ Srb = IrpStack->Parameters.Scsi.Srb;
+
+ /* Get LUN extension */
+ LunExtension = SpiGetLunExtension(DeviceExtension,
+ Srb->PathId,
+ Srb->TargetId,
+ Srb->Lun);
+
+ /* Check if we are in a reset state */
+ if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
+ {
+ /* Mark the we've got requests while being in the reset state */
+ DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET_REQUEST;
+ return TRUE;
+ }
+
+ /* 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)
@@ -1817,6 +1921,9 @@
/* Initialize a list of requests */
InitializeListHead(&LunExtension->SrbInfo.Requests);
+
+ /* Initialize timeout counter */
+ LunExtension->RequestTimeout = -1;
/* TODO: Initialize other fields */
@@ -2390,29 +2497,31 @@
static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt,
- IN PVOID ServiceContext)
-{
- PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
- BOOLEAN Result;
-
- DPRINT("ScsiPortIsr() called!\n");
-
- DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
-
- Result =
DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
- if (Result == FALSE)
- {
- return(FALSE);
- }
-
- if (DeviceExtension->IrpFlags)
- {
- IoRequestDpc(DeviceExtension->DeviceObject,
- DeviceExtension->CurrentIrp,
- DeviceExtension);
- }
-
- return(TRUE);
+ IN PVOID ServiceContext)
+{
+ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
+ BOOLEAN Result;
+
+ DPRINT("ScsiPortIsr() called!\n");
+
+ DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
+
+ /* If interrupts are disabled - we don't expect any */
+ if (DeviceExtension->InterruptData.Flags & SCSI_PORT_DISABLE_INTERRUPTS)
+ return FALSE;
+
+ /* 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);
+ }
+
+ return TRUE;
}
@@ -2483,7 +2592,7 @@
KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
ScsiPortStartPacket,
- DeviceExtension))
+ DpcDeviceObject))
{
DPRINT1("Synchronization failed!\n");
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 22:29:15 2007
@@ -20,8 +20,19 @@
#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 @@
{
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 @@
INQUIRYDATA InquiryData;
KDEVICE_QUEUE DeviceQueue;
+ ULONG QueueCount;
+
+ LONG RequestTimeout;
SCSI_REQUEST_BLOCK_INFO SrbInfo;
@@ -125,6 +140,10 @@
PBUSES_CONFIGURATION_INFORMATION BusesConfig;
ULONG PortNumber;
+ LONG ActiveRequestCounter;
+ ULONG Flags;
+ LONG TimeOutCount;
+
KSPIN_LOCK IrpLock;
KSPIN_LOCK SpinLock;
PKINTERRUPT Interrupt;
@@ -158,10 +177,15 @@
/* 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;