#include "pic.h" #include "io.h" #include "logger.h" #define PIC1_COMMAND 0x20 #define PIC1_DATA 0x21 #define PIC2_COMMAND 0xA0 #define PIC2_DATA 0xA1 #define ICW1_INIT 0x10 // Инициализация #define ICW1_IC4 0x01 // Будет ICW4 #define ICW4_8086 0x01 // Режим 8086/8186 void pic_remap(uint8_t master_offset, uint8_t slave_offset) { log_info(LOG_DETAIL, "Remapping PIC..."); // Сохраняем текущие маски прерываний (какое железо сейчас отключено) uint8_t a1 = inb(PIC1_DATA); uint8_t a2 = inb(PIC2_DATA); // Свисток к началу инициализации (ICW1) outb(PIC1_COMMAND, ICW1_INIT | ICW1_IC4); io_wait(); outb(PIC2_COMMAND, ICW1_INIT | ICW1_IC4); io_wait(); // Задаем новые смещения векторов (ICW2) outb(PIC1_DATA, master_offset); // Master IRQ 0-7 -> вешаем на master_offset (32) io_wait(); outb(PIC2_DATA, slave_offset); // Slave IRQ 8-15 -> вешаем на slave_offset (40) io_wait(); // Связываем Master и Slave между собой (ICW3) outb(PIC1_DATA, 4); // Сообщаем Master, что Slave сидит на IRQ2 (00000100б = 4) io_wait(); outb(PIC2_DATA, 2); // Сообщаем Slave его каскадный ID (2) io_wait(); // Включаем режим 8086 (ICW4) outb(PIC1_DATA, ICW4_8086); io_wait(); outb(PIC2_DATA, ICW4_8086); io_wait(); // Восстанавливаем сохраненные маски outb(PIC1_DATA, a1); outb(PIC2_DATA, a2); log_info(LOG_DETAIL, "PIC remapped"); } // Запретить прерывание от конкретного IRQ void pic_set_mask(uint8_t irq_line) { uint16_t port; if (irq_line < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; irq_line -= 8; } uint8_t value = inb(port) | (1 << irq_line); outb(port, value); } // Разрешить прерывание от конкретного IRQ void pic_clear_mask(uint8_t irq_line) { uint16_t port; if (irq_line < 8) { port = PIC1_DATA; } else { port = PIC2_DATA; irq_line -= 8; } uint8_t value = inb(port) & ~(1 << irq_line); outb(port, value); }