init_intrinfo()
Initialize the intrinfo data structure in the system page.
Synopsis:
#include "startup.h"
				
void init_intrinfo (void)Arguments:
None.
Description:
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.
- specifying edge or level triggering
 - specifying whether an active interrupt is indicated by a high or low signal
 - nesting interrupts
 - setting interrupt priorities
 
Initially, all interrupts should be masked. The kernel uses the interrupt unmask kernel callout when necessary. For example, when a driver calls InterruptAttachThread(), the kernel provides structures that map the interrupt vector numbers used by the driver-level InterruptAttachThread() and InterruptAttachEvent() calls, and the interrupt connected to the interrupt controllers.
- ARM
 - No default version exists; you must supply one.
 - x86
 - You would need to change this generic function only if your hardware doesn't support the standard PC-compatible dual 8259 configuration.
 
- the interrupt controller hardware as appropriate (e.g., on x86, it should program the two 8259 interrupt controllers)
 - the intrinfo system page structure, with the information needed to work with the interrupt controller hardware
 
This initialization of the structure is done via a call to the function add_interrupt_array().
Example:
void init_intrinfo() {
    init_intrinfo_8259(3);
}#include "startup.h"
#include <x86_64/intr.h>
// Initialize interrupt controller hardware and intrinfo structure in the
// system page.
// This code is hardware-dependent and may have to be changed by end users.
// This version is for the standard IBM PC interrupt controller setup.
#define CONTROLLER FIRST_HARDWARE_INTERRUPT
#define WORKER (CONTROLLER+8)
const static struct startup_intrinfo intrs[] = {
{ _NTO_INTR_CLASS_EXTERNAL, 7, _NTO_INTR_SPARE, CONTROLLER, 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, CONTROLLER+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, WORKER, 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, WORKER+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 worker, edge mode, normal nested, IST visible
out8(0xa0, 0x11);  io_safe();
out8(0xa1, WORKER); io_safe();
out8(0xa1, 0x02);  io_safe();
out8(0xa1, 0x01);  io_safe();
out8(0xa1, 0xff);
out8(0xa0, 0x0b);
// Reprogram 8259 controller, edge mode, normal nested, IST visible
out8(0x20, 0x11);   io_safe();
out8(0x21, CONTROLLER); 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.
Suppose pin 2 is the lowest. Then the order is:
3,4,5,6,7,0,1,2 -> (worker) 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);
/* Populate the interrupt kernel callout array in the system page */
add_interrupt_array(intrs, sizeof(intrs));
}