summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/arch/amd64/driver/fsroot.c2
-rw-r--r--src/kernel/arch/amd64/driver/ps2.c55
-rw-r--r--src/kernel/arch/amd64/driver/serial.c2
-rw-r--r--src/kernel/arch/amd64/driver/util.h1
-rw-r--r--src/kernel/ring.h1
5 files changed, 42 insertions, 19 deletions
diff --git a/src/kernel/arch/amd64/driver/fsroot.c b/src/kernel/arch/amd64/driver/fsroot.c
index 0970d0b..98880fe 100644
--- a/src/kernel/arch/amd64/driver/fsroot.c
+++ b/src/kernel/arch/amd64/driver/fsroot.c
@@ -48,7 +48,7 @@ static int handle(struct vfs_request *req) {
// TODO don't hardcode
const char src[] =
"com1\0"
- "ps2\0"
+ "ps2/\0"
"ata/\0"
"video/";
return req_readcopy(req, src, sizeof src);
diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c
index e3aaef8..7ed369b 100644
--- a/src/kernel/arch/amd64/driver/ps2.c
+++ b/src/kernel/arch/amd64/driver/ps2.c
@@ -1,9 +1,11 @@
#include <kernel/arch/amd64/driver/ps2.h>
+#include <kernel/arch/amd64/driver/util.h>
#include <kernel/arch/amd64/interrupts/irq.h>
#include <kernel/arch/amd64/port_io.h>
#include <kernel/panic.h>
#include <kernel/ring.h>
#include <kernel/vfs/request.h>
+#include <shared/mem.h>
static volatile uint8_t backlog_buf[64];
static volatile ring_t backlog = {(void*)backlog_buf, sizeof backlog_buf, 0, 0};
@@ -11,41 +13,60 @@ static volatile ring_t backlog = {(void*)backlog_buf, sizeof backlog_buf, 0, 0};
static void accept(struct vfs_request *req);
static bool is_ready(struct vfs_backend *self);
-static struct vfs_request *blocked_on = NULL;
+static struct vfs_request *kb_queue = NULL;
static struct vfs_backend backend = BACKEND_KERN(is_ready, accept);
void ps2_init(void) { vfs_mount_root_register("/ps2", &backend); }
void ps2_irq(void) {
ring_put1b((void*)&backlog, port_in8(0x60));
- if (blocked_on) {
- accept(blocked_on);
- blocked_on = NULL;
+ if (kb_queue) {
+ accept(kb_queue);
+ kb_queue = kb_queue->postqueue_next;
vfs_backend_tryaccept(&backend);
}
}
+enum {
+ H_ROOT,
+ H_KB,
+};
+
static void accept(struct vfs_request *req) {
// when you fix something here go also fix it in the COM1 driver
int ret;
- bool valid;
switch (req->type) {
case VFSOP_OPEN:
- valid = req->input.len == 0;
- vfsreq_finish_short(req, valid ? 0 : -1);
- break;
- case VFSOP_READ:
- if (ring_size((void*)&backlog) == 0) {
- // nothing to read
- blocked_on = req;
- } else if (req->caller) {
- if (ret < 0) ret = 0;
- ret = ring_to_virt((void*)&backlog, req->caller->pages, req->output.buf, req->output.len);
- vfsreq_finish_short(req, ret);
+ if (!req->input.kern) panic_invalid_state();
+ if (req->input.len == 1) {
+ vfsreq_finish_short(req, H_ROOT);
+ } else if (req->input.len == 3 && !memcmp(req->input.buf_kern, "/kb", 3)) {
+ vfsreq_finish_short(req, H_KB);
} else {
vfsreq_finish_short(req, -1);
}
break;
+ case VFSOP_READ:
+ if ((long __force)req->id == H_ROOT) {
+ const char data[] = "kb";
+ ret = req_readcopy(req, data, sizeof data);
+ vfsreq_finish_short(req, ret);
+ } else if ((long __force)req->id == H_KB) {
+ if (ring_size((void*)&backlog) == 0) {
+ /* nothing to read, join queue */
+ assert(!req->postqueue_next);
+ struct vfs_request **slot = &kb_queue;
+ while (*slot) slot = &(*slot)->postqueue_next;
+ *slot = req;
+ } else if (req->caller) {
+ if (ret < 0) ret = 0;
+ ret = ring_to_virt((void*)&backlog, req->caller->pages, req->output.buf, req->output.len);
+ vfsreq_finish_short(req, ret);
+ } else {
+ vfsreq_finish_short(req, -1);
+ }
+ } else panic_invalid_state();
+ break;
default:
vfsreq_finish_short(req, -1);
break;
@@ -53,5 +74,5 @@ static void accept(struct vfs_request *req) {
}
static bool is_ready(struct vfs_backend __attribute__((unused)) *self) {
- return blocked_on == NULL;
+ return true;
}
diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c
index 1401642..d8ee90b 100644
--- a/src/kernel/arch/amd64/driver/serial.c
+++ b/src/kernel/arch/amd64/driver/serial.c
@@ -47,7 +47,7 @@ void serial_irq(void) {
ring_put1b((void*)&backlog, port_in8(COM1));
if (blocked_on) {
accept(blocked_on);
- blocked_on = NULL;
+ blocked_on = blocked_on->postqueue_next;
vfs_backend_tryaccept(&backend);
}
}
diff --git a/src/kernel/arch/amd64/driver/util.h b/src/kernel/arch/amd64/driver/util.h
index fd8d506..bfdd25c 100644
--- a/src/kernel/arch/amd64/driver/util.h
+++ b/src/kernel/arch/amd64/driver/util.h
@@ -1,4 +1,5 @@
#pragma once
+#include <stddef.h>
struct vfs_request;
int req_readcopy(struct vfs_request *req, const void *buf, size_t len);
diff --git a/src/kernel/ring.h b/src/kernel/ring.h
index f5f9679..e288cb9 100644
--- a/src/kernel/ring.h
+++ b/src/kernel/ring.h
@@ -1,4 +1,5 @@
#pragma once
+// TODO merge into driver/util.h
#include <shared/container/ring.h>
struct pagedir;