toaruos/kernel/devices/timer.c

78 lines
1.3 KiB
C
Raw Normal View History

/* vim: tabstop=4 shiftwidth=4 noexpandtab
*
* Programmable Interrupt Timer
*/
2011-01-16 19:56:44 +03:00
#include <system.h>
#include <logging.h>
2011-01-16 19:56:44 +03:00
#define PIT_A 0x40
#define PIT_B 0x41
#define PIT_C 0x42
#define PIT_CONTROL 0x43
#define PIT_MASK 0xFF
#define PIT_SCALE 1193180
#define PIT_SET 0x36
#define TIMER_IRQ 0
/*
* Set the phase (in hertz) for the Programmable
* Interrupt Timer (PIT).
*/
2011-01-16 19:56:44 +03:00
void
timer_phase(
int hz
) {
int divisor = PIT_SCALE / hz;
outportb(PIT_CONTROL, PIT_SET);
outportb(PIT_A, divisor & PIT_MASK);
outportb(PIT_A, (divisor >> 8) & PIT_MASK);
2011-01-16 19:56:44 +03:00
}
/*
* Internal timer counters
*/
2011-01-18 03:22:48 +03:00
long timer_ticks = 0;
2011-01-16 19:56:44 +03:00
unsigned long ticker = 0;
/*
* IRQ handler for when the timer fires
*/
2011-01-16 19:56:44 +03:00
void
timer_handler(
struct regs *r
) {
++timer_ticks;
irq_ack(TIMER_IRQ);
switch_task(1);
2011-01-16 19:56:44 +03:00
}
/*
* Device installer for the PIT
*/
2011-01-16 19:56:44 +03:00
void timer_install() {
2011-12-27 05:23:58 +04:00
blog("Installing Programmable Interval Timer...");
LOG(INFO,"Initializing interval timer");
irq_install_handler(TIMER_IRQ, timer_handler);
timer_phase(100); /* 100Hz */
2011-12-27 05:23:58 +04:00
bfinish(0);
2011-01-16 19:56:44 +03:00
}
/*
* Wait until `ticks` calls to the timer
* handler have happened, then resume execution.
*/
2011-01-16 19:56:44 +03:00
void
timer_wait(
int ticks
) {
/* end tick count */
2011-01-18 03:22:48 +03:00
long eticks;
eticks = (long)timer_ticks + (long)ticks;
while(timer_ticks < eticks) {
/* Halt for interrupt */
IRQS_ON_AND_PAUSE;
}
2011-01-16 19:56:44 +03:00
}