summaryrefslogtreecommitdiff
path: root/src/kernel/kbd.c
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2020-09-13 03:19:57 -0400
committerBenji Dial <benji6283@gmail.com>2020-09-13 03:19:57 -0400
commit1e4a254674f668839e5de273916024c16814b045 (patch)
tree6774f4d4398a29c4aafb4120070975d864ffcde4 /src/kernel/kbd.c
parentb8284137d4e0eec11c78bc14047243fce6a51373 (diff)
downloadportland-os-1e4a254674f668839e5de273916024c16814b045.tar.gz
(basic, not much tested) keyboard, better panic
Diffstat (limited to 'src/kernel/kbd.c')
-rw-r--r--src/kernel/kbd.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c
new file mode 100644
index 0000000..73a5ec6
--- /dev/null
+++ b/src/kernel/kbd.c
@@ -0,0 +1,285 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "panic.h"
+#include "log.h"
+#include "util.h"
+
+static uint32_t *kbd_in_pointer;
+static uint32_t *kbd_out_pointer;
+
+#define KBD_BUFFER_LENGTH 1024
+static uint32_t kbd_buffer[KBD_BUFFER_LENGTH];
+
+static uint32_t mod_mask;
+
+enum {
+ PS2_CMD = 0x64,
+ PS2_DATA = 0x60
+};
+
+enum {
+ PS2C_READ_CONFIG = 0x20,
+ PS2C_WRITE_CONFIG = 0x60,
+ PS2C_DISABLE = 0xad,
+ PS2C_ENABLE = 0xae
+};
+
+enum {
+ PS2S_CODE_READY = 0x01
+};
+
+enum {
+ PS2G_XT_COMPAT = 0x40
+};
+
+void init_kbd() {
+ outb(PS2_CMD, PS2C_READ_CONFIG);
+ uint8_t config = inb(PS2_DATA);
+ outb(PS2_CMD, PS2C_WRITE_CONFIG);
+ outb(PS2_DATA, config | PS2G_XT_COMPAT);
+
+ kbd_in_pointer = kbd_buffer;
+ kbd_out_pointer = kbd_buffer;
+ mod_mask = 0;
+}
+
+uint32_t get_key_code() {
+ if (kbd_in_pointer == kbd_out_pointer)
+ return 0;
+ uint32_t code = *kbd_out_pointer;
+ if (++kbd_out_pointer == kbd_buffer + KBD_BUFFER_LENGTH)
+ kbd_out_pointer = kbd_buffer;
+ return code;
+}
+
+enum {
+ MOD_LSHIFT = 0x00100,
+ MOD_RSHIFT = 0x00200,
+ MOD_CAPS = 0x00400,
+ MOD_INSERT = 0x00800,
+ MOD_NUMPAD = 0x01000,
+ MOD_SCROLL = 0x02000,
+ MOD_LALT = 0x04000,
+ MOD_RALT = 0x08000,
+ MOD_LCTRL = 0x10000,
+ MOD_RCTRL = 0x20000,
+ MOD_LMETA = 0x40000,
+ MOD_RMETA = 0x80000
+};
+
+enum {
+ CODE_CAPS = 0x80,
+ CODE_INSERT,
+ CODE_NUMPAD,
+ CODE_SCROLL,
+ CODE_LSHIFT,
+ CODE_RSHIFT,
+ CODE_LALT,
+ CODE_RALT,
+ CODE_LCTRL,
+ CODE_RCTRL,
+ CODE_LMETA,
+ CODE_RMETA,
+ /* 0x8c - 0x97 reserved */
+ /* 0x98 - 0x9f unassigned */
+ CODE_F1 = 0xa0,
+ CODE_F2,
+ CODE_F3,
+ CODE_F4,
+ CODE_F5,
+ CODE_F6,
+ CODE_F7,
+ CODE_F8,
+ CODE_F9,
+ CODE_F10,
+ CODE_F11,
+ CODE_F12,
+ /* 0xac - 0xaf unassigned */
+ CODE_NUM0 = 0xb0,
+ CODE_NUM1,
+ CODE_NUM2,
+ CODE_NUM3,
+ CODE_NUM4,
+ CODE_NUM5,
+ CODE_NUM6,
+ CODE_NUM7,
+ CODE_NUM8,
+ CODE_NUM9,
+ CODE_NTIMES,
+ CODE_NPLUS,
+ CODE_NENTER,
+ CODE_NMINUS,
+ CODE_NDOT,
+ CODE_NSLASH,
+ /* 0xc0 unassigned */
+ CODE_DELETE,
+ CODE_HOME,
+ CODE_END,
+ CODE_PUP,
+ CODE_PDOWN,
+ CODE_UP,
+ CODE_DOWN,
+ CODE_LEFT,
+ CODE_RIGHT,
+ CODE_ESC,
+ CODE_MENU,
+ CODE_PAUSE,
+ CODE_PRSCR,
+ /* 0xce - 0xef unassigned */
+ CODE_END_LSHIFT = 0xf0,
+ CODE_END_RSHIFT,
+ CODE_END_LALT,
+ CODE_END_RALT,
+ CODE_END_LCTRL,
+ CODE_END_RCTRL,
+ CODE_END_LMETA,
+ CODE_END_RMETA
+};
+
+static const uint32_t mod_bits[] = {
+ MOD_CAPS,
+ MOD_INSERT,
+ MOD_NUMPAD,
+ MOD_SCROLL,
+ MOD_LSHIFT,
+ MOD_RSHIFT,
+ MOD_LALT,
+ MOD_RALT,
+ MOD_LCTRL,
+ MOD_RCTRL,
+ MOD_LMETA,
+ MOD_RMETA
+};
+
+static const uint32_t *const unmod_bits = mod_bits + 4;
+
+//in these tables, 0x00 represents an unknown key,
+// and 0xff represents a key release.
+
+static const uint8_t codes[] = {
+ 0, CODE_ESC, '1', '2', '3', '4', '5', '6',
+ '7', '8', '9', '0', '-', '=', '\b', '\t',
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
+ 'o', 'p', '[', ']', '\n', CODE_LCTRL, 'a', 's',
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
+ '\'', '`', CODE_LSHIFT, '\\', 'z', 'x', 'c', 'v',
+ 'b', 'n', 'm', ',', '.', '/', CODE_RSHIFT, CODE_NTIMES,
+ CODE_LALT, ' ', CODE_CAPS, CODE_F1, CODE_F2, CODE_F3, CODE_F4, CODE_F5,
+ CODE_F6, CODE_F7, CODE_F8, CODE_F9, CODE_F10, CODE_NUMPAD, CODE_SCROLL, CODE_NUM7,
+ CODE_NUM8, CODE_NUM9, CODE_NMINUS, CODE_NUM4, CODE_NUM5, CODE_NUM6, CODE_NPLUS, CODE_NUM1,
+ CODE_NUM2, CODE_NUM3, CODE_NUM0, CODE_NDOT, 0, 0, 0, CODE_F11,
+ CODE_F12, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_LCTRL, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, CODE_END_LSHIFT, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_RSHIFT, 0xff,
+ CODE_END_LALT, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0xff,
+ 0xff, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const uint8_t codes_e0[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, CODE_NENTER, CODE_RCTRL, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, CODE_NSLASH, 0, 0,
+ CODE_RALT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, CODE_HOME,
+ CODE_UP, CODE_PUP, 0, CODE_LEFT, 0, CODE_RIGHT, 0, CODE_END,
+ CODE_DOWN, CODE_PDOWN, CODE_INSERT, CODE_DELETE, 0, 0, 0, 0,
+ 0, 0, 0, CODE_LMETA, CODE_RMETA, CODE_MENU, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0xff, CODE_END_RCTRL, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0xff, 0, 0,
+ CODE_END_RALT, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0xff,
+ 0xff, 0xff, 0, 0xff, 0, 0xff, 0, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0,
+ 0, 0, 0, CODE_END_LMETA, CODE_END_RMETA, 0xff, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+void on_kbd_isr() {
+ while (inb(PS2_CMD) & PS2S_CODE_READY) {
+ uint8_t code = inb(PS2_DATA);
+ if (code == 0xe1) {
+ code = inb(PS2_DATA);
+ if (code == 0x1d) {
+ if (inb(PS2_DATA) != 0x45)
+ code = 0;
+ else
+ code = CODE_PAUSE;
+ }
+ else if (code == 0x9d) {
+ if (inb(PS2_DATA) != 0xc5)
+ code = 0;
+ else
+ code = 0xff;
+ }
+ else
+ code = 0;
+ }
+ else if (code == 0xe0) {
+ code = inb(PS2_DATA);
+ if (code == 0x2a) {
+ if ((inb(PS2_DATA) != 0xe0) ||
+ (inb(PS2_DATA) != 0x37))
+ code = 0;
+ else
+ code = CODE_PRSCR;
+ }
+ else if (code == 0xb7) {
+ if ((inb(PS2_DATA) != 0xe0) ||
+ (inb(PS2_DATA) != 0xaa))
+ code = 0;
+ else
+ code = 0xff;
+ }
+ else
+ code = codes_e0[code];
+ }
+ else
+ code = codes[code];
+
+ if (!code)
+ PANIC("Unknown scancode.");
+
+ if (code < 0xf0)
+ *kbd_in_pointer++ = mod_mask | code;
+ if ((code >= 0x80) && (code <= 0x83))
+ mod_mask ^= mod_bits[code & 0x03];
+ else if ((code >= 0x84) && (code <= 0x8b))
+ mod_mask |= mod_bits[code & 0x0f];
+ else if (code >= 0xf0)
+ mod_mask &= ~unmod_bits[code & 0x0f];
+ }
+} \ No newline at end of file