76 lines
2.3 KiB
C
76 lines
2.3 KiB
C
#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);
|
||
}
|