xref: /xv6-public/ioapic.c (revision c8b29f6d)
1*c8b29f6dSkaashoek #include "types.h"
2*c8b29f6dSkaashoek #include "mp.h"
3*c8b29f6dSkaashoek #include "defs.h"
4*c8b29f6dSkaashoek #include "x86.h"
5*c8b29f6dSkaashoek #include "traps.h"
6*c8b29f6dSkaashoek #include "ioapic.h"
7*c8b29f6dSkaashoek 
8*c8b29f6dSkaashoek struct ioapic {
9*c8b29f6dSkaashoek   uint ioregsel;  uint p01; uint p02; uint p03;
10*c8b29f6dSkaashoek   uint iowin;     uint p11; uint p12; uint p13;
11*c8b29f6dSkaashoek };
12*c8b29f6dSkaashoek 
13*c8b29f6dSkaashoek 
14*c8b29f6dSkaashoek #define	IOAPIC_REDTBL_LO(i)	(IOAPIC_REDTBL + (i) * 2)
15*c8b29f6dSkaashoek #define	IOAPIC_REDTBL_HI(i)	(IOAPIC_REDTBL_LO(i) + 1)
16*c8b29f6dSkaashoek 
17*c8b29f6dSkaashoek static uint
18*c8b29f6dSkaashoek ioapic_read(struct ioapic *io, int reg)
19*c8b29f6dSkaashoek {
20*c8b29f6dSkaashoek   io->ioregsel = reg;
21*c8b29f6dSkaashoek   return (io->iowin);
22*c8b29f6dSkaashoek }
23*c8b29f6dSkaashoek 
24*c8b29f6dSkaashoek static void
25*c8b29f6dSkaashoek ioapic_write(struct ioapic *io, int reg, uint val)
26*c8b29f6dSkaashoek {
27*c8b29f6dSkaashoek   io->ioregsel = reg;
28*c8b29f6dSkaashoek   io->iowin = val;
29*c8b29f6dSkaashoek }
30*c8b29f6dSkaashoek 
31*c8b29f6dSkaashoek void
32*c8b29f6dSkaashoek ioapic_init(void)
33*c8b29f6dSkaashoek {
34*c8b29f6dSkaashoek   struct ioapic *io;
35*c8b29f6dSkaashoek   uint l, h;
36*c8b29f6dSkaashoek   int nintr;
37*c8b29f6dSkaashoek   uchar id;
38*c8b29f6dSkaashoek   int i;
39*c8b29f6dSkaashoek 
40*c8b29f6dSkaashoek   io = (struct ioapic *) IO_APIC_BASE;
41*c8b29f6dSkaashoek   l = ioapic_read(io, IOAPIC_VER);
42*c8b29f6dSkaashoek   nintr =  ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
43*c8b29f6dSkaashoek   id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
44*c8b29f6dSkaashoek   if (id != ioapic_id)
45*c8b29f6dSkaashoek     panic ("ioapic_init: id isn't equal to ioapic_id\n");
46*c8b29f6dSkaashoek   cprintf ("ioapic VER: 0x%x id %d nintr %d\n", l, id, nintr);
47*c8b29f6dSkaashoek   for (i = 0; i < nintr; i++) {
48*c8b29f6dSkaashoek     // active-hi and edge-triggered for ISA interrupts
49*c8b29f6dSkaashoek     // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
50*c8b29f6dSkaashoek     // Assume that pins 1-15 are ISA interrupts and that all
51*c8b29f6dSkaashoek     l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
52*c8b29f6dSkaashoek     l = l & ~IOART_INTMASK;  // allow INTs
53*c8b29f6dSkaashoek     l |= IOART_INTMSET;
54*c8b29f6dSkaashoek     l = l & ~IOART_INTPOL;   // active hi
55*c8b29f6dSkaashoek     l = l & ~IOART_TRGRMOD;  // edgee triggered
56*c8b29f6dSkaashoek     l = l & ~IOART_DELMOD;   // fixed
57*c8b29f6dSkaashoek     l = l & ~IOART_DESTMOD;  // physical mode
58*c8b29f6dSkaashoek     l = l | (IRQ_OFFSET + i); // vector
59*c8b29f6dSkaashoek     ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
60*c8b29f6dSkaashoek     h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
61*c8b29f6dSkaashoek     h &= ~IOART_DEST;
62*c8b29f6dSkaashoek     ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
63*c8b29f6dSkaashoek     //    cprintf("intr %d: lo 0x%x hi 0x%x\n", i, l, h);
64*c8b29f6dSkaashoek   }
65*c8b29f6dSkaashoek }
66*c8b29f6dSkaashoek 
67*c8b29f6dSkaashoek void
68*c8b29f6dSkaashoek ioapic_enable (int irq, int cpu)
69*c8b29f6dSkaashoek {
70*c8b29f6dSkaashoek   uint l, h;
71*c8b29f6dSkaashoek   struct ioapic *io;
72*c8b29f6dSkaashoek 
73*c8b29f6dSkaashoek   io = (struct ioapic *) IO_APIC_BASE;
74*c8b29f6dSkaashoek   l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
75*c8b29f6dSkaashoek   l = l & ~IOART_INTMASK;  // allow INTs
76*c8b29f6dSkaashoek   ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
77*c8b29f6dSkaashoek   h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
78*c8b29f6dSkaashoek   h &= ~IOART_DEST;
79*c8b29f6dSkaashoek   h |= (cpu << APIC_ID_SHIFT);  // for fun, disk interrupts to cpu 1
80*c8b29f6dSkaashoek   ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
81*c8b29f6dSkaashoek   cprintf("intr %d: lo 0x%x hi 0x%x\n", irq, l, h);
82*c8b29f6dSkaashoek }
83