From 6cedec8d7a3f586b08ce6f51ad853d9bd19ceda9 Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Mon, 24 Oct 2016 20:32:34 -0500 Subject: [PATCH] timer interrupt handing --- timer.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ timer.h | 3 +++ 2 files changed, 78 insertions(+) create mode 100644 timer.c create mode 100644 timer.h diff --git a/timer.c b/timer.c new file mode 100644 index 0000000..e344e91 --- /dev/null +++ b/timer.c @@ -0,0 +1,75 @@ +#include + +#include "interrupt.h" +#include "kernel.h" +#include "timer.h" + +#include "ioport.h" +#include "cpu.h" + +#include + +static struct interrupt_handler timer; + +/* This will keep track of how many ticks that the system +* has been running for */ +volatile uint64_t timer_ticks = 0; +static int timer_hz = 18; + +static uint64_t timer_ns; /* nanoseconds per time tick */ + +struct timespec system_time; /* global system time */ + +#define ONE_BILLION 1000000000ULL + +/* See http://wiki.osdev.org/Programmable_Interval_Timer + * for a possibly better algorithm + */ +static void setfreq(int hz) { + int enable; + unsigned int divisor; + + if (hz < 18) hz = 18; + divisor = 1193182/hz; + + timer_hz = 1193182 / divisor; + +#if 0 + printk("timer hz %llu\n", (uint64_t)hz); + printk("timer divisor %u\n", divisor); + printk("timer hz actual %llu\n", (uint64_t)timer_hz); +#endif + + enable = interrupts_enabled(); + if (enable) disable_interrupts(); + outport8(0x43, 0x34); + outport8(0x40, (uint8_t)(divisor & 0xFF)); /* Set low byte of divisor */ + outport8(0x40, (uint8_t)(divisor >> 8 & 0xFF)); /* Set high byte of divisor */ + + timer_ns = (uint64_t)1000000000ULL / timer_hz; + /* now, let's disable the pit and use the RTC */ + if (enable) enable_interrupts(); +} + +static void timer_handler(struct interrupt_context *c, void *unused) { + timer_ticks++; + system_time.tv_nsec += timer_ns; + while (system_time.tv_nsec >= ONE_BILLION) { + system_time.tv_sec++; + system_time.tv_nsec -= ONE_BILLION; + } +} + +void init_timer(int hz) { + int enable; + timer.handler = timer_handler; + timer.context = 0; + system_time.tv_sec = 0; + system_time.tv_nsec = 0; + + enable = interrupts_enabled(); + if (enable) disable_interrupts(); + interrupt_add_handler(IRQ0, &timer); + setfreq(hz); + if (enable) enable_interrupts(); +} diff --git a/timer.h b/timer.h new file mode 100644 index 0000000..7e3b215 --- /dev/null +++ b/timer.h @@ -0,0 +1,3 @@ +void init_timer(int hz); +extern volatile uint64_t timer_ticks; +extern struct timespec system_time; -- 2.40.0