1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
#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};
static void accept(struct vfs_request *req);
static bool is_ready(struct vfs_backend *self);
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 (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;
switch (req->type) {
case VFSOP_OPEN:
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;
}
}
static bool is_ready(struct vfs_backend __attribute__((unused)) *self) {
return true;
}
|