#include "kernel/kernel.h" #include "asm/int.h" #include "asm/pit.h" #include "driver/mouse.h" #include "interrupts.h" #include "asm/x86.h" /** The size of our interrupts table */ #define INT_MAX 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; } /** Installs the interrupt table */ void int_install() { idtd.size=sizeof(struct int_desc)*INT_MAX; uint32_t addr=(uint32_t)&idt[0]; idtd.baseHi=addr>>16; idtd.baseLo=0xffff&addr; __asm__("lidt %0"::"m" (idtd)); } /* * Interrupt dispatcher * * Remeber that we are inside an interrupt here! * */ uint32_t interrupt_handler(uint32_t esp, uint32_t irq) { if(irq==0)asm_pit_tick(); // mouse and kb if(irq==1 || irq==12 ){ uint32_t in=x86_inb(0x60); if(irq=1)keyboard_handle(in); // do this in separate thread! // klog("0x60 in %d",in); } // 0x80 - a syscall is coming in if(irq==128){ uint32_t *stack=esp; uint32_t eax=stack[11]; uint32_t ebx=stack[8]; uint32_t ecx=stack[10]; uint32_t edx=stack[9]; // klog("syscall: %d (ebx=0x%08X,ecx=0x%08X,edx=0x%08X)",eax,ebx,ecx,edx); task_syscall(eax,ebx,ecx,edx); esp=my_scheduler(esp,2); // force scheduling of pid=2 (kernel worker) } if(irq==0 || irq==129)esp=my_scheduler(esp,-1); // autoschedule if(irq==255)kpanic("Unhandled Interrupt!"); return esp; } // log helpers // void errlog(uint32_t error_code) { klog("error_code: 0x%08X",error_code); } void defklog(uint32_t eip, uint16_t cs, uint32_t flags) { klog("eip: 0x%08X",eip); klog("segment: 0x%08X",cs); klog("eflags: 0x%08X",flags); } void show_error(uint32_t err) { klog("interrupt error code: 0x%08x",err); klog("External Event: %x",err&0b001); klog("Location: %x",err&0b110); klog("Selector: %x",err&0b1111111111111000); } // void int_default() { klog("default handler"); kpanic("unhandled interrupt (is this a panic or should just iognore?)"); } void exception_handle_0(){ kpanic("Divide by 0"); } void exception_handle_1(){ kpanic("Single step (debugger)"); } void exception_handle_2(){ kpanic("Non Maskable Interrupt"); } void exception_handle_3(){ kpanic("Breakpoint (debugger)"); } void exception_handle_4(){ kpanic("Overflow"); } void exception_handle_5(){ kpanic("Bounds check"); } void exception_handle_6(){ kpanic("Undefined OP Code"); } void exception_handle_7(){ kpanic("No coprocessor"); } void exception_handle_8(){ kpanic("Double Fault"); } void exception_handle_9(){ kpanic("Coprocessor Segment Overrun"); } void exception_handle_10(){ kpanic("Invalid TSS"); } void exception_handle_11(){ kpanic("Segment Not Present"); } void exception_handle_12(){ kpanic("Stack Segment Overrun"); } void exception_handle_13(uint32_t error_code,uint32_t eip,uint16_t cs,uint16_t unused, uint32_t flags) { errlog(error_code); defklog(eip,cs,flags); kpanic("Exception: Fault: General Protection Fault"); } void exception_handle_14(uint32_t error_code,uint32_t eip,uint16_t cs,uint16_t unused, uint32_t flags) { errlog(error_code); klog("error_code_P: %d",error_code&1?1:0); klog("error_code_W/R: %d",error_code&2?1:0); klog("error_code_U/S: %d",error_code&4?1:0); klog("error_code_RSVD: %d",error_code&8?1:0); klog("error_code_I/D: %d",error_code&16?1:0); klog("at addr: 0x%08X",x86_get_cr(2)); defklog(eip,cs,flags); kpanic("Exception: Fault: Page Fault"); } void exception_handle_15(){ kpanic("Unassigned"); } void exception_handle_16(){ kpanic("Coprocessor error"); } void exception_handle_17(){ kpanic("Alignment Check"); } void exception_handle_18(){ kpanic("Machine Check"); } // set default handler for all interrupts for a start void interrupts_init(uint16_t sel) { // Setup PIC klog("setting up PIC",&idt,&idtd); asm_pic_setup(); klog("initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd); // Default interrupt handling for(int i=0; i 32) int_install_ir(32, 0b10001110, 0x08,&int0); // Keyboard interrupt handler (irq 1 => 33) int_install_ir(33, 0b10001110, 0x08,&int1); // Mouse interrupt handler (irq 12 => 34) int_install_ir(44, 0b10001110, 0x08,&int12); // System Calls / they can be called from ring3 (0b11) int_install_ir(0x80, 0b11101110, 0x08,&int128); // Wake Scheduler int_install_ir(0x81, 0b11101110, 0x08,&int129); // install IVT int_install(); }