- 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.

svn path=/trunk/; revision=26192
This commit is contained in:
Aleksey Bragin 2007-03-28 10:41:03 +00:00
parent 24387402f3
commit ce0e0958b4
2 changed files with 217 additions and 120 deletions

View file

@ -41,9 +41,6 @@
#include "scsiport_int.h" #include "scsiport_int.h"
/* #define USE_DEVICE_QUEUES */
/* TYPES *********************************************************************/ /* TYPES *********************************************************************/
#define IRP_FLAG_COMPLETE 0x00000001 #define IRP_FLAG_COMPLETE 0x00000001
@ -99,6 +96,13 @@ static NTSTATUS
SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
IN PIRP Irp); 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 static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt, ScsiPortIsr(IN PKINTERRUPT Interrupt,
IN PVOID ServiceContext); IN PVOID ServiceContext);
@ -1091,17 +1095,60 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
case RequestComplete: case RequestComplete:
{ {
PSCSI_REQUEST_BLOCK Srb; PSCSI_REQUEST_BLOCK Srb;
PSCSI_REQUEST_BLOCK_INFO SrbData;
Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK); Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
DPRINT("Notify: RequestComplete (Srb %p)\n", Srb); DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE; // 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; break;
case NextRequest: case NextRequest:
DPRINT("Notify: NextRequest\n"); DPRINT("Notify: NextRequest\n");
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT; DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
break; break;
case NextLuRequest: case NextLuRequest:
@ -1386,7 +1433,6 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
PSCSI_REQUEST_BLOCK Srb; PSCSI_REQUEST_BLOCK Srb;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
ULONG DataSize = 0;
DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
DeviceObject, Irp); DeviceObject, Irp);
@ -1397,6 +1443,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
Srb = Stack->Parameters.Scsi.Srb; Srb = Stack->Parameters.Scsi.Srb;
if (Srb == NULL) if (Srb == NULL)
{ {
DPRINT1("ScsiPortDispatchScsi() called with Srb = NULL!\n");
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
@ -1417,6 +1464,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
Srb->Lun); Srb->Lun);
if (LunExtension == NULL) if (LunExtension == NULL)
{ {
DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
Status = STATUS_NO_SUCH_DEVICE; Status = STATUS_NO_SUCH_DEVICE;
Srb->SrbStatus = SRB_STATUS_NO_DEVICE; Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
@ -1430,52 +1478,56 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
switch (Srb->Function) 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_EXECUTE_SCSI:
case SRB_FUNCTION_IO_CONTROL: case SRB_FUNCTION_IO_CONTROL:
#ifdef USE_DEVICE_QUEUES /* Mark IRP as pending in all cases */
IoMarkIrpPending(Irp);
if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE) if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
{ {
IoMarkIrpPending(Irp); /* Start IO directly */
IoStartPacket (DeviceObject, Irp, NULL, NULL); IoStartPacket(DeviceObject, Irp, NULL, NULL);
} }
else else
{ {
KIRQL oldIrql; KIRQL oldIrql;
KeRaiseIrql (DISPATCH_LEVEL, /* We need to be at DISPATCH_LEVEL */
&oldIrql); KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
/* Insert IRP into the queue */
if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue, if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
&Irp->Tail.Overlay.DeviceQueueEntry, &Irp->Tail.Overlay.DeviceQueueEntry,
Srb->QueueSortKey)) Srb->QueueSortKey))
{ {
Srb->SrbStatus = SRB_STATUS_SUCCESS; /* It means queue is empty, and we just start this request */
IoMarkIrpPending(Irp); IoStartPacket(DeviceObject, Irp, NULL, NULL);
IoStartPacket (DeviceObject, Irp, NULL, NULL);
} }
/* Back to the old IRQL */
KeLowerIrql (oldIrql); KeLowerIrql (oldIrql);
} }
#else return STATUS_PENDING;
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: case SRB_FUNCTION_CLAIM_DEVICE:
DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n"); case SRB_FUNCTION_ATTACH_DEVICE:
DPRINT (" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n");
/* Reference device object and keep the device object */ /* Reference device object and keep the device object */
/* TODO: Check if it's OK */
ObReferenceObject(DeviceObject); ObReferenceObject(DeviceObject);
LunExtension->DeviceObject = DeviceObject; LunExtension->DeviceObject = DeviceObject;
LunExtension->DeviceClaimed = TRUE; LunExtension->DeviceClaimed = TRUE;
@ -1484,6 +1536,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
case SRB_FUNCTION_RELEASE_DEVICE: case SRB_FUNCTION_RELEASE_DEVICE:
DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n"); DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
/* TODO: Check if it's OK */
DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n", DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
Srb->PathId, Srb->TargetId, Srb->Lun); Srb->PathId, Srb->TargetId, Srb->Lun);
@ -1500,7 +1553,6 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
} }
Irp->IoStatus.Status = Status; Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = DataSize;
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
@ -2304,6 +2356,37 @@ SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
return STATUS_SUCCESS; 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 static BOOLEAN STDCALL
ScsiPortIsr(IN PKINTERRUPT Interrupt, ScsiPortIsr(IN PKINTERRUPT Interrupt,

View file

@ -20,6 +20,7 @@
#define LUS_NUMBER 8 #define LUS_NUMBER 8
/* Flags */ /* Flags */
#define SCSI_PORT_NEXT_REQUEST_READY 0x0008
#define SCSI_PORT_SCAN_IN_PROGRESS 0x8000 #define SCSI_PORT_SCAN_IN_PROGRESS 0x8000
typedef enum _SCSI_PORT_TIMER_STATES typedef enum _SCSI_PORT_TIMER_STATES
@ -44,6 +45,8 @@ typedef struct _SCSI_PORT_DEVICE_BASE
typedef struct _SCSI_REQUEST_BLOCK_INFO typedef struct _SCSI_REQUEST_BLOCK_INFO
{ {
LIST_ENTRY Requests; LIST_ENTRY Requests;
PSCSI_REQUEST_BLOCK Srb;
struct _SCSI_REQUEST_BLOCK_INFO *CompletedRequests;
} SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO; } SCSI_REQUEST_BLOCK_INFO, *PSCSI_REQUEST_BLOCK_INFO;
typedef struct _SCSI_PORT_LUN_EXTENSION typedef struct _SCSI_PORT_LUN_EXTENSION
@ -97,6 +100,15 @@ typedef struct _BUSES_CONFIGURATION_INFORMATION
PSCSI_BUS_SCAN_INFO BusScanInfo[1]; PSCSI_BUS_SCAN_INFO BusScanInfo[1];
} BUSES_CONFIGURATION_INFORMATION, *PBUSES_CONFIGURATION_INFORMATION; } 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 * SCSI_PORT_DEVICE_EXTENSION
* *
@ -127,6 +139,8 @@ typedef struct _SCSI_PORT_DEVICE_EXTENSION
ULONG LunExtensionSize; ULONG LunExtensionSize;
PSCSI_PORT_LUN_EXTENSION LunExtensionList[LUS_NUMBER]; PSCSI_PORT_LUN_EXTENSION LunExtensionList[LUS_NUMBER];
SCSI_PORT_INTERRUPT_DATA InterruptData;
ULONG SrbExtensionSize; ULONG SrbExtensionSize;
PIO_SCSI_CAPABILITIES PortCapabilities; PIO_SCSI_CAPABILITIES PortCapabilities;