1000Hz PIC timer working + IDT dispatch/handler fixes

This commit is contained in:
2025-12-27 13:52:05 +01:00
parent 24d75463b8
commit 54f26c506e
9 changed files with 204 additions and 52 deletions

74
src/time/timer.c Normal file
View File

@@ -0,0 +1,74 @@
#include <stdint.h>
#include "../io/serial.h"
/*
For now, the timer module will be using the PIC.
Even though it's quite old, it's still supported by newer CPUs
and it will be precise enough for what we'll do. Also it's easier
to implement than ACPI etc. (we may upgrade to ACPI when we're
interested in multi-core functionnality like SMP)
*/
volatile uint64_t ticks = 0;
void pic_remap()
{
uint8_t master_mask = inb(0x21);
uint8_t slave_mask = inb(0xA1);
// ICW1: start initialization
outb(0x20, 0x11);
outb(0xA0, 0x11);
// ICW2: vector offsets
outb(0x21, 0x20); // Master PIC -> 0x20
outb(0xA1, 0x28); // Slave PIC -> 0x28
// ICW3: tell Master about Slave at IRQ2 (0000 0100)
outb(0x21, 0x04);
// ICW3: tell Slave its cascade identity (0000 0010)
outb(0xA1, 0x02);
// ICW4: 8086 mode
outb(0x21, 0x01);
outb(0xA1, 0x01);
// Restore saved masks
outb(0x21, master_mask);
outb(0xA1, slave_mask);
}
void pic_enable()
{
// Enabling IRQ0 (unmasking it) but not the others
uint8_t mask = inb(0x21);
mask &= ~(1 << 0); // Clear bit 0 (IRQ0)
outb(0x21, mask);
}
/*
Base frequency = 1.193182 MHz
1 tick per ms (divide by 1000) = roughly 1193 Hz
*/
void pit_init()
{
uint32_t frequency = 1000; // 1 kHz
uint32_t divisor = 1193182 / frequency;
// Set PIT to mode 3, channel 0
outb(0x43, 0x36); // 0x36
// Send divisor (low byte, then high byte)
outb(0x40, divisor & 0xFF);
outb(0x40, (divisor >> 8) & 0xFF);
}
void timer_init()
{
// Remapping the PIC, because at startup it conflicts with
// the reserved IRQs we have for faults/exceptions etc.
// so we move its IRQ0 to something not reserved (32)
pic_remap();
pic_enable();
pit_init();
}