diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 3 | ||||
-rw-r--r-- | kernel/drivers/int.c | 21 | ||||
-rw-r--r-- | kernel/drivers/pit.c | 20 | ||||
-rw-r--r-- | kernel/drivers/rtc.c | 2 | ||||
-rw-r--r-- | kernel/features/dev.c | 2 | ||||
-rw-r--r-- | kernel/features/proc.c | 13 | ||||
-rw-r--r-- | kernel/features/syscall.c | 2 | ||||
-rw-r--r-- | kernel/features/timer.c (renamed from kernel/drivers/timer.c) | 65 | ||||
-rw-r--r-- | kernel/inc/drivers/int.h | 2 | ||||
-rw-r--r-- | kernel/inc/drivers/pit.h | 8 | ||||
-rw-r--r-- | kernel/inc/proc.h | 7 | ||||
-rw-r--r-- | kernel/inc/timer.h (renamed from kernel/inc/drivers/timer.h) | 7 |
12 files changed, 130 insertions, 22 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 9fed3f1..85ff419 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -15,7 +15,7 @@ COBJS = entry_asm.o \ drivers/ide.o \ drivers/vbe.o \ drivers/bga.o \ - drivers/timer.o \ + drivers/pit.o \ drivers/vmware.o \ drivers/ps2/ps2.o \ drivers/ps2/mouse.o \ @@ -27,6 +27,7 @@ COBJS = entry_asm.o \ features/fb.o \ features/logger.o \ features/load.o \ + features/timer.o \ features/proc.o \ features/proc_asm.o \ features/syscall.o diff --git a/kernel/drivers/int.c b/kernel/drivers/int.c index f6a5134..d5f0a67 100644 --- a/kernel/drivers/int.c +++ b/kernel/drivers/int.c @@ -172,19 +172,32 @@ static u32 int_special_handler(struct int_frame *frame) * Universal handler */ +static u8 int_enabled = 1; + u32 int_handler(u32 esp); u32 int_handler(u32 esp) { struct int_frame *frame = (struct int_frame *)esp; - if (frame->int_no < 32) + if (frame->int_no < 32) { int_trap_handler(frame); - else if (frame->int_no < 48) + } else if (int_enabled && frame->int_no < 48) { esp = int_event_handler(frame); - else if (frame->int_no >= 128 && frame->int_no < 144) + } else if (frame->int_no >= 128 && frame->int_no < 144) { esp = int_special_handler(frame); - else + } else if (frame->int_no >= 48) { panic("Unknown interrupt: %d\n", frame->int_no); + } pic_ack(frame->int_no); return esp; } + +void int_disable(void) +{ + int_enabled = 0; +} + +void int_enable(void) +{ + int_enabled = 1; +} diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c new file mode 100644 index 0000000..abba5e8 --- /dev/null +++ b/kernel/drivers/pit.c @@ -0,0 +1,20 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#include <def.h> +#include <drivers/cpu.h> +#include <drivers/pit.h> +#include <timer.h> + +CLEAR static void pit_phase(u32 hz) +{ + u32 divisor = 3579545 / 3 / hz; + outb(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD + outb(0x40, (u8)(divisor & 0xFF)); + outb(0x40, (u8)(divisor >> 8)); +} + +CLEAR void pit_install(void) +{ + pit_phase(1000); + timer_install_handler(); +} diff --git a/kernel/drivers/rtc.c b/kernel/drivers/rtc.c index b67829e..0a9a3fd 100644 --- a/kernel/drivers/rtc.c +++ b/kernel/drivers/rtc.c @@ -3,10 +3,10 @@ #include <def.h> #include <drivers/cpu.h> #include <drivers/rtc.h> -#include <drivers/timer.h> #include <fs.h> #include <mem.h> #include <str.h> +#include <timer.h> static u8 rtc_busy(void) { diff --git a/kernel/features/dev.c b/kernel/features/dev.c index 0e082f9..c190a8a 100644 --- a/kernel/features/dev.c +++ b/kernel/features/dev.c @@ -8,7 +8,6 @@ #include <drivers/cpu.h> #include <drivers/int.h> #include <drivers/ps2.h> -#include <drivers/timer.h> #include <drivers/vbe.h> #include <drivers/vmware.h> #include <fb.h> @@ -21,6 +20,7 @@ #include <rand.h> #include <str.h> #include <syscall.h> +#include <timer.h> struct dev_listener { u32 group; diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 03f45c9..9f4b38b 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -4,7 +4,6 @@ #include <dev.h> #include <drivers/cpu.h> #include <drivers/gdt.h> -#include <drivers/timer.h> #include <errno.h> #include <fs.h> #include <load.h> @@ -14,6 +13,7 @@ #include <proc.h> #include <stack.h> #include <str.h> +#include <timer.h> #define PROC(node) ((struct proc *)node->data) @@ -133,6 +133,17 @@ struct proc *proc_from_pid(u32 pid) return NULL; } +void proc_timer_check(u32 time) +{ + struct node *iterator = proc_list_blocked->head; + while (iterator) { + struct proc *proc = PROC(iterator); + if (proc->timer.mode == TIMER_MODE_SLEEP && time >= proc->timer.data) + dev_unblock_pid(proc->pid); + iterator = iterator->next; + } +} + CLEAR void proc_set_quantum(struct proc *proc, u32 value) { proc->quantum.val = value; diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index 16a83d6..86b675c 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -3,7 +3,6 @@ #include <dev.h> #include <drivers/cpu.h> #include <drivers/int.h> -#include <drivers/timer.h> #include <errno.h> #include <fs.h> #include <load.h> @@ -14,6 +13,7 @@ #include <str.h> #include <sys.h> #include <syscall.h> +#include <timer.h> static u32 syscall_handler(u32 esp) { diff --git a/kernel/drivers/timer.c b/kernel/features/timer.c index 977647c..674dd1a 100644 --- a/kernel/drivers/timer.c +++ b/kernel/features/timer.c @@ -1,24 +1,18 @@ // MIT License, Copyright (c) 2020 Marvin Borner +#include <assert.h> #include <def.h> #include <dev.h> #include <drivers/cpu.h> #include <drivers/int.h> +#include <drivers/pit.h> #include <drivers/rtc.h> -#include <drivers/timer.h> #include <mem.h> #include <proc.h> +#include <timer.h> static u32 timer_ticks = 0; -CLEAR static void timer_phase(int hz) -{ - int divisor = 3579545 / 3 / hz; - outb(0x43, 0x36); // 01 10 11 0b // CTR, RW, MODE, BCD - outb(0x40, (u8)(divisor & 0xFF)); - outb(0x40, (u8)(divisor >> 8)); -} - u32 timer_get(void) { return timer_ticks; @@ -26,10 +20,20 @@ u32 timer_get(void) static void timer_handler(void) { + int_disable(); if (timer_ticks >= U32_MAX) timer_ticks = 0; else timer_ticks++; + proc_timer_check(timer_ticks); + int_enable(); +} + +CLEAR void timer_install_handler(void) +{ + static u8 check = 0; + assert(check++ == 0); + int_event_handler_add(0, timer_handler); } // "Delay" function with CPU sleep @@ -56,21 +60,56 @@ static res timer_read(void *buf, u32 offset, u32 count) { UNUSED(offset); + // TODO: Make sleeping more accurate + struct proc *proc = proc_current(); + if (proc->timer.mode == TIMER_MODE_SLEEP) { + dev_block(DEV_TIMER, proc); + proc->timer.mode = TIMER_MODE_DEFAULT; + } + struct timer timer = timer_struct(); memcpy_user(buf, &timer, MIN(count, sizeof(timer))); return MIN(count, sizeof(timer)); } +static res timer_control(u32 request, void *arg1, void *arg2, void *arg3) +{ + UNUSED(arg2); + UNUSED(arg3); + + switch (request) { + case DEVCTL_TIMER_SLEEP: { + struct proc *proc = proc_current(); + proc->timer.mode = TIMER_MODE_SLEEP; + proc->timer.data = timer_ticks + (u32)arg1; + return EOK; + } + default: + return -EINVAL; + } +} + +static res timer_ready(void) +{ + struct proc *proc = proc_current(); + if (proc->timer.mode == TIMER_MODE_SLEEP) { + if (timer_ticks >= proc->timer.data) + return EOK; + return -EAGAIN; + } + return EOK; +} + // Install timer handler into IRQ0 CLEAR void timer_install(void) { - /* hpet_install(10000); // TODO: Find optimal femtosecond period */ - /* if (!hpet) */ - timer_phase(1000); - int_event_handler_add(0, timer_handler); + // hpet_install(10000); // TODO: Reimplement hpet + pit_install(); struct dev_dev *dev = zalloc(sizeof(*dev)); dev->read = timer_read; + dev->control = timer_control; + dev->ready = timer_ready; dev_add(DEV_TIMER, dev); } diff --git a/kernel/inc/drivers/int.h b/kernel/inc/drivers/int.h index 8146898..9dd4a6f 100644 --- a/kernel/inc/drivers/int.h +++ b/kernel/inc/drivers/int.h @@ -44,6 +44,8 @@ struct idt_ptr { } PACKED; void idt_install(void); +void int_enable(void); +void int_disable(void); void int_trap_handler_add(u32 int_no, void (*handler)(u32 esp)); void int_event_handler_add(u32 int_no, void (*handler)(void)); diff --git a/kernel/inc/drivers/pit.h b/kernel/inc/drivers/pit.h new file mode 100644 index 0000000..b3cd507 --- /dev/null +++ b/kernel/inc/drivers/pit.h @@ -0,0 +1,8 @@ +// MIT License, Copyright (c) 2021 Marvin Borner + +#ifndef PIT_H +#define PIT_H + +void pit_install(void); + +#endif diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 42ff75d..5cc1fef 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -8,6 +8,7 @@ #include <list.h> #include <stack.h> #include <sys.h> +#include <timer.h> #define PROC_QUANTUM 15 // Milliseconds or something // TODO #define PROC_STACK_SIZE 0x4000 // 16KiB @@ -51,6 +52,11 @@ struct proc { u8 val; u8 cnt; } quantum; + + struct { + enum timer_mode mode; + u32 data; + } timer; }; u32 scheduler(u32 esp); @@ -62,6 +68,7 @@ u8 proc_idle(void); struct proc *proc_from_pid(u32 pid); void proc_exit(s32 status); void proc_yield(void); +void proc_timer_check(u32 time); void proc_set_quantum(struct proc *proc, u32 value) NONNULL; void proc_reset_quantum(struct proc *proc) NONNULL; void proc_state(struct proc *proc, enum proc_state state) NONNULL; diff --git a/kernel/inc/drivers/timer.h b/kernel/inc/timer.h index ea1643b..1233f6e 100644 --- a/kernel/inc/drivers/timer.h +++ b/kernel/inc/timer.h @@ -5,6 +5,13 @@ #include <def.h> +enum timer_mode { + TIMER_MODE_DEFAULT, + TIMER_MODE_SLEEP, +}; + +void timer_install_handler(void); + u32 timer_get(void); void timer_wait(u32 ticks); void timer_install(void); |