summaryrefslogtreecommitdiff
path: root/kernel/interrupts.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/interrupts.c')
-rw-r--r--kernel/interrupts.c62
1 files changed, 24 insertions, 38 deletions
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index b0a473a..5a788c8 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -13,15 +13,11 @@
#include "apic.h"
#include "ringbuffer.h"
-ringbuffer mouse_in;
-ringbuffer kb_in;
-
-//
-
/** The size of our interrupts table */
#define INT_MAX 256 // 0-255
-static uint32_t handlers[INT_MAX]; // addresses of interrupt handlers.
+/** Addresses of the registered interrupt handlers */
+static uint32_t handlers[INT_MAX];
/** The interrupt descriptor table */
struct int_desc
@@ -53,7 +49,8 @@ static void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr)
idt[irq].sel=sel;
}
-void interrupt_handler_register(uint32_t irq, uint32_t func_addr)
+/** register an interrupt handler for given irq number */
+void interrupt_register(uint32_t irq, uint32_t func_addr)
{
if(irq<128||irq>160)kpanic("irq number out of range!");
if(handlers[irq]!=0)kpanic("handler already registered!");
@@ -62,41 +59,38 @@ void interrupt_handler_register(uint32_t irq, uint32_t func_addr)
/*
* Interrupt dispatcher
- *
* Remeber that we are inside an interrupt here!
- *
*/
uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
{
+
uint32_t *stack;
- // process irq
- switch(irq)
+ if(handlers[irq]!=0)
{
- case INTERRUPT_PIT_TIMER:
- asm_pit_tick();
- break;
-
- case INTERRUPT_KEYBOARD:
- ringbuffer_put(&kb_in,x86_inb(0x60));
- break;
+ uint32_t (*f)(uint32_t esp)=handlers[irq];
+ esp=f(esp);
+ apic_eoi();
+ }
+ else if(irq!=INTERRUPT_SYSCALL&&irq!=INTERRUPT_IPI&&irq!=INTERRUPT_APIC_TIMER)
+ {
+ kpanic("unhandled interrupt %d",irq);
+ }
- case INTERRUPT_MOUSE:
- ringbuffer_put(&mouse_in,x86_inb(0x60));
- break;
+ // process IRQ
+ switch(irq)
+ {
case INTERRUPT_SYSCALL:
stack=esp;
task_syscall(stack[11],stack[8],stack[10],stack[9]); //eax,ebx,ecx,edx
+ esp=scheduler_wake_worker(esp);
break;
- case INTERRUPT_E1000:
- e1000_irq(INTERRUPT_E1000);
- break;
-
- case INTERRUPT_APIC_TIMER:
- case INTERRUPT_IPI:
+ case INTERRUPT_APIC_TIMER: // frequency is configured in smp.c
+ case INTERRUPT_IPI: // inter process interrupt
esp=scheduler_run(esp,0);
+ apic_eoi();
break;
case 255: // default or spurious
@@ -107,29 +101,21 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
// reschedule to kernel worker on these
if(irq==INTERRUPT_SYSCALL||irq==INTERRUPT_KEYBOARD||irq==INTERRUPT_MOUSE)
{
-
esp=scheduler_wake_worker(esp);
}
- // ack all to LAPIC, except software syscalls
- if(irq!=INTERRUPT_SYSCALL)
- apic_eoi();
+ // Ack all to LAPIC, except software syscalls
return esp;
+
}
/**
- * init interrupt descriptor table
+ * init interrupt descriptor table (TODO; do we seriously have to hardcode this?)
*/
void interrupts_init()
{
- // TODO????
- klog("Initializing Mouse and Kb input buffers");
- fixme("use a regular pipe-file");
- kb_in=ringbuffer_init(1);// 4096 bytes ringbuffer;
- mouse_in=ringbuffer_init(1);// 4096 bytes ringbuffer;
klog("Initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd);
- //
// Default interrupt handling
for(int i=0; i<INT_MAX; i++)