#include "types.h" #include "irq.h" /* Interrupts: * * 0x00 - 0x1F exceptions / Intel reserved * 0x20 - 0x2F hardware interrupts * 0x30 - system interrupts */ #define ICW1_ICW4 0x01 #define ICW1_SINGLE 0x02 #define ICW1_INTERVAL4 0x04 #define ICW1_LEVEL 0x08 #define ICW1_INIT 0x10 #define ICW4_8086 0x01 #define ICW4_AUTO 0x02 #define ICW4_BUF_SLAVE 0x08 #define ICW4_BUF_MASTER 0x0c #define ICW4_SFNM 0x10 #define IDT_PRESENT 0x80 #define IDT_DPL(x) ((x) << 5) // ASM linkages //void enable_interrupts(); void load_idt(); void isr0(); void isr13(); void isr14(); void isr32(); void isr33(); void isr128(); struct idt_entry idt[256]; struct idt_descriptor idt_p; void sti() { __asm__("sti"); } void cli() { __asm__("cli"); } void set_idt_gate(unsigned char n, unsigned short selector, unsigned long base, unsigned char flags) { struct idt_entry *e = &idt[n]; e->base_low = base & 0xFFFF; e->base_high = (base >> 16) & 0xFFFF; e->selector = selector; e->flags = flags | 0x0E; } void install_isr(unsigned char n, isr_t isr) { set_idt_gate(n, 0x08, (unsigned int)isr, IDT_PRESENT | IDT_DPL(0)); } void remap_pics(int offset1, int offset2) { unsigned char m1, m2; // Store masks m1 = inportb(PIC1_DATA); m2 = inportb(PIC2_DATA); // Start initialization outportb(PIC1_COMMAND, ICW1_INIT + ICW1_ICW4); iowait(); outportb(PIC2_COMMAND, ICW1_INIT + ICW1_ICW4); iowait(); // Define vectors outportb(PIC1_DATA, offset1); iowait(); outportb(PIC2_DATA, offset2); iowait(); // Important stuff outportb(PIC1_DATA, 4); iowait(); outportb(PIC2_DATA, 2); iowait(); outportb(PIC1_DATA, ICW4_8086); iowait(); outportb(PIC2_DATA, ICW4_8086); iowait(); // Restore masks outportb(PIC1_DATA, m1); outportb(PIC2_DATA, m2); } void set_pic_masks(unsigned char m1, unsigned char m2) { outportb(PIC1_DATA, m1); outportb(PIC2_DATA, m2); } void install_isr(unsigned char n, void (*isr)()) { set_idt_gate(n, 0x08, (unsigned int)isr, IDT_PRESENT | IDT_DPL(0)); } void irq_mask_bit_clear(uchar b1, uchar b2) { uchar m1 = inportb(PIC1_DATA); uchar m2 = inportb(PIC2_DATA); outportb(PIC1_DATA, m1 & ~b1); outportb(PIC2_DATA, m2 & ~b2); } void irq_mask_bit_set(uchar b1, uchar b2) { uchar m1 = inportb(PIC1_DATA); uchar m2 = inportb(PIC2_DATA); outportb(PIC1_DATA, m1 | b1); outportb(PIC2_DATA, m2 | b2); } void irq_init() { // Remap hardware interrupts to proper range remap_pics(0x20, 0x28); // Init IDT memset(&idt, 0, 256 * sizeof(struct idt_entry)); // Set some handlers set_idt_gate(0, 0x08, (unsigned int)&isr0, IDT_PRESENT | IDT_DPL(0)); set_idt_gate(13, 0x08, (unsigned int)&isr13, IDT_PRESENT | IDT_DPL(0)); set_idt_gate(14, 0x08, (unsigned int)&isr14, IDT_PRESENT | IDT_DPL(0)); set_idt_gate(32, 0x08, (unsigned int)&isr32, IDT_PRESENT | IDT_DPL(0)); set_idt_gate(33, 0x08, (unsigned int)&isr33, IDT_PRESENT | IDT_DPL(0)); set_idt_gate(128, 0x08, (unsigned int)&isr128, IDT_PRESENT | IDT_DPL(0)); idt_p.limit = 256 * sizeof(struct idt_entry) - 1; idt_p.base = (unsigned int)&idt; printf(" IRQ: Loading IDT\n"); // Load IDT load_idt(); // Enable only keyboard controller and timer set_pic_masks(0xFC, 0xFF); // // Enable hw interrupts // // NOOOO DON'T ENABLE THEM // sti(); } // Division by zero void interrupt_0() { panic("Division by zero, OH SHI--"); } // General Protection Fault void interrupt_13() { panic("General Protection Fault! "); }