Initialize the intrinfo data structure in the system page.
#include "startup.h" void init_intrinfo (void)
None.
This function initializes the interrupt controller hardware and populates the system page's intrinfo data structure. Because this function is hardware-dependent, you may have to write your own, which you call from the generic init_intrinfo() function.
Tasks the init_intrinfo() function typically performs include programming the interrupt controller register(s), and setting the interrupt masking. Interrupt control register programming can include:
Initially, all interrupts should be masked. The kernel uses the interrupt unmask kernel callout when necessary. For example, when a driver calls InterruptAttach(), the kernel provides structures that map the interrupt vector numbers used by the driver-level InterruptAttach() and InterruptAttachEvent() calls, and the interrupt connected to the interrupt controllers.
The init_intrinfo() function performs different tasks on ARM and x86 platforms:
If you're providing your own function, make sure it initializes:
This initialization of the structure is done via a call to the function add_interrupt_array().
Below is the source code for an init_intrinfo() function for an x86 board. Note that it simply calls a hardware-specific function that does the work:
void init_intrinfo() { init_intrinfo_8259(3); }
Below is the source code for a standard x86 interrupt controller setup function (init_intrinfo_8259()) called in the example above:
#include "startup.h" #include <x86/intr.h> // // Initialize interrupt controller hardware and intrinfo structure in the // system page. // This code is hardware dependant and may have to be changed // changed by end users. // // This version is for the standard IBM PC interrupt controller setup. #define MASTER FIRST_HARDWARE_INTERRUPT #define SLAVE (MASTER+8) const static struct startup_intrinfo intrs[] = { { _NTO_INTR_CLASS_EXTERNAL, 7, _NTO_INTR_SPARE, MASTER, 1, 0, {INTR_GENFLAG_NOGLITCH, 0, &interrupt_id_8259m}, {0, 0, &interrupt_eoi_8259m}, &interrupt_mask_8259m, &interrupt_unmask_8259m, &interrupt_config_8259m, }, { _NTO_INTR_CLASS_EXTERNAL+7, 1, _NTO_INTR_SPARE, MASTER+7, 1, 0, {0, 0, &interrupt_id_8259m7}, {0, 0, &interrupt_eoi_8259m}, &interrupt_mask_8259m7, &interrupt_unmask_8259m7, 0, }, { _NTO_INTR_CLASS_EXTERNAL+8, 7, _NTO_INTR_SPARE, SLAVE, 1, 0, {INTR_GENFLAG_NOGLITCH, 0, &interrupt_id_8259s}, {0, 0, &interrupt_eoi_8259s}, &interrupt_mask_8259s, &interrupt_unmask_8259s, 0, }, { _NTO_INTR_CLASS_EXTERNAL+15, 1, _NTO_INTR_SPARE, SLAVE+7, 1, 0, {0, 0, &interrupt_id_8259s7}, {0, 0, &interrupt_eoi_8259s}, &interrupt_mask_8259s7, &interrupt_unmask_8259s7, 0, }, { X86_INTR_CLASS_NMI, 2, _NTO_INTR_SPARE, 2, 0, INTR_FLAG_NMI | INTR_FLAG_CPU_FAULT, {0, 0, &interrupt_id_nmi_bios}, {INTR_GENFLAG_LOAD_INTRMASK, 0, &interrupt_eoi_nmi_bios}, &interrupt_mask_nmi_bios, &interrupt_unmask_nmi_bios, &interrupt_config_nmi_bios, }, }; void init_intrinfo_8259(unsigned top_prio_irq) { // Reprogram 8259 slave, edge mode, normal nested, isr visible out8(0xa0, 0x11); io_safe(); out8(0xa1, SLAVE); io_safe(); out8(0xa1, 0x02); io_safe(); out8(0xa1, 0x01); io_safe(); out8(0xa1, 0xff); out8(0xa0, 0x0b); // Reprogram 8259 master, edge mode, normal nested, isr visible out8(0x20, 0x11); io_safe(); out8(0x21, MASTER); io_safe(); out8(0x21, 0x04); io_safe(); out8(0x21, 0x01); io_safe(); out8(0x21, 0xfb); io_safe(); out8(0x20, 0x0b); /* Here we're sending the OCW2, to pin down the *lowest* priority IRQ, and, in effect, choosing the highest one as well, since the highest priority IRQ must follow in rotation from the lowest. eg. pin 2 as the lowest, then the order is: 3,4,5,6,7,0,1,2 -> (slave) 8,9,10,11,12,13,14,15 */ /* OCW2 to pin lowest prio IRQ */ out8(0x20, (((top_prio_irq-1) & 0x07) | 0xc0)); // Make sure both NMI sources are masked out8(0x61,(in8(0x61) & 0x3) | 0x0c); // Global NMI enable out8(0x70, 0x7f); add_interrupt_array(intrs, sizeof(intrs)); }
Note that the last action in the example above is to call add_interrupt_array() to populate the interrupt kernel callout array in the system page.