NdisMRegisterInterrupt

NDIS_STATUS
   NdisMRegisterInterrupt(
       OUT PNDIS_MINIPORT_INTERRUPT
Interrupt,
       IN NDIS_HANDLE MiniportAdapterHandle,
       IN UINT InterruptVector,
       IN UINT InterruptLevel,
       IN BOOLEAN RequestIsr,
       IN BOOLEAN SharedInterrupt,
       IN NDIS_INTERRUPT_MODE InterruptMode
       );

NdisMRegisterInterrupt sets up a mapping between a NIC driver’s MiniportISR and MiniportHandleInterrupt functions, already registered with NdisMRegisterMiniport, and the bus-relative vector and level on which its NIC interrupts.

Parameters

Interrupt

Points to caller-allocated resident memory containing an opaque interrupt object, which NdisMRegisterInterrupt initializes and for which it returns a handle the miniport uses in subsequent calls to NdisMSynchronizeWithInterrupt.

MiniportAdapterHandle

Specifies the handle input to MiniportInitialize.

InterruptVector

Specifies the bus-relative vector number used by the NIC.

InterruptLevel

Specifies the bus-relative DIRQL for the interrupt. This value is almost always the same as that of InterruptVector.

RequestIsr

Specifies TRUE if the MiniportISR function should be called each time the NIC interrupts. If the NIC can share an interrupt with other devices on the I/O bus, this parameter must be set to TRUE.

SharedInterrupt

Specifies TRUE if other devices on the I/O bus can use this interrupt line. If this parameter is set to FALSE and another device already claimed the given interrupt vector in the registry, NdisMRegisterInterrupt will fail.

InterruptMode

Specifies the type of interrupt that the NIC generates as one of the following values:

NdisInterruptLatched

Interrupts are triggered by a transition from low to high on the interrupt line.

NdisInterruptLevelSensitive

Interrupts are active as long as the interrupt line is asserted.

Return Value

NdisMRegisterInterrupt can return one of the following:

NDIS_STATUS_SUCCESS

NDIS initialized the interrupt object and returned a valid Interrupt handle, claimed hardware resources in the registry for the NIC, such as the given vector if the NIC does not share an IRQ, and set up the MiniportISR (or MiniportDisableInterrupt) and associated MiniportHandleInterrupt functions to be called when an interrupt occurs as requested in the call to NdisMRegisterInterrupt.

NDIS_STATUS_RESOURCE_CONFLICT

An attempt to claim the vector or level in the registry has failed, possibly because another driver already claimed the interrupt for its device. NdisMRegisterInterrupt logs an error if this occurs.

NDIS_STATUS_RESOURCES

NDIS could not allocate sufficient memory to claim resources in the registry for the NIC.

NDIS_STATUS_FAILURE

The attempt to initialize the interrupt object failed, possibly due to another driver’s prior claim on the InterruptVector or InterruptLevel in the registry.

Comments

A NIC driver must call NdisMRegisterInterrupt from its MiniportInitialize function if its NIC generates interrupts. The driver of a NIC that does not generate interrupts calls NdisMInitializeTimer and NdisMSetPeriodicTimer instead of NdisMRegisterInterrupt.

MiniportInitialize must call NdisMSetAttributes or NdisMSetAttributesEx before calling NdisMRegisterInterrupt.

MiniportInitialize obtained the bus-relative values passed to NdisMRegisterInterrupt either from the registry or by calling a bus-type-specific NdisXxx configuration function.

If its call to NdisMRegisterInterrupt fails, MiniportInitialize should release all resources it already allocated for its NIC and, then, fail initialization for that NIC.

NdisMRegisterInterrupt distinguishes between the InterruptVector (the interrupt line that the card asserts to interrupt the system) and the InterruptLevel (the hardware priority, that is, the DIRQL, of that interrupt assigned by the system). Usually, these values can be assumed to be equal, unless the driver writer knows that they are different for a particular NIC or unless the miniport controls more than one NIC that share resources in the current platform.

If its NIC can share an IRQ with other devices on the I/O bus, the caller of NdisMRegisterInterrupt must set both the SharedInterrupt and RequestIsr parameters to TRUE. Such a NIC driver’s MiniportISR can be called when no interrupt for the NIC is outstanding. In these circumstances, MiniportISR should return FALSE as soon as possible, indicating that the interrupt was not recognized and should leave interrupts enabled on its NIC.

