summaryrefslogtreecommitdiff
path: root/kernel/src/interrupt/idt.c
blob: 6df37938d8f6c85d0c6e9da3d6f4a514f218e330 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys.h>
#include <print.h>
#include <panic.h>

#include "acpi/acpi.h"
#include "drivers/ps2kb.h"
#include "drivers/ps2mouse.h"
#include "tty/color.h"
#include "idt.h"
#include "pic.h"
#include "tty/term.h"

static int timer = 0;

void idt_pic_eoi(uint8_t exception) {
	pic_eoi(exception - PIC_REMAP_OFFSET);
}

void idt_pic_timer(void) {
	uint32_t state = term_save();
	term_setfg(VGA_LIGHT_GREEN);
	term_setpos(60, 0);
	puts("        ");
	term_setpos(60, 0);
	printk("%d", timer);
	timer += 1;
	term_load(state);
}

void idt_pic_keyboard(void) {
	ps2kb_recv();
}

void idt_pic_mouse(void) {
	ps2mouse_recv();
}

void idt_exception_handler(uint8_t exception) {
	char* msg;
	switch(exception) {
		case 0x00:
			msg = "Division by zero";
			break;
		case 0x02:
			msg = "NMI";
			break;
		case 0x04:
			msg = "Overflow";
			break;
		case 0x06:
			msg = "invalid opcode";
			break;
		case 0x08:
			msg = "double fault";
			break;
		case 0x0A:
			msg = "invalid task state segment";
			break;
		case 0x0C:
			msg = "stack segment fault";
			break;
		case 0x0D:
			msg = "general protection fault";
			break;
		case 0x0E:
			msg = "page fault";
			break;
		default:
			msg = "unknown exception";
			break;
	}
	panic("E%u: %s", exception, msg);
}

__attribute__((aligned(0x10)))
static struct IdtEntry idt[256];
static struct Idtr idtr;
extern void* isr_stub_table[];

static void set_descriptor(uint8_t vector, void* isr, uint8_t flags) {
	struct IdtEntry* entry = &idt[vector];
	entry->isr_low = (size_t)isr & 0xffff;
	entry->kernel_cs = 0x08;
	entry->attributes = flags;
	entry->isr_high = (size_t)isr >> 16;
	entry->_reserved = 0;
}

void idt_init(void) {

    debugk("Loading IDT");

	idtr.base = (uintptr_t)&idt[0];
	idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1;

	for(int i = 0; i < IDT_INTERRUPTS; i++) {
		set_descriptor(i, isr_stub_table[i], 0x8e);
	}

	__asm__ volatile ("lidt %0" : : "m"(idtr));

    succek("IDT has been loaded");
}