#include <stdint.h>

#include "gdt.h"
#include "idt.h"
#include "bits.h"



typedef struct {
    uint16_t offset_low;
    uint16_t selector;
    uint8_t reserved;
    uint8_t flags;
    uint16_t offset_high;
} idt_entry_t;


typedef struct {
    uint16_t limit;
    uint32_t base;
} __attribute__((packed)) idtr_t;


extern void* isr_stub_table[];

__attribute__((aligned(0x10)))
static idt_entry_t idt[IDT_MAX_VECTORS] = { 0 };

static idtr_t idtr;

void idt_set_desc(uint8_t vector, const void *isr, uint8_t flags) {
    idt_entry_t *desc = &idt[vector];

    desc->offset_low = (uintptr_t)isr & 0xFFFF;
    desc->reserved = 0;
    desc->selector = GDT_OFFSET_KERNEL_CODE;
    desc->flags = flags;
    desc->offset_high = ((uintptr_t)isr >> 16) & 0xFFFF;
}

void idt_init() {
    idtr.base = (uintptr_t)&idt[0];
    idtr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_VECTORS - 1;

    for (uint8_t vector = 0; vector < IDT_RESERVED_VECTORS; ++vector) {
        idt_set_desc(vector, isr_stub_table[vector], IDTENTRY_KERNEL_INT);
    }

    __asm__ volatile ("lidt %0" : : "m"(idtr)); // load the new IDT
}