ioapic.c (2129B)
1 // The I/O APIC manages hardware interrupts for an SMP system. 2 // http://www.intel.com/design/chipsets/datashts/29056601.pdf 3 // See also picirq.c. 4 5 #include "types.h" 6 #include "defs.h" 7 #include "traps.h" 8 #include "memlayout.h" 9 10 #define IOAPIC 0xFEC00000 // Default physical address of IO APIC 11 12 #define REG_ID 0x00 // Register index: ID 13 #define REG_VER 0x01 // Register index: version 14 #define REG_TABLE 0x10 // Redirection table base 15 16 // The redirection table starts at REG_TABLE and uses 17 // two registers to configure each interrupt. 18 // The first (low) register in a pair contains configuration bits. 19 // The second (high) register contains a bitmask telling which 20 // CPUs can serve that interrupt. 21 #define INT_DISABLED 0x00010000 // Interrupt disabled 22 #define INT_LEVEL 0x00008000 // Level-triggered (vs edge-) 23 #define INT_ACTIVELOW 0x00002000 // Active low (vs high) 24 #define INT_LOGICAL 0x00000800 // Destination is CPU id (vs APIC ID) 25 26 volatile struct ioapic *ioapic; 27 28 // IO APIC MMIO structure: write reg, then read or write data. 29 struct ioapic { 30 uint reg; 31 uint pad[3]; 32 uint data; 33 }; 34 35 static uint 36 ioapicread(int reg) 37 { 38 ioapic->reg = reg; 39 return ioapic->data; 40 } 41 42 static void 43 ioapicwrite(int reg, uint data) 44 { 45 ioapic->reg = reg; 46 ioapic->data = data; 47 } 48 49 void 50 ioapicinit(void) 51 { 52 int i, id, maxintr; 53 54 if(!ismp) 55 return; 56 57 ioapic = (volatile struct ioapic*) IO2V(IOAPIC); 58 maxintr = (ioapicread(REG_VER) >> 16) & 0xFF; 59 id = ioapicread(REG_ID) >> 24; 60 if(id != ioapicid) 61 cprintf("ioapicinit: id isn't equal to ioapicid; not a MP\n"); 62 63 // Mark all interrupts edge-triggered, active high, disabled, 64 // and not routed to any CPUs. 65 for(i = 0; i <= maxintr; i++){ 66 ioapicwrite(REG_TABLE+2*i, INT_DISABLED | (T_IRQ0 + i)); 67 ioapicwrite(REG_TABLE+2*i+1, 0); 68 } 69 } 70 71 void 72 ioapicenable(int irq, int cpunum) 73 { 74 if(!ismp) 75 return; 76 77 // Mark interrupt edge-triggered, active high, 78 // enabled, and routed to the given cpunum, 79 // which happens to be that cpu's APIC ID. 80 ioapicwrite(REG_TABLE+2*irq, T_IRQ0 + irq); 81 ioapicwrite(REG_TABLE+2*irq+1, cpunum << 24); 82 }