Whenever I press a key, instead of sending irq 1, it crashes my os with a triple fault. It does the same with the PIT, so I have disabled it for now. I have tried to do it manually with asm("int $1"), but it still crashes. I am compiling with gcc & nasm. Here are my codes:
irq.c:
Code:
#include "irq.h"
void* irq_routines[16] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
void irq_add_handler(int irq, void (*handler) (struct registers* r)) {
irq_routines[irq] = handler;
}
void irq_remove_handler(int irq) {
irq_routines[irq] = 0;
}
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 irq_init(void) {
irq_remap();
set_idt_gate(32, (unsigned) irq0);
set_idt_gate(33, (unsigned) irq1);
set_idt_gate(34, (unsigned) irq2);
set_idt_gate(35, (unsigned) irq3);
set_idt_gate(36, (unsigned) irq4);
set_idt_gate(37, (unsigned) irq5);
set_idt_gate(38, (unsigned) irq6);
set_idt_gate(39, (unsigned) irq7);
set_idt_gate(40, (unsigned) irq8);
set_idt_gate(41, (unsigned) irq9);
set_idt_gate(42, (unsigned) irq10);
set_idt_gate(43, (unsigned) irq11);
set_idt_gate(44, (unsigned) irq12);
set_idt_gate(45, (unsigned) irq13);
set_idt_gate(46, (unsigned) irq14);
set_idt_gate(47, (unsigned) irq15);
}
void irq_handler(struct registers* r) {
void (*handler) (struct registers* r);
handler = irq_routines[r->num - 32];
if (handler) {
handler(r);
} if (r->num >= 40) {
outportb(0xA0, 0x20);
}
outportb(0x20, 0x20);
}
I don't think irq.h is important. Its just some
Code:
extern void irq ... ();
.
keyboard.c
Code:
#include "keyboard_driver.h"
static uint8 press;
static uint8 release;
void keyboard_handler(struct registers* r) {
uint8 scancode;
scancode = inportb(0x60);
println("Keypress", 0x07);
if (scancode & 0x80) release = scancode;
else press = scancode;
}
void keyboard_install(void) {
while (inportb(0x64) & 0x1) {
inportb(0x60);
}
outportb(0x64, 0xae);
outportb(0x64, 0x20);
uint8 status = (inportb(0x60) | 1) & ~0x10;
outportb(0x64, 0x60);
outportb(0x60, status);
outportb(0x60, 0xf4);
//irq_add_handler(33, keyboard_handler);
irq_add_handler(1, keyboard_handler);
}
uint8 poll_key(void) {
uint8 temp = press;
press = 127;
return temp;
}
uint8 poll_key_release(void) {
uint8 temp = release;
release = 127;
return temp;
}
idt.c
Code:
static uint8 flags = 0x8E;
void set_idt_gate(int n, uint32 handler) {
idt[n].high_offset = high_16(handler);
idt[n].low_offset = low_16(handler);
idt[n].sel = KERNEL_CS;
idt[n].always0 = 0;
idt[n].flags = flags;
}
void set_idt(void) {
idt_reg.limit = (uint32) &idt;
idt_reg.base = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
}
void set_idt_flags(uint8 _flags) {
flags = _flags;
}
and the assembly for interrupts:
Code:
global irq0
continues up to...
global irq15
irq0:
cli
push byte 0
push byte 32
jmp irq_common
irq1:
cli
push byte 0
push byte 33
jmp irq_common .. and so on...
extern irq_handler
irq_common:
pusha
push ds
push es
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, esp
push eax
mov eax, irq_handler
call eax
pop eax
pop gs
pop fs
pop es
pop ds
popa
add esp, 8
iret
Thanks in advance!