- Move handlers of SRB_FUNCTION_ATTACH and RELEASE to a standalone function, and don't do reference/dereference of the DeviceObject

- Implement RELEASE_QUEUE and FLUSH_QUEUE srb functions
- Turn off DPRINTs, since scsiport seems to finally work (without advanced features, but enough to install and boot using ATAPI and DISK drivers)!

svn path=/trunk/; revision=26226
This commit is contained in:
Aleksey Bragin 2007-04-01 12:13:55 +00:00
parent 01da330bc2
commit 1d3fb59485

View file

@ -37,18 +37,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
//#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "scsiport_int.h" #include "scsiport_int.h"
ULONG InternalDebugLevel = 0;
/* TYPES *********************************************************************/ /* TYPES *********************************************************************/
#define IRP_FLAG_COMPLETE 0x00000001
#define IRP_FLAG_NEXT 0x00000002
#define IRP_FLAG_NEXT_LU 0x00000004
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
static BOOLEAN static BOOLEAN
@ -201,6 +198,10 @@ SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
static VOID static VOID
SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension); SpiCleanupAfterInit(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
static NTSTATUS
SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP Irp);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -265,19 +266,17 @@ ScsiDebugPrint(IN ULONG DebugPrintLevel,
IN PCHAR DebugMessage, IN PCHAR DebugMessage,
...) ...)
{ {
char Buffer[256]; char Buffer[256];
va_list ap; va_list ap;
#if 0 if (DebugPrintLevel > InternalDebugLevel)
if (DebugPrintLevel > InternalDebugLevel) return;
return;
#endif
va_start(ap, DebugMessage); va_start(ap, DebugMessage);
vsprintf(Buffer, DebugMessage, ap); vsprintf(Buffer, DebugMessage, ap);
va_end(ap); va_end(ap);
DbgPrint(Buffer); DbgPrint(Buffer);
} }
@ -1726,12 +1725,13 @@ ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n", DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
PathId, TargetId, Lun); PathId, TargetId, Lun);
/* FIXME: Implement it! */ /* FIXME: Implement it! */
ASSERT(FALSE);
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT; // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
// DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU; // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
/* Hack! */ /* Hack! */
DeviceExtension->IrpFlags |= IRP_FLAG_NEXT; // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
} }
break; break;
@ -2186,6 +2186,88 @@ ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
static NTSTATUS
SpiHandleAttachRelease(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
PIRP Irp)
{
PSCSI_LUN_INFO LunInfo;
PIO_STACK_LOCATION IrpStack;
PDEVICE_OBJECT DeviceObject;
PSCSI_REQUEST_BLOCK Srb;
KIRQL Irql;
/* Get pointer to the SRB */
IrpStack = IoGetCurrentIrpStackLocation(Irp);
Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
/* Check if PathId matches number of buses */
if (DeviceExtension->BusesConfig == NULL ||
DeviceExtension->BusesConfig->NumberOfBuses <= Srb->PathId)
{
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
return STATUS_DEVICE_DOES_NOT_EXIST;
}
/* Get pointer to LunInfo */
LunInfo = DeviceExtension->BusesConfig->BusScanInfo[Srb->PathId]->LunInfo;
/* Find matching LunInfo */
while (LunInfo)
{
if (LunInfo->PathId == Srb->PathId &&
LunInfo->TargetId == Srb->TargetId &&
LunInfo->Lun == Srb->Lun)
{
break;
}
LunInfo = LunInfo->Next;
}
/* If we couldn't find it - exit */
if (LunInfo == NULL)
return STATUS_DEVICE_DOES_NOT_EXIST;
/* Get spinlock */
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
/* Release, if asked */
if (Srb->Function == SRB_FUNCTION_RELEASE_DEVICE)
{
LunInfo->DeviceClaimed = FALSE;
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
return STATUS_SUCCESS;
}
/* Attach, if not already claimed */
if (LunInfo->DeviceClaimed)
{
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
Srb->SrbStatus = SRB_STATUS_BUSY;
return STATUS_DEVICE_BUSY;
}
/* Save the device object */
DeviceObject = LunInfo->DeviceObject;
if (Srb->Function == SRB_FUNCTION_CLAIM_DEVICE)
LunInfo->DeviceClaimed = TRUE;
if (Srb->Function == SRB_FUNCTION_ATTACH_DEVICE)
LunInfo->DeviceObject = Srb->DataBuffer;
Srb->DataBuffer = DeviceObject;
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
return STATUS_SUCCESS;
}
/********************************************************************** /**********************************************************************
* NAME INTERNAL * NAME INTERNAL
@ -2212,7 +2294,10 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
PSCSI_PORT_LUN_EXTENSION LunExtension; PSCSI_PORT_LUN_EXTENSION LunExtension;
PIO_STACK_LOCATION Stack; PIO_STACK_LOCATION Stack;
PSCSI_REQUEST_BLOCK Srb; PSCSI_REQUEST_BLOCK Srb;
KIRQL Irql;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PIRP NextIrp, IrpList;
PKDEVICE_QUEUE_ENTRY Entry;
DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n", DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
DeviceObject, Irp); DeviceObject, Irp);
@ -2239,9 +2324,9 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun); DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
LunExtension = SpiGetLunExtension(DeviceExtension, LunExtension = SpiGetLunExtension(DeviceExtension,
Srb->PathId, Srb->PathId,
Srb->TargetId, Srb->TargetId,
Srb->Lun); Srb->Lun);
if (LunExtension == NULL) if (LunExtension == NULL)
{ {
DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n"); DPRINT("ScsiPortDispatchScsi() called with an invalid LUN\n");
@ -2261,7 +2346,7 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
case SRB_FUNCTION_SHUTDOWN: case SRB_FUNCTION_SHUTDOWN:
case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_FLUSH:
DPRINT (" SRB_FUNCTION_SHUTDOWN or FLUSH\n"); DPRINT (" SRB_FUNCTION_SHUTDOWN or FLUSH\n");
if (DeviceExtension->PortConfig->CachesData == FALSE) if (DeviceExtension->CachesData == FALSE)
{ {
/* All success here */ /* All success here */
Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->SrbStatus = SRB_STATUS_SUCCESS;
@ -2289,11 +2374,11 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
KeRaiseIrql (DISPATCH_LEVEL, &oldIrql); KeRaiseIrql (DISPATCH_LEVEL, &oldIrql);
/* Insert IRP into the queue */ /* 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))
{ {
/* It means queue is empty, and we just start this request */ /* It means the queue is empty, and we just start this request */
IoStartPacket(DeviceObject, Irp, NULL, NULL); IoStartPacket(DeviceObject, Irp, NULL, NULL);
} }
@ -2307,23 +2392,106 @@ ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
DPRINT (" SRB_FUNCTION_CLAIM_DEVICE or ATTACH\n"); 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 */ Status = SpiHandleAttachRelease(DeviceExtension, Irp);
ObReferenceObject(DeviceObject);
LunExtension->DeviceObject = DeviceObject;
LunExtension->DeviceClaimed = TRUE;
Srb->DataBuffer = DeviceObject;
break; break;
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",
Srb->PathId, Srb->TargetId, Srb->Lun);
/* Dereference device object and clear the device object */ /* Dereference device object and clear the device object */
ObDereferenceObject(LunExtension->DeviceObject); Status = SpiHandleAttachRelease(DeviceExtension, Irp);
LunExtension->DeviceObject = NULL; break;
LunExtension->DeviceClaimed = FALSE;
case SRB_FUNCTION_RELEASE_QUEUE:
DPRINT(" SRB_FUNCTION_RELEASE_QUEUE\n");
/* Guard with the spinlock */
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
if (!(LunExtension->Flags & LUNEX_FROZEN_QUEUE))
{
DPRINT("Queue is not frozen really\n");
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
Status = STATUS_SUCCESS;
break;
}
/* Unfreeze the queue */
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
if (LunExtension->SrbInfo.Srb == NULL)
{
/* Get next logical unit request */
SpiGetNextRequestFromLun(DeviceExtension, LunExtension);
KeLowerIrql(Irql);
}
else
{
DPRINT("The queue has active request\n");
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
}
Srb->SrbStatus = SRB_STATUS_SUCCESS;
Status = STATUS_SUCCESS;
break;
case SRB_FUNCTION_FLUSH_QUEUE:
DPRINT(" SRB_FUNCTION_FLUSH_QUEUE\n");
/* Guard with the spinlock */
KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
if (!(LunExtension->Flags & LUNEX_FROZEN_QUEUE))
{
DPRINT("Queue is not frozen really\n");
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
/* Make sure there is no active request */
ASSERT(LunExtension->SrbInfo.Srb == NULL);
/* Compile a list from the device queue */
IrpList = NULL;
while ((Entry = KeRemoveDeviceQueue(&LunExtension->DeviceQueue)) != NULL)
{
NextIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
/* Get the Srb */
Stack = IoGetCurrentIrpStackLocation(NextIrp);
Srb = Stack->Parameters.Scsi.Srb;
/* Set statuse */
Srb->SrbStatus = SRB_STATUS_REQUEST_FLUSHED;
NextIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
/* Add then to the list */
NextIrp->Tail.Overlay.ListEntry.Flink = (PLIST_ENTRY)IrpList;
IrpList = NextIrp;
}
/* Unfreeze the queue */
LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
/* Release the spinlock */
KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
/* Complete those requests */
while (IrpList)
{
NextIrp = IrpList;
IrpList = (PIRP)NextIrp->Tail.Overlay.ListEntry.Flink;
IoCompleteRequest(NextIrp, 0);
}
Status = STATUS_SUCCESS;
break; break;
default: default: