#include #include #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 #define PIC2_COMMAND 0xA0 #define PIC2_DATA 0xA1 #define PIC_EOI 0x20 #define ICW1_INIT 0x10 #define ICW1_ICW4 0x01 #define ICW4_8086 0x01 void pic_send_eoi(uint8_t irq) { if (irq >= 8) { outb(PIC2_COMMAND, PIC_EOI); } outb(PIC1_COMMAND, PIC_EOI); } void pic_init(void) { outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait(); outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait(); // Remap Master PIC to 0x20 (32), Slave PIC to 0x28 (40) outb(PIC1_DATA, 0x20); io_wait(); outb(PIC2_DATA, 0x28); io_wait(); outb(PIC1_DATA, 4); // Tell Master that Slave is at IRQ2 io_wait(); outb(PIC2_DATA, 2); // Tell Slave its cascade identity io_wait(); outb(PIC1_DATA, ICW4_8086); io_wait(); outb(PIC2_DATA, ICW4_8086); io_wait(); // Mask all interrupts initially except Cascade (IRQ2) outb(PIC1_DATA, 0xFB); outb(PIC2_DATA, 0xFF); } void pic_set_mask(uint8_t irq) { uint16_t port; if (irq < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; irq -= 8; } uint8_t value = inb(port) | (1 << irq); outb(port, value); } void pic_clear_mask(uint8_t irq) { uint16_t port; if (irq < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; irq -= 8; uint8_t master_val = inb(PIC1_DATA) & ~(1 << 2); outb(PIC1_DATA, master_val); } uint8_t value = inb(port) & ~(1 << irq); outb(port, value); } void pic_disable(void) { outb(PIC1_DATA, 0xFF); outb(PIC2_DATA, 0xFF); }