When interrupts are enabled on the NIC, a driver’s MiniportISR can be called at any time following a successful call to NdisMRegisterInterrupt, even during initialization. Such a driver’s MiniportInitialize function should not call NdisMRegisterInterrupt until it has set up all state the driver needs to handle an interrupt. The MiniportHandleInterrupt function is not queued for subsequent execution if the driver’s MiniportInitialize function is currently executing and an interrupt occurs.

For most drivers of NICs that do not share an IRQ, the MiniportISR function seldom runs except, possibly, during driver initialization. Such a miniport sets RequestIsr to FALSE when MiniportInitialize calls NdisMRegisterInterrupt, and such a driver has a MiniportDisableInterrupt function and, possibly, a MiniportEnableInterrupt function. The NDIS library then calls the driver’s MiniportDisableInterrupt function when an interrupt occurs on the NIC and the driver’s MiniportHandleInterrupt function does most of the I/O processing for the interrupt. Before MiniportHandleInterrupt returns control, either NDIS calls MiniportEnableInterrupt or MiniportHandleInterrupt re-enables interrupts on the NIC itself.

Whether a miniport with an ISR sets RequestIsr to TRUE when it calls NdisMRegisterInterrupt or not, NDIS acknowledges the interrupt to the operating system so that interrupts from other devices are not blocked.

If a miniport sets RequestIsr to TRUE when it calls NdisMRegisterInterrupt, it must dismiss the interrupt on its NIC by setting the state of the network interface card so that the NIC no longer asserts the interrupt. Interrupts can remain enabled on the NIC following the dismissal of the interrupt, or they can be disabled, depending on the design of the driver. The timing of such a dismissal depends on the InterruptMode specified when the driver called NdisMRegisterInterrupt, as follows:

·For NdisInterruptLevelSensitive interrupts, MiniportISR must dismiss each interrupt as its NIC generates that interrupt. Otherwise, the interrupt is reasserted on the NIC as soon as MiniportISR returns control. If MiniportISR determines that the NIC did not generate a particular interrupt, it should return control with FALSE as soon as possible so that the ISRs for other devices on the same bus can be called promptly to dismiss the interrupt on the device that actually generated that interrupt.

·For NdisInterruptLatched interrupts, dismissing an interrupt on the NIC is not as time-critical as it is for shared interrupts. If the miniport is designed such that each call to MiniportISR causes a subsequent call to the associated MiniportHandleInterrupt function, MiniportHandleInterrupt can dismiss the interrupt on the NIC. As an alternative, such a driver can set RequestIsr to FALSE when it calls NdisMRegisterInterrupt and supply a MiniportDisableInterrupt function, which will be called instead of MiniportISR unless MiniportHalt or MiniportInitialize is currently executing.

When a miniport supports full-duplex sends and receives, NDIS serializes calls to its MiniportISR or MiniportDisableInterrupt function for sends. NDIS separately serializes calls to its MiniportISR or MiniportDisableInterrupt function for all other operations that can cause an interrupt. Calls to the MiniportReset function are both synchronized and synchronous; NDIS prevents all other code paths in a full-duplex miniport from being entered while a device-reset operation is occurring.

If a miniport does not support full-duplex sends and receives, NDIS serializes all calls to the MiniportISR or MiniportDisableInterrupt function for any NIC the miniport controls. While such a driver’s MiniportISR or MiniportDisableInterrupt function is processing a particular NIC interrupt, it will not be called to handle a second interrupt from the same NIC on another processor in an SMP machine.

However, the ISR (or MiniportDisableInterrupt function) of any driver that controls more than one device can run concurrently in SMP platforms if two of that driver’s devices happen to generate interrupts almost simultaneously and interrupts are enabled on the NIC.

If it is possible that an interrupt can occur while another driver function is accessing resources that also can be accessed from MiniportISR or MiniportDisableInterrupt, the other function must call NdisMSynchronizeWithInterrupt to have the driver-supplied MiniportSynchronizeISR function access the shared resources at DIRQL.

Callers of NdisMRegisterInterrupt run at IRQL PASSIVE_LEVEL.

See Also

MiniportDisableInterrupt, MiniportEnableInterrupt, MiniportHandleInterrupt, MiniportInitialize, MiniportISR, MiniportReset, MiniportSynchronizeISR, MiniportTimer, NdisMDeregisterInterrupt, NdisMInitializeTimer, NdisMPciAssignResources, NdisMSetAttributes, NdisMSetAttributesEx, NdisMSetPeriodicTimer, NdisMSynchronizeWithInterrupt, NdisOpenConfiguration, NdisReadEisaSlotInformation, NdisReadMcaPosInformation, NdisReadPciSlotInformation