Clean up PS/2 keyboard driver, new IPC mechanism MBus (message bus)

This commit is contained in:
2025-11-11 23:10:38 +01:00
parent 07fc8a5562
commit 4fe907a733
6 changed files with 253 additions and 75 deletions

View File

@ -52,6 +52,7 @@ SRCFILES += $(call GRABSRC, \
path \ path \
rbuf \ rbuf \
ipc/pipe \ ipc/pipe \
ipc/mbus \
dev \ dev \
randcrypto \ randcrypto \
time \ time \

View File

@ -7,6 +7,7 @@
#include "sysdefs/dev.h" #include "sysdefs/dev.h"
#include "proc/proc.h" #include "proc/proc.h"
#include "io/io.h" #include "io/io.h"
#include "ipc/mbus/mbus.h"
#include "errors.h" #include "errors.h"
#include "hshtb.h" #include "hshtb.h"
#include "kprintf.h" #include "kprintf.h"
@ -152,100 +153,31 @@ int32_t ps2kb_intr(void) {
return c; return c;
} }
typedef struct Ps2kbEvConsumer { IpcMBus *PS2KB_MBUS;
struct Ps2kbEvConsumer *next;
Proc *proc;
RBuf rbuf;
} Ps2kbEvConsumer;
struct {
SpinLock spinlock;
Ps2kbEvConsumer *list;
} PS2KB_CONSUMERS = {0};
int32_t ps2kbdev_readch(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { int32_t ps2kbdev_readch(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)dev; (void)buffer; (void)len;
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; uint8_t b;
int32_t r = -1; int32_t r = ipc_mbusconsume("ps2kb", &b, pid);
if (r > 0) {
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; return b;
} else { } else {
return E_NOTYET; return E_NOTYET;
} }
} }
#define CONSUMER_RBUF_MAX 0x400
int32_t ps2kbdev_attchcons(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) { int32_t ps2kbdev_attchcons(struct Dev *dev, uint8_t *buffer, size_t len, uint64_t pid) {
(void)dev; (void)buffer; (void)len; (void)dev; (void)buffer; (void)len;
spinlock_acquire(&PROCS.spinlock); return ipc_mbusattchcons("ps2kb", pid);
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) { void ps2kbdev_intr(void) {
int32_t c = ps2kb_intr(); int32_t c = ps2kb_intr();
if (c >= 0) { if (c >= 0) {
uint8_t b = c; uint8_t b = c;
spinlock_acquire(&PS2KB_CONSUMERS.spinlock); ipc_mbuspublish("ps2kb", &b);
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);
} }
} }
@ -255,7 +187,7 @@ void ps2kbdev_init(void) {
Dev *ps2kbdev; Dev *ps2kbdev;
HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev); HSHTB_ALLOC(DEVTABLE.devs, ident, "ps2kbdev", ps2kbdev);
spinlock_init(&ps2kbdev->spinlock); spinlock_init(&ps2kbdev->spinlock);
spinlock_init(&PS2KB_CONSUMERS.spinlock); PS2KB_MBUS = ipc_mbusmake("ps2kb", 1, 0x100);
ps2kbdev->fns[DEV_PS2KBDEV_READCH] = &ps2kbdev_readch; ps2kbdev->fns[DEV_PS2KBDEV_READCH] = &ps2kbdev_readch;
ps2kbdev->fns[DEV_PS2KBDEV_ATTCHCONS] = &ps2kbdev_attchcons; ps2kbdev->fns[DEV_PS2KBDEV_ATTCHCONS] = &ps2kbdev_attchcons;
} }

202
kernel/ipc/mbus/mbus.c Normal file
View File

