1 // The I/O APIC manages hardware interrupts for an SMP system.
2 // http://www.intel.com/design/chipsets/datashts/29056601.pdf
9 #define IOAPIC 0xFEC00000 // Default physical address of IO APIC
11 #define REG_ID 0x00 // Register index: ID
12 #define REG_VER 0x01 // Register index: version
13 #define REG_TABLE 0x10 // Redirection table base
15 // The redirection table starts at REG_TABLE and uses
16 // two registers to configure each interrupt.
17 // The first (low) register in a pair contains configuration bits.
18 // The second (high) register contains a bitmask telling which
19 // CPUs can serve that interrupt.
20 #define INT_DISABLED 0x00010000 // Interrupt disabled
21 #define INT_LEVEL 0x00008000 // Level-triggered (vs edge-)
22 #define INT_ACTIVELOW 0x00002000 // Active low (vs high)
23 #define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID)
25 volatile struct ioapic
*ioapic
;
27 // IO APIC MMIO structure: write reg, then read or write data.
42 ioapicwrite(int reg
, uint data
)
56 ioapic
= (volatile struct ioapic
*)IOAPIC
;
57 maxintr
= (ioapicread(REG_VER
) >> 16) & 0xFF;
58 id
= ioapicread(REG_ID
) >> 24;
60 cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n");
62 // Mark all interrupts edge-triggered, active high, disabled,
63 // and not routed to any CPUs.
64 for(i
= 0; i
<= maxintr
; i
++){
65 ioapicwrite(REG_TABLE
+2*i
, INT_DISABLED
| (T_IRQ0
+ i
));
66 ioapicwrite(REG_TABLE
+2*i
+1, 0);
71 ioapicenable(int irq
, int cpunum
)
76 // Mark interrupt edge-triggered, active high,
77 // enabled, and routed to the given cpunum,
78 // which happens to be that cpu's APIC ID.
79 ioapicwrite(REG_TABLE
+2*irq
, T_IRQ0
+ irq
);
80 ioapicwrite(REG_TABLE
+2*irq
+1, cpunum
<< 24);