Author: ion
Date: Sat Jul 1 22:56:09 2006
New Revision: 22744
URL:
http://svn.reactos.org/svn/reactos?rev=22744&view=rev
Log:
- 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.
Modified:
trunk/reactos/ntoskrnl/io/device.c
trunk/reactos/ntoskrnl/io/pnpmgr.c
Modified: trunk/reactos/ntoskrnl/io/device.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/device.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/io/device.c (original)
+++ trunk/reactos/ntoskrnl/io/device.c Sat Jul 1 22:56:09 2006
@@ -80,111 +80,6 @@
ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
&ShutdownListLock);
}
-}
-
-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
@@ -1247,137 +1142,157 @@
/*
* @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)
-{
- PKDEVICE_QUEUE_ENTRY entry;
- PIRP Irp;
-
- entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue,
- Key);
-
- if (entry != NULL)
- {
- Irp = CONTAINING_RECORD(entry,
- IRP,
- Tail.Overlay.DeviceQueueEntry);
+NTAPI
+IoStartNextPacketByKey(IN PDEVICE_OBJECT DeviceObject,
+ IN BOOLEAN Cancelable,
+ IN ULONG Key)
+{
+ PKDEVICE_QUEUE_ENTRY Entry;
+ PIRP Irp;
+ KIRQL OldIrql;
+
+ /* Acquire the cancel lock if this is cancelable */
+ if (Cancelable) IoAcquireCancelSpinLock(&OldIrql);
+
+ /* Clear the current IRP */
+ DeviceObject->CurrentIrp = NULL;
+
+ /* Remove an entry from the queue */
+ Entry = KeRemoveByKeyDeviceQueue(&DeviceObject->DeviceQueue, Key);
+ if (Entry)
+ {
+ /* 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);
- DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
- }
- else
- {
- DPRINT("No next irp\n");
- DeviceObject->CurrentIrp = NULL;
- }
+
+ /* 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
+ {
+ /* 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)
-{
- PKDEVICE_QUEUE_ENTRY entry;
- PIRP Irp;
-
- DPRINT("IoStartNextPacket(DeviceObject 0x%p, Cancelable %d)\n",
- DeviceObject, Cancelable);
-
- entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
-
- if (entry!=NULL)
- {
- Irp = CONTAINING_RECORD(entry,IRP,Tail.Overlay.DeviceQueueEntry);
+NTAPI
+IoStartNextPacket(IN PDEVICE_OBJECT DeviceObject,
+ IN BOOLEAN Cancelable)
+{
+ PKDEVICE_QUEUE_ENTRY Entry;
+ PIRP Irp;
+ KIRQL OldIrql;
+
+ /* Acquire the cancel lock if this is cancelable */
+ if (Cancelable) IoAcquireCancelSpinLock(&OldIrql);
+
+ /* Clear the current IRP */
+ DeviceObject->CurrentIrp = NULL;
+
+ /* Remove an entry from the queue */
+ Entry = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
+ if (Entry)
+ {
+ /* Get the IRP and set it */
+ Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DeviceQueueEntry);
DeviceObject->CurrentIrp = Irp;
- DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);
- }
- else
- {
- DeviceObject->CurrentIrp = NULL;
- }
+
+ /* Call the Start I/O Routine */
+ DeviceObject->DriverObject->DriverStartIo(DeviceObject, Irp);
+ }
+ else
+ {
+ /* 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)
-{
- BOOLEAN stat;
- KIRQL oldirql;
-
- DPRINT("IoStartPacket(Irp 0x%p)\n", Irp);
-
- ASSERT_IRQL(DISPATCH_LEVEL);
-
- IoAcquireCancelSpinLock(&oldirql);
-
- if (CancelFunction != NULL)
- {
- Irp->CancelRoutine = CancelFunction;
- }
-
- if (Key!=0)
- {
- stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
- &Irp->Tail.Overlay.DeviceQueueEntry,
- *Key);
- }
- else
- {
- stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
- &Irp->Tail.Overlay.DeviceQueueEntry);
- }
-
-
- if (!stat)
- {
- IoReleaseCancelSpinLock(DISPATCH_LEVEL);
+NTAPI
+IoStartPacket(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PULONG Key,
+ IN PDRIVER_CANCEL CancelFunction)
+{
+ BOOLEAN Stat;
+ KIRQL OldIrql, CancelIrql;
+
+ /* Raise to dispatch level */
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+ /* Check if we should acquire the cancel lock */
+ if (CancelFunction)
+ {
+ /* Acquire and set it */
+ IoAcquireCancelSpinLock(&CancelIrql);
+ Irp->CancelRoutine = CancelFunction;
+ }
+
+ /* Check if we have a key */
+ if (Key)
+ {
+ /* Insert by key */
+ Stat = KeInsertByKeyDeviceQueue(&DeviceObject->DeviceQueue,
+ &Irp->Tail.Overlay.DeviceQueueEntry,
+ *Key);
+ }
+ else
+ {
+ /* Insert without a key */
+ Stat = KeInsertDeviceQueue(&DeviceObject->DeviceQueue,
+ &Irp->Tail.Overlay.DeviceQueueEntry);
+ }
+
+ /* Check if this was a first insert */
+ if (!Stat)
+ {
+ /* Set the IRP */
DeviceObject->CurrentIrp = Irp;
- DeviceObject->DriverObject->DriverStartIo(DeviceObject,Irp);
- if (oldirql < DISPATCH_LEVEL)
- {
- KeLowerIrql(oldirql);
+
+ /* 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);
+ }
+ else
+ {
+ /* 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);
+ }
}
- }
- else
- {
- IoReleaseCancelSpinLock(oldirql);
- }
+ }
+
+ /* Return back to previous IRQL */
+ KeLowerIrql(OldIrql);
}
/* EOF */
Modified: trunk/reactos/ntoskrnl/io/pnpmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr.c (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr.c Sat Jul 1 22:56:09 2006
@@ -42,6 +42,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