rev |
line source |
nuclear@33
|
1 #include <stdio.h>
|
nuclear@37
|
2 #include <time.h>
|
nuclear@33
|
3 #include "intr.h"
|
nuclear@33
|
4 #include "asmops.h"
|
nuclear@34
|
5 #include "timer.h"
|
nuclear@33
|
6 #include "config.h"
|
nuclear@33
|
7
|
nuclear@33
|
8 /* frequency of the oscillator driving the 8254 timer */
|
nuclear@33
|
9 #define OSC_FREQ_HZ 1193182
|
nuclear@33
|
10
|
nuclear@33
|
11 /* macro to divide and round to the nearest integer */
|
nuclear@33
|
12 #define DIV_ROUND(a, b) ((a) / (b) + ((a) % (b)) / ((b) / 2))
|
nuclear@33
|
13
|
nuclear@33
|
14 /* I/O ports connected to the 8254 */
|
nuclear@33
|
15 #define PORT_DATA0 0x40
|
nuclear@33
|
16 #define PORT_DATA1 0x41
|
nuclear@33
|
17 #define PORT_DATA2 0x42
|
nuclear@33
|
18 #define PORT_CMD 0x43
|
nuclear@33
|
19
|
nuclear@33
|
20 /* command bits */
|
nuclear@33
|
21 #define CMD_CHAN0 0
|
nuclear@33
|
22 #define CMD_CHAN1 (1 << 6)
|
nuclear@33
|
23 #define CMD_CHAN2 (2 << 6)
|
nuclear@33
|
24 #define CMD_RDBACK (3 << 6)
|
nuclear@33
|
25
|
nuclear@33
|
26 #define CMD_LATCH 0
|
nuclear@33
|
27 #define CMD_ACCESS_LOW (1 << 4)
|
nuclear@33
|
28 #define CMD_ACCESS_HIGH (2 << 4)
|
nuclear@33
|
29 #define CMD_ACCESS_BOTH (3 << 4)
|
nuclear@33
|
30
|
nuclear@33
|
31 #define CMD_OP_INT_TERM 0
|
nuclear@33
|
32 #define CMD_OP_ONESHOT (1 << 1)
|
nuclear@33
|
33 #define CMD_OP_RATE (2 << 1)
|
nuclear@33
|
34 #define CMD_OP_SQWAVE (3 << 1)
|
nuclear@33
|
35 #define CMD_OP_SOFT_STROBE (4 << 1)
|
nuclear@33
|
36 #define CMD_OP_HW_STROBE (5 << 1)
|
nuclear@33
|
37
|
nuclear@33
|
38 #define CMD_MODE_BIN 0
|
nuclear@33
|
39 #define CMD_MODE_BCD 1
|
nuclear@33
|
40
|
nuclear@33
|
41
|
nuclear@33
|
42 static void intr_handler();
|
nuclear@33
|
43
|
nuclear@33
|
44
|
nuclear@33
|
45 void init_timer(void)
|
nuclear@33
|
46 {
|
nuclear@34
|
47 /* calculate the reload count: round(osc / freq) */
|
nuclear@34
|
48 int reload_count = DIV_ROUND(OSC_FREQ_HZ, TICK_FREQ_HZ);
|
nuclear@33
|
49
|
nuclear@33
|
50 /* set the mode to square wave for channel 0, both low
|
nuclear@34
|
51 * and high reload count bytes will follow...
|
nuclear@33
|
52 */
|
nuclear@33
|
53 outb(CMD_CHAN0 | CMD_ACCESS_BOTH | CMD_OP_SQWAVE, PORT_CMD);
|
nuclear@33
|
54
|
nuclear@34
|
55 /* write the low and high bytes of the reload count to the
|
nuclear@33
|
56 * port for channel 0
|
nuclear@33
|
57 */
|
nuclear@34
|
58 outb(reload_count & 0xff, PORT_DATA0);
|
nuclear@34
|
59 outb((reload_count >> 8) & 0xff, PORT_DATA0);
|
nuclear@33
|
60
|
nuclear@33
|
61 /* set the timer interrupt handler */
|
nuclear@35
|
62 interrupt(IRQ_TO_INTR(0), intr_handler);
|
nuclear@33
|
63 }
|
nuclear@33
|
64
|
nuclear@33
|
65 /* This will be called by the interrupt dispatcher approximately
|
nuclear@33
|
66 * every 1/250th of a second, so it must be extremely fast.
|
nuclear@33
|
67 * For now, just increasing a tick counter will suffice.
|
nuclear@33
|
68 */
|
nuclear@33
|
69 static void intr_handler()
|
nuclear@33
|
70 {
|
nuclear@33
|
71 nticks++;
|
nuclear@33
|
72
|
nuclear@33
|
73 if(nticks % TICK_FREQ_HZ == 0) {
|
nuclear@37
|
74 /*printf("%lu sec\n", nticks / TICK_FREQ_HZ);*/
|
nuclear@37
|
75 time_t t = time(0);
|
nuclear@37
|
76
|
nuclear@37
|
77 printf("%s", asctime(gmtime(&t)));
|
nuclear@33
|
78 }
|
nuclear@33
|
79 }
|