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