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

extern "C" {
extern void asm_int_handler0(void);
extern void asm_int_handler1(void);
}

void Idt::init(void) {
    table.limit  = Idt::NUM * sizeof(IdtEntry) - 1;
    table.offset = (uint32)entry;
    for (int i = 0; i < Idt::NUM; i++) {
        set(i, 0, 0, 0, 0);
    }
    set(0x20, (uint32)asm_int_handler0, 
        Gdt::KERNEL_CS * sizeof(GdtEntry), 0, 0x8E); 
    set(0x21, (uint32)asm_int_handler1, 
        Gdt::KERNEL_CS * sizeof(GdtEntry), 0, 0x8E); 
    load();
}

void Idt::set(int index, uint32 offset, uint16 selector, uint8 copy, uint8 type) {
    IdtEntry& desc = entry[index];

    desc.offset_low = offset & 0xFFFF;
    desc.offset_hi  = (offset >> 16) & 0xFFFF;
    desc.selector   = selector;
    desc.copy       = copy;
    desc.type       = type;
}

void Idt::load(void) const
{
    __asm__ __volatile__("lidt %0" :: "m" (table));
}
