#define FOOLOS_MODULE_NAME "interrupts" #include "lib/logger/log.h" // logger facilities #include "interrupts.h" #include "lib/int/stdint.h" #include "x86.h" void int_clock_handler(); void int_kb_handler(); void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr); void int_default_handler(); void mouse_handler(); // 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]; // interrupt descriptor table descriptor static struct idt_desc { uint16_t size; uint16_t baseLo; uint16_t baseHi; } idtd; void int_default() { } void show_error(uint32_t err) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"interrupt error code: 0x%08x",err); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"External Event: %x",err&0b001); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Location: %x",err&0b110); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"Selector: %x",err&0b1111111111111000); } void int_irq0(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Divide by 0"); X86_IRQ_END } void int_irq1(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Single step (debugger)"); X86_IRQ_END } void int_irq2(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Non Maskable Interrupt"); X86_IRQ_END } void int_irq3(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Breakpoint (debugger)"); X86_IRQ_END } void int_irq4(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Overflow"); X86_IRQ_END } void int_irq5(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Bounds check"); X86_IRQ_END } void int_irq6(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Undefined OP Code"); X86_IRQ_END } void int_irq7(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"No coprocessor"); X86_IRQ_END } void int_irq8(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Double Fault"); X86_IRQ_END } void int_irq9(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor Segment Overrun"); X86_IRQ_END } void int_irq10(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Invalid TSS"); X86_IRQ_END } void int_irq11(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Segment Not Present"); X86_IRQ_END } void int_irq12(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Stack Segment Overrun"); X86_IRQ_END } void int_irq13() { X86_IRQ_BEGIN uint32_t err; asm("pop %eax"); // get Error Code asm ("mov %%eax, %0":"=r"(err)); show_error(err); panic(FOOLOS_MODULE_NAME,"General Protection Fault"); X86_IRQ_END } void int_irq14(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Page Fault"); X86_IRQ_END } void int_irq15(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Unassigned"); X86_IRQ_END } void int_irq16(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Coprocessor error"); X86_IRQ_END } void int_irq17(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Alignment Check"); X86_IRQ_END } void int_irq18(){ X86_IRQ_BEGIN panic(FOOLOS_MODULE_NAME,"Machine Check"); X86_IRQ_END } //set a handler for a specific interrupt void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr) { uint64_t base=(uint64_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; } // set default handler for all interrupts for a start void int_init(uint16_t sel) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"initializing. IDT: 0x%08x, IDTD: 0x%08X",&idt,&idtd); int i; for(i=0; i 32) int_install_ir(32, 0b10001110, 0x08,&int_clock_handler); // install keyboard interrupt handler (irq 1 => 33) int_install_ir(33, 0b10001110, 0x08,&int_kb_handler); #ifdef FOOLOS_COMPILE_FLOPPY // install floppy interrupt handler (irq 6 => 38) int_install_ir(38, 0b10001110, 0x08,&int_floppy_handler); #endif //mouse int_install_ir(44, 0b10001110, 0x08,&mouse_handler); int_install(); // now we can enable interrupts back again x86_int_enable(); } void int_install() { idtd.size=sizeof(struct int_desc)*INT_MAX; uint32_t addr=&idt[0]; idtd.baseHi=addr>>16; idtd.baseLo=0xffff&addr; __asm__("lidt %0"::"m" (idtd)); }