50 lines
1.2 KiB
C++
50 lines
1.2 KiB
C++
#include <interrupt/pit.h>
|
|
#include <common.h>
|
|
#include <string_utils.h>
|
|
#include <interrupt/pic.h>
|
|
#include <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;
|
|
|
|
// 命令字节:通道 0,低/高字节,速率生成器,二进制
|
|
outb(PIT_COMMAND_PORT, 0x36);
|
|
|
|
// 发送除数(先低字节后高字节)
|
|
outb(PIT_CHANNEL0_DATA, (UINT8)(divisor & 0xFF));
|
|
outb(PIT_CHANNEL0_DATA, (UINT8)((divisor >> 8) & 0xFF));
|
|
|
|
// 取消屏蔽 IRQ 0(定时器)
|
|
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;
|
|
}
|