aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/keyboard
diff options
context:
space:
mode:
authorNic Gaffney <gaffney_nic@protonmail.com>2024-02-06 04:58:35 -0600
committerNic Gaffney <gaffney_nic@protonmail.com>2024-02-06 04:58:35 -0600
commitecf636f2797647d5dfc38a4562cae53fe275217d (patch)
treec71d113c553821c2b949eb6a6cd67de5f2fce068 /src/kernel/keyboard
parentf1dee4bc58e4bfb97a1b41831c5d4fc327882991 (diff)
downloadgftos-ecf636f2797647d5dfc38a4562cae53fe275217d.tar.gz
Interrupts + basic keyboard driver
Diffstat (limited to 'src/kernel/keyboard')
-rw-r--r--src/kernel/keyboard/compile_flags.txt1
-rw-r--r--src/kernel/keyboard/isr.c49
-rw-r--r--src/kernel/keyboard/isr_wrap.s8
-rw-r--r--src/kernel/keyboard/pic.c65
4 files changed, 123 insertions, 0 deletions
diff --git a/src/kernel/keyboard/compile_flags.txt b/src/kernel/keyboard/compile_flags.txt
new file mode 100644
index 0000000..2af49c7
--- /dev/null
+++ b/src/kernel/keyboard/compile_flags.txt
@@ -0,0 +1 @@
+-I../../include/
diff --git a/src/kernel/keyboard/isr.c b/src/kernel/keyboard/isr.c
new file mode 100644
index 0000000..223bf9f
--- /dev/null
+++ b/src/kernel/keyboard/isr.c
@@ -0,0 +1,49 @@
+#include "asm.h"
+#include "print.h"
+#include "str.h"
+#include <stdint.h>
+static uint8_t shift_held = 0;
+static uint8_t capslock = 0;
+
+void keyboard_handler() {
+ const char *scancodes =
+ "??1234567890-=?\tqwertyuiop[]\n?asdfghjkl;'`?\\zxcvbnm,./?*? ";
+ const char *SCANCODES =
+ "\?\?!@#$%^&*()_+?\tQWERTYUIOP{}\n?ASDFGHJKL:\"~?|ZXCVBNM<>??*? ";
+
+ unsigned char sc = inb(0x60);
+
+ uint8_t isheld = shift_held != 0;
+ char c = ((isheld | capslock) & !(isheld & capslock)) ? SCANCODES[sc]
+ : scancodes[sc];
+
+ if (capslock & (!isheld) && !isalpha(c))
+ c = scancodes[sc];
+ if (isheld && !isalpha(c))
+ c = SCANCODES[sc];
+
+ if (sc < 0x59 && scancodes[sc] != '?')
+ printf("%c", c);
+
+ switch (sc) {
+ case 0x2A:
+ shift_held |= 0b10;
+ break;
+ case 0x36:
+ shift_held |= 0b01;
+ break;
+ case 0xAA:
+ shift_held &= 0b01;
+ break;
+ case 0xB6:
+ shift_held &= 0b10;
+ break;
+ case 0x0E:
+ delete_char();
+ break;
+ case 0x3A:
+ capslock = !capslock;
+ break;
+ }
+ outb(0x20, 0x20);
+}
diff --git a/src/kernel/keyboard/isr_wrap.s b/src/kernel/keyboard/isr_wrap.s
new file mode 100644
index 0000000..6f6c58b
--- /dev/null
+++ b/src/kernel/keyboard/isr_wrap.s
@@ -0,0 +1,8 @@
+extern keyboard_handler
+extern wrap_keyboard_handler
+wrap_keyboard_handler:
+ pushad
+ cld
+ call keyboard_handler
+ popad
+ iret
diff --git a/src/kernel/keyboard/pic.c b/src/kernel/keyboard/pic.c
index 0c81629..e1b4fb3 100644
--- a/src/kernel/keyboard/pic.c
+++ b/src/kernel/keyboard/pic.c
@@ -1 +1,66 @@
#include "asm.h"
+#include <stdint.h>
+#define PIC1 0x20
+#define PIC2 0xA0
+#define PIC1_COMMAND PIC1
+#define PIC1_DATA (PIC1 + 1)
+#define PIC2_COMMAND PIC2
+#define PIC2_DATA (PIC2 + 1)
+
+void PIC_init(int offset1, int offset2) {
+ uint8_t a1, a2;
+
+ a1 = inb(PIC1_DATA);
+ a2 = inb(PIC2_DATA);
+
+ outb(PIC1_COMMAND, 0x11); // Init PIC1
+ io_wait();
+ outb(PIC2_COMMAND, 0x11); // Init PIC2
+ io_wait();
+ outb(PIC1_DATA, offset1); // ICW2: Master PIC vector offset
+ io_wait();
+ outb(PIC2_DATA, offset2); // ICW2: Slave PIC vector offset
+ io_wait();
+ outb(PIC1_DATA, 4);
+ io_wait();
+ outb(PIC2_DATA, 2);
+ io_wait();
+ outb(PIC1_DATA, 0x01);
+ io_wait();
+ outb(PIC2_DATA, 0x01);
+ io_wait();
+
+ outb(PIC1_DATA, a1); // restore saved masks.
+ outb(PIC2_DATA, a2);
+}
+
+void IRQ_mask(uint8_t line) {
+ uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA;
+ line = line > 8 ? line - 8 : line;
+ uint8_t val = inb(port) | (1 << line);
+ outb(port, val);
+}
+
+void IRQ_unmask(uint8_t line) {
+ uint16_t port = line < 8 ? PIC1_DATA : PIC2_DATA;
+ line = line > 8 ? line - 8 : line;
+ uint8_t val = inb(port) & ~(1 << line);
+ outb(port, val);
+}
+
+void PIC_disable(void) {
+ outb(PIC1_DATA, 0xff);
+ outb(PIC2_DATA, 0xff);
+}
+
+uint16_t PIC_irr(void) {
+ outb(PIC1_COMMAND, 0x0a);
+ outb(PIC2_COMMAND, 0x0a);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}
+
+uint16_t PIC_isr(void) {
+ outb(PIC1_COMMAND, 0x0b);
+ outb(PIC2_COMMAND, 0x0b);
+ return (inb(PIC2_COMMAND) << 8) | inb(PIC1_COMMAND);
+}