From fbbe8a1cb4c421e9658c5009ecfab6845137587b Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Sun, 7 Aug 2022 19:16:15 +0200
Subject: driver/ps2: prepare for mouse support

---
 src/kernel/arch/amd64/driver/fsroot.c |  2 +-
 src/kernel/arch/amd64/driver/ps2.c    | 55 ++++++++++++++++++++++++-----------
 src/kernel/arch/amd64/driver/serial.c |  2 +-
 src/kernel/arch/amd64/driver/util.h   |  1 +
 src/kernel/ring.h                     |  1 +
 src/user/app/init/driver/ps2.c        |  2 +-
 6 files changed, 43 insertions(+), 20 deletions(-)

(limited to 'src')

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;
 
diff --git a/src/user/app/init/driver/ps2.c b/src/user/app/init/driver/ps2.c
index 532695f..7653f83 100644
--- a/src/user/app/init/driver/ps2.c
+++ b/src/user/app/init/driver/ps2.c
@@ -79,7 +79,7 @@ static void main_loop(void) {
 }
 
 void ps2_drv(void) {
-	fd = _syscall_open("/kdev/ps2", 9, 0);
+	fd = _syscall_open("/kdev/ps2/kb", 12, 0);
 	if (fd < 0) exit(1);
 
 	main_loop();
-- 
cgit v1.2.3