3.1.3.1 Providing Interrupt Support

A miniport can, but is not always required to, provide an interrupt handler. For instance, a miniport that manages a non-interrupting device and polls its device with a MiniportTimer function cannot depend on interrupts and thus does not have an interrupt handler. A miniport for a NIC with a shared interrupt must always provide an interrupt handler. The definition of the interrupt function follows.

VOID
    MiniportISR(
        OUT PBOOLEAN  InterruptRecognized,
        OUT PBOOLEAN  QueueMiniportHandleInterrupt,
        IN NDIS_HANDLE  MiniportAdapterContext
        );

When any network device interrupts, NDIS fields the interrupt; that is, NDIS is always called first when a NIC interrupts. NDIS determines which miniport the interrupt belongs to. Then NDIS either calls the appropriate miniport’s MiniportISR function, or handles the interrupt for the miniport if the miniport has specified in its call to NdisMRegisterInterrupt that it does not want to have its ISR called. If NDIS does not call a miniport’s ISR function, NDIS disables further interrupts by calling the miniport’s MiniportDisableInterrupt function and then queues the miniport’s MiniportHandleInterrupt DPC function.

If a miniport must or chooses to handle its device interrupts, it registers its ISR handler in NDIS_MINIPORT_CHARACTERISTICS and indicates that it wants its ISR handler called by setting the RequestIsr argument of NdisMRegisterInterrupt to TRUE.

A miniport for a NIC that interrupts must provide an ISR handler if any of the following is true.

If a device interrupts but the interrupt is not shared, the miniport can request that NDIS completely process the interrupt by specifying RequestIsr to FALSE in the miniport’s NdisMRegisterInterrupt call. When NDIS gets the interrupt, NDIS calls the miniport’s MiniportDisableInterrupt function, to disable further interrupts, queues the miniport’s MiniportHandleInterrupt function and returns TRUE to notify the I/O system that it recognizes the interrupt. MiniportHandleInterrupt must re-enable interrupts as soon as practical, otherwise, NDIS reenables interrupts by calling the miniport’s MiniportEnableInterrupt function if one exists.

Even if a miniport of a device that interrupts sets RequestIsr to FALSE, the miniport sometimes must provide an ISRHandler. If a NIC can generate an interrupt during the miniport’s initialization or when it is halting, such an interrupt will not be handled by NDIS but will be passed to the miniport. Therefore such a miniport must provide a MiniportISR function.

In summary, a miniport must provide an ISR handler if it manages a device that can interrupt during initialization or during a halt operation, if its NIC shares an IRQ, or if, when its device interrupts, it must capture interrupt-specific data at DIRQL. A miniport can specify that NDIS handle its interrupts if interrupts are not shared, if there is no device state that must be captured in the ISR at DIRQL, and if it can guarantee its NIC will not interrupt during initialization or halting. The miniport requests that NDIS handle interrupts by calling NdisMRegisterInterrupt with RequestIsr set to FALSE and SharedInterrupt set to FALSE.

If a driver manages a device that does not interrupt, it typically polls its device using a timer. This type of driver must initialize any timers it requires for its operation in MiniportInitialize. See Section 3.2.5 for more information.

Enabling and Disabling Interrupts

If the NIC does not generate an interrupt, the miniport does not need to provide a MiniportEnableInterrupt or MiniportDisableInterrupt function. If a miniport always handles its interrupts in a MiniportISR function, and schedules a MiniportHandleInterrupt function, it might not provide specific MiniportEnableInterrupt or MiniportDisableInterrupt functions. Instead, such a miniport can choose to disable interrupts within its ISR and enable them within its DPC, without providing specific functions for this purpose. If a miniport specifies that NDIS handle its interrupts, it must supply a MiniportDisableInterrupt function and if it does not reenable interrupts in its MiniportHandleInterrupt function, it must have a MiniportEnableInterrupt function.

Combining Interrupts and Polling

Sometimes a driver developer can improve the performance of a driver by combining polling a NIC with the use of interrupts. For instance, a driver can be designed to enable interrupts for receive indications but disable them for send-complete indications. A miniport might set a timer and, at timer expiration, check for send completions. In addition, when an interrupt on a receive occurs, the miniport also checks for send-completes. This is a reasonable strategy when network traffic is high: the number of interrupts handled is minimized, and no packets are missed.

A driver that implements this strategy can also sample the traffic on the network and, if traffic is high, it uses the strategy just described. If traffic on the network is low, the driver should enable both send-complete and receive interrupts because the number of interrupts is expected to be lower than in a high traffic environment and the possibility of adversely affecting the driver’s send performance exists.

A driver that uses both polling and interrupts disables interrupts when it is using polling to manage its device and enables interrupts when using interrupts to manage its device. The driver also can have NDIS process its device’s interrupts when they are enabled, subject to the same restrictions as already described. That is, that the interrupt is not shared, that any information needed by the miniport can be captured in its MiniportHandleInterrupt function, and that its NIC will never interrupt during initialization or halting.