mirror of
https://github.com/reactos/reactos.git
synced 2024-10-06 09:24:11 +00:00
- Move IopInitialize/StartDevice to PnP Manager
- I/O Packet APIs fixes Part 1: - Clear the current IRP before parsing the Device Queues - Respect Cancelable parameter in IoStartNextPacket(ByKey) instead of ignoring it (acquire the cancel lock when it's requested) - Raise IRQL to DISPATCH_LEVEL in IoStartPacket instead of expecting the caller to do it and crashing. Also only use Cancel Lock if a Cancel Function was specified. - Actually handle the case where the IRP Was cancelled right after insert and the Cancel Routine has to be called. svn path=/trunk/; revision=22744
This commit is contained in:
parent
036139907e
commit
51989fa847
|
@ -82,111 +82,6 @@ IoShutdownRegisteredDevices(VOID)
|
|||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
IopInitializeDevice(PDEVICE_NODE DeviceNode,
|
||||
PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN IsPnpDriver = FALSE;
|
||||
|
||||
if (DriverObject->DriverExtension->AddDevice)
|
||||
{
|
||||
/* This is a Plug and Play driver */
|
||||
DPRINT("Plug and Play driver found\n");
|
||||
|
||||
ASSERT(DeviceNode->PhysicalDeviceObject);
|
||||
|
||||
DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
|
||||
DriverObject->DriverExtension->AddDevice);
|
||||
|
||||
IsPnpDriver = !IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER);
|
||||
Status = DriverObject->DriverExtension->AddDevice(
|
||||
DriverObject, IsPnpDriver ? DeviceNode->PhysicalDeviceObject : NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IsPnpDriver)
|
||||
{
|
||||
Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
|
||||
|
||||
if (Fdo == DeviceNode->PhysicalDeviceObject)
|
||||
{
|
||||
/* FIXME: What do we do? Unload the driver or just disable the device? */
|
||||
DbgPrint("An FDO was not attached\n");
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (Fdo->DeviceType == FILE_DEVICE_ACPI)
|
||||
{
|
||||
static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
|
||||
|
||||
/* There can be only one system power device */
|
||||
if (!SystemPowerDeviceNodeCreated)
|
||||
{
|
||||
PopSystemPowerDeviceNode = DeviceNode;
|
||||
SystemPowerDeviceNodeCreated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Fdo);
|
||||
}
|
||||
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
IopStartDevice(
|
||||
PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
IO_STACK_LOCATION Stack;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
|
||||
|
||||
Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
|
||||
Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList;
|
||||
Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated;
|
||||
|
||||
Status = IopInitiatePnpIrp(
|
||||
Fdo,
|
||||
&IoStatusBlock,
|
||||
IRP_MN_START_DEVICE,
|
||||
&Stack);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IopInitiatePnpIrp() failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY))
|
||||
{
|
||||
DPRINT("Device needs enumeration, invalidating bus relations\n");
|
||||
Status = IopInvalidateDeviceRelations(DeviceNode, BusRelations);
|
||||
IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Fdo);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
DeviceNode->Flags |= DN_STARTED;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName,
|
||||
|
@ -1247,137 +1142,157 @@ IoSetStartIoAttributes(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Dequeues the next packet from the given device object's
|
||||
* associated device queue according to a specified sort-key value and calls
|
||||
* the drivers StartIo routine with that IRP
|
||||
* ARGUMENTS:
|
||||
* DeviceObject = Device object for which the irp is to dequeued
|
||||
* Cancelable = True if IRPs in the key can be canceled
|
||||
* Key = Sort key specifing which entry to remove from the queue
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
IoStartNextPacketByKey(PDEVICE_OBJECT DeviceObject,
|
||||
BOOLEAN Cancelable,
|
||||
ULONG Key)
|
||||
NTAPI
|
||||
IoStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN BOOLEAN Cancelable,
|
||||
IN ULONG Key)
|
||||
{
|
||||
PKDEVICE_QUEUE_ENTRY entry;
|
||||
PKDEVICE_QUEUE_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
KIRQL OldIrql;
|
||||
|
||||
entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
Key);
|
||||
/* Acquire the cancel lock if this is cancelable */
|
||||
if (Cancelable) IoAcquireCancelSpinLock(&OldIrql);
|
||||
|
||||
if (entry != NULL)
|
||||
/* Clear the current IRP */
|
||||
DeviceObject->CurrentIrp = NULL;
|
||||
|
||||
/* Remove an entry from the queue */
|
||||
Entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, Key);
|
||||
if (Entry)
|
||||
{
|
||||
Irp = CONTAINING_RECORD(entry,
|
||||
IRP,
|
||||
Tail.Overlay.DeviceQueueEntry);
|
||||
/* Get the IRP and set it */
|
||||
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
|
||||
DeviceObject->CurrentIrp = Irp;
|
||||
DPRINT("Next irp is 0x%p\n", Irp);
|
||||
|
||||
/* Release the cancel lock if we had acquired it */
|
||||
if (Cancelable) IoReleaseCancelSpinLock(OldIrql);
|
||||
|
||||
/* Call the Start I/O Routine */
|
||||
DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("No next irp\n");
|
||||
DeviceObject->CurrentIrp = NULL;
|
||||
/* Otherwise, release the cancel lock if we had acquired it */
|
||||
if (Cancelable) IoReleaseCancelSpinLock(OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Removes the next packet from the device's queue and calls
|
||||
* the driver's StartIO
|
||||
* ARGUMENTS:
|
||||
* DeviceObject = Device
|
||||
* Cancelable = True if irps in the queue can be canceled
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
IoStartNextPacket(PDEVICE_OBJECT DeviceObject,
|
||||
BOOLEAN Cancelable)
|
||||
NTAPI
|
||||
IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN BOOLEAN Cancelable)
|
||||
{
|
||||
PKDEVICE_QUEUE_ENTRY entry;
|
||||
PKDEVICE_QUEUE_ENTRY Entry;
|
||||
PIRP Irp;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINT("IoStartNextPacket(DeviceObject 0x%p, Cancelable %d)\n",
|
||||
DeviceObject, Cancelable);
|
||||
/* Acquire the cancel lock if this is cancelable */
|
||||
if (Cancelable) IoAcquireCancelSpinLock(&OldIrql);
|
||||
|
||||
entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
|
||||
/* Clear the current IRP */
|
||||
DeviceObject->CurrentIrp = NULL;
|
||||
|
||||
if (entry!=NULL)
|
||||
/* Remove an entry from the queue */
|
||||
Entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
|
||||
if (Entry)
|
||||
{
|
||||
Irp = CONTAINING_RECORD(entry,IRP,Tail.Overlay.DeviceQueueEntry);
|
||||
/* Get the IRP and set it */
|
||||
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
|
||||
DeviceObject->CurrentIrp = Irp;
|
||||
|
||||
/* Call the Start I/O Routine */
|
||||
DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceObject->CurrentIrp = NULL;
|
||||
/* Otherwise, release the cancel lock if we had acquired it */
|
||||
if (Cancelable) IoReleaseCancelSpinLock(OldIrql);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*
|
||||
* FUNCTION: Either call the device's StartIO routine with the packet or,
|
||||
* if the device is busy, queue it.
|
||||
* ARGUMENTS:
|
||||
* DeviceObject = Device to start the packet on
|
||||
* Irp = Irp to queue
|
||||
* Key = Where to insert the irp
|
||||
* If zero then insert in the tail of the queue
|
||||
* CancelFunction = Optional function to cancel the irqp
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
IoStartPacket(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PULONG Key,
|
||||
PDRIVER_CANCEL CancelFunction)
|
||||
NTAPI
|
||||
IoStartPacket(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
IN PULONG Key,
|
||||
IN PDRIVER_CANCEL CancelFunction)
|
||||
{
|
||||
BOOLEAN stat;
|
||||
KIRQL oldirql;
|
||||
BOOLEAN Stat;
|
||||
KIRQL OldIrql, CancelIrql;
|
||||
|
||||
DPRINT("IoStartPacket(Irp 0x%p)\n", Irp);
|
||||
/* Raise to dispatch level */
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||
|
||||
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||
|
||||
IoAcquireCancelSpinLock(&oldirql);
|
||||
|
||||
if (CancelFunction != NULL)
|
||||
/* Check if we should acquire the cancel lock */
|
||||
if (CancelFunction)
|
||||
{
|
||||
/* Acquire and set it */
|
||||
IoAcquireCancelSpinLock(&CancelIrql);
|
||||
Irp->CancelRoutine = CancelFunction;
|
||||
}
|
||||
|
||||
if (Key!=0)
|
||||
/* Check if we have a key */
|
||||
if (Key)
|
||||
{
|
||||
stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
/* Insert by key */
|
||||
Stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
&Irp->Tail.Overlay.DeviceQueueEntry,
|
||||
*Key);
|
||||
}
|
||||
else
|
||||
{
|
||||
stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
/* Insert without a key */
|
||||
Stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
&Irp->Tail.Overlay.DeviceQueueEntry);
|
||||
}
|
||||
|
||||
|
||||
if (!stat)
|
||||
/* Check if this was a first insert */
|
||||
if (!Stat)
|
||||
{
|
||||
IoReleaseCancelSpinLock(DISPATCH_LEVEL);
|
||||
/* Set the IRP */
|
||||
DeviceObject->CurrentIrp = Irp;
|
||||
|
||||
/* Release the cancel lock if we had a cancel function */
|
||||
if (CancelFunction) IoReleaseCancelSpinLock(CancelIrql);
|
||||
|
||||
/* Call the Start I/O function */
|
||||
DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
|
||||
if (oldirql < DISPATCH_LEVEL)
|
||||
{
|
||||
KeLowerIrql(oldirql);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IoReleaseCancelSpinLock(oldirql);
|
||||
/* The packet was inserted... check if we have a cancel function */
|
||||
if (CancelFunction)
|
||||
{
|
||||
/* Check if the IRP got cancelled */
|
||||
if (Irp->Cancel)
|
||||
{
|
||||
/*
|
||||
* Set the cancel IRQL, clear the currnet cancel routine and
|
||||
* call ours
|
||||
*/
|
||||
Irp->CancelIrql = CancelIrql;
|
||||
Irp->CancelRoutine = NULL;
|
||||
CancelFunction(DeviceObject, Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, release the lock */
|
||||
IoReleaseCancelSpinLock(CancelIrql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return back to previous IRQL */
|
||||
KeLowerIrql(OldIrql);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -44,6 +44,111 @@ IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
|
|||
return ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FASTCALL
|
||||
IopInitializeDevice(PDEVICE_NODE DeviceNode,
|
||||
PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
BOOLEAN IsPnpDriver = FALSE;
|
||||
|
||||
if (DriverObject->DriverExtension->AddDevice)
|
||||
{
|
||||
/* This is a Plug and Play driver */
|
||||
DPRINT("Plug and Play driver found\n");
|
||||
|
||||
ASSERT(DeviceNode->PhysicalDeviceObject);
|
||||
|
||||
DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
|
||||
DriverObject->DriverExtension->AddDevice);
|
||||
|
||||
IsPnpDriver = !IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER);
|
||||
Status = DriverObject->DriverExtension->AddDevice(
|
||||
DriverObject, IsPnpDriver ? DeviceNode->PhysicalDeviceObject : NULL);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (IsPnpDriver)
|
||||
{
|
||||
Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
|
||||
|
||||
if (Fdo == DeviceNode->PhysicalDeviceObject)
|
||||
{
|
||||
/* FIXME: What do we do? Unload the driver or just disable the device? */
|
||||
DbgPrint("An FDO was not attached\n");
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (Fdo->DeviceType == FILE_DEVICE_ACPI)
|
||||
{
|
||||
static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
|
||||
|
||||
/* There can be only one system power device */
|
||||
if (!SystemPowerDeviceNodeCreated)
|
||||
{
|
||||
PopSystemPowerDeviceNode = DeviceNode;
|
||||
SystemPowerDeviceNodeCreated = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Fdo);
|
||||
}
|
||||
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
|
||||
IopDeviceNodeSetFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
IopStartDevice(
|
||||
PDEVICE_NODE DeviceNode)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
IO_STACK_LOCATION Stack;
|
||||
PDEVICE_OBJECT Fdo;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Sending IRP_MN_START_DEVICE to driver\n");
|
||||
|
||||
Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
|
||||
Stack.Parameters.StartDevice.AllocatedResources = DeviceNode->ResourceList;
|
||||
Stack.Parameters.StartDevice.AllocatedResourcesTranslated = DeviceNode->ResourceListTranslated;
|
||||
|
||||
Status = IopInitiatePnpIrp(
|
||||
Fdo,
|
||||
&IoStatusBlock,
|
||||
IRP_MN_START_DEVICE,
|
||||
&Stack);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IopInitiatePnpIrp() failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY))
|
||||
{
|
||||
DPRINT("Device needs enumeration, invalidating bus relations\n");
|
||||
Status = IopInvalidateDeviceRelations(DeviceNode, BusRelations);
|
||||
IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
ObDereferenceObject(Fdo);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
DeviceNode->Flags |= DN_STARTED;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
|
||||
|
|
Loading…
Reference in a new issue