Servicing an Interrupt
This topic describes how to service a DIRQL interrupt. For information about servicing a passive-level interrupt, see Supporting Passive Level Interrupts.
Servicing an interrupt consists of two, and sometimes three, steps:
Saving volatile information (such as register contents) quickly, in an interrupt service routine that runs at IRQL = DIRQL.
Processing the saved volatile information in a deferred procedure call (DPC) that runs at IRQL = DISPATCH_LEVEL.
Performing additional work at IRQL = PASSIVE_LEVEL, if necessary.
When a device generates a hardware interrupt, the framework calls the driver's interrupt service routine (ISR), which framework-based drivers implement as an EvtInterruptIsr callback function.
The EvtInterruptIsr callback function, which runs at the device's DIRQL, must quickly save interrupt information, such as register contents, that will be lost if another interrupt occurs.
Typically, the EvtInterruptIsr callback function schedules a deferred procedure call (DPC) to process the saved information later at a lower IRQL (DISPATCH_LEVEL). Framework-based drivers implement DPC routines as EvtInterruptDpc or EvtDpcFunc callback functions.
Most drivers use a single EvtInterruptDpc callback function for each type of interrupt. To schedule execution of an EvtInterruptDpc callback function, a driver must call WdfInterruptQueueDpcForIsr from within the EvtInterruptIsr callback function.
If your driver creates multiple framework queue objects for each device, you might consider using a separate DPC object and EvtDpcFunc callback function for each queue. To schedule execution of an EvtDpcFunc callback function, the driver must first create one or more DPC objects by calling WdfDpcCreate, typically in the driver's EvtDriverDeviceAdd callback function. Then the driver's EvtInterruptIsr callback function can call WdfDpcEnqueue.
Drivers typically complete I/O requests in their EvtInterruptDpc or EvtDpcFunc callback functions.
Sometimes a driver must perform some interrupt-servicing operations at IRQL = PASSIVE_LEVEL. In such cases the driver's EvtInterruptDpc or EvtDpcFunc callback function, executing at IRQL = DISPATCH_LEVEL, can schedule execution of one or more framework work items, which run at IRQL = PASSIVE_LEVEL.
For an example of a driver that uses work items while servicing device interrupts, see the PCIDRV sample driver.