From 9644ad0b4e634f7e45fef55bfe1141535b4bfb02 Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sun, 7 Sep 2025 20:53:36 +0200 Subject: [PATCH] Handle ps2 keyboard via special process --- kernel/Makefile | 3 + kernel/drivers/ps2kb/ps2kb.c | 144 +++++++++++++++++++++++++++--- kernel/drivers/ps2kb/ps2kb.h | 4 +- kernel/hal/x86_64/intr.c | 6 +- kernel/proc/kproc/kproc.c | 16 ++++ kernel/proc/kproc/kproc.h | 11 +++ kernel/proc/proc.c | 31 +++---- kernel/proc/ps2kbproc/ps2kbproc.c | 19 ++++ kernel/proc/ps2kbproc/ps2kbproc.h | 11 +++ kernel/proc/termproc/termproc.c | 25 ++++++ kernel/proc/termproc/termproc.h | 11 +++ kernel/spinlock/spinlock.c | 26 ++++-- kernel/spinlock/spinlock.h | 1 + kernel/syscall/ipcpipe.c | 27 ++++++ std/include/stdatomic.h | 6 ++ user/init/main.c | 11 +++ 16 files changed, 312 insertions(+), 40 deletions(-) create mode 100644 kernel/proc/kproc/kproc.c create mode 100644 kernel/proc/kproc/kproc.h create mode 100644 kernel/proc/ps2kbproc/ps2kbproc.c create mode 100644 kernel/proc/ps2kbproc/ps2kbproc.h create mode 100644 kernel/proc/termproc/termproc.c create mode 100644 kernel/proc/termproc/termproc.h diff --git a/kernel/Makefile b/kernel/Makefile index 34a5ae3..e7af3a1 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -53,6 +53,9 @@ SRCFILES += $(call GRABSRC, \ fs/portlfs \ baseimg \ proc \ + proc/kproc \ + proc/ps2kbproc \ + proc/termproc \ hal \ hal/$(ARCH) \ std \ diff --git a/kernel/drivers/ps2kb/ps2kb.c b/kernel/drivers/ps2kb/ps2kb.c index b44f96a..a427b2f 100644 --- a/kernel/drivers/ps2kb/ps2kb.c +++ b/kernel/drivers/ps2kb/ps2kb.c @@ -3,17 +3,139 @@ #include "hal/hal.h" #include "kprintf.h" -void ps2kb_write(uint8_t val) { - while (io_in8(0x64) & 2); - io_out8(0x64, val); -} +#define KB_CTL_STATUS 0x64 +#define KB_DATA_IN_BUF 0x01 +#define KB_DATA 0x60 -uint8_t ps2kb_read(void) { - while (!(io_in8(0x64) & 1)); - return io_in8(0x60); -} +#define KB_SHIFT (1<<0) +#define KB_CTL (1<<1) +#define KB_ALT (1<<2) -void ps2kb_intr(void) { - uint8_t scancode = ps2kb_read(); - kprintf("%02x\n", scancode); +#define KB_CAPSLOCK (1<<3) +#define KB_NUMLOCK (1<<4) +#define KB_SCRLLOCK (1<<5) +#define KB_E0ESC (1<<6) + +#define KB_HOME 0xe0 +#define KB_END 0xe1 +#define KB_UP 0xe2 +#define KB_DOWN 0xe3 +#define KB_LEFT 0xe4 +#define KB_RIGHT 0xe5 +#define KB_PAGEUP 0xe6 +#define KB_PAGEDN 0xe7 +#define KB_INSERT 0xe8 +#define KB_DELETE 0xe9 + +#define C(x) ((x)-'@') + +static uint8_t shiftcode[0x100] = { + [0x1d] KB_CTL, + [0x2a] KB_SHIFT, + [0x38] KB_ALT, + [0x9d] KB_CTL, + [0xb8] KB_ALT, +}; + +static uint8_t togglecode[0x100] = { + [0x3a] KB_CAPSLOCK, + [0x45] KB_NUMLOCK, + [0x46] KB_SCRLLOCK, +}; + +static uint8_t normalmap[0x100] = { + 0x0, 0x1b, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\b', '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', '\n', 0x0, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', 0x0, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', 0x0, '*', + 0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', 0x0, 0x0, 0x0, 0x0, + [0x9c] '\n', + [0xb5] '/', + [0xc8] KB_UP, [0xd0] KB_DOWN, + [0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN, + [0xcb] KB_LEFT, [0xcd] KB_RIGHT, + [0x97] KB_HOME, [0xcf] KB_END, + [0xd2] KB_INSERT, [0xd3] KB_DELETE, +}; + +static uint8_t shiftmap[256] = { + 0x0, 033,'!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\b', '\t', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', 0x0, 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '"', '~', 0x0, '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', 0x0, '*', + 0x0, ' ', 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', + '8', '9', '-', '4', '5', '6', '+', '1', + '2', '3', '0', '.', 0x0, 0x0, 0x0, 0x0, + [0x9C] '\n', + [0xB5] '/', + [0xc8] KB_UP, [0xd0] KB_DOWN, + [0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN, + [0xcb] KB_LEFT, [0xcd] KB_RIGHT, + [0x97] KB_HOME, [0xcf] KB_END, + [0xd2] KB_INSERT, [0xd3] KB_DELETE, +}; + +static uint8_t ctlmap[256] = +{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'), + C('O'), C('P'), 0x0, 0x0, '\r', 0x0, C('A'), C('S'), + C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), 0x0, + 0x0, 0x0, 0x0, C('\\'), C('Z'), C('X'), C('C'), C('V'), + C('B'), C('N'), C('M'), 0x0, 0x0, C('/'), 0x0, 0x0, + [0x9C] '\r', + [0xB5] C('/'), + [0xc8] KB_UP, [0xd0] KB_DOWN, + [0xc9] KB_PAGEUP, [0xd1] KB_PAGEDN, + [0xcb] KB_LEFT, [0xcd] KB_RIGHT, + [0x97] KB_HOME, [0xcf] KB_END, + [0xd2] KB_INSERT, [0xd3] KB_DELETE, +}; + +int32_t ps2kb_intr(void) { + static uint8_t shift; + static uint8_t *charcode[4] = { normalmap, shiftmap, ctlmap, ctlmap }; + uint32_t st, data, c; + + st = io_in8(KB_CTL_STATUS); + if (!(st & KB_DATA_IN_BUF)) { + return -1; + } + data = io_in8(KB_DATA); + + if (data == 0xe0) { + shift |= KB_E0ESC; + return 0; + } else if (data & 0x80) { + data = (shift & KB_E0ESC ? data : data & 0x7F); + shift &= ~(shiftcode[data] | KB_E0ESC); + return 0; + } else if (shift & KB_E0ESC) { + data |= 0x80; + shift &= ~KB_E0ESC; + } + + shift |= shiftcode[data]; + shift ^= togglecode[data]; + c = charcode[shift & (KB_CTL | KB_SHIFT)][data]; + if (shift & KB_CAPSLOCK) { + if ('a' <= c && c <= 'z') { + c += 'A' - 'a'; + } else if ('A' <= c && c <= 'Z') { + c += 'a' - 'A'; + } + } + + return c; } diff --git a/kernel/drivers/ps2kb/ps2kb.h b/kernel/drivers/ps2kb/ps2kb.h index 37a2724..2824321 100644 --- a/kernel/drivers/ps2kb/ps2kb.h +++ b/kernel/drivers/ps2kb/ps2kb.h @@ -3,8 +3,6 @@ #include -void ps2kb_write(uint8_t val); -uint8_t ps2kb_read(void); -void ps2kb_intr(void); +int32_t ps2kb_intr(void); #endif // DRIVERS_PS2KB_H_ diff --git a/kernel/hal/x86_64/intr.c b/kernel/hal/x86_64/intr.c index 9f8b979..ad27f56 100644 --- a/kernel/hal/x86_64/intr.c +++ b/kernel/hal/x86_64/intr.c @@ -13,6 +13,8 @@ #include "syscall/syscall.h" #include "errors.h" #include "drivers/ps2kb/ps2kb.h" +#include "ipc/pipe/pipe.h" +#include "proc/ps2kbproc/ps2kbproc.h" void hal_intr_disable(void) { asm volatile("cli"); @@ -197,7 +199,9 @@ void intr_handleintr(IntrStackFrame *frame) { proc_sched((void *)frame); break; case INTR_IRQBASE+1: - ps2kb_intr(); + int32_t c = ps2kb_intr(); + uint8_t *bytes = (uint8_t *)&c; + ipc_pipewrite(PS2KBPROC->pipes[0], bytes, sizeof(c)); intr_eoi(frame->trapnum - INTR_IRQBASE); break; } diff --git a/kernel/proc/kproc/kproc.c b/kernel/proc/kproc/kproc.c new file mode 100644 index 0000000..ea92798 --- /dev/null +++ b/kernel/proc/kproc/kproc.c @@ -0,0 +1,16 @@ +#include +#include "proc/proc.h" +#include "hal/hal.h" +#include "ipc/pipe/pipe.h" +#include "kprintf.h" + +Proc *KPROC; + +void kproc_init(Proc *proc) { + KPROC = proc; +} + +void kproc_fn(void) { + for (;;) { + } +} diff --git a/kernel/proc/kproc/kproc.h b/kernel/proc/kproc/kproc.h new file mode 100644 index 0000000..6e13468 --- /dev/null +++ b/kernel/proc/kproc/kproc.h @@ -0,0 +1,11 @@ +#ifndef PROC_KPROC_KPROC_H_ +#define PROC_KPROC_KPROC_H_ + +#include "proc/proc.h" + +extern Proc *KPROC; + +void kproc_fn(void); +void kproc_init(Proc *proc); + +#endif // PROC_KPROC_KPROC_H_ diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 2296943..63f6868 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -13,6 +13,9 @@ #include "vfs/vfs.h" #include "bootinfo/bootinfo.h" #include "ipc/pipe/pipe.h" +#include "kproc/kproc.h" +#include "ps2kbproc/ps2kbproc.h" +#include "termproc/termproc.h" #define PROC_REAPER_FREQ 30 @@ -281,30 +284,22 @@ void proc_status(void) { } } -Proc *kproc = NULL; - -void proc_kproc(void) { - char buf[100]; - hal_memset(buf, 0, sizeof(buf)); - for (;;) { - int32_t read = ipc_piperead(kproc->pipes[1], buf, sizeof(buf)); - kprintf("%.*s", read, buf); - hal_memset(buf, 0, sizeof(buf)); - } -} - void proc_init(void) { spinlock_init(&PROCS.spinlock); PROCS.procs = NULL; - kproc = proc_spawnkern(&proc_kproc, "kproc"); - kproc->pipes[1] = dlmalloc(sizeof(IpcPipe)); - ipc_pipeinit(kproc->pipes[1]); - proc_register(kproc); - PROCS.current = kproc; + kproc_init(proc_spawnkern(&kproc_fn, "kproc")); + proc_register(KPROC); + PROCS.current = KPROC; + + ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); + proc_register(PS2KBPROC); + + termproc_init(proc_spawnkern(&termproc_fn, "termproc")); + proc_register(TERMPROC); Proc *init = proc_spawnuser("base", "/bin/init"); - init->pipes[0] = kproc->pipes[1]; + init->pipes[0] = TERMPROC->pipes[1]; proc_register(init); hal_switchproc(&PROCS.current->platformdata.trapframe, (void *)PROCS.current->platformdata.cr3); diff --git a/kernel/proc/ps2kbproc/ps2kbproc.c b/kernel/proc/ps2kbproc/ps2kbproc.c new file mode 100644 index 0000000..5ffa38e --- /dev/null +++ b/kernel/proc/ps2kbproc/ps2kbproc.c @@ -0,0 +1,19 @@ +#include +#include "proc/proc.h" +#include "dlmalloc/malloc.h" +#include "ipc/pipe/pipe.h" + +Proc *PS2KBPROC; + +void ps2kbproc_init(Proc *proc) { + PS2KBPROC = proc; + PS2KBPROC->pipes[0] = dlmalloc(sizeof(IpcPipe)); + ipc_pipeinit(PS2KBPROC->pipes[0]); +} + +void ps2kbproc_fn(void) { + for (;;) { + + } +} + diff --git a/kernel/proc/ps2kbproc/ps2kbproc.h b/kernel/proc/ps2kbproc/ps2kbproc.h new file mode 100644 index 0000000..a3dc6e0 --- /dev/null +++ b/kernel/proc/ps2kbproc/ps2kbproc.h @@ -0,0 +1,11 @@ +#ifndef PROC_PS2KB_PS2KBPROC_H_ +#define PROC_PS2KB_PS2KBPROC_H_ + +#include "proc/proc.h" + +extern Proc *PS2KBPROC; + +void ps2kbproc_fn(void); +void ps2kbproc_init(Proc *proc); + +#endif // PROC_PS2KB_PS2KBPROC_H_ diff --git a/kernel/proc/termproc/termproc.c b/kernel/proc/termproc/termproc.c new file mode 100644 index 0000000..7167029 --- /dev/null +++ b/kernel/proc/termproc/termproc.c @@ -0,0 +1,25 @@ +#include +#include "proc/proc.h" +#include "ipc/pipe/pipe.h" +#include "kprintf.h" +#include "hal/hal.h" +#include "dlmalloc/malloc.h" + +Proc *TERMPROC; + +void termproc_init(Proc *proc) { + TERMPROC = proc; + TERMPROC->pipes[1] = dlmalloc(sizeof(IpcPipe)); + ipc_pipeinit(TERMPROC->pipes[1]); +} + +void termproc_fn(void) { + char buf[100]; + for (;;) { + hal_memset(buf, 0, sizeof(buf)); + int32_t read = ipc_piperead(TERMPROC->pipes[1], (uint8_t *)buf, sizeof(buf)); + if (read > 0) { + kprintf("%.*s", read, buf); + } + } +} diff --git a/kernel/proc/termproc/termproc.h b/kernel/proc/termproc/termproc.h new file mode 100644 index 0000000..ecb98e6 --- /dev/null +++ b/kernel/proc/termproc/termproc.h @@ -0,0 +1,11 @@ +#ifndef PROC_TERMPROC_TERMPROC_H_ +#define PROC_TERMPROC_TERMPROC_H_ + +#include "proc/proc.h" + +extern Proc *TERMPROC; + +void termproc_init(Proc *proc); +void termproc_fn(void); + +#endif // PROC_TERMPROC_TERMPROC_H_ diff --git a/kernel/spinlock/spinlock.c b/kernel/spinlock/spinlock.c index 136ea9a..97307db 100644 --- a/kernel/spinlock/spinlock.c +++ b/kernel/spinlock/spinlock.c @@ -1,24 +1,36 @@ #include #include +#include #include "spinlock.h" #include "hal/hal.h" +#include "kprintf.h" void spinlock_init(SpinLock *sl) { atomic_store(&sl->lock, false); + sl->flags = 0; +} + +uint64_t spinlock_irqsave(void) { + uint64_t flags; + asm volatile("pushfq; cli; popq %0" : "=r"(flags)); + return flags; +} + +void spinlock_irqrestore(uint64_t flags) { + asm volatile("pushq %0; popfq" :: "r"(flags)); } void spinlock_acquire(SpinLock *sl) { - bool unlocked = false; - while (!atomic_compare_exchange_weak(&sl->lock, &unlocked, true)) { - unlocked = false; + sl->flags = spinlock_irqsave(); + + while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) { SPINLOCK_HINT(); } } void spinlock_release(SpinLock *sl) { - bool locked = true; - if (atomic_compare_exchange_strong(&sl->lock, &locked, false)) { - atomic_store(&sl->lock, false); - } + atomic_clear_flag_explicit(&sl->lock, memory_order_release); + + spinlock_irqrestore(sl->flags); } diff --git a/kernel/spinlock/spinlock.h b/kernel/spinlock/spinlock.h index 3d9e53f..c802060 100644 --- a/kernel/spinlock/spinlock.h +++ b/kernel/spinlock/spinlock.h @@ -6,6 +6,7 @@ typedef struct { atomic_bool lock; + uint64_t flags; } SpinLock; #define SPINLOCK_HINT() asm volatile("pause") diff --git a/kernel/syscall/ipcpipe.c b/kernel/syscall/ipcpipe.c index c698f58..f5696a6 100644 --- a/kernel/syscall/ipcpipe.c +++ b/kernel/syscall/ipcpipe.c @@ -8,6 +8,7 @@ #include "spinlock/spinlock.h" #include "errors.h" #include "util/util.h" +#include "kprintf.h" int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { uint64_t pid = pid1; @@ -64,8 +65,34 @@ int32_t SYSCALL5(sys_ipcpipe, pid1, pipenum1, cmd1, buffer1, len1) { IpcPipe *pipe = proc->pipes[pipenum]; + if (pipe == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + ret = ipc_pipewrite(pipe, buffer, len1); } break; + case IPCPIPE_READ: { + if (pipenum >= PROC_PIPEHANDLES_MAX) { + ret = E_INVALIDARGUMENT; + goto done; + } + + uint8_t *const buffer = (uint8_t *const)buffer1; + if (buffer == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + IpcPipe *pipe = proc->pipes[pipenum]; + + if (pipe == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + ret = ipc_piperead(pipe, buffer, len1); + } break; default: { ret = E_INVALIDARGUMENT; } break; diff --git a/std/include/stdatomic.h b/std/include/stdatomic.h index 3170f38..c111f3a 100644 --- a/std/include/stdatomic.h +++ b/std/include/stdatomic.h @@ -20,6 +20,12 @@ #define atomic_compare_exchange_strong(p, old, new) \ __atomic_compare_exchange_n(p, old, new, false, memory_order_relaxed, memory_order_relaxed) +#define atomic_test_and_set_explicit(p, memory_order) \ + __atomic_test_and_set(p, memory_order) + +#define atomic_clear_flag_explicit(p, memory_order) \ + __atomic_clear(p, memory_order) + #define atomic_bool _Atomic(bool) #endif diff --git a/user/init/main.c b/user/init/main.c index 2ad9d2a..852f423 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -5,6 +5,8 @@ #include #include #include +#include +#include void main(void) { debugprint(ANSIQ_SCR_CLR_ALL); @@ -24,6 +26,15 @@ void main(void) { uprintf("Hello world using uprintf\n"); + while(1) { + int32_t kbchar; + int32_t read = ipcpipe(1, 0, IPCPIPE_READ, (uint8_t *)&kbchar, sizeof(kbchar)); + + if (read > 0 && (kbchar >= 0x20 && kbchar <= 0x7F)) { + uprintf("%c", (char)kbchar); + } + } + for(;;); }