-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathisr.c
160 lines (142 loc) · 3.96 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// Implementation for Interrupt Service Routines
// http://wiki.osdev.org/Interrupt_Service_Routines
#include "isr.h"
#include "idt.h"
#include "ports.h"
#include "timer.h"
#include "../drivers/keyboard.h"
#include "../drivers/screen.h"
#include "../libc/mem.h"
#include "../libc/string.h"
isr_t interrupt_handlers[256];
// Array of messages when some exception is occured
// Its indexes are mapped to interrupt codes
char *exception_messages[] = {
"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",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
// Maps ISR in interrupt.asm to gates in IDT
void isr_install() {
set_idt_gate(0, (uint32_t)isr0);
set_idt_gate(1, (uint32_t)isr1);
set_idt_gate(2, (uint32_t)isr2);
set_idt_gate(3, (uint32_t)isr3);
set_idt_gate(4, (uint32_t)isr4);
set_idt_gate(5, (uint32_t)isr5);
set_idt_gate(6, (uint32_t)isr6);
set_idt_gate(7, (uint32_t)isr7);
set_idt_gate(8, (uint32_t)isr8);
set_idt_gate(9, (uint32_t)isr9);
set_idt_gate(10, (uint32_t)isr10);
set_idt_gate(11, (uint32_t)isr11);
set_idt_gate(12, (uint32_t)isr12);
set_idt_gate(13, (uint32_t)isr13);
set_idt_gate(14, (uint32_t)isr14);
set_idt_gate(15, (uint32_t)isr15);
set_idt_gate(16, (uint32_t)isr16);
set_idt_gate(17, (uint32_t)isr17);
set_idt_gate(18, (uint32_t)isr18);
set_idt_gate(19, (uint32_t)isr19);
set_idt_gate(20, (uint32_t)isr20);
set_idt_gate(21, (uint32_t)isr21);
set_idt_gate(22, (uint32_t)isr22);
set_idt_gate(23, (uint32_t)isr23);
set_idt_gate(24, (uint32_t)isr24);
set_idt_gate(25, (uint32_t)isr25);
set_idt_gate(26, (uint32_t)isr26);
set_idt_gate(27, (uint32_t)isr27);
set_idt_gate(28, (uint32_t)isr28);
set_idt_gate(29, (uint32_t)isr29);
set_idt_gate(30, (uint32_t)isr30);
set_idt_gate(31, (uint32_t)isr31);
// Remap the PIC
// http://wiki.osdev.org/8259_PIC#Initialisation
port_byte_out(0x20, 0x11);
port_byte_out(0xA0, 0x11);
port_byte_out(0x21, 0x20);
port_byte_out(0xA1, 0x28);
port_byte_out(0x21, 0x04);
port_byte_out(0xA1, 0x02);
port_byte_out(0x21, 0x01);
port_byte_out(0xA1, 0x01);
port_byte_out(0x21, 0x0);
port_byte_out(0xA1, 0x0);
// Install IRQs into our IDT
set_idt_gate(32, (uint32_t)irq0);
set_idt_gate(33, (uint32_t)irq1);
set_idt_gate(34, (uint32_t)irq2);
set_idt_gate(35, (uint32_t)irq3);
set_idt_gate(36, (uint32_t)irq4);
set_idt_gate(37, (uint32_t)irq5);
set_idt_gate(38, (uint32_t)irq6);
set_idt_gate(39, (uint32_t)irq7);
set_idt_gate(40, (uint32_t)irq8);
set_idt_gate(41, (uint32_t)irq9);
set_idt_gate(42, (uint32_t)irq10);
set_idt_gate(43, (uint32_t)irq11);
set_idt_gate(44, (uint32_t)irq12);
set_idt_gate(45, (uint32_t)irq13);
set_idt_gate(46, (uint32_t)irq14);
set_idt_gate(47, (uint32_t)irq15);
set_idt();
}
// Calls every time when some interrupt is occured
// This function is available in interrupt.asm file via extern in asm
void isr_handler(registers_t r) {
char s[3];
print("Received interrupt: ");
itoa(r.int_no, s);
print(s);
print("\n");
print(exception_messages[r.int_no]);
print("\n");
}
void irq_install() {
__asm__ __volatile__("sti");
init_timer(50);
init_keyboard();
}
// Calls every time when hardware interrupt is occured
void irq_handler(registers_t r) {
if (r.int_no >= 40) {
port_byte_out(0xA0, 0x20);
}
port_byte_out(0x20, 0x20);
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
}
void register_interrupt_handler(uint8_t n, isr_t handler) {
interrupt_handlers[n] = handler;
}