major refactorings

Signed-off-by: kaguya3311 <kaguya3311@national.shitposting.agency>
This commit is contained in:
kaguya
2026-05-18 04:02:59 -04:00
parent f7aa6f913a
commit b28a6bcf29
211 changed files with 17699 additions and 8107 deletions
+195
View File
@@ -0,0 +1,195 @@
#include "ps2.h"
#include "drivers/input/input.h"
#include "arch/x86_64/sys/irq.h"
#include "arch/x86_64/boot/isr.h"
#include "arch/x86_64/cpu/io.h"
#include "arch/x86_64/sys/ioapic.h"
#include "arch/x86_64/sys/apic.h"
#include "libk/stdio.h"
#include "libk/debug.h"
#include "drivers/video/render.h"
/* ── PS/2 I/O ports ───────────────────────────────────────────────────────── */
#define PS2_DATA_PORT 0x60 /* Read: scancode / Write: command data */
#define PS2_STATUS_PORT 0x64 /* Read: controller status */
#define PS2_CMD_PORT 0x64 /* Write: controller command */
/* Status register bits */
#define PS2_STATUS_OBF (1 << 0) /* Output buffer full (data ready to read) */
#define PS2_STATUS_IBF (1 << 1) /* Input buffer full (don't write yet) */
/* ── IRQ number for the keyboard ─────────────────────────────────────────── */
#define KBD_IRQ 1
#define KBD_IDT_VECTOR (0x20 + KBD_IRQ) /* 0x21 with PIC_REMAP_OFFSET=0x20 */
/* ── Modifier state ───────────────────────────────────────────────────────── */
static bool s_shift = false;
static bool s_ctrl = false;
static bool s_alt = false;
static bool s_caps_lock = false;
static bool s_extended = false; /* true after receiving 0xE0 prefix */
/* ══════════════════════════════════════════════════════════════════════════
* Set-1 keycode → ASCII translation tables
*
* Index = Set-1 make code (0x000x58 covers the full AT-101 layout).
* 0x00 = unmapped / non-printable.
* ══════════════════════════════════════════════════════════════════════════ */
static const char s_normal[128] = {
/*00*/ 0, 0, '1', '2', '3', '4', '5', '6',
/*08*/ '7', '8', '9', '0', '-', '=', '\b', '\t',
/*10*/ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
/*18*/ 'o', 'p', '[', ']', '\n', 0, 'a', 's',
/*20*/ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
/*28*/ '\'','`', 0, '\\','z', 'x', 'c', 'v',
/*30*/ 'b', 'n', 'm', ',', '.', '/', 0, '*',
/*38*/ 0, ' ', 0, 0, 0, 0, 0, 0,
/*40*/ 0, 0, 0, 0, 0, 0, 0, '7',
/*48*/ '8', '9', '-', '4', '5', '6', '+', '1',
/*50*/ '2', '3', '0', '.', 0, 0, 0, 0,
/*58*/ 0
};
static const char s_shifted[128] = {
/*00*/ 0, 0, '!', '@', '#', '$', '%', '^',
/*08*/ '&', '*', '(', ')', '_', '+', '\b', '\t',
/*10*/ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
/*18*/ 'O', 'P', '{', '}', '\n', 0, 'A', 'S',
/*20*/ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
/*28*/ '"', '~', 0, '|', 'Z', 'X', 'C', 'V',
/*30*/ 'B', 'N', 'M', '<', '>', '?', 0, '*',
/*38*/ 0, ' ', 0, 0, 0, 0, 0, 0,
/*40*/ 0, 0, 0, 0, 0, 0, 0, '7',
/*48*/ '8', '9', '-', '4', '5', '6', '+', '1',
/*50*/ '2', '3', '0', '.', 0, 0, 0, 0,
/*58*/ 0
};
/* ══════════════════════════════════════════════════════════════════════════
* Extended (0xE0-prefixed) make codes we care about
* ══════════════════════════════════════════════════════════════════════════ */
typedef enum {
/* Regular Set-1 make codes (non-extended) */
SC_LSHIFT = 0x2A,
SC_RSHIFT = 0x36,
SC_LCTRL = 0x1D,
SC_LALT = 0x38,
SC_CAPSLOCK = 0x3A,
SC_BACKSPACE= 0x0E,
SC_ENTER = 0x1C,
SC_TAB = 0x0F,
SC_ESC = 0x01,
/* Function keys */
SC_F1 = 0x3B, SC_F2 = 0x3C, SC_F3 = 0x3D, SC_F4 = 0x3E,
SC_F5 = 0x3F, SC_F6 = 0x40, SC_F7 = 0x41, SC_F8 = 0x42,
SC_F9 = 0x43, SC_F10 = 0x44, SC_F11 = 0x57, SC_F12 = 0x58,
} scancode_t;
/* ══════════════════════════════════════════════════════════════════════════
* IRQ1 handler
* ══════════════════════════════════════════════════════════════════════════ */
void ps2_kbd_handler(Registers *regs)
{
(void)regs;
/*
* Always drain the output buffer even if we don't handle the byte,
* otherwise the PS/2 controller stalls and stops sending interrupts.
*/
uint8_t status = x86_64_inb(PS2_STATUS_PORT);
if (!(status & PS2_STATUS_OBF)) {
/* Spurious interrupt with no data — just return */
return;
}
uint8_t byte = x86_64_inb(PS2_DATA_PORT);
/* ── Handle 0xE0 extended-key prefix ─────────────────────────────── */
if (byte == 0xE0) {
s_extended = true;
return;
}
/* ── Decode make / break ─────────────────────────────────────────── */
bool pressed = !(byte & 0x80); /* bit 7 = 0 → make, 1 → break */
uint8_t scancode = byte & 0x7F; /* strip the break bit */
bool extended = s_extended;
s_extended = false;
/* ── Update modifier keys ────────────────────────────────────────── */
if (!extended) {
switch (scancode) {
case SC_LSHIFT: case SC_RSHIFT:
s_shift = pressed;
return; /* don't push a key event for bare modifiers */
case SC_LCTRL:
s_ctrl = pressed;
return;
case SC_LALT:
s_alt = pressed;
return;
case SC_CAPSLOCK:
if (pressed) s_caps_lock = !s_caps_lock;
return;
}
}
/* ── Translate to ASCII ──────────────────────────────────────────── */
char ascii = 0;
if (!extended && scancode < 128) {
bool use_upper = s_shift ^ s_caps_lock; /* XOR: caps inverts shift */
ascii = use_upper ? s_shifted[scancode] : s_normal[scancode];
}
/* Extended keys (arrows, home, end, etc.) leave ascii=0 */
/* ── Push event ──────────────────────────────────────────────────── */
input_push_key(scancode, ascii, pressed);
if (pressed && ascii) {
input_push_char(ascii);
}
}
/* ══════════════════════════════════════════════════════════════════════════
* Public helpers
* ══════════════════════════════════════════════════════════════════════════ */
uint8_t ps2_kbd_read_scancode(void)
{
/* Spin until data is available (for early/polled use only) */
while (!(x86_64_inb(PS2_STATUS_PORT) & PS2_STATUS_OBF))
asm volatile("pause");
return x86_64_inb(PS2_DATA_PORT);
}
/* ══════════════════════════════════════════════════════════════════════════
* Initialisation
* ══════════════════════════════════════════════════════════════════════════ */
void ps2_kbd_init(void)
{
/*
* ── Step 1: Flush the PS/2 output buffer ─────────────────────────
*
* Any leftover bytes from before boot will cause the controller to
* withhold interrupts. Drain them now.
*/
int attempts = 16;
while (attempts-- && (x86_64_inb(PS2_STATUS_PORT) & PS2_STATUS_OBF))
(void)x86_64_inb(PS2_DATA_PORT);
x86_64_APIC_IRQ_RedirectAndRegister(1, 0x21, ps2_kbd_handler);
kprintf("[PS2] Keyboard driver initialised (IRQ%d vector 0x%02x)\n",
KBD_IRQ, KBD_IDT_VECTOR);
}