diff options
Diffstat (limited to 'kernel/features/io.c')
-rw-r--r-- | kernel/features/io.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/kernel/features/io.c b/kernel/features/io.c index b8275f9..6042818 100644 --- a/kernel/features/io.c +++ b/kernel/features/io.c @@ -3,15 +3,18 @@ #include <assert.h> #include <def.h> #include <fb.h> +#include <interrupts.h> #include <io.h> #include <list.h> #include <mm.h> +#include <proc.h> #include <ps2.h> #include <rand.h> #include <str.h> #include <timer.h> PROTECTED static struct io_dev *io_mappings[IO_MAX] = { 0 }; +PROTECTED static struct list *io_listeners[IO_MAX] = { 0 }; static u8 io_type_valid(enum io_type io) { @@ -75,11 +78,48 @@ res io_read(enum io_type io, void *buf, u32 offset, u32 count) if (!(dev = io_get(io)) || !dev->read) return -ENOENT; + if (dev->ready && !dev->ready()) + return -EAGAIN; + return dev->read(buf, offset, count); } +void io_block(enum io_type io, struct proc *proc, struct regs *r) +{ + assert(r->eax == SYS_IOREAD); + assert(io_type_valid(io)); + list_add(io_listeners[io], proc); + proc_state(proc_current(), PROC_BLOCKED); + proc_yield(r); +} + +void io_unblock(enum io_type io) +{ + struct page_dir *dir_bak; + memory_backup_dir(&dir_bak); + + assert(io_type_valid(io)); + struct node *iterator = io_listeners[io]->head; + while (iterator) { + struct proc *proc = iterator->data; + struct regs *r = &proc->regs; + + memory_switch_dir(proc->page_dir); + r->eax = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); + memory_switch_dir(dir_bak); + + proc_state(proc, PROC_RUNNING); + struct node *next = iterator->next; + list_remove(io_listeners[io], iterator); + iterator = next; + } +} + CLEAR void io_install(struct boot_info *boot) { + for (u32 i = 0; i < IO_MAX; i++) + io_listeners[i] = list_new(); + ps2_detect(); u8 ps2_keyboard = ps2_keyboard_detect(); |