diff --git a/arch/hwint.c b/arch/hwint.c index 03f207a..e18fd20 100644 --- a/arch/hwint.c +++ b/arch/hwint.c @@ -4,6 +4,7 @@ #include "config.h" #include "asm.h" #include "logger.h" +#include "pic.h" static const char *const messages[] = { "Unhandled hardware interrupt: 0", @@ -35,15 +36,7 @@ void hwint_handler(struct IsrRegisters regs) return; } - // Send an EOI (end of interrupt) signal to the PICs - - if (regs.int_no >= 40) { // TODO: hardcoded - // Send reset signal to slave - outportb(0xA0, 0x20); // TODO: hardcoded - } - - // Send reset signal to master - outportb(0x20, 0x20); // TODO: hardcoded + pic_end_of_interrupt(regs.int_no); const unsigned char hwint_no = regs.int_no - INT_HWINT_FIRST; diff --git a/arch/pic.c b/arch/pic.c index 165c6c2..3dfa147 100644 --- a/arch/pic.c +++ b/arch/pic.c @@ -9,10 +9,19 @@ #define SLAVE_COMMAND 0xA0 #define SLAVE_DATA 0xA1 -void pic_remap(const unsigned char master_irq_start, const unsigned char slave_irq_start) +#define IRQS_COUNT 8 + +static unsigned char master_irq_start = 0; +static unsigned char slave_irq_start = 8; + +void pic_remap(const unsigned char new_master_irq_start, const unsigned char new_slave_irq_start) { logger_info_from("pic", "Remap the IRQ table."); + // Remember IRQ numbers + master_irq_start = new_master_irq_start; + slave_irq_start = new_slave_irq_start; + // Save masks unsigned char master_mask = inportb(MASTER_DATA); unsigned char slave_mask = inportb(SLAVE_DATA); @@ -22,8 +31,8 @@ void pic_remap(const unsigned char master_irq_start, const unsigned char slave_i outportb(SLAVE_COMMAND, 0x11); // Set IRQ vectors - outportb(MASTER_DATA, master_irq_start); - outportb(SLAVE_DATA, slave_irq_start); + outportb(MASTER_DATA, new_master_irq_start); + outportb(SLAVE_DATA, new_slave_irq_start); // Connect master and slave with each other outportb(MASTER_DATA, 0x04); @@ -37,3 +46,19 @@ void pic_remap(const unsigned char master_irq_start, const unsigned char slave_i outportb(MASTER_DATA, master_mask); outportb(SLAVE_DATA, slave_mask); } + +void pic_end_of_interrupt(const unsigned char irq) +{ + const unsigned char to_master = master_irq_start <= irq && irq < master_irq_start + IRQS_COUNT; + const unsigned char to_slave = slave_irq_start <= irq && irq < slave_irq_start + IRQS_COUNT; + + if (!(to_master || to_slave)) { + return; + } + + if (to_slave) { + outportb(SLAVE_COMMAND, 0x20); + } + + outportb(MASTER_COMMAND, 0x20); +} diff --git a/arch/pic.h b/arch/pic.h index c1caa68..11f5238 100644 --- a/arch/pic.h +++ b/arch/pic.h @@ -3,4 +3,6 @@ void pic_remap(unsigned char master_irq_start, unsigned char slave_irq_start); +void pic_end_of_interrupt(unsigned char irq); + #endif