Added .gitignore
[comos.git] / kernel / timer.c
blobd0c63c19ea69b50166e0abae69f681b950123508
1 #include "timer.h"
2 #include "portio.h"
3 #include "console.h"
4 #include "interrupt.h"
5 #include "stdint.h"
6 #include "general.h"
7 #include "critical.h"
8 #include "task.h"
10 #define TIMER_IRQ 0 // the IRQ the PIT is connected to
11 #define TIMER_FREQ 1000 // frequency to set the timer to
12 #define CTL 0x43 // control register
13 #define CNT0 0x40 // count register 0
14 #define CNT1 0x41 // count register 1
15 #define CNT2 0x42 // count register 2
17 static tick_t tick = 0; // current tick number
18 static unsigned long freq; // current timer frequency
20 tick_t get_tick(void)
22 return tick;
25 static void timer_interrupt(int vector, struct interrupt_stack *is)
27 tick++;
28 ack_irq(TIMER_IRQ);
30 if(!(tick % 20))
31 {if(MULTITASKING){switch_task(is);}}
34 void set_frequency(unsigned long new_freq)
36 unsigned short divisor;
37 divisor = 1193180 / new_freq;
38 freq = (1193180LL << 32) / divisor;
39 outb(CTL, 0x36);
40 outb(CNT0, divisor);
41 outb(CNT0, divisor >> 8);
44 // timer initialization
45 void timer_init(void)
47 unsigned char p61h;
48 // Timer's base frequency is 1,193,180 Hz
49 // We set the frequency divider to get
50 // TIMER_FREQ Hz output
51 outb(CTL, 0x54);
52 outb(CNT1, 18); // LSB only clock divisor (?)
53 tick = 0;
54 interrupt_set_handler(irq_to_int(TIMER_IRQ), timer_interrupt);
55 set_frequency(TIMER_FREQ);
56 unmask_irq(TIMER_IRQ);
58 outb(CTL, 0xB6);
59 outb(CNT2, 54);
60 outb(CNT2, 124);
61 p61h = inb(0x61);
62 p61h |= 3;
63 outb(0x61, p61h);
66 uint64_t read_cpu_timestamp(void)
68 uint32_t hi, lo;
69 __asm__ __volatile__("rdtsc;":"=d"(hi),"=a"(lo)::"memory");
70 return (uint64_t)(((uint64_t)hi << 32) | lo);