#include "kernel.h" #include "log.h" #include "asm_int.h" #include "asm_pit.h" #include "driver/mouse.h" #include "driver/keyboard.h" #include "interrupts.h" #include "scheduler.h" #include "asm_x86.h" #include "smp.h" #include "apic.h" /** The size of our interrupts table */ #define INT_MAX 256 // 0-255 /** The interrupt descriptor table */ static struct int_desc { uint16_t addrLo; uint16_t sel; uint8_t zeros; uint8_t flags; uint16_t addrHi; } idt[INT_MAX]; /** The interrupt descriptor table descriptor */ static struct idt_desc { uint16_t size; uint16_t baseLo; uint16_t baseHi; } idtd; /** Sets a handler for a specific interrupt */ static void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr) { uint64_t base=(uint32_t)&(*(uint32_t*)addr); idt[irq].addrLo = base & 0xffff; idt[irq].addrHi = (base >> 16) & 0xffff; idt[irq].zeros=0; idt[irq].flags=flags; idt[irq].sel=sel; } /* * Interrupt dispatcher * * Remeber that we are inside an interrupt here! * */ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) { // pit timer at 1/25 sec. if(irq==INTERRUPT_PIT_TIMER)asm_pit_tick(); // kb if(irq==INTERRUPT_KEYBOARD) { uint32_t in=x86_inb(0x60); } // mouse if(irq==INTERRUPT_MOUSE) { uint32_t in=x86_inb(0x60); /* if(irq==INTERRUPT_KEYBOARD){ keyboard_handle(in); // do this in separate thread via syscalls? task_wake_all(); } */ // TODO: mouse // test ipi //apic_ipi(2,0x81); // force cpu16 to autoschedule? just test //klog("0x60 in %d",in); } // 0x80 - a syscall is coming in if(irq==INTERRUPT_SYSCALL) { uint32_t *stack=esp; uint32_t eax=stack[11]; uint32_t ebx=stack[8]; uint32_t ecx=stack[10]; uint32_t edx=stack[9]; task_syscall(eax,ebx,ecx,edx); esp=scheduler_run(esp,2); } // schedules on APIC timer 0x8C and IPI 0x81 if(irq==INTERRUPT_APIC_TIMER || irq==INTERRUPT_IPI) { esp=scheduler_run(esp,-1); } // ack all except software syscalls if(irq!=INTERRUPT_SYSCALL)apic_eoi(); // default and spurious if(irq==255)kpanic("Spurious/Unknown Interrupt!?"); return esp; } /** * init interrupt descriptor table */ void interrupts_init(uint16_t sel) { klog("initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd); // Default interrupt handling for(int i=0; i>16; idtd.baseLo=0xffff&addr; __asm__("lidt %0"::"m" (idtd)); }