xv6

port of xv6 to x86-64
git clone http://frotz.net/git/xv6.git
Log | Files | Refs | README | LICENSE

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 }