@ -0,0 +1,202 @@
#include <stdint.h>
#include <stddef.h>
#include "spinlock/spinlock.h"
#include "rbuf/rbuf.h"
#include "proc/proc.h"
#include "ipc/mbus/mbus.h"
#include "std/string.h"
#include "dlmalloc/malloc.h"
#include "util/util.h"
#include "hshtb.h"
#include "errors.h"
#include "kprintf.h"
IpcMBuses IPC_MBUSES;
void ipc_mbusinit(void) {
memset(&IPC_MBUSES, 0, sizeof(IPC_MBUSES));
spinlock_init(&IPC_MBUSES.spinlock);
}
IpcMBus *ipc_mbusmake(const char *name, size_t objsize, size_t objmax) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_ALLOC(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return NULL;
}
mbus->objsize = objsize;
mbus->objmax = objmax;
return mbus;
}
int32_t ipc_mbusdelete(const char *name) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_GET(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return E_NOENTRY;
}
IpcMBusCons *cons, *constmp;
spinlock_acquire(&mbus->spinlock);
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
LL_REMOVE(mbus->consumers, cons);
dlfree(cons->rbuf.buffer);
dlfree(cons);
}
spinlock_release(&mbus->spinlock);
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_DELETE(IPC_MBUSES.mbuses, ident, (char *)name);
spinlock_release(&IPC_MBUSES.spinlock);
return E_OK;
}
int32_t ipc_mbuspublish(const char *name, const uint8_t *const buffer) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_GET(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return E_NOENTRY;
}
size_t i = 0;
IpcMBusCons *cons, *constmp;
spinlock_acquire(&mbus->spinlock);
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
for (; i < mbus->objsize; i++) {
if (rbuf_push(&cons->rbuf, buffer[i]) < 0) {
break;
}
}
}
spinlock_release(&mbus->spinlock);
return i;
}
int32_t ipc_mbusconsume(const char *name, uint8_t *const buffer, uint64_t pid) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_GET(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return E_NOENTRY;
}
size_t i = 0;
IpcMBusCons *cons, *constmp;
spinlock_acquire(&mbus->spinlock);
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
if (cons->pid == pid) {
for (; i < mbus->objsize; i++) {
if (rbuf_pop(&cons->rbuf, &buffer[i]) < 0) {
break;
}
}
break;
}
}
spinlock_release(&mbus->spinlock);
return i;
}
int32_t ipc_mbusattchcons(const char *name, uint64_t pid) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_GET(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return E_NOENTRY;
}
IpcMBusCons *cons = dlmalloc(sizeof(*cons));
if (cons == NULL) {
return E_NOMEMORY;
}
memset(cons, 0, sizeof(*cons));
cons->pid = pid;
uint8_t *buffer = dlmalloc(mbus->objsize * mbus->objmax);
if (buffer == NULL) {
dlfree(cons);
return E_NOMEMORY;
}
rbuf_init(&cons->rbuf, buffer, mbus->objsize * mbus->objmax);
LL_APPEND(mbus->consumers, cons);
return E_OK;
}
int32_t ipc_mbusdttchcons(const char *name, uint64_t pid) {
IpcMBus *mbus = NULL;
spinlock_acquire(&IPC_MBUSES.spinlock);
HSHTB_GET(IPC_MBUSES.mbuses, ident, (char *)name, mbus);
spinlock_release(&IPC_MBUSES.spinlock);
if (mbus == NULL) {
return E_NOENTRY;
}
IpcMBusCons *cons, *constmp;
spinlock_acquire(&mbus->spinlock);
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
if (cons->pid == pid) {
LL_REMOVE(mbus->consumers, cons);
dlfree(cons->rbuf.buffer);
dlfree(cons);
break;
}
}
spinlock_release(&mbus->spinlock);
return E_OK;
}
void ipc_mbustick(void) {
spinlock_acquire(&IPC_MBUSES.spinlock);
for (size_t i = 0; i < LEN(IPC_MBUSES.mbuses); i++) {
IpcMBus *mbus = &IPC_MBUSES.mbuses[i];
if (mbus->_hshtbstate != HSHTB_TAKEN) {
continue;
}
IpcMBusCons *cons, *constmp;
spinlock_acquire(&mbus->spinlock);
LL_FOREACH_SAFE(mbus->consumers, cons, constmp) {
spinlock_acquire(&PROCS.spinlock);
Proc *proc = NULL;
LL_FINDPROP(PROCS.procs, proc, pid, cons->pid);
spinlock_release(&PROCS.spinlock);
if (proc == NULL) {
LL_REMOVE(mbus->consumers, cons);
dlfree(cons->rbuf.buffer);
dlfree(cons);
}
}
spinlock_release(&mbus->spinlock);
}
spinlock_release(&IPC_MBUSES.spinlock);
}

39
kernel/ipc/mbus/mbus.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef IPC_MBUS_MBUS_H_
#define IPC_MBUS_MBUS_H_
#include <stdint.h>
#include <stddef.h>
#include "proc/proc.h"
#include "rbuf/rbuf.h"
typedef struct IpcMBusCons {
struct IpcMBusCons *next;
uint64_t pid;
RBuf rbuf;
} IpcMBusCons;
typedef struct {
int _hshtbstate;
char ident[0x100];
SpinLock spinlock;
IpcMBusCons *consumers;
size_t objsize, objmax;
} IpcMBus;
typedef struct {
SpinLock spinlock;
IpcMBus mbuses[0x100];
} IpcMBuses;
extern IpcMBuses IPC_MBUSES;
void ipc_mbusinit(void);
IpcMBus *ipc_mbusmake(const char *name, size_t objsize, size_t objmax);
int32_t ipc_mbusdelete(const char *name);
int32_t ipc_mbuspublish(const char *name, const uint8_t *const buffer);
int32_t ipc_mbusconsume(const char *name, uint8_t *const buffer, uint64_t pid);
int32_t ipc_mbusattchcons(const char *name, uint64_t pid);
int32_t ipc_mbusdttchcons(const char *name, uint64_t pid);
void ipc_mbustick(void);
#endif // IPC_MBUS_MBUS_H_

View File

@ -17,6 +17,7 @@
#include "vmm/vmm.h" #include "vmm/vmm.h"
#include "cpu/hang.h" #include "cpu/hang.h"
#include "cpu/gdt.h" #include "cpu/gdt.h"
#include "ipc/mbus/mbus.h"
void log_bootinfo(void) { void log_bootinfo(void) {
char buf[100]; char buf[100];
@ -48,6 +49,7 @@ void kmain(void) {
pmm_init(); pmm_init();
vmm_init(); vmm_init();
randcrypto_init(); randcrypto_init();
ipc_mbusinit();
dev_init(); dev_init();
storedev_init(); storedev_init();
diskpart_init(); diskpart_init();

View File

@ -9,6 +9,7 @@
#include "vfs/vfs.h" #include "vfs/vfs.h"
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "ipc/pipe/pipe.h" #include "ipc/pipe/pipe.h"
#include "ipc/mbus/mbus.h"
#include "sysdefs/proc.h" #include "sysdefs/proc.h"
#include "sysdefs/fs.h" #include "sysdefs/fs.h"
#include "time/time.h" #include "time/time.h"
@ -222,6 +223,7 @@ void proc_reaper(void) {
void proc_tick(void) { void proc_tick(void) {
proc_reaper(); proc_reaper();
ipc_mbustick();
} }
void proc_sched(void *cpustate) { void proc_sched(void *cpustate) {