kern
annotate src/timer.c @ 47:f65b348780e3
continuing with the process implementation. not done yet, panics.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 28 Jul 2011 05:43:04 +0300 |
parents | 710739e33da8 |
children | b1e8c8251884 |
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 } |