os/irq.c
2024-05-23 20:59:18 +03:00

92 lines
2.2 KiB
C

#include <stdint.h>
#include "interrupts.h"
#include "io.h"
#include "sys.h"
#include "idt.h"
#include "tty.h"
extern void irq0(void);
extern void irq1(void);
extern void irq2(void);
extern void irq3(void);
extern void irq4(void);
extern void irq5(void);
extern void irq6(void);
extern void irq7(void);
extern void irq8(void);
extern void irq9(void);
extern void irq10(void);
extern void irq11(void);
extern void irq12(void);
extern void irq13(void);
extern void irq14(void);
extern void irq15(void);
void *irq_routines[NB_IRQ_ROUTINES] = {0};
void irq_install_handler(uint8_t irq, void (*handler)(Stack *registers))
{
irq_routines[irq] = handler;
}
void irq_uninstall_handler(uint8_t irq)
{
irq_routines[irq] = 0;
}
void irq_call_handler(Stack *registers)
{
void (*handler)(Stack *registers);
handler = irq_routines[registers->id - 32];
if (handler)
handler(registers);
}
static void irq_remap(void) // PIC REMAP
{
outb(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
outb(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
outb(PIC1_DATA, PIC1_OFFSET);
outb(PIC2_DATA, PIC2_OFFSET);
outb(PIC1_DATA, 0x04);
outb(PIC2_DATA, 0x02);
outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086);
}
void irq_install(void)
{
irq_remap();
idt_set_gate(32, (uint32_t)irq0, 0x08, 0x8E);
idt_set_gate(33, (uint32_t)irq1, 0x08, 0x8E);
idt_set_gate(34, (uint32_t)irq2, 0x08, 0x8E);
idt_set_gate(35, (uint32_t)irq3, 0x08, 0x8E);
idt_set_gate(36, (uint32_t)irq4, 0x08, 0x8E);
idt_set_gate(37, (uint32_t)irq5, 0x08, 0x8E);
idt_set_gate(38, (uint32_t)irq6, 0x08, 0x8E);
idt_set_gate(39, (uint32_t)irq7, 0x08, 0x8E);
idt_set_gate(40, (uint32_t)irq8, 0x08, 0x8E);
idt_set_gate(41, (uint32_t)irq9, 0x08, 0x8E);
idt_set_gate(42, (uint32_t)irq10, 0x08, 0x8E);
idt_set_gate(43, (uint32_t)irq11, 0x08, 0x8E);
idt_set_gate(44, (uint32_t)irq12, 0x08, 0x8E);
idt_set_gate(45, (uint32_t)irq13, 0x08, 0x8E);
idt_set_gate(46, (uint32_t)irq14, 0x08, 0x8E);
idt_set_gate(47, (uint32_t)irq15, 0x08, 0x8E);
sys_enable_interrupts();
}
void irq_handler(Stack *registers)
{
irq_call_handler(registers);
if (registers->id >= 40)
{
outb(PIC2_CMD, PIC_EOI);
}
outb(PIC1_CMD, PIC_EOI);
}