#include #include #include #include #include #define PIT_COUNTER0 0x40 #define PIT_CMD 0x43 #define CMD_BINARY 0x00 // Use Binary counter values #define CMD_BCD 0x01 // Use Binary Coded Decimal counter values #define CMD_MODE0 0x00 // Interrupt on Terminal Count #define CMD_MODE1 0x02 // Hardware Retriggerable One-Shot #define CMD_MODE2 0x04 // Rate Generator #define CMD_MODE3 0x06 // Square Wave #define CMD_MODE4 0x08 // Software Trigerred Strobe #define CMD_MODE5 0x0a // Hardware Trigerred Strobe #define CMD_LATCH 0x00 #define CMD_RW_LOW 0x10 // Least Significant Byte #define CMD_RW_HI 0x20 // Most Significant Byte #define CMD_RW_BOTH 0x30 // Least followed by Most Significant Byte #define CMD_COUNTER0 0x00 #define CMD_COUNTER1 0x40 #define CMD_COUNTER2 0x80 #define CMD_READBACK 0xc0 #define PIT_FREQUENCY 1193182 static volatile unsigned long long ticks = 0; static int pit_callback(void) { clock_advance(1); ticks++; return 0; } static struct irq_hook pit_irq_hook = {.irq_callback = pit_callback}; void pit_start(unsigned int hz) { hook_irq(IRQ0, &pit_irq_hook); unsigned int divisor = PIT_FREQUENCY / hz; outportb(PIT_CMD, CMD_BINARY | CMD_MODE2 | CMD_RW_BOTH | CMD_COUNTER0); outportb(PIT_COUNTER0, divisor); outportb(PIT_COUNTER0, divisor >> 8); } void pit_stop(void) { unsigned int divisor = PIT_FREQUENCY / 20; outportb(PIT_CMD, CMD_BINARY | CMD_MODE4 | CMD_RW_BOTH | CMD_COUNTER0); outportb(PIT_COUNTER0, divisor); outportb(PIT_COUNTER0, divisor >> 8); unhook_irq(IRQ0, &pit_irq_hook); }