-
Notifications
You must be signed in to change notification settings - Fork 0
/
interrupts.c
77 lines (57 loc) · 2.29 KB
/
interrupts.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
#include "interrupts.h"
#include "pic.h"
#include "io.h"
#include "serial.h"
#include "keyboard.h"
#define INTERRUPTS_DESCRIPTOR_COUNT 256
#define INTERRUPTS_KEYBOARD 33
struct IDTDescriptor idt_descriptors[INTERRUPTS_DESCRIPTOR_COUNT];
struct IDT idt;
void interrupts_init_descriptor(int index, unsigned int address)
{
idt_descriptors[index].offset_high = (address >> 16) & 0xFFFF; // offset bits 0..15
idt_descriptors[index].offset_low = (address & 0xFFFF); // offset bits 16..31
idt_descriptors[index].segment_selector = 0x08; // The second (code) segment selector in GDT: one segment is 64b.
idt_descriptors[index].reserved = 0x00; // Reserved.
/*
Bit: | 31 16 | 15 | 14 13 | 12 | 11 10 9 8 | 7 6 5 | 4 3 2 1 0 |
Content: | offset high | P | DPL | S | D and GateType | 0 0 0 | reserved
P If the handler is present in memory or not (1 = present, 0 = not present). Set to 0 for unused interrupts or for Paging.
DPL Descriptor Privilige Level, the privilege level the handler can be called from (0, 1, 2, 3).
S Storage Segment. Set to 0 for interrupt gates.
D Size of gate, (1 = 32 bits, 0 = 16 bits).
*/
idt_descriptors[index].type_and_attr = (0x01 << 7) | // P
(0x00 << 6) | (0x00 << 5) | // DPL
0xe; // 0b1110=0xE 32-bit interrupt gate
}
void interrupts_install_idt()
{
interrupts_init_descriptor(INTERRUPTS_KEYBOARD, (unsigned int) interrupt_handler_33);
idt.address = (int) &idt_descriptors;
idt.size = sizeof(struct IDTDescriptor) * INTERRUPTS_DESCRIPTOR_COUNT;
interrupts_load_idt((int) &idt);
pic_remap(PIC_PIC1_OFFSET, PIC_PIC2_OFFSET);
}
/* Interrupt handlers ********************************************************/
void interrupt_handler(__attribute__((unused)) struct cpu_state cpu, unsigned int interrupt, __attribute__((unused)) struct stack_state stack)
{
unsigned char scan_code;
unsigned char ascii;
switch (interrupt){
case INTERRUPTS_KEYBOARD:
scan_code = keyboard_read_scan_code();
if (scan_code <= KEYBOARD_MAX_ASCII) {
ascii = keyboard_scan_code_to_ascii[scan_code];
serial_configure_baud_rate(SERIAL_COM1_BASE, 4);
serial_configure_line(SERIAL_COM1_BASE);
char str[1];
str[0] = ascii;
serial_write(str, 1);
}
pic_acknowledge(interrupt);
break;
default:
break;
}
}