kernel: add standard clock system

This commit is contained in:
2023-04-28 20:51:51 +01:00
parent 995e364b21
commit 72d8facd47
5 changed files with 123 additions and 35 deletions

View File

@@ -1,13 +1,42 @@
#include <socks/printk.h>
#include <socks/clock.h>
#include <socks/cpu.h>
#include <arch/ports.h>
#include <arch/irq.h>
static unsigned long long tick_counter = 0;
#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)
{
tick_counter++;
clock_advance(1);
ticks++;
return 0;
}
@@ -17,39 +46,20 @@ static struct irq_hook pit_irq_hook = {
void pit_start(unsigned int hz)
{
tick_counter = 0;
unsigned int divisor = 1193180 / hz;
outportb(0x43, 0x36);
uint8_t lo = (uint8_t)(divisor & 0xFF);
uint8_t hi = (uint8_t)((divisor >> 8) & 0xFF);
outportb(0x40, lo);
outportb(0x40, hi);
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)
{
/* lowest possible frequency */
unsigned int divisor = 1193180;
outportb(0x43, 0x36);
uint8_t lo = (uint8_t)(divisor & 0xFF);
uint8_t hi = (uint8_t)((divisor >> 8) & 0xFF);
outportb(0x40, lo);
outportb(0x40, hi);
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);
}
void pit_wait(unsigned int ticks)
{
unsigned long long end = tick_counter + ticks;
while (READ_ONCE(tick_counter) < end) {
}
}