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;