4. Code to Enable Interrupts
In the PCIDRV sample, the EvtInterruptEnable callback appears in isrdpc.c. The required code is quite simple, as the following shows:
NTSTATUS
NICEvtInterruptEnable(
IN WDFINTERRUPT Interrupt,
IN WDFDEVICE AssociateDevice
)
{
PFDO_DATA fdoData;
fdoData = FdoGetData(AssociateDevice);
NICEnalbeInterrupt(Interrupt, fdoData);
return STATUS_SUCCESS;
}
NICEnableInterupt is simply a macro that sets the PCI device register to enable interrupts.
5. Code to Disable Interrupts
In the PCIDRV sample, the EvtInterruptDisable callback (also in isrdpc.c) simply calls the internal NICDisableInterrupt macro to set the PCI device register to disable interrupts. The following is the code:
NTSTATUS
NICEvtInterruptDisable(
IN WDFINTERRUPT Interrupt,
IN WDFDEVICE AssociatedDevice
)
{
PFDO_DATA fdoData;
fdoData = FdoGetData(AssociatedDevice);
NICDisableInterrupt(fdoData);
return STATUS_SUCCESS;
}
6. Post-Interrupt Enable and Pre-Interrupt Disable Processing
Some devices cause interrupt storms if they are
initialized after their interrupts are enabled. The driver for such a
device must therefore be able to perform initialization after the
device enters DO but before its
interrupt is enabled. Other devices, however, cannot be initialized
until the interrupt is enabled. To enable correct operation of both
types of devices, KMDF supplies post-interrupt enable and pre-interrupt
disable events for which drivers can register.
When powering up a device, KMDF invokes a driver’s callbacks in the following order:
EvtDeviceDOEntryPostInterruptsEnabled
KMDF calls EvtDeviceDOEntry
first. Drivers that must initialize their devices before the interrupt
is connected (for example, to prevent interrupt storms) should do so in
this callback. Next, KMDF calls EvtInterruptEnable. Drivers should enable their interrupts and do little or nothing else in this function because it is called at DIRQL. Finally, KMDF calls EvtDeviceDOEntryPostInterruptsEnabled at PASSIVE_LEVEL. Drivers that must initialize their devices after the interrupt is connected should do so in this callback.
At power-down, KMDF calls the corresponding paired functions in the opposite order:
EvtDeviceDOExitPreInterruptsDisabled
To undo work done by the EvtDeviceDOEntryPostInterruptsEnabled, a driver registers an EvtDeviceDOExitPreInterruptsDisabled function. Like the post-enable function, the pre-disable function does work at PASSIVE_LEVEL in preparation for disabling the interrupt.
A driver must register the post-interrupt enable and pre-interrupt disable callbacks in the WDF_PNPPOWER_EVENT_CALLBACKS structure before creating the device object. The PCIDRV sample fills this structure in its EvtDriverDeviceAdd callback, as follows:
pnpPowerCallbacks.EvtDeviceDOEntryPostInterruptsEnabled =
NICEvtDeviceDOEntryPostInterruptsEnabled;
pnpPowerCallbacks.EvtDeviceDOExitPreInterruptsDisabled =
NICEvtDeviceDOExitPreInterruptsDisabled;
In the current version of the PCIDRV sample, both of these functions are stubs.