1000Hz PIC timer working + IDT dispatch/handler fixes
This commit is contained in:
74
src/time/timer.c
Normal file
74
src/time/timer.c
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user