kern

annotate src/timer.c @ 41:928b0ebfff4d

merged the timer/rtc/etc from the misc branch
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 14 Jun 2011 01:19:07 +0300
parents 2c401f69128e
children f65b348780e3
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 time_t t = time(0);
nuclear@37 75 printf("%s", asctime(gmtime(&t)));
nuclear@33 76 }
nuclear@33 77 }