diff --git a/sys/SConscript b/sys/SConscript index 9caaea5..49c5ae4 100644 --- a/sys/SConscript +++ b/sys/SConscript @@ -18,6 +18,7 @@ src_amd64 = [ "amd64/pmap.c", "amd64/lapic.c", "amd64/ioapic.c", + "amd64/irq.c", "dev/x86/debugcons.c", "dev/x86/vgacons.c", "dev/x86/ide.c", diff --git a/sys/amd64/ioapic.c b/sys/amd64/ioapic.c index 3e6960c..fc0a264 100644 --- a/sys/amd64/ioapic.c +++ b/sys/amd64/ioapic.c @@ -51,7 +51,7 @@ IOAPIC_Init() uint32_t id = (IOAPIC_Read(IOAPICID) >> 24) & 0x0F; uint32_t maxInts = (IOAPIC_Read(IOAPICVER) >> 16) & 0xFF; - kprintf("IOAPIC ID:%d Max Interrupts: %d\n", id, maxInts); + kprintf("IOAPIC: ID:%d Max Interrupts: %d\n", id, maxInts); for (i = 0; i <= IOREDTBL_LEN; i++) { diff --git a/sys/amd64/irq.c b/sys/amd64/irq.c new file mode 100644 index 0000000..7d0f89e --- /dev/null +++ b/sys/amd64/irq.c @@ -0,0 +1,52 @@ + +#include + +#include + +#include "trap.h" +#include "ioapic.h" +#include + +LIST_HEAD(IRQHandlerList, IRQHandler); +struct IRQHandlerList handlers[T_IRQ_LEN]; + +void +IRQ_Init() +{ + int i; + + for (i = 0; i < T_IRQ_LEN; i++) + { + LIST_INIT(&handlers[i]); + } +} + +void +IRQ_Handler(int irq) +{ + struct IRQHandler *h; + LIST_FOREACH(h, &handlers[irq], link) + { + h->cb(h->arg); + } +} + +void +IRQ_Register(int irq, struct IRQHandler *h) +{ + ASSERT(irq < T_IRQ_LEN); + + LIST_INSERT_HEAD(&handlers[irq], h, link); + + IOAPIC_Enable(irq); +} + +void +IRQ_Unregister(int irq, struct IRQHandler *h) +{ + LIST_REMOVE(h, link); + + if (LIST_EMPTY(&handlers[irq])) + IOAPIC_Disable(irq); +} + diff --git a/sys/amd64/lapic.c b/sys/amd64/lapic.c index 4e83d69..9872391 100644 --- a/sys/amd64/lapic.c +++ b/sys/amd64/lapic.c @@ -99,7 +99,7 @@ LAPIC_Init() base = rdmsr(IA32_APIC_BASE_MSR); wrmsr(IA32_APIC_BASE_MSR, base | IA32_APIC_BASE_MSR_ENABLE); - kprintf("CPU %d LAPIC found at 0x%016llx\n", LAPIC_CPU(), base); + kprintf("LAPIC: CPU %d found at 0x%016llx\n", LAPIC_CPU(), base); // Enable interrupts LAPIC_Write(LAPIC_SIV, LAPIC_SIV_ENABLE | T_IRQ_SPURIOUS); diff --git a/sys/amd64/machine.c b/sys/amd64/machine.c index 24f0286..4948c2c 100644 --- a/sys/amd64/machine.c +++ b/sys/amd64/machine.c @@ -89,6 +89,7 @@ void Machine_Init() PAlloc_AddRegion(16*1024*1024, 16*1024*1024); PMap_Init(); + IRQ_Init(); LAPIC_Init(); IOAPIC_Init(); diff --git a/sys/amd64/trap.c b/sys/amd64/trap.c index 5d0d5dd..daa54bc 100644 --- a/sys/amd64/trap.c +++ b/sys/amd64/trap.c @@ -3,6 +3,7 @@ #include #include +#include #include "amd64.h" #include "lapic.h" @@ -89,10 +90,10 @@ trap_entry(TrapFrame *tf) // Halt on kernel errors if (tf->vector <= T_CPU_LAST && tf->cs == SEL_KCS) { - Trap_Dump(tf); - - while (1) - hlt(); + kprintf("Kernel Fault!\n"); + Trap_Dump(tf); + while (1) + hlt(); } switch (tf->vector) @@ -111,15 +112,32 @@ trap_entry(TrapFrame *tf) if (tf->vector >= T_IRQ_BASE && tf->vector <= T_IRQ_MAX) { - kprintf("IRQ: %d\n", tf->vector); - - LAPIC_SendEOI(); + kprintf("IRQ: %d\n", tf->vector); + IRQ_Handler(tf->vector - T_IRQ_BASE); + LAPIC_SendEOI(); return; } - Trap_Dump(tf); + // LAPIC Special Vectors + if (tf->vector == T_IRQ_SPURIOUS) + return; + if (tf->vector == T_IRQ_ERROR) + { + kprintf("LAPIC Error!\n"); + while (1) + hlt(); + } + if (tf->vector == T_IRQ_THERMAL) + { + kprintf("Thermal Error!\n"); + while (1) + hlt(); + } - while (1) { } + kprintf("Unhandled Interrupt!\n"); + Trap_Dump(tf); + while (1) + hlt(); } diff --git a/sys/amd64/trap.h b/sys/amd64/trap.h index 0ccfe28..282f3e9 100644 --- a/sys/amd64/trap.h +++ b/sys/amd64/trap.h @@ -31,6 +31,7 @@ #define T_IRQ_TIMER (T_IRQ_BASE + 0) #define T_IRQ_KBD (T_IRQ_BASE + 1) #define T_IRQ_COM1 (T_IRQ_BASE + 4) +#define T_IRQ_MOUSE (T_IRQ_BASE + 12) #define T_IRQ_SPURIOUS (T_IRQ_BASE + 24) #define T_IRQ_ERROR (T_IRQ_BASE + 25) #define T_IRQ_THERMAL (T_IRQ_BASE + 26) diff --git a/sys/include/irq.h b/sys/include/irq.h new file mode 100644 index 0000000..d94cfcf --- /dev/null +++ b/sys/include/irq.h @@ -0,0 +1,20 @@ + +#ifndef __IRQ_H__ +#define __IRQ_H__ + +#include + +typedef struct IRQHandler { + int irq; + void (*cb)(void*); + void *arg; + LIST_ENTRY(IRQHandler) link; +} IRQHandler; + +void IRQ_Init(); +void IRQ_Handler(int irq); +void IRQ_Register(int irq, struct IRQHandler *h); +void IRQ_Unregister(int irq, struct IRQHandler *h); + +#endif /* __IRQ_H__ */ +