/* GDT・IDT */

#include "bootpack.h"

void gdtidt_init(void)
{
	struct segdesc *gdt = (struct segdesc *) GDT_ADDR;
	struct gatedesc *idt = (struct gatedesc *) IDT_ADDR;
	int i;

	/* GDTの初期化 */
	for(i = 0; i <= GDT_LIMIT / 8; i++) {
		seg_set(gdt + i, 0, 0, 0);
	}
	lgdtr(GDT_LIMIT, GDT_ADDR);

	/* GDTの設定 */
	seg_set(gdt + 1,     GDT1_ADDR,     GDT1_LIMIT, AR_DATA_RW);	/* メモリ全体 */
	seg_set(gdt + 2, BOOTPACK_ADDR, BOOTPACK_LIMIT, AR_CODE_ER);	/* bootpack.hrb */

	/* IDTの初期化 */
	for(i = 0; i <= IDT_LIMIT / 8; i++) {
		gate_set(idt + i, 0, 0, 0);
	}
	lidtr(IDT_LIMIT, IDT_ADDR);

	/*
	  IDTの設定
	  int 0x07: except_asm_fpu		: FPU例外
	  int 0x0c: except_asm_stack	: スタック例外
	  int 0x0d: except_asm_general	: 一般保護例外
	  int 0x20: timer_aihandle		: タイマ
	  int 0x21: keyboard_aihandle	: キーボード
	  int 0x26: fdc_aihandle		: FDC
	  int 0x27: except_adm_dfint	: 不完全割り込み
	  int 0x2c: mouse_aihandle		: マウス
	  int 0x30: api_asm				: TbitOS専用のAPI
	  int 0x40: api_haritomo_asm	: はりぼて共通API（未実装）
	*/
	gate_set(idt + 0x07, (int) except_asm_fpu, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x0c, (int) except_asm_stack, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x0d, (int) except_asm_general, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x20, (int) timer_aihandle, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x21, (int) keyboard_aihandle, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x26, (int) fdc_aihandle, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x27, (int) except_asm_dfint, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x2c, (int) mouse_aihandle, 2 * 8, AR_INTGATE);
	gate_set(idt + 0x30, (int) api_asm, 2 * 8, AR_INTGATE + AR_APP);
	return;
}

void seg_set(struct segdesc *sd, unsigned int base, unsigned int limit, int ar)
{
	if(limit > 0xfffff) {
		ar |= 0x8000;		/* G-bit on */
		limit /= 0x1000;	/* 4KB単位にする */
	}
	sd->limit_low = limit & 0xffff;
	sd->base_low = base & 0xffff;
	sd->base_mid = (base >> 16) & 0xff;
	sd->access = ar & 0xff;
	sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
	sd->base_high = (base >> 24) & 0xff;
	return;
}

void gate_set(struct gatedesc *gd, int offset, int selector, int ar)
{
	gd->offset_low = offset & 0xffff;
	gd->selector = selector;
	gd->dw_count = (ar >> 8) & 0xff;
	gd->access = ar & 0xff;
	gd->offset_high = (offset >> 16) & 0xffff;
	return;
}
