diff --git a/src/arch/x86_64/idt.c b/src/arch/x86_64/idt.c index 724afb35..77eafada 100644 --- a/src/arch/x86_64/idt.c +++ b/src/arch/x86_64/idt.c @@ -10,7 +10,10 @@ // 0x21 -> lapic nmi // 0x22 -> mmu invalidate page ipi // ... +// 0x40 -> ps2 keyboard isr +// ... // 0x80 -> timer +// ... idtentry_t idt[256]; @@ -57,6 +60,8 @@ void idt_bspinit(){ idt_setentry(&idt[VECTOR_LAPICNMI], asmisr_lapicnmi, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0); idt_setentry(&idt[VECTOR_TIMER], asmisr_timer, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0); + + idt_setentry(&idt[VECTOR_PS2KBD], asmisr_ps2kbd, 0x28, FLAGS_PRESENT | FLAGS_TYPE_INTERRUPT, 0); idt_reload(); diff --git a/src/arch/x86_64/include/arch/idt.h b/src/arch/x86_64/include/arch/idt.h index c07f2105..fc040659 100644 --- a/src/arch/x86_64/include/arch/idt.h +++ b/src/arch/x86_64/include/arch/idt.h @@ -27,6 +27,7 @@ #define VECTOR_PANIC 0x20 #define VECTOR_LAPICNMI 0x21 #define VECTOR_MMUINVAL 0x22 +#define VECTOR_PS2KBD 0x40 #define VECTOR_TIMER 0x80 typedef struct{ diff --git a/src/arch/x86_64/include/arch/isr.h b/src/arch/x86_64/include/arch/isr.h index fbbef535..d82a9392 100644 --- a/src/arch/x86_64/include/arch/isr.h +++ b/src/arch/x86_64/include/arch/isr.h @@ -10,6 +10,7 @@ extern void asmisr_pagefault(); extern void asmisr_panic(); extern void asmisr_lapicnmi(); extern void asmisr_mmuinval(); +extern void asmisr_ps2kbd(); extern void asmisr_timer(); #endif diff --git a/src/arch/x86_64/include/arch/ps2kbd.h b/src/arch/x86_64/include/arch/ps2kbd.h new file mode 100644 index 00000000..ade6f936 --- /dev/null +++ b/src/arch/x86_64/include/arch/ps2kbd.h @@ -0,0 +1,6 @@ +#ifndef _ARCH_PS2KBD_H_INCLUDE +#define _ARCH_PS2KBD_H_INCLUDE + +void ps2kbd_init(); + +#endif diff --git a/src/arch/x86_64/isr.asm b/src/arch/x86_64/isr.asm index 39b282bb..1013985d 100644 --- a/src/arch/x86_64/isr.asm +++ b/src/arch/x86_64/isr.asm @@ -145,4 +145,5 @@ isr asmisr_general, isr_general except asmisr_except, isr_except isr asmisr_lapicnmi, isr_lapicnmi isr asmisr_mmuinval, isr_mmuinval +isr asmisr_ps2kbd, isr_ps2kbd isr asmisr_timer, isr_timer diff --git a/src/arch/x86_64/isr.c b/src/arch/x86_64/isr.c index b5a8544d..e0066bd3 100644 --- a/src/arch/x86_64/isr.c +++ b/src/arch/x86_64/isr.c @@ -30,6 +30,11 @@ void isr_mmuinval(){ apic_eoi(); } +void isr_ps2kbd(arch_regs* reg){ + ps2kbd_irq(); + apic_eoi(); +} + void isr_timer(arch_regs* reg){ timer_irq(reg); apic_eoi(); diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index 61c6deda..5c24ac59 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -73,6 +73,8 @@ void kmain(){ keyboard_init(); + ps2kbd_init(); + sched_runinit(); _panic("End of kmain()", 0); diff --git a/src/arch/x86_64/ps2kbd.c b/src/arch/x86_64/ps2kbd.c new file mode 100644 index 00000000..43ccebb2 --- /dev/null +++ b/src/arch/x86_64/ps2kbd.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include + +#define PS2_PORT_DATA 0x60 +#define PS2_PORT_COMMAND 0x64 +#define PS2_PORT_STATUS 0x64 +#define RESEND 0xFE +#define ACK 0xFA +#define ECHO 0xEE +#define KEYBOARDIRQ 1 + +static int kb; + +static uint8_t ps2cmd(uint8_t cmd){ + + uint8_t response; + + for(size_t i = 0; i < 3; ++i){ + outb(PS2_PORT_DATA, cmd); + response = inb(PS2_PORT_DATA); + + if(response != RESEND) + break; + + } + + return response; + +} + +static char asciitable[] = { + 0, '\033', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', 0, 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '7', '8', '9', '-', '4', '5', '6', '+', '4', '1', '2', '3', '0', '.', 0, 0, 0, 0, 0 +}; + +void ps2kbd_irq(){ + uint8_t scancode = inb(0x60); + if(scancode == 0xE0) + return; // TODO support extended scancodes + + kbpacket_t packet; + + // TODO convert scancode to keycode + + packet.flags = 0; + + if(scancode & 0x80){ + packet.flags = KBPACKET_FLAGS_RELEASED; + scancode &= 0x7F; + } + + packet.ascii = asciitable[scancode]; + + keyboard_packet(kb, &packet); + +} + +void ps2kbd_init(){ + + // maybe the ps/2 controller and keyboard should be initialised to a known state + // and not be assumed to be set up in a working manner by the firmware/bootloader + + // this probably shouldn't assume the keyboard always being in the first port but oh well + + // clear keyboard buffer data + + inb(PS2_PORT_DATA); + + if(ps2cmd(ECHO) != ECHO){ + printf("No PS/2 keyboard found.\n"); + return; + } + + ioapic_setlegacyirq(KEYBOARDIRQ, VECTOR_PS2KBD, arch_getcls()->lapicid, false); + + kb = keyboard_getnew(); +} diff --git a/src/include/kernel/keyboard.h b/src/include/kernel/keyboard.h index 80e698b6..7fb4ac57 100644 --- a/src/include/kernel/keyboard.h +++ b/src/include/kernel/keyboard.h @@ -1,6 +1,8 @@ #ifndef _KEYBOARD_H_INCLUDE #define _KEYBOARD_H_INCLUDE +#define KBPACKET_FLAGS_RELEASED 1 + #include #include