Newer
Older
tree-os / src / kernel / drivers / interrupts / irqs.c
#include <_stdio.h>
#include <interrupts.h>
#include <irqs.h>
#include <ports.h>
#include <task.h>
#include <timer.h>

#define OFFSET_1 32
#define OFFSET_2 40

void remapPIC(int offset1, int offset2) {
    printf("remapping PIC\n");
    outb(0x20, 0x11);
    outb(0xA0, 0x11);
    outb(0x21, 0x20);
    outb(0xA1, offset1);
    outb(0x21, offset2);
    outb(0xA1, 0x02);
    outb(0x21, 0x01);
    outb(0xA1, 0x01);
    outb(0x21, 0x0);
    outb(0xA1, 0x0);
}

void setupIRQs() {
    printf("setting IRQs\n");
    setInterrupt(OFFSET_1 + 0, &irqHandler0);
    setInterrupt(OFFSET_1 + 1, &irqHandler1);
    setInterrupt(OFFSET_1 + 2, &irqHandler2);
    setInterrupt(OFFSET_1 + 3, &irqHandler3);
    setInterrupt(OFFSET_1 + 4, &irqHandler4);
    setInterrupt(OFFSET_1 + 5, &irqHandler5);
    setInterrupt(OFFSET_1 + 6, &irqHandler6);
    setInterrupt(OFFSET_1 + 7, &irqHandler7);
    setInterrupt(OFFSET_2 + 0, &irqHandler8);
    setInterrupt(OFFSET_2 + 1, &irqHandler9);
    setInterrupt(OFFSET_2 + 2, &irqHandler10);
    setInterrupt(OFFSET_2 + 3, &irqHandler11);
    setInterrupt(OFFSET_2 + 4, &irqHandler12);
    setInterrupt(OFFSET_2 + 5, &irqHandler13);
    setInterrupt(OFFSET_2 + 6, &irqHandler14);
    setInterrupt(OFFSET_2 + 7, &irqHandler15);
    remapPIC(OFFSET_1, OFFSET_2);
}

void *irqHandlers[16];

void setIRQHandler(uint8_t irqNumber, void *fun) {
    irqHandlers[irqNumber] = fun;
}

void handleIRQ(regs *registers) {
    if (registers->int_no >= OFFSET_2) {
        outb(0xA0, 0x20);
    }
    outb(0x20, 0x20);
    uint8_t irqNumber = registers->int_no - OFFSET_1;
    void (*handler)() = irqHandlers[irqNumber];
    if (handler) {
        handler();
        return;
    }
    if (irqNumber == 7 || irqNumber == 2) {
        // irq2 should not be fired, irq 7 indicates a spurious irq
        return;
    }
    printf("unhandeled IRQ no. 0x%x was triggered!\n", irqNumber);
}