diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/drivers/ps2/keyboard.c | 5 | ||||
-rw-r--r-- | kernel/features/io.c | 40 | ||||
-rw-r--r-- | kernel/features/proc.c | 2 | ||||
-rw-r--r-- | kernel/features/syscall.c | 10 | ||||
-rw-r--r-- | kernel/inc/io.h | 5 |
5 files changed, 60 insertions, 2 deletions
diff --git a/kernel/drivers/ps2/keyboard.c b/kernel/drivers/ps2/keyboard.c index 3c2cdbb..616c539 100644 --- a/kernel/drivers/ps2/keyboard.c +++ b/kernel/drivers/ps2/keyboard.c @@ -43,6 +43,8 @@ static void keyboard_handler(struct regs *r) state = 0; merged = 0; + + io_unblock(IO_KEYBOARD); } static res keyboard_read(void *buf, u32 offset, u32 count) @@ -63,7 +65,8 @@ static res keyboard_ready(void) CLEAR void ps2_keyboard_reset(void) { - stack_clear(queue); + if (queue) + stack_clear(queue); } CLEAR void ps2_keyboard_install(u8 device) 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(); diff --git a/kernel/features/proc.c b/kernel/features/proc.c index a71919e..6ddeb32 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -124,6 +124,8 @@ void proc_reset_quantum(struct proc *proc) void proc_state(struct proc *proc, enum proc_state state) { + assert(proc != idle_proc->data); + if (state == PROC_RUNNING && !list_first_data(proc_list_running, proc)) { assert(list_remove(proc_list_blocked, list_first_data(proc_list_blocked, proc))); assert(list_add(proc_list_running, proc)); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index abd7130..2c30a3b 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -60,7 +60,12 @@ static void syscall_handler(struct regs *r) break; } case SYS_IOREAD: { - r->eax = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); + res ret = io_read(r->ebx, (void *)r->ecx, r->edx, r->esi); + if (ret == -EAGAIN) { + io_block(r->ebx, proc_current(), r); + } else { + r->eax = ret; + } break; } case SYS_IOWRITE: { @@ -87,10 +92,12 @@ static void syscall_handler(struct regs *r) break; } case SYS_EXIT: { + r->eax = EOK; proc_exit(proc_current(), r, (s32)r->ebx); break; } case SYS_YIELD: { + r->eax = EOK; proc_yield(r); break; } @@ -126,6 +133,7 @@ static void syscall_handler(struct regs *r) // TODO: Reimplement network functions using VFS default: { + r->eax = -EINVAL; printf("Unknown syscall %d!\n", num); break; } diff --git a/kernel/inc/io.h b/kernel/inc/io.h index 5176bd3..3291bfc 100644 --- a/kernel/inc/io.h +++ b/kernel/inc/io.h @@ -5,6 +5,8 @@ #include <boot.h> #include <def.h> +#include <interrupts.h> +#include <proc.h> #include <sys.h> struct io_dev { @@ -22,4 +24,7 @@ res io_write(enum io_type io, void *buf, u32 offset, u32 count); res io_read(enum io_type io, void *buf, u32 offset, u32 count); res io_poll(u32 *devs) NONNULL; +void io_block(enum io_type io, struct proc *proc, struct regs *r) NONNULL; +void io_unblock(enum io_type io); + #endif |