From a81ac96e3041aa9925406b05f74d72b53386adfe Mon Sep 17 00:00:00 2001 From: Stepan Usatiuk Date: Mon, 29 Apr 2024 00:20:28 +0200 Subject: [PATCH] PS2Keyboard: Janky ps2 driver --- .../newlib/libc/sys/ficus/syscalls.c | 17 +- src/arch/x86/CMakeLists.txt | 1 + src/arch/x86/PS2Keyboard.cpp | 251 ++++++++++++++++++ src/arch/x86/PS2Keyboard.hpp | 32 +++ src/arch/x86/idt.cpp | 5 +- src/arch/x86/kmain.cpp | 6 +- src/kernel/FbTty.cpp | 4 + src/kernel/FbTty.hpp | 3 + 8 files changed, 313 insertions(+), 6 deletions(-) create mode 100644 src/arch/x86/PS2Keyboard.cpp create mode 100644 src/arch/x86/PS2Keyboard.hpp diff --git a/ficus-toolchain/newlib/newlib-4.4.0.20231231/newlib/libc/sys/ficus/syscalls.c b/ficus-toolchain/newlib/newlib-4.4.0.20231231/newlib/libc/sys/ficus/syscalls.c index e42c31b3f..fa403c41a 100644 --- a/ficus-toolchain/newlib/newlib-4.4.0.20231231/newlib/libc/sys/ficus/syscalls.c +++ b/ficus-toolchain/newlib/newlib-4.4.0.20231231/newlib/libc/sys/ficus/syscalls.c @@ -42,9 +42,9 @@ int _close(int file) { return _do_syscall(SYSCALL_CLOSE_ID, file, 0, 0); } -char **environ; /* pointer to array of char * strings that define the current environment variables */ +char **environ = 0; /* pointer to array of char * strings that define the current environment variables */ -int _execve(char *name, char **argv, char **env) { +int _execve(char *name, char **argv, char **env) { return _do_syscall(SYSCALL_EXECVE_ID, (uint64_t) name, (uint64_t) argv, (uint64_t) env); } @@ -53,6 +53,7 @@ int _fork() { } int _getpid() { + return -1; } int _isatty(int file) { return file == 0 || file == 1 || file == 2; } @@ -62,9 +63,11 @@ int _fstat(int file, struct stat *st) { } int _kill(int pid, int sig) { + return -1; } int _link(char *old, char *new) { + return -1; } int _lseek(int file, int ptr, int dir) { @@ -84,12 +87,19 @@ caddr_t _sbrk(int incr) { } int _stat(const char *file, struct stat *st) { + return -1; } clock_t _times(struct tms *buf) { + buf->tms_cstime = 0; + buf->tms_cutime = 0; + buf->tms_stime = 0; + buf->tms_utime = 0; + return 0; } int _unlink(char *name) { + return -1; } int _wait(int *status) { @@ -118,6 +128,9 @@ int usleep(useconds_t useconds) { int _gettimeofday(struct timeval *restrict p, void *restrict z) { + p->tv_sec = 0; + p->tv_usec = 0; + return 0; } void print_mem() { diff --git a/src/arch/x86/CMakeLists.txt b/src/arch/x86/CMakeLists.txt index 4a4378615..7361f1195 100644 --- a/src/arch/x86/CMakeLists.txt +++ b/src/arch/x86/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources(kernel.elf PRIVATE limine_modules.cpp handle_exception.cpp LimineFramebuffer.cpp + PS2Keyboard.cpp ) target_include_directories(kernel.elf PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/arch/x86/PS2Keyboard.cpp b/src/arch/x86/PS2Keyboard.cpp new file mode 100644 index 000000000..2755a0f63 --- /dev/null +++ b/src/arch/x86/PS2Keyboard.cpp @@ -0,0 +1,251 @@ +// +// Created by Stepan Usatiuk on 28.04.2024. +// + +#include "PS2Keyboard.hpp" + +#include + +#define PORTD 0x60 // COM1 +#define PORTS 0x64 // COM1 +#define PORTC 0x64 // COM1 + +static void wait_in() { + while ((inb(PORTS) & 1) == 0) { + __builtin_ia32_pause(); + } +} + +static void wait_out() { + while (inb(PORTS) & 2) { + __builtin_ia32_pause(); + } +} + +static void outb_wait(uint16_t port, uint8_t val) { + wait_out(); + outb(port, val); +} + +static uint8_t inb_wait(uint16_t port) { + wait_in(); + return inb(port); +} + +void PS2Keyboard::this_pooler() { + mutex.lock(); + while (true) { + isrcv.wait(mutex); + wait_in(); + + bool read_something = false; + + while ((inb(PORTS) & 1) != 0) { + int read = inb_wait(PORTD); + char r = -1; + if (read == 0xF0) { + inb_wait(PORTD); + continue; + } + switch (read) { + case 0x1C: + r = 'a'; + break; + case 0x24: + r = 'e'; + break; + case 0x2C: + r = 't'; + break; + case 0x34: + r = 'g'; + break; + case 0x3C: + r = 'u'; + break; + case 0x44: + r = 'o'; + break; + case 0x15: + r = 'q'; + break; + case 0x1D: + r = 'w'; + break; + case 0x21: + r = 'c'; + break; + case 0x29: + r = ' '; + break; + case 0x2D: + r = 'r'; + break; + case 0x31: + r = 'n'; + break; + case 0x35: + r = 'y'; + break; + case 0x4D: + r = 'p'; + break; + case 0x1A: + r = 'z'; + break; + case 0x22: + r = 'x'; + break; + case 0x2A: + r = 'v'; + break; + case 0x32: + r = 'b'; + break; + case 0x3A: + r = 'm'; + break; + case 0x42: + r = 'k'; + break; + case 0x1B: + r = 's'; + break; + case 0x23: + r = 'd'; + break; + case 0x2B: + r = 'f'; + break; + case 0x33: + r = 'h'; + break; + case 0x3B: + r = 'j'; + break; + case 0x43: + r = 'i'; + break; + case 0x4B: + r = 'l'; + break; + + case 0x54: + r = '('; + break; + case 0x5B: + r = ')'; + break; + case 0x5A: { + read_something = true; + if (!buf.full()) + buf.push_back((char) '\n'); + if (!buf.full()) + buf.push_back((char) '\r'); + break; + } + case 0x16: + r = '1'; + break; + case 0x1E: + r = '2'; + break; + case 0x26: + r = '3'; + break; + case 0x25: + r = '4'; + break; + case 0x2E: + r = '5'; + break; + case 0x36: + r = '6'; + break; + case 0x3D: + r = '7'; + break; + case 0x3E: + r = '8'; + break; + case 0x46: + r = '9'; + break; + } + + if (r != -1) { + read_something = true; + if (!buf.full()) + buf.push_back((char) r); + } + } + + if (read_something) + readercv.notify_all(); + } + mutex.unlock(); +} + +PS2Keyboard::PS2Keyboard() { + outb_wait(PORTC, 0xAD); // Disable 1 + outb_wait(PORTC, 0xA7); // Disable 2 + inb(PORTD); + outb_wait(PORTC, 0x20); // Read conf + uint8_t old_conf = inb_wait(PORTD); + old_conf &= ~(1 << 0 | 1 << 1 | 1 << 6); + outb_wait(PORTC, 0x60); // Write conf + outb_wait(PORTD, old_conf); + + outb_wait(PORTC, 0xAA); + assert(inb_wait(PORTD) == 0x55); + outb_wait(PORTC, 0xAB); + assert(inb_wait(PORTD) == 0x00); + outb_wait(PORTC, 0xAE); + + outb_wait(PORTC, 0x20); // Read conf + old_conf = inb_wait(PORTD); + old_conf |= 1; // Enable IRQ1 + outb_wait(PORTC, 0x60); // Write conf + outb_wait(PORTD, old_conf); + + outb_wait(PORTD, 0xFF); // Reset + assert(inb_wait(PORTD) == 0xFA); + outb_wait(PORTD, 0xF6); // Set default + assert(inb_wait(PORTD) == 0xFA); + + outb_wait(PORTD, 0xF0); // Scancode + assert(inb_wait(PORTD) == 0xFA); + + outb_wait(PORTD, 2); // Scancode 2 + assert(inb_wait(PORTD) == 0xFA); + + + outb_wait(PORTD, 0xF4); // Scan + assert(inb_wait(PORTD) == 0xFA); + + for (int i = 0; i < 256; i++) states[i] = false; + + Task *task = new Task(Task::TaskMode::TASKMODE_KERN, (void (*)(void))(&PS2Keyboard::this_pooler), "ps2kbd"); + task->_frame.rdi = reinterpret_cast(this); + task->start(); + + attach_interrupt(1, &PS2Keyboard::isr, this); + Arch::IDT::IRQ_clear_mask(1); +} +void PS2Keyboard::isr(void *tty) { + ((PS2Keyboard *) tty)->this_isr(); +} + +void PS2Keyboard::this_isr() { + isrcv.notify_one(); +} + +char PS2Keyboard::readchar() { + mutex.lock(); + while (buf.empty()) { + readercv.wait(mutex); + } + char ret = buf.pop_back(); + mutex.unlock(); + return ret; +} diff --git a/src/arch/x86/PS2Keyboard.hpp b/src/arch/x86/PS2Keyboard.hpp new file mode 100644 index 000000000..3dc129a0b --- /dev/null +++ b/src/arch/x86/PS2Keyboard.hpp @@ -0,0 +1,32 @@ +// +// Created by Stepan Usatiuk on 28.04.2024. +// + +#ifndef PS2KEYBOARD_HPP +#define PS2KEYBOARD_HPP + +#include +#include +#include + + +class PS2Keyboard { + // TODO: Possibly there should be 2 mutexes? + Mutex mutex; + CV readercv; + CV isrcv; + static void isr(void *tty); + + void this_isr(); + void this_pooler(); + char process_scancode(int); + bool states[256]; + CircularBuffer buf; + +public: + PS2Keyboard(); + char readchar(); +}; + + +#endif //PS2KEYBOARD_HPP diff --git a/src/arch/x86/idt.cpp b/src/arch/x86/idt.cpp index 97d1bcef1..a82721e5d 100644 --- a/src/arch/x86/idt.cpp +++ b/src/arch/x86/idt.cpp @@ -173,7 +173,10 @@ namespace Arch::IDT { Scheduler::switch_task(frame); PIC_sendEOI(0); } - extern "C" void pic1_irq_real_1() { + extern "C" __attribute__((force_align_arg_pointer)) void pic1_irq_real_1() { + if (handlers[1] != nullptr) { + handlers[1](handlers_args[1]); + } PIC_sendEOI(1); } extern "C" void pic1_irq_real_2() { diff --git a/src/arch/x86/kmain.cpp b/src/arch/x86/kmain.cpp index efe288ae3..7befffba7 100644 --- a/src/arch/x86/kmain.cpp +++ b/src/arch/x86/kmain.cpp @@ -34,10 +34,10 @@ #include void templates_tester() { - GlobalTtyManager.all_tty_putstr("Testing templates\n"); + // GlobalTtyManager.all_tty_putstr("Testing templates\n"); for (int i = 0; i < 5; i++) test_templates(); - GlobalTtyManager.all_tty_putstr("Testing templates OK\n"); + // GlobalTtyManager.all_tty_putstr("Testing templates OK\n"); } void vfs_tester() { @@ -46,9 +46,9 @@ void vfs_tester() { } void ktask_main() { - GlobalTtyManager.add_tty(new SerialTty()); for (int i = 0; i < framebuffer_count; i++) GlobalTtyManager.add_tty(new FbTty(new LimineFramebuffer(&framebuffers[i]))); + GlobalTtyManager.add_tty(new SerialTty()); (new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester"))->start(); (new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start(); diff --git a/src/kernel/FbTty.cpp b/src/kernel/FbTty.cpp index 1efbb7659..5f951ec62 100644 --- a/src/kernel/FbTty.cpp +++ b/src/kernel/FbTty.cpp @@ -32,6 +32,10 @@ void FbTty::putstr(const char *str) { } } char FbTty::readchar() { + char r = kbd.readchar(); + if (r != '\r') + putchar(r); + return r; } void FbTty::next_col() { _cur_col++; diff --git a/src/kernel/FbTty.hpp b/src/kernel/FbTty.hpp index c65c63bbc..a95847ff5 100644 --- a/src/kernel/FbTty.hpp +++ b/src/kernel/FbTty.hpp @@ -4,6 +4,7 @@ #ifndef FBTTY_HPP #define FBTTY_HPP +#include #include @@ -28,6 +29,8 @@ private: void next_col(); void next_row(); + + PS2Keyboard kbd; };