Installable ISRs and the Kernel (Windows Embedded CE 6.0)
1/6/2010
An installable interrupt service routine (ISR) is one that can be installed and allowed to hook an interrupt after the kernel is built. Usually, if an interrupt has to be hooked to provide service to some event, the code has to be built in when the kernel is originally built. If a new device is inserted into a Peripheral Component Interconnect (PCI) bus for example, the code to handle the interrupt request (IRQ) has to be in the kernel already; otherwise, the IRQ cannot be hooked. OEMs can plan for some expansion and build an OEM adaptation layer (OAL) that accommodates various devices in a flexible way. However, if an unknown device is inserted into the board support package (BSP), there is a high likelihood that you cannot access it.
OEMs must plan only for what IRQ is exposed to an ISR that is not built into the kernel. When an ISR is installed, the following considerations must be taken into account:
The driver DLL is similar to any driver DLL that creates an interrupt service thread (IST) and waits for it to be triggered. To install the ISR DLL, call the LoadIntChainHandler function, which loads the ISR DLL into the kernel's address space and initializes it. This function also forces the kernel to create a list of installed ISRs that handle a particular interrupt.
Note
The installable ISR DLL must be in the FILES Section with no fixup variable or in the MODULES Section with the kernel flag, K, set for a kernel-style fixup variable. A fixup variable is the functionality of ROMIMAGE that allows you to initialize a global variable in the Nk.exe at MAKEIMG time.
The ISR DLL is a stripped-down DLL that can be loaded by the kernel and used to provide a service to an IRQ. Like a regular ISR, an installed ISR returns a SYSINTR_* value that triggers a waiting IST in the driver DLL.
The OEM must forward any IRQs to the installed ISRs. The OEM is still the first call that the kernel makes if an OEM has hooked an IRQ by calling HookInterrupt. The OEM can handle any IRQs they want to in the traditional ISRs that are built into the kernel. OEMs must decide if an IRQ should be handled by an installed ISR. Any IRQ that the OEM enables to be handled by an installed ISR is triggered by a call to NKCallIntChain. When the kernel is called and is passed an interrupt value from the OEM, the kernel looks for all the installed ISRs that have registered for the same value. Then, based on a first in, first out (FIFO) ordering, the kernel goes through the list until the first ISR in the list returns a value other than SYSINTR_CHAIN. After a value, that is not an SYSINTR_CHAIN value, is returned, the kernel stops calling additional installed ISRs and returns this value to the caller of NKCallIntChain.
The following list shows what OEMs must do based on the return value from NKCallIntChain.
- If the entire list is processed and the ISR does not handle the IRQ, the NKCallIntChain function returns SYSINTR_CHAIN.
- If the return value from NKCallIntChain is not SYSINTR_CHAIN, OEMs should disable the interrupt and return the SYSINTR_* value to the kernel.
- If the value returned from NKCallIntChain is SYSINTR_CHAIN, OEMs should return SYSINTR_NOP to the kernel and leave the interrupt enabled.
The generic installable ISR sample code is located in %_WINCEROOT%\Public\Common\Oak\Drivers\GIISR. The generic installable ISR must export the following functions:
The following I/O control codes are specific to the driver:
- IOCTL_GIISR_INFO
- IOCTL_GIISR_PORTVALUE
See Also
Concepts
Other Resources
Defining an Interrupt Identifier
Implementing an ISR
Loader
PCI Bus Driver
Real-Time Priority System