#include "stlio.h" #include "interrupts.h" #include "serial.h" #include "mem.h" #include "types.h" #include "ports.h" #include "pit.h" #include "kbd.h" const char* err_msg[] = { "Divide by zero\n", "Debug Exception\n", "Non Maskable Interrupt Exception\n", "Breakpoint Exception\n", "Into Detected Overflow Exception\n", "Out of Bounds Exception\n", "Invalid Opcode Exception\n", "No Coprocessor Exception\n", "Double Fault Exception\n", "Coprocessor Segment Overrun Exception\n", "Bad TSS Exception\n", "Segment Not Present Exception\n", "Stack Fault Exception\n", "General Protection Fault Exception\n", "Page Fault Exception\n", "Unknown Interrupt Exception\n", "Coprocessor Fault Exception\n", "Alignment Check Exception (486+)\n", "Machine Check Exception (Pentium/586+)\n", "Reserved Exceptions\n", /* for 19 - 31 */ }; extern void load_idt(); // found in interrupts_entry.s extern void no_err_handler_0(); extern void no_err_handler_1(); extern void no_err_handler_2(); extern void no_err_handler_3(); extern void no_err_handler_4(); extern void no_err_handler_5(); extern void no_err_handler_6(); extern void no_err_handler_7(); extern void err_code_handler_8(); extern void no_err_handler_9(); extern void err_code_handler_10(); extern void err_code_handler_11(); extern void err_code_handler_12(); extern void err_code_handler_13(); extern void err_code_handler_14(); extern void no_err_handler_15(); extern void no_err_handler_16(); extern void no_err_handler_17(); extern void no_err_handler_18(); extern void no_err_handler_19(); extern void no_err_handler_20(); extern void no_err_handler_21(); extern void no_err_handler_22(); extern void no_err_handler_23(); extern void no_err_handler_24(); extern void no_err_handler_25(); extern void no_err_handler_26(); extern void no_err_handler_27(); extern void no_err_handler_28(); extern void no_err_handler_29(); extern void no_err_handler_30(); extern void no_err_handler_31(); // Remapped IRQ's extern void irq_handler_0(); extern void irq_handler_1(); extern void irq_handler_2(); extern void irq_handler_3(); extern void irq_handler_4(); extern void irq_handler_5(); extern void irq_handler_6(); extern void irq_handler_7(); extern void irq_handler_8(); extern void irq_handler_9(); extern void irq_handler_10(); extern void irq_handler_11(); extern void irq_handler_12(); extern void irq_handler_13(); extern void irq_handler_14(); extern void irq_handler_15(); void* irq_handlers[16] = {0}; void setup_idt_entry(u32 t_idx, u32 base, u16 sel, u8 type_attrs) { // Configuring a single given entry in the IDT table IDT[t_idx].offset_low = (base & 0xffff); IDT[t_idx].offset_high = ((base >> 16) & 0xffff); IDT[t_idx].type_attrs = type_attrs; IDT[t_idx].zero = 0; IDT[t_idx].selector = sel; } // Generic interrupt handler to be used later on void interrupt_handler(struct cpu_reg_state* cpu) { // treating things on the stack like it were a cpu_reg_state // NOTE: dummy stuff to stop gcc from complaining atm printf("handled exception\n"); if(cpu->int_no < 32) { printf(err_msg[cpu->int_no]); } return; } // Pass the index into the table and the handler(strut* cpu_reg_state) void init_irq_handler(u32 irq, void (*handler)(struct cpu_reg_state* cpu)) { // install handle irq_handlers[irq] = handler; } void irq_handler(struct cpu_reg_state* cpu) { void (*handler)(struct cpu_reg_state* cpu); // Dispatcher for irq's handler = irq_handlers[cpu->int_no - 0x20]; // Handler the timer by hand because fuck this tbh if(handler) { handler(cpu); } // pretend like nothing happend for now if(cpu->int_no >= 40) { serialport_write_byte(0xa0, 0x20); } // notify master pic controller that we're done handling the interrupt serialport_write_byte(0x20, 0x20); } void init_idt() { // setup special idt pointer idt_ptr.address = (u32)(&IDT); idt_ptr.limit = (sizeof(struct IDT_Entry) * IDT_SIZE) - 1; // clear table memset((u8*)IDT, 0x00, (sizeof(struct IDT_Entry) * IDT_SIZE)); // add interrupt service routines here setup_idt_entry(0,(u32)no_err_handler_0,0x08, 0x8e); setup_idt_entry(1,(u32)no_err_handler_1,0x08, 0x8e); setup_idt_entry(2,(u32)no_err_handler_2,0x08, 0x8e); setup_idt_entry(3,(u32)no_err_handler_3,0x08, 0x8e); setup_idt_entry(4,(u32)no_err_handler_4,0x08, 0x8e); setup_idt_entry(5,(u32)no_err_handler_5,0x08, 0x8e); setup_idt_entry(6,(u32)no_err_handler_6,0x08, 0x8e); setup_idt_entry(7,(u32)no_err_handler_7,0x08, 0x8e); setup_idt_entry(8,(u32)err_code_handler_8,0x08, 0x8e); setup_idt_entry(9,(u32)no_err_handler_9,0x08, 0x8e); setup_idt_entry(10,(u32)err_code_handler_10,0x08, 0x8e); setup_idt_entry(11,(u32)err_code_handler_11,0x08, 0x8e); setup_idt_entry(12,(u32)err_code_handler_12,0x08, 0x8e); setup_idt_entry(13,(u32)err_code_handler_13,0x08, 0x8e); setup_idt_entry(14,(u32)err_code_handler_14,0x08, 0x8e); setup_idt_entry(15,(u32)no_err_handler_15,0x08, 0x8e); setup_idt_entry(16,(u32)no_err_handler_16,0x08, 0x8e); setup_idt_entry(17,(u32)no_err_handler_17,0x08, 0x8e); setup_idt_entry(18,(u32)no_err_handler_18,0x08, 0x8e); setup_idt_entry(19,(u32)no_err_handler_19,0x08, 0x8e); setup_idt_entry(20,(u32)no_err_handler_20,0x08, 0x8e); setup_idt_entry(21,(u32)no_err_handler_21,0x08, 0x8e); setup_idt_entry(22,(u32)no_err_handler_22,0x08, 0x8e); setup_idt_entry(23,(u32)no_err_handler_23,0x08, 0x8e); setup_idt_entry(24,(u32)no_err_handler_24,0x08, 0x8e); setup_idt_entry(25,(u32)no_err_handler_25,0x08, 0x8e); setup_idt_entry(26,(u32)no_err_handler_26,0x08, 0x8e); setup_idt_entry(27,(u32)no_err_handler_27,0x08, 0x8e); setup_idt_entry(28,(u32)no_err_handler_28,0x08, 0x8e); setup_idt_entry(29,(u32)no_err_handler_29,0x08, 0x8e); setup_idt_entry(30,(u32)no_err_handler_30,0x08, 0x8e); setup_idt_entry(31,(u32)no_err_handler_31,0x08, 0x8e); // Load IDT with all the new information in place, ready to use load_idt(); // clear table in case there's garbage in there memset((u8*)irq_handlers, 0, sizeof(void*)); irq_handlers[0] = pit_inc_ticks; // LULW // Remap irq's to proper location serialport_write_byte(0x20, 0x11); serialport_write_byte(0xA0, 0x11); serialport_write_byte(0x21, 0x20); serialport_write_byte(0xA1, 0x28); serialport_write_byte(0x21, 0x04); serialport_write_byte(0xA1, 0x02); serialport_write_byte(0x21, 0x01); serialport_write_byte(0xA1, 0x01); serialport_write_byte(0x21, 0x0); serialport_write_byte(0xA1, 0x0); // Install handlers for irq's setup_idt_entry(32,(u32)irq_handler_0,0x08, 0x8e); setup_idt_entry(33,(u32)irq_handler_1,0x08, 0x8e); setup_idt_entry(34,(u32)irq_handler_2,0x08, 0x8e); setup_idt_entry(35,(u32)irq_handler_3,0x08, 0x8e); setup_idt_entry(36,(u32)irq_handler_4,0x08, 0x8e); setup_idt_entry(37,(u32)irq_handler_5,0x08, 0x8e); setup_idt_entry(38,(u32)irq_handler_6,0x08, 0x8e); setup_idt_entry(39,(u32)irq_handler_7,0x08, 0x8e); setup_idt_entry(40,(u32)irq_handler_8,0x08, 0x8e); setup_idt_entry(41,(u32)irq_handler_9,0x08, 0x8e); setup_idt_entry(42,(u32)irq_handler_10,0x08, 0x8e); setup_idt_entry(43,(u32)irq_handler_11,0x08, 0x8e); setup_idt_entry(44,(u32)irq_handler_12,0x08, 0x8e); setup_idt_entry(45,(u32)irq_handler_13,0x08, 0x8e); setup_idt_entry(46,(u32)irq_handler_14,0x08, 0x8e); setup_idt_entry(47,(u32)irq_handler_15,0x08, 0x8e); // Enable interrupt flags __asm__ __volatile__("sti"); }