-
Notifications
You must be signed in to change notification settings - Fork 0
/
isr.c
104 lines (93 loc) · 2.1 KB
/
isr.c
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
#include "port.h"
#include "screen.h"
#include "system.h"
static const char *exceptions[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check"
};
static irq_handler_t isr_routines[256] = {NULL};
void register_isr(unsigned irq, irq_handler_t handler)
{
if (isr_routines[irq])
printf("WARNING: re-assigning IRQ %d\n", irq);
isr_routines[irq] = handler;
}
static void irq_remap(void)
{
outportb(0x20, 0x11);
outportb(0xA0, 0x11);
outportb(0x21, 0x20);
outportb(0xA1, 0x28);
outportb(0x21, 0x04);
outportb(0xA1, 0x02);
outportb(0x21, 0x01);
outportb(0xA1, 0x01);
outportb(0x21, 0x0);
outportb(0xA1, 0x0);
}
void isrs_install(void)
{
unsigned i;
extern void int_stubs(void);
char *p = (char *)int_stubs;
irq_remap();
/* Each IRQ stub is 9 bytes long, so we just allocate them in this
* loop. */
for (i = 0; i < 47; i++, p += 9)
idt_set_gate(i, (unsigned)p, 0x08, 0x8E);
/* Enable IRQs */
__asm__ __volatile__ ("sti");
}
static void exception_msg(unsigned ex)
{
puts("Fatal exception: ");
if (ex < ARRAY_SIZE(exceptions))
puts(exceptions[ex]);
else
puts("Reserved Exception");
puts("\nPanicking: System Halted!\n");
for (;;);
}
static void irq_handler(struct regs *r)
{
/* If the IDT entry that was invoked was greater than 40
* (meaning IRQ8 - 15), then we need to send an EOI to the slave
* controller. */
if (r->int_no >= 40)
outportb(0xA0, 0x20);
/* In either case, we need to send an EOI to the master interrupt
* controller too. */
outportb(0x20, 0x20);
}
void isr_handler(struct regs *r)
{
irq_handler_t handler = isr_routines[r->int_no];
if (handler) {
handler(r);
} else {
if (r->int_no < 32)
/* This shouldn't return */
exception_msg(r->int_no);
else
printf("Unhandled IRQ %d\n", r->int_no-32);
}
if (r->int_no > 31)
irq_handler(r);
}