MushOS  0.1
A UNIX-like OS prototype, written from scratch
Loading...
Searching...
No Matches
interruption_tables.c
1#include "interruption_tables.h"
2
3#include "../../lib/base/generic.h"
4#include "../../lib/base/stdio.h"
5#include "../../lib/base/memory.h"
6
7#include "../drivers/ports_io.h"
8
9#include "kernel.h"
10#include "interruptions.h"
11
12
13#define interruptions_placement 0x500
14
15
16IDT* idt_table;
17interruption_handler interruption_handlers[256];
18
19
20static void debug(registers* regs) {
21 bad("Registers:\n\teax: %h\n\tebx: %h\n\tecx: %h\n\tedx: %h\n", regs->eax, regs->ebx, regs->ecx, regs->edx)
22 bad("Stack:\n\tebp: %h\n\tesp: %h\n", regs->ebp, regs->esp_plus + 0x14)
23 bad("Instruction:\n\teip: %h\n", regs->eip)
24 bad("IO:\n\tesi: %h\n\tedi: %h\n", regs->esi, regs->edi)
25 u_dword arg = 0;
26 for (int i = 0; i < 10; ++i) {
27 asm volatile ("mov (%1), %0" : "=r" (arg) : "r" (regs->esp_plus + 0x14 + i * sizeof(u_dword)));
28 bad("Orbital arg #%d: %h\n", i, arg)
29 }
30}
31
32static void create_idt_entry (u_dword pos, u_dword base, u_word selector, u_byte flags) {
33 idt_table->entries[pos].base_low = (base & 0xffff);
34 idt_table->entries[pos].selector = selector;
35 idt_table->entries[pos].always0 = 0x00;
36 idt_table->entries[pos].flags = flags;
37 idt_table->entries[pos].base_high = (base >> 16);
38}
39
40void init_interruptions() {
41 idt_table = (IDT*) interruptions_placement;
42 memory_clear((byte *) idt_table->entries, 256 * sizeof(IDT_entry), 0);
43
44 u_word CS = 0x08;
45 create_idt_entry(0, (u_dword) isr0, CS, 0b10001110);
46 create_idt_entry(1, (u_dword) isr1, CS, 0b10001110);
47 create_idt_entry(2, (u_dword) isr2, CS, 0b10001110);
48 create_idt_entry(3, (u_dword) isr3, CS, 0b10001110);
49 create_idt_entry(4, (u_dword) isr4, CS, 0b10001110);
50 create_idt_entry(5, (u_dword) isr5, CS, 0b10001110);
51 create_idt_entry(6, (u_dword) isr6, CS, 0b10001110);
52 create_idt_entry(7, (u_dword) isr7, CS, 0b10001110);
53 create_idt_entry(8, (u_dword) isr8, CS, 0b10001110);
54 create_idt_entry(9, (u_dword) isr9, CS, 0b10001110);
55 create_idt_entry(10, (u_dword) isr10, CS, 0b10001110);
56 create_idt_entry(11, (u_dword) isr11, CS, 0b10001110);
57 create_idt_entry(12, (u_dword) isr12, CS, 0b10001110);
58 create_idt_entry(13, (u_dword) isr13, CS, 0b10001110);
59 create_idt_entry(14, (u_dword) isr14, CS, 0b10001110);
60 create_idt_entry(15, (u_dword) isr15, CS, 0b10001110);
61 create_idt_entry(16, (u_dword) isr16, CS, 0b10001110);
62 create_idt_entry(17, (u_dword) isr17, CS, 0b10001110);
63 create_idt_entry(18, (u_dword) isr18, CS, 0b10001110);
64 create_idt_entry(19, (u_dword) isr19, CS, 0b10001110);
65 create_idt_entry(20, (u_dword) isr20, CS, 0b10001110);
66 create_idt_entry(21, (u_dword) isr21, CS, 0b10001110);
67 create_idt_entry(22, (u_dword) isr22, CS, 0b10001110);
68 create_idt_entry(23, (u_dword) isr23, CS, 0b10001110);
69 create_idt_entry(24, (u_dword) isr24, CS, 0b10001110);
70 create_idt_entry(25, (u_dword) isr25, CS, 0b10001110);
71 create_idt_entry(26, (u_dword) isr26, CS, 0b10001110);
72 create_idt_entry(27, (u_dword) isr27, CS, 0b10001110);
73 create_idt_entry(28, (u_dword) isr28, CS, 0b10001110);
74 create_idt_entry(29, (u_dword) isr29, CS, 0b10001110);
75 create_idt_entry(30, (u_dword) isr30, CS, 0b10001110);
76 create_idt_entry(31, (u_dword) isr31, CS, 0b10001110);
77
78 u_byte master_mask = port_byte_in(0x21);
79 u_byte slave_mask = port_byte_in(0xA1);
80 port_byte_out(0x20, 0x11);
81 port_byte_out(0xA0, 0x11);
82 port_byte_out(0x21, 0x20);
83 port_byte_out(0xA1, 0x28);
84 port_byte_out(0x21, 0x04);
85 port_byte_out(0xA1, 0x02);
86 port_byte_out(0x21, 0x01);
87 port_byte_out(0xA1, 0x01);
88 port_byte_out(0x21, 0x0);
89 port_byte_out(0xA1, 0x0);
90 port_byte_out(0x21, master_mask);
91 port_byte_out(0xA1, slave_mask);
92
93 create_idt_entry(32, (u_dword) irq0, CS, 0b10001110);
94 create_idt_entry(33, (u_dword) irq1, CS, 0b10001110);
95 create_idt_entry(34, (u_dword) irq2, CS, 0b10001110);
96 create_idt_entry(35, (u_dword) irq3, CS, 0b10001110);
97 create_idt_entry(36, (u_dword) irq4, CS, 0b10001110);
98 create_idt_entry(37, (u_dword) irq5, CS, 0b10001110);
99 create_idt_entry(38, (u_dword) irq6, CS, 0b10001110);
100 create_idt_entry(39, (u_dword) irq7, CS, 0b10001110);
101 create_idt_entry(40, (u_dword) irq8, CS, 0b10001110);
102 create_idt_entry(41, (u_dword) irq9, CS, 0b10001110);
103 create_idt_entry(42, (u_dword) irq10, CS, 0b10001110);
104 create_idt_entry(43, (u_dword) irq11, CS, 0b10001110);
105 create_idt_entry(44, (u_dword) irq12, CS, 0b10001110);
106 create_idt_entry(45, (u_dword) irq13, CS, 0b10001110);
107 create_idt_entry(46, (u_dword) irq14, CS, 0b10001110);
108 create_idt_entry(47, (u_dword) irq15, CS, 0b10001110);
109
110 create_idt_entry(48, (u_dword) isr48, CS, 0b10001110);
111 create_idt_entry(49, (u_dword) isr49, CS, 0b10001110);
112 create_idt_entry(50, (u_dword) isr50, CS, 0b10001110);
113 create_idt_entry(51, (u_dword) isr51, CS, 0b10001110);
114 create_idt_entry(52, (u_dword) isr52, CS, 0b10001110);
115
116
117 for (int i = 53; i < 256; ++i) {
118 create_idt_entry(i, (u_dword) isr32, CS, 0b10001110);
119 }
120
121 idt_table->descriptor.size = 256 * sizeof(IDT_entry) - 1;
122 idt_table->descriptor.pos = (u_dword) &(idt_table->entries);
123
124 idt_flush((u_dword) &(idt_table->descriptor));
125}
126
127void init_debug_handler() {
128 set_interrupt_handler(49, debug);
129}
130
131
132
133void set_interrupt_handler(u_byte n, interruption_handler handler) {
134 interruption_handlers[n] = handler;
135 if (n != 32) info("Handler set for interruption: %d\n", n)
136}
137
138static void silent_interrupt_handler(registers* regs) {}
139
140void silence_interrupt(u_byte n) {
141 interruption_handlers[n] = silent_interrupt_handler;
142 if (n != 32) info("Interruption silenced: %d\n", n)
143}
144
145
146
147void isr_handler(registers* regs) {
148 if (regs->int_no == DEFAULT_IRS) bad("Received undefined user interrupt.")
149
150 if (interruption_handlers[regs->int_no] != nullptr) {
151 interruption_handler handler = interruption_handlers[regs->int_no];
152 handler(regs);
153 } else if (regs->int_no < 48) PANIC("Received undefined interrupt: %h", regs->int_no)
154 else PANIC("Received some interrupt: %h", regs->int_no)
155}
156
157void irq_handler(registers* regs) {
158 // Send an EOI (end of interrupt) signal to the PICs.
159 // If this interrupt involved the slave.
160
161 if (regs->int_no >= 40) {
162 // Send reset signal to slave.
163 port_byte_out(0xA0, 0x20);
164 }
165 // Send reset signal to master. (As well as slave, if necessary).
166 port_byte_out(0x20, 0x20);
167
168 if (interruption_handlers[regs->int_no] != nullptr) {
169 interruption_handler handler = interruption_handlers[regs->int_no];
170 handler(regs);
171 } else info("Received hardware interrupt: %h\n", regs->int_no - 15)
172}