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-ne... ============================================================================== --- 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-ne... ============================================================================== --- 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;