[ros-diffs] [ion] 22744: - 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.

ion at svn.reactos.org ion at svn.reactos.org
Sat Jul 1 20:56:09 CEST 2006


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=22744&r1=22743&r2=22744&view=diff
==============================================================================
--- 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=22744&r1=22743&r2=22744&view=diff
==============================================================================
--- 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




More information about the Ros-diffs mailing list