7 /* frequency of the oscillator driving the 8254 timer */
8 #define OSC_FREQ_HZ 1193182
10 /* macro to divide and round to the nearest integer */
11 #define DIV_ROUND(a, b) ((a) / (b) + ((a) % (b)) / ((b) / 2))
13 /* I/O ports connected to the 8254 */
14 #define PORT_DATA0 0x40
15 #define PORT_DATA1 0x41
16 #define PORT_DATA2 0x42
21 #define CMD_CHAN1 (1 << 6)
22 #define CMD_CHAN2 (2 << 6)
23 #define CMD_RDBACK (3 << 6)
26 #define CMD_ACCESS_LOW (1 << 4)
27 #define CMD_ACCESS_HIGH (2 << 4)
28 #define CMD_ACCESS_BOTH (3 << 4)
30 #define CMD_OP_INT_TERM 0
31 #define CMD_OP_ONESHOT (1 << 1)
32 #define CMD_OP_RATE (2 << 1)
33 #define CMD_OP_SQWAVE (3 << 1)
34 #define CMD_OP_SOFT_STROBE (4 << 1)
35 #define CMD_OP_HW_STROBE (5 << 1)
37 #define CMD_MODE_BIN 0
38 #define CMD_MODE_BCD 1
41 #define MSEC_TO_TICKS(ms) ((ms) * TICK_FREQ_HZ / 1000)
44 int dt; /* remaining ticks delta from the previous event */
45 struct timer_event *next;
48 /* defined in intr_asm.S */
49 void intr_entry_fast_timer(void);
51 static struct timer_event *evlist;
56 /* calculate the reload count: round(osc / freq) */
57 int reload_count = DIV_ROUND(OSC_FREQ_HZ, TICK_FREQ_HZ);
59 /* set the mode to square wave for channel 0, both low
60 * and high reload count bytes will follow...
62 outb(CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE, PORT_CMD);
64 /* write the low and high bytes of the reload count to the
67 outb(reload_count & 0xff, PORT_DATA0);
68 outb((reload_count >> 8) & 0xff, PORT_DATA0);
70 /* set the timer interrupt handler */
71 /*interrupt(IRQ_TO_INTR(0), timer_handler);*/
72 /* set low level fast timer interrupt routine directly in the IDT */
73 set_intr_entry(IRQ_TO_INTR(0), intr_entry_fast_timer);
77 static void timer_handler(int inum)