#include "desctbl.h"

struct SegmentDescriptor {
    short limit_low, base_low;
    char  base_mid, access_right;
    char  limit_high, base_high;
} __attribute__((packed));

struct GateDescriptor {
    short offset_low, selector;
    char  dw_count, access_right;
    short offset_high;
} __attribute__((packed));

#define ADR_IDT   0x0026f800
#define LIMIT_IDT 0x000007ff

#define AR_INTGATE32 0x008e

void load_idtr(int limit, int addr);
int  get_cs(void);

static void set_gatedesc(struct GateDescriptor *gd, int offset, int selector, int ar)
{
    gd->offset_low   = offset & 0xffff;
    gd->selector     = selector;
    gd->dw_count     = (ar >> 8) & 0xff;
    gd->access_right = ar & 0xff;
    gd->offset_high  = (offset >> 16) & 0xffff;
}

extern void asm_int_handler21(void);

void init_gdtidt(void)
{
    struct GateDescriptor *idt = (struct GateDescriptor *)ADR_IDT;
    int i;
    int cs = get_cs();

    for (i = 0; i <= LIMIT_IDT / 8; i++) {
        set_gatedesc(idt + i, 0, 0, 0);
    }
    load_idtr(LIMIT_IDT, ADR_IDT);

    set_gatedesc(idt + 0x21, (int)asm_int_handler21, cs, AR_INTGATE32);
}