jankos/interrupts.c
shockrahwow 8c84915b71 removed int_keyboard
warning gets in the way and its not yet implemented anyway
2019-11-14 17:36:32 -08:00

213 lines
7.1 KiB
C

#include "stlio.h"
#include "interrupts.h"
#include "serial.h"
#include "mem.h"
#include "types.h"
#include "ports.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];
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];
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*));
// 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");
}