3.2.4 Registering An Interrupt

After a miniport has called NdisMSetAttributes or NdisMSetAttributesEx, claimed its hardware, and claimed other I/O resources it needs to use that device, if the adapter it manages interrupts, the miniport must call NdisMRegisterInterrupt to identify the interrupt its device uses and to claim an interrupt vector/level for its NIC. The miniport allocates resident storage for an opaque variable of type NDIS_MINIPORT_INTERRUPT and passes a pointer to the variable to NdisMRegisterInterrupt. The miniport passes information about its interrupt such as the bus-relative interrupt vector and interrupt level, whether its MiniportISR should be called at every interrupt, whether its interrupt is shared, and its interrupt mode.

The interrupt mode specified by the miniport is either NdisInterruptLevelSensitive or NdisInterruptLatched. NdisMRegisterInterrupt makes HAL calls on behalf of the miniport to claim an interrupt vector and then connects to the interrupt by calling the I/O system. When NDIS connects to the interrupt, it supplies its own ISR function to be called first on any interrupt. Therefore, when an interrupt occurs, control always goes to NDIS first. Within the NDIS ISR, the decision is made (based on the value of RequestIsr supplied to NdisMRegisterInterrupt) whether to pass the interrupt to the miniport’s MiniportISR or MiniportDisableInterrupt function or to handle the interrupt within NDIS and then to queue MiniportHandleInterrupt.

NdisMRegisterInterrupt has no effect on the state of the NIC. However, since the miniport is now connected to the interrupt, when NdisMRegisterInterrupt returns, the miniport can possibly receive interrupts depending on the characteristics of the NIC. If its NIC could generate interrupts immediately, the miniport should perform whatever adapter-specific steps it requires to prepare itself to handle interrupts before calling NdisMRegisterInterrupt. That is, the miniport must create and initialize any structures it needs, perhaps initializing any spin locks it needs to synchronize access to shared data. When a miniport has registered its interrupt and is prepared to handle interrupts, the miniport can enable interrupts in a device-specific manner, for instance by resetting the NIC.

It is good practice for a miniport to test its device during initialization to make sure the device is capable of generating interrupts. When NdisMRegisterInterrupt returns, a miniport can perform this test. If the device is not operating correctly, the miniport should free all claimed resources and return NDIS_STATUS_FAILURE from MiniportInitialize so that the miniport can be unloaded by the system.

If the miniport wants to change the default timeout, it must do this by calling NdisMSetAttributesEx. This function must be called in MiniportInitialize. After MiniportInitialize returns, the driver cannot change the default timeout behavior. See the Section 3.1.3.6 for a discussion of the miniport’s CheckForHang function.

The miniport should finally call NdisMRegisterAdapterShutdownHandler to register a shutdown handler function with NDIS, unless the miniport is a WAN miniport. WAN miniports do not register such a handler.

A miniport passes NdisMRegisterAdapterShutdownHandler, the symbolic address of its MiniportShutdown function, the miniport adapter handle assigned by NDIS and context to be passed to MiniportShutdown when it is called. NdisMRegisterAdapterShutdownHandler is typically called last from MiniportInitialize, just before the miniport returns from MiniportInitialize.