#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" #include "ringbuffer.h" ringbuffer mouse_in; ringbuffer kb_in; /** 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) { uint32_t *stack; // process irq switch(irq) { case INTERRUPT_PIT_TIMER: asm_pit_tick(); break; case INTERRUPT_KEYBOARD: ringbuffer_put(&kb_in,x86_inb(0x60)); break; case INTERRUPT_MOUSE: ringbuffer_put(&mouse_in,x86_inb(0x60)); break; case INTERRUPT_SYSCALL: stack=esp; task_syscall(stack[11],stack[8],stack[10],stack[9]); //eax,ebx,ecx,edx break; case INTERRUPT_APIC_TIMER: case INTERRUPT_IPI: esp=scheduler_run(esp,0); break; case 255: // default or spurious kpanic("Spurious/Unknown Interrupt!?"); break; } // 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(); return esp; } /** * init interrupt descriptor table */ void interrupts_init(uint16_t sel) { 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>16; idtd.baseLo=0xffff&addr; __asm__("lidt %0"::"m" (idtd)); }