#include "../includes/pic.h" #include "../includes/io.h" #include "../includes/idt.h" #include "../includes/irq.h" #define PIC1_PORT 0x20 #define PIC1_DATA_PORT 0X21 #define PIC2_PORT 0xA0 #define PIC2_DATA_PORT 0XA1 #define PIC1_START_INTERRUPT 0x20 #define PIC2_START_INTERRUPT 0x28 #define PIC2_END_INTERRUPT PIC2_START_INTERRUPT + 7 #define PIC_ACK 0x20 void pic_acknowledge(unsigned int interrupt_no) { if (interrupt_no < PIC2_START_INTERRUPT) outb(PIC1_PORT, PIC_ACK); else outb(PIC2_PORT, PIC_ACK); } void setup_pics(void) { // The PIC uses Initialization Command Words (ICW) to communicate. // So we start with the first ICW, 0x11, this tells the PIC to expect // 3 more ICWs. outb(PIC1_PORT, 0x11); outb(PIC2_PORT, 0x11); // This tells the pic what offset to use when it generates the interrupt numbers. // Since the first 32 ISRs are reserved by the CPU we must start at IRS32 and work // our way up. When the PIC recieves an interrupt on it's input line, it will add // the supplied values to that number before sending the newly made number to the CPU. // Thereby remapping an interrupt number that would have normally conflicted with the // values in the IDT. outb(PIC1_DATA_PORT, PIC1_START_INTERRUPT); outb(PIC2_DATA_PORT, PIC2_START_INTERRUPT); // This ICW allows for cascading of their outputs to inputs between each other. // I'm not sure what that really means but at this current time I'm not going to // be doing this, so the bits will all be set to zero. outb(PIC1_DATA_PORT, 0x00); outb(PIC2_DATA_PORT, 0x00); // This is the environment info, and setting the lowest bit tells the PICs // that we're running in 80x86 mode. outb(PIC1_DATA_PORT, 0x01); outb(PIC2_DATA_PORT, 0x01); // Finally, we have the interrupt masks. outb(PIC1_DATA_PORT, 0xFF); outb(PIC2_DATA_PORT, 0xFF); idt_set_gate(33, (unsigned long) &irq1, 0x08, 0x8E); }