Files
Sylva/kernel/interrupt/pit.cpp
T
2026-05-31 19:58:14 +08:00

49 lines
1.1 KiB
C++

#include <kernel/pit.h>
#include <common.h>
#include <kernel/pic.h>
#include <kernel/serial.h>
static inline void outb(UINT16 port, UINT8 val) {
ASM("outb %0, %1" : : "a"(val), "Nd"(port));
}
static volatile UINT64 g_ticks = 0;
static timer_callback_t g_tick_handler = NULL;
extern "C" void pit_irq_handler(void) {
g_ticks++;
if (g_tick_handler) {
g_tick_handler();
}
}
void pit_init(void) {
serial_write("PIT: initializing channel 0 at ");
serial_write_hex(PIT_TICK_HZ);
serial_write(" Hz\n");
UINT32 divisor = PIT_BASE_FREQ / PIT_TICK_HZ;
// Command byte: channel 0, lobyte/hibyte, rate generator, binary
outb(PIT_COMMAND_PORT, 0x36);
// Send divisor (low byte first, then high byte)
outb(PIT_CHANNEL0_DATA, (UINT8)(divisor & 0xFF));
outb(PIT_CHANNEL0_DATA, (UINT8)((divisor >> 8) & 0xFF));
// Unmask IRQ 0 (timer)
pic_unmask_irq(0);
serial_write("PIT: divisor = ");
serial_write_hex(divisor);
serial_write("\n");
}
void pit_set_tick_handler(timer_callback_t handler) {
g_tick_handler = handler;
}
UINT64 pit_get_ticks(void) {
return g_ticks;
}