diff --git a/kernel/Makefile b/kernel/Makefile index fee4e7d..6a414c3 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -58,7 +58,6 @@ SRCFILES += $(call GRABSRC, \ path \ rbuf \ ipc/pipe \ - drivers/ps2kb \ drivers/serial \ dev \ ) diff --git a/kernel/dev/ps2kbdev.c b/kernel/dev/ps2kbdev.c index 0aadcda..a602564 100644 --- a/kernel/dev/ps2kbdev.c +++ b/kernel/dev/ps2kbdev.c @@ -9,15 +9,185 @@ #include "util/util.h" #include "hshtb.h" #include "sysdefs/devctl.h" +#include "proc/proc.h" -Ps2KbFastBuf PS2KB_BUF; +#define KB_CTL_STATUS 0x64 +#define KB_DATA_IN_BUF 0x01 +#define KB_DATA 0x60 + +#define KB_SHIFT (1<<0) +#define KB_CTL (1<<1) +#define KB_ALT (1<<2) + +#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, + [0x36] 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; +} + +typedef struct Ps2kbEvConsumer { + struct Ps2kbEvConsumer *next; + Proc *proc; + RBuf rbuf; +} Ps2kbEvConsumer; + +struct { + SpinLock spinlock; + Ps2kbEvConsumer *list; +} PS2KB_CONSUMERS = {0}; int32_t ps2kbdev_readch(uint8_t *buffer, size_t len, void *extra) { - (void)buffer; (void)len; (void)extra; - uint8_t b = 0; - spinlock_acquire(&PS2KB_BUF.spinlock); - int32_t r = rbuf_pop(&PS2KB_BUF.rbuf, &b); - spinlock_release(&PS2KB_BUF.spinlock); + uint64_t pid = (uint64_t)buffer; + Proc *consproc = NULL; + spinlock_acquire(&PROCS.spinlock); + Proc *proc, *proctmp; + LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) { + if (proc->pid == pid) { + consproc = proc; + } + } + spinlock_release(&PROCS.spinlock); + + if (consproc == NULL) { + return E_INVALIDOPER; + } + + uint8_t b; + int32_t r = -1; + + spinlock_acquire(&PS2KB_CONSUMERS.spinlock); + Ps2kbEvConsumer *cons, *constmp; + LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) { + if (cons->proc == consproc) { + r = rbuf_pop(&cons->rbuf, &b); + break; + } + } + spinlock_release(&PS2KB_CONSUMERS.spinlock); if (r == 0) { return b; @@ -26,14 +196,61 @@ int32_t ps2kbdev_readch(uint8_t *buffer, size_t len, void *extra) { } } +#define CONSUMER_RBUF_MAX 0x400 + +int32_t ps2kbdev_attchcons(uint8_t *buffer, size_t len, void *extra) { + uint64_t pid = (uint64_t)buffer; + spinlock_acquire(&PROCS.spinlock); + Proc *proc, *proctmp; + LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) { + if (proc->pid == pid) { + Ps2kbEvConsumer *cons = dlmalloc(sizeof(*cons)); + cons->proc = proc; + uint8_t *buf = dlmalloc(CONSUMER_RBUF_MAX); + rbuf_init(&cons->rbuf, buf, CONSUMER_RBUF_MAX); + spinlock_acquire(&PS2KB_CONSUMERS.spinlock); + LL_APPEND(PS2KB_CONSUMERS.list, cons); + spinlock_release(&PS2KB_CONSUMERS.spinlock); + break; + } + } + spinlock_release(&PROCS.spinlock); + return E_OK; +} + +void ps2kbdev_intr(void) { + int32_t c = ps2kb_intr(); + if (c >= 0) { + uint8_t b = c; + spinlock_acquire(&PS2KB_CONSUMERS.spinlock); + Ps2kbEvConsumer *cons, *constmp; + LL_FOREACH_SAFE(PS2KB_CONSUMERS.list, cons, constmp) { + bool found = false; + spinlock_acquire(&PROCS.spinlock); + Proc *proc, *proctmp; + LL_FOREACH_SAFE(PROCS.procs, proc, proctmp) { + if (proc == cons->proc) { + found = true; + } + } + if (!found) { + LL_REMOVE(PS2KB_CONSUMERS.list, cons); + } + spinlock_release(&PROCS.spinlock); + + rbuf_push(&cons->rbuf, b); + } + spinlock_release(&PS2KB_CONSUMERS.spinlock); + } +} + void ps2kbdev_init(void) { - const int bufsz = 0x1000; - uint8_t *buf = dlmalloc(bufsz); - rbuf_init(&PS2KB_BUF.rbuf, buf, bufsz); - PS2KB_BUF.init = true; + intr_attchhandler(&ps2kbdev_intr, INTR_IRQBASE+1); Dev *ps2kbdev; HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev); spinlock_init(&ps2kbdev->spinlock); + spinlock_init(&PS2KB_CONSUMERS.spinlock); ps2kbdev->fns[DEV_PS2KBDEV_READCH] = &ps2kbdev_readch; + ps2kbdev->fns[DEV_PS2KBDEV_ATTCHCONS] = &ps2kbdev_attchcons; } diff --git a/kernel/dev/ps2kbdev.h b/kernel/dev/ps2kbdev.h index 384857b..188e268 100644 --- a/kernel/dev/ps2kbdev.h +++ b/kernel/dev/ps2kbdev.h @@ -4,17 +4,7 @@ #include #include #include "dev.h" -#include "rbuf/rbuf.h" -#include "spinlock/spinlock.h" - -typedef struct { - RBuf rbuf; - SpinLock spinlock; - bool init; -} Ps2KbFastBuf; void ps2kbdev_init(void); -extern Ps2KbFastBuf PS2KB_BUF; - #endif // DEV_PS2KBDEV_H_ diff --git a/kernel/drivers/ps2kb/ps2kb.c b/kernel/drivers/ps2kb/ps2kb.c deleted file mode 100644 index 5bc1bd4..0000000 --- a/kernel/drivers/ps2kb/ps2kb.c +++ /dev/null @@ -1,142 +0,0 @@ -#include -#include "ps2kb.h" -#include "hal/hal.h" -#include "kprintf.h" - -#define KB_CTL_STATUS 0x64 -#define KB_DATA_IN_BUF 0x01 -#define KB_DATA 0x60 - -#define KB_SHIFT (1<<0) -#define KB_CTL (1<<1) -#define KB_ALT (1<<2) - -#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, - [0x36] 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 deleted file mode 100644 index 2824321..0000000 --- a/kernel/drivers/ps2kb/ps2kb.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef DRIVERS_PS2KB_H_ -#define DRIVERS_PS2KB_H_ - -#include - -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 b389cb7..85ed5c0 100644 --- a/kernel/hal/x86_64/intr.c +++ b/kernel/hal/x86_64/intr.c @@ -12,10 +12,25 @@ #include "proc/proc.h" #include "syscall/syscall.h" #include "errors.h" -#include "drivers/ps2kb/ps2kb.h" #include "ipc/pipe/pipe.h" #include "rbuf/rbuf.h" -#include "dev/ps2kbdev.h" +#include "dlmalloc/malloc.h" +#include "util/util.h" + +typedef struct IntrHandler { + struct IntrHandler *next; + void (*fn)(void); + int irq; +} IntrHandler; + +IntrHandler *INTR_HANDLERS = NULL; + +void intr_attchhandler(void (*fn)(void), int irq) { + IntrHandler *ih = dlmalloc(sizeof(*ih)); + ih->fn = fn; + ih->irq = irq; + LL_APPEND(INTR_HANDLERS, ih); +} typedef struct BackTraceFrame { struct BackTraceFrame *rbp; @@ -211,13 +226,12 @@ void intr_handleintr(IntrStackFrame *frame) { intr_eoi(); proc_sched((void *)frame); break; - case INTR_IRQBASE+1: - int32_t c = ps2kb_intr(); - if (c >= 0 && PS2KB_BUF.init) { - uint8_t b = c; - spinlock_acquire(&PS2KB_BUF.spinlock); - rbuf_push(&PS2KB_BUF.rbuf, b); - spinlock_release(&PS2KB_BUF.spinlock); + default: + IntrHandler *ih, *ihtmp; + LL_FOREACH_SAFE(INTR_HANDLERS, ih, ihtmp) { + if (ih->irq == frame->trapnum) { + ih->fn(); + } } intr_eoi(); break; diff --git a/kernel/hal/x86_64/intr.h b/kernel/hal/x86_64/intr.h index 232f202..cff9dc5 100644 --- a/kernel/hal/x86_64/intr.h +++ b/kernel/hal/x86_64/intr.h @@ -33,6 +33,7 @@ typedef struct { uint64_t ss; } PACKED IntrStackFrame; +void intr_attchhandler(void (*fn)(void), int irq); void intr_init(void); #endif // HAL_INTR_H_ diff --git a/share/sysdefs/devctl.h b/share/sysdefs/devctl.h index d32657b..2963128 100644 --- a/share/sysdefs/devctl.h +++ b/share/sysdefs/devctl.h @@ -5,7 +5,8 @@ #define DEV_TERMDEV_PUTCH 0 -#define DEV_PS2KBDEV_READCH 0 +#define DEV_PS2KBDEV_READCH 0 +#define DEV_PS2KBDEV_ATTCHCONS 1 #define DEV_SERIALDEV_SENDB 0 #define DEV_SERIALDEV_SENDREADY 1 diff --git a/user/init/main.c b/user/init/main.c index 0d99c0b..90f2d7d 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -21,12 +21,8 @@ void tb_runinitscript(void) { r = ipcpipe(tb, IPCPIPE_OUT, IPCPIPE_READ, (uint8_t *)buf, sizeof(buf)-1); if (r > 0) { devctl(&termdev, DEV_TERMDEV_PUTCH, (uint8_t *)buf, string_len(buf), 0); - } - - r = devctl(&ps2kbdev, DEV_PS2KBDEV_READCH, NULL, 0, 0); - if (r != E_NOTYET) { - uint8_t b = r; - ipcpipe(tb, IPCPIPE_IN, IPCPIPE_WRITE, &b, 1); + } else { + schedrelease(); } } } @@ -34,6 +30,7 @@ void tb_runinitscript(void) { void main(void) { PID = (uint64_t)processctl(-1, PCTL_GETPID, 0, 0, 0); devctl(&ps2kbdev, DEVCTL_GET_HANDLE, (uint8_t *)"ps2kbdev", 0, 0); + devctl(&ps2kbdev, DEV_PS2KBDEV_ATTCHCONS, (uint8_t *)PID, 0, 0); tb_runinitscript(); diff --git a/user/tb/main.c b/user/tb/main.c index 9175c28..f1608af 100644 --- a/user/tb/main.c +++ b/user/tb/main.c @@ -7,6 +7,7 @@ #define LINEBUF_MAX 1024 PID_t PID; +Dev_t ps2kbdev; struct { char *modestr; @@ -106,8 +107,9 @@ void do_mode_interactive(void) { uint8_t b = 0; for (;;) { - int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); - if (nrd > 0) { + int32_t key = devctl(&ps2kbdev, DEV_PS2KBDEV_READCH, (uint8_t *)PID, 0, 0); + if (key > 0) { + b = (uint8_t)key; switch (b) { case C('C'): case 0xE9: @@ -155,6 +157,8 @@ void main(void) { } if (CONFIG.mode == MODE_INTERACTIVE) { + devctl(&ps2kbdev, DEVCTL_GET_HANDLE, (uint8_t *)"ps2kbdev", 0, 0); + devctl(&ps2kbdev, DEV_PS2KBDEV_ATTCHCONS, (uint8_t *)PID, 0, 0); do_mode_interactive(); } else if (CONFIG.mode == MODE_RUNFILE) { if (CONFIG.filepath == NULL) {