9.1.5 Setting Up DpcForIsr and CustomDpc Routines
The DriverEntry routine must register any DpcForIsr and initialize each CustomDpc routine an NT device driver has as follows:
·Call IoInitializeDpcRequest with the entry point for the DpcForIsr and a pointer to the driver-created device object representing the physical device that generates interrupts.
·Call KeInitializeDpc with a pointer to the driver’s storage for the DPC object, the entry point for the CustomDpc routine, and a DeferredContext pointer to a context area, which is passed to the CustomDpc routine when it is run.
If an NT driver has a CustomDpc routine, it must provide resident storage for a Kernel-defined DPC object. Usually, such a driver stores the DPC object in the device extension of the device object that it creates to represent its physical device that generates interrupts. Such a driver’s ISR is likely to access this device extension to save context for the CustomDpc routine, and the ISR must pass the Dpc object pointer to KeInsertQueueDpc when it queues the CustomDpc routine.
However, an NT device driver can provide storage for its DPC objects and context for interrupt-driven I/O operations in driver-allocated nonpaged pool or in the controller extension if the driver sets up a controller object.
Note that a CustomDpc routine differs from a CustomTimerDpc routine in how each is queued, the former with KeInsertQueueDpc and the latter with KeSetTimer or KeSetTimerEx. That is, for a CustomTimerDpc routine, the driver also must allocate storage for and initialize a Kernel-defined timer object, and it cannot pass the SystemArgument1 and SystemArgument2 pointers to its CustomTimerDpc routine with KeSetTimer or KeSetTimerEx.
For more information about DPC objects, see Chapter 3. For more information about CustomTimerDpc routines, see Chapter 14.