CeDOS - src/kernel/interrupts.c

src/kernel/interrupts.c (view raw)

#include "cedos/drivers/console.h"

#include "cedos/sched/sched.h"

#include "cedos/interrupts.h"
#include "cedos/pic.h"
#include "cedos/core.h"
#include "cedos/pit.h"

#define array_sizeof(array) (sizeof(array)/sizeof(array[0]))
#define NULL ((void*)0)

#define MAKE_IDT_ENTRY(func, selector, type) { \
        (uint16_t)(func), \
        (uint16_t)(selector), \
        0, \
        (uint8_t)(type), \
        (uint16_t)(0xC000) \
    }

INTERRUPT(default_isr, frame) {
    printk("interrupt was issued\n");
}

INTERRUPT(breakpoint_isr, frame) {
    printk("BREAKPOINT WAS HIT\n");
}

EXCEPTION(double_fault_isr, frame, error_code) {
    kpanic("CRITICAL: DOUBLE FAULT");
}

EXCEPTION(gpf_isr, frame, error_code) {
    kfault("CRITICAL: GENERAL PROTECTION FAULT", frame, error_code);
}

INTERRUPT(pic1_handler, frame) {
    printk("PIC1 INTERRUPT\n");
    pic1_eoi();
}

INTERRUPT(pic2_handler, frame) {
    printk("PIC2 INTERRUPT\n");
    pic2_eoi();
}

IDT_ENTRY IDT[INTERRUPT_COUNT];

void install_interrupt(int num, void* func, uint16_t selector, uint8_t type) {
    IDT[num].offset_0 = (uint16_t)((uint32_t)func);
    IDT[num].selector = selector;
    IDT[num].__zero = 0;
    IDT[num].type_attr = type;
    IDT[num].offset_16 = (uint16_t)((uint32_t)(func) >> 16);
}

struct {
    uint16_t limit;
    void* offset;
}__attribute__((packed)) IDT_DESC = {
    sizeof(IDT),
    IDT
};

int interrupts_init(void) {
    for (uint32_t i = 0; i < INTERRUPT_COUNT; i++) {
        if (i == 0x03) {
            install_interrupt(i, breakpoint_isr, 0x18, INT_GATE);
        } else if (i == 0x08) {
            install_interrupt(i, double_fault_isr, 0x18, INT_GATE);
        } else if (i == 0x0d) {
            install_interrupt(i, gpf_isr, 0x18, INT_GATE);
        } else if (i >= 0x21 || i < 0x28) {
            install_interrupt(i, pic1_handler, 0x18, INT_GATE);
        } else if (i >= 0x28 || i < 0x30) {
            install_interrupt(i, pic2_handler, 0x18, INT_GATE);
        } else {
            install_interrupt(i, default_isr, 0x18, INT_GATE);
        }
    }
    
    __asm__ volatile (
            "lidt (%0)\n" : : 
            "m" (IDT_DESC)
        );

    return 1;
}