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
|
#include "clock.h"
#include "def.h"
#include "halt.h"
#include "font.h"
#include "heap.h"
#include "pic.h"
#include "thread.h"
#include "io.h"
#include "string.h"
#include "debug.h"
extern u64 idt_entries[256]; // isr.asm
void interrupt_handler(interrupt_frame *frame)
{
if (frame->which < 32) {
debug_exception(frame);
} else if (frame->which-32 < 16) {
u64 irq = frame->which-32;
if (irq == 8) {
outb(0x70, 0x0C);
inb(0x71);
monoclock_rtc_time += RTC_RATE;
monoclock_last_cycles = clock_cycles();
} else {
if (queue_write.len == queue_write.cap) {
panic(S("queue exceeded\n"));
/*
// TODO: kmalloc would cause a race condition
queue_write.cap = queue_write.cap == 0 ? 1 : queue_write.cap * 2;
queue_write.data = krealloc(queue_write.data, queue_write.cap);
*/
}
event *e = &queue_write.data[queue_write.len++];
e->irq = irq;
if (e->irq == 1) {
e->data.scancode = inb(IO_PS2_DATA);
}
}
ack_irq(irq);
}
}
typedef struct {
u16 size;
u64 addr;
} __attribute__((packed)) idt_descriptor;
idt_descriptor idtr;
void interrupts_init()
{
typedef struct {
u16 offset_1;
u16 selector;
u8 ist;
u8 type_attrs;
u16 offset_2;
u32 offset_3;
u32 zero;
} __attribute__((packed)) interrupt_descriptor;
interrupt_descriptor *idt = kmalloc(256 * sizeof *idt);
for (int i = 0; i < 255; i++) {
union {
struct {
u16 offset_1;
u16 offset_2;
u32 offset_3;
} __attribute__((packed)) off;
u64 addr;
} __attribute__((packed)) isr = {
.addr = idt_entries[i],
};
idt[i] = (interrupt_descriptor) {
.offset_1 = isr.off.offset_1,
.selector = 0x8,
.ist = 0,
.type_attrs = 0x8E,
.offset_2 = isr.off.offset_2,
.offset_3 = isr.off.offset_3,
.zero = 0,
};
}
idtr = (idt_descriptor) {
.size = 256 * sizeof *idt - 1,
.addr = (u64) &idt[0],
};
asm("lidt %0" : : "m"(idtr));
}
|