#ifdef __TESTING__ #include #endif #include #include void PIC_sendEOI(uint8_t irq) { if (irq >= 8) // if we're over the PIC1 limit outb(PIC2_COMMAND, PIC_EOI); outb(PIC1_COMMAND, PIC_EOI); // if the IRQ came from the slave, it must go to both PICs } void PIC_remap(int offset1, int offset2) { #ifdef __TESTING__ kinfo("Remapping the PIC..."); #endif // The io_wait calls are necessary for older machines, to give the PIC time to react // // After the init, the PIC requires 3 init words // ICW2 // its vector offset // ICW3 // how its wired to the master/slave // ICW4 // additional info about the environment outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the init sequence, in cascade mode io_wait(); outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); io_wait(); outb(PIC1_DATA, offset1); // ICW2 - the offset for master io_wait(); outb(PIC2_DATA, offset2); // same as above for slave io_wait(); outb(PIC1_DATA, 4); // ICW3 - Tells master theres a slave at IRQ2 io_wait(); outb(PIC2_DATA, 2); // ICW3 - Tells slave the cascade identity io_wait(); outb(PIC1_DATA, ICW4_8086); // ICW4 - Use 8086 mode (not 8080 mode) io_wait(); outb(PIC2_DATA, ICW4_8086); io_wait(); // Unmask the PICs outb(PIC1_DATA, 0); outb(PIC2_DATA, 0); #ifdef __TESTING__ kinfo("Remapped the PIC!"); #endif } void pic_disable(void) { // Mask the PIC interrupts to disable them outb(PIC1_DATA, 0xFF); outb(PIC2_DATA, 0xFF); #ifdef __TESTING__ kinfo("Disabled the PIC"); #endif } void IRQ_set_mask(uint8_t IRQline) // Masked IRQlines are ignored by the PIC, masked IRQ2 will fully ignore the slave { uint16_t port; uint8_t value; if (IRQline < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; IRQline -= 8; } value = inb(port) | (1 << IRQline); outb(port, value); } void IRQ_clear_mask(uint8_t IRQline) { uint16_t port; uint8_t value; if (IRQline < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; IRQline -= 8; } value = inb(port) & ~(1 << IRQline); outb(port, value); } static uint16_t __pic_get_irq_reg(int ocw3) { /** OCW3 to PIC CMD to get the register values * PIC2 is chained, and represents IRQs 8-1. * PIC1 is IRQs 0-7, with 2 being the chain **/ outb(PIC1_COMMAND, ocw3); outb(PIC2_COMMAND, ocw3); return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND); } uint16_t pic_get_irr(void) { return __pic_get_irq_reg(PIC_READ_IRR); } uint16_t pic_get_isr(void) { return __pic_get_irq_reg(PIC_READ_ISR); }