12 static struct interrupt_handler timer;
14 /* This will keep track of how many ticks that the system
15 * has been running for */
16 volatile uint64_t timer_ticks = 0;
17 static int timer_hz = 18;
19 static uint64_t timer_ns; /* nanoseconds per time tick */
21 struct timespec system_time; /* global system time */
23 #define ONE_BILLION 1000000000ULL
25 /* See http://wiki.osdev.org/Programmable_Interval_Timer
26 * for a possibly better algorithm
28 static void setfreq(int hz) {
35 timer_hz = 1193182 / divisor;
38 printk("timer hz %llu\n", (uint64_t)hz);
39 printk("timer divisor %u\n", divisor);
40 printk("timer hz actual %llu\n", (uint64_t)timer_hz);
43 enable = interrupts_enabled();
44 if (enable) disable_interrupts();
46 outport8(0x40, (uint8_t)(divisor & 0xFF)); /* Set low byte of divisor */
47 outport8(0x40, (uint8_t)(divisor >> 8 & 0xFF)); /* Set high byte of divisor */
49 timer_ns = (uint64_t)1000000000ULL / timer_hz;
50 /* now, let's disable the pit and use the RTC */
51 if (enable) enable_interrupts();
54 static void timer_handler(struct interrupt_context *c, void *unused) {
56 system_time.tv_nsec += timer_ns;
57 while (system_time.tv_nsec >= ONE_BILLION) {
59 system_time.tv_nsec -= ONE_BILLION;
63 void init_timer(int hz) {
65 timer.handler = timer_handler;
67 system_time.tv_sec = 0;
68 system_time.tv_nsec = 0;
70 enable = interrupts_enabled();
71 if (enable) disable_interrupts();
72 interrupt_add_handler(IRQ0, &timer);
74 if (enable) enable_interrupts();