summaryrefslogtreecommitdiff
path: root/ioapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'ioapic.c')
-rw-r--r--ioapic.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/ioapic.c b/ioapic.c
new file mode 100644
index 0000000..776f895
--- /dev/null
+++ b/ioapic.c
@@ -0,0 +1,82 @@
+#include "types.h"
+#include "mp.h"
+#include "defs.h"
+#include "x86.h"
+#include "traps.h"
+#include "ioapic.h"
+
+struct ioapic {
+ uint ioregsel; uint p01; uint p02; uint p03;
+ uint iowin; uint p11; uint p12; uint p13;
+};
+
+
+#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
+#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
+
+static uint
+ioapic_read(struct ioapic *io, int reg)
+{
+ io->ioregsel = reg;
+ return (io->iowin);
+}
+
+static void
+ioapic_write(struct ioapic *io, int reg, uint val)
+{
+ io->ioregsel = reg;
+ io->iowin = val;
+}
+
+void
+ioapic_init(void)
+{
+ struct ioapic *io;
+ uint l, h;
+ int nintr;
+ uchar id;
+ int i;
+
+ io = (struct ioapic *) IO_APIC_BASE;
+ l = ioapic_read(io, IOAPIC_VER);
+ nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
+ id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
+ if (id != ioapic_id)
+ panic ("ioapic_init: id isn't equal to ioapic_id\n");
+ cprintf ("ioapic VER: 0x%x id %d nintr %d\n", l, id, nintr);
+ for (i = 0; i < nintr; i++) {
+ // active-hi and edge-triggered for ISA interrupts
+ // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
+ // Assume that pins 1-15 are ISA interrupts and that all
+ l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
+ l = l & ~IOART_INTMASK; // allow INTs
+ l |= IOART_INTMSET;
+ l = l & ~IOART_INTPOL; // active hi
+ l = l & ~IOART_TRGRMOD; // edgee triggered
+ l = l & ~IOART_DELMOD; // fixed
+ l = l & ~IOART_DESTMOD; // physical mode
+ l = l | (IRQ_OFFSET + i); // vector
+ ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
+ h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
+ h &= ~IOART_DEST;
+ ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
+ // cprintf("intr %d: lo 0x%x hi 0x%x\n", i, l, h);
+ }
+}
+
+void
+ioapic_enable (int irq, int cpu)
+{
+ uint l, h;
+ struct ioapic *io;
+
+ io = (struct ioapic *) IO_APIC_BASE;
+ l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
+ l = l & ~IOART_INTMASK; // allow INTs
+ ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
+ h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
+ h &= ~IOART_DEST;
+ h |= (cpu << APIC_ID_SHIFT); // for fun, disk interrupts to cpu 1
+ ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
+ cprintf("intr %d: lo 0x%x hi 0x%x\n", irq, l, h);
+}