summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/arch/amd64/driver/ps2.c7
-rw-r--r--src/kernel/arch/amd64/driver/rtl8139.c9
-rw-r--r--src/kernel/arch/amd64/driver/serial.c3
-rw-r--r--src/kernel/arch/amd64/driver/util.c44
-rw-r--r--src/kernel/arch/amd64/driver/util.h7
-rw-r--r--src/kernel/types.h1
-rw-r--r--src/kernel/vfs/request.c59
-rw-r--r--src/kernel/vfs/request.h12
8 files changed, 86 insertions, 56 deletions
diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c
index f0c5f2c..86fcffd 100644
--- a/src/kernel/arch/amd64/driver/ps2.c
+++ b/src/kernel/arch/amd64/driver/ps2.c
@@ -19,8 +19,8 @@ static volatile ring_t mouse_backlog = {(void*)mouse_buf, sizeof mouse_buf, 0, 0
static void accept(VfsReq *req);
static void ps2_irq(void);
-static VfsReq *kb_queue = NULL;
-static VfsReq *mouse_queue = NULL;
+static ReqQueue kb_queue;
+static ReqQueue mouse_queue;
static void wait_out(void) {
while ((port_in8(PS2 + 4) & 2) != 0);
@@ -58,6 +58,9 @@ void ps2_init(void) {
irq_fn[IRQ_PS2KB] = ps2_irq;
irq_fn[IRQ_PS2MOUSE] = ps2_irq;
+ postqueue_init(&kb_queue);
+ postqueue_init(&mouse_queue);
+
vfs_root_register("/dev/ps2/", accept);
}
diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c
index a005df5..bce1071 100644
--- a/src/kernel/arch/amd64/driver/rtl8139.c
+++ b/src/kernel/arch/amd64/driver/rtl8139.c
@@ -13,7 +13,7 @@
static void accept(VfsReq *req);
static void rtl8139_irq(void);
-static VfsReq *blocked_on = NULL;
+static ReqQueue blocked_on;
enum {
@@ -86,6 +86,8 @@ void rtl8139_init(uint32_t bdf) {
mac[i] = port_in8(iobase + Mac + i);
}
+ postqueue_init(&blocked_on);
+
vfs_root_register("/dev/eth/", accept);
}
@@ -100,7 +102,10 @@ static void rtl8139_irq(void) {
/* bit 0 of cmd - Rx Buffer Empty
* not a do while() because sometimes the bit is empty on IRQ. no clue why. */
while (!(port_in8(iobase + Cmd) & 1)) {
- if (!postqueue_pop(&blocked_on, accept)) {
+ VfsReq *req = postqueue_pop(&blocked_on);
+ if (req) {
+ accept(req);
+ } else {
rx_irq_enable(false);
break;
}
diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c
index 6f383a3..eb347d0 100644
--- a/src/kernel/arch/amd64/driver/serial.c
+++ b/src/kernel/arch/amd64/driver/serial.c
@@ -16,12 +16,13 @@ static bool COM1_exists = false;
static void accept(VfsReq *req);
static void serial_irq(void);
-static VfsReq *hung_reads = NULL;
+static ReqQueue hung_reads;
void serial_init(void) {
if (COM1_exists) {
vfs_root_register("/dev/com1", accept);
}
+ postqueue_init(&hung_reads);
}
static bool serial_selftest(void) {
diff --git a/src/kernel/arch/amd64/driver/util.c b/src/kernel/arch/amd64/driver/util.c
index 2b33849..f02c4e2 100644
--- a/src/kernel/arch/amd64/driver/util.c
+++ b/src/kernel/arch/amd64/driver/util.c
@@ -13,50 +13,6 @@ int req_readcopy(VfsReq *req, const void *buf, size_t len) {
return req->output.len;
}
-void postqueue_join(VfsReq **queue, VfsReq *req) {
- if (req->postqueue_next)
- panic_invalid_state();
-
- while (*queue)
- queue = &(*queue)->postqueue_next;
- *queue = req;
-}
-
-bool postqueue_pop(VfsReq **queue, void (*accept)(VfsReq *)) {
- VfsReq *req = *queue;
- if (req == NULL) return false;
- *queue = req->postqueue_next;
- req->postqueue_next = NULL;
- accept(req);
- return true;
-}
-
-void postqueue_ringreadall(VfsReq **queue, ring_t *r) {
- VfsReq *req;
- char tmp[64];
- size_t mlen = 0;
- if (ring_used(r) == 0) return;
-
- /* read as much as the biggest request wants */
- for (req = *queue; req; req = req->postqueue_next)
- mlen = max(mlen, req->output.len);
- mlen = min(mlen, sizeof tmp);
- mlen = ring_get(r, tmp, mlen);
-
- while (*queue) {
- req = *queue;
- *queue = req->postqueue_next;
- req->postqueue_next = NULL;
-
- size_t ret = min(mlen, req->output.len);
- assert(req->type == VFSOP_READ);
- if (req->caller) {
- pcpy_to(req->caller, req->output.buf, tmp, ret);
- }
- vfsreq_finish_short(req, ret);
- }
-}
-
size_t ring_to_virt(ring_t *r, Proc *proc, void __user *ubuf, size_t max) {
char tmp[32];
if (max > sizeof tmp) max = sizeof tmp;
diff --git a/src/kernel/arch/amd64/driver/util.h b/src/kernel/arch/amd64/driver/util.h
index 6fae977..898875a 100644
--- a/src/kernel/arch/amd64/driver/util.h
+++ b/src/kernel/arch/amd64/driver/util.h
@@ -15,11 +15,4 @@ int req_readcopy(VfsReq *req, const void *buf, size_t len);
req->input.len == plen && \
memcmp(req->input.buf_kern, path, plen) == 0)
-void postqueue_join(VfsReq **queue, VfsReq *req);
-bool postqueue_pop(VfsReq **queue, void (*accept)(VfsReq *));
-
-/** If there are any pending read requests, and the ring buffer isn't empty, fulfill them
- * all with a single read. */
-void postqueue_ringreadall(VfsReq **queue, ring_t *r);
-
size_t ring_to_virt(ring_t *r, Proc *proc, void __user *ubuf, size_t max);
diff --git a/src/kernel/types.h b/src/kernel/types.h
index e186479..b8308a5 100644
--- a/src/kernel/types.h
+++ b/src/kernel/types.h
@@ -10,6 +10,7 @@ FORWARD_STRUCT(Proc)
FORWARD_STRUCT(VfsBackend)
FORWARD_STRUCT(VfsMount)
FORWARD_STRUCT(VfsReq)
+FORWARD_STRUCT(ReqQueue)
/* arch-specific stuff */
FORWARD_STRUCT(GfxInfo)
diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c
index d4ea16c..8f44afb 100644
--- a/src/kernel/vfs/request.c
+++ b/src/kernel/vfs/request.c
@@ -242,3 +242,62 @@ vfsback_provdown(VfsBackend *b)
}
vfsback_checkfree(b);
}
+
+void
+postqueue_init(ReqQueue *q)
+{
+ q->head = NULL;
+}
+
+void
+postqueue_join(ReqQueue *q, VfsReq *req)
+{
+ if (req->postqueue_next)
+ panic_invalid_state();
+
+ VfsReq **it = &q->head;
+ while (*it != NULL) {
+ it = &(*it)->postqueue_next;
+ }
+ *it = req;
+}
+
+VfsReq *
+postqueue_pop(ReqQueue *q)
+{
+ VfsReq *req = q->head;
+ if (req) {
+ q->head = req->postqueue_next;
+ req->postqueue_next = NULL;
+ }
+ return req;
+}
+
+void
+postqueue_ringreadall(ReqQueue *q, ring_t *r)
+{
+ VfsReq **queue = &q->head; /* whatever */
+ VfsReq *req;
+ char tmp[64];
+ size_t mlen = 0;
+ if (ring_used(r) == 0) return;
+
+ /* read as much as the biggest request wants */
+ for (req = *queue; req; req = req->postqueue_next)
+ mlen = max(mlen, req->output.len);
+ mlen = min(mlen, sizeof tmp);
+ mlen = ring_get(r, tmp, mlen);
+
+ while (*queue) {
+ req = *queue;
+ *queue = req->postqueue_next;
+ req->postqueue_next = NULL;
+
+ size_t ret = min(mlen, req->output.len);
+ assert(req->type == VFSOP_READ);
+ if (req->caller) {
+ pcpy_to(req->caller, req->output.buf, tmp, ret);
+ }
+ vfsreq_finish_short(req, ret);
+ }
+}
diff --git a/src/kernel/vfs/request.h b/src/kernel/vfs/request.h
index 06c46e7..616c044 100644
--- a/src/kernel/vfs/request.h
+++ b/src/kernel/vfs/request.h
@@ -1,5 +1,6 @@
#pragma once
#include <kernel/types.h>
+#include <shared/ring.h>
#include <stdbool.h>
#include <stddef.h>
@@ -77,3 +78,14 @@ void vfsback_userdown(VfsBackend *);
/** Decrements the "provider" reference count. */
void vfsback_provdown(VfsBackend *);
+
+struct ReqQueue {
+ VfsReq *head;
+};
+void postqueue_init(ReqQueue *q);
+void postqueue_join(ReqQueue *q, VfsReq *req);
+VfsReq *postqueue_pop(ReqQueue *q);
+
+/** If there are any pending read requests, and the ring buffer isn't empty, fulfill them
+ * all with a single read. */
+void postqueue_ringreadall(ReqQueue *q, ring_t *r);