From b8fba03773ca8d77566f2b2c662dc64d2fecdd7d Mon Sep 17 00:00:00 2001 From: Tomas Date: Mon, 28 Apr 2025 18:48:40 +0200 Subject: [PATCH] Implemented PIT --- TODO | 12 +++++++++-- kernel/include/isr.h | 2 +- kernel/include/system.h | 1 + kernel/include/timer.h | 22 ++++++++++++++++++++ kernel/src/isr.c | 16 +++++++------- kernel/src/kernel.c | 9 ++++++-- kernel/src/timer.c | 46 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 kernel/include/timer.h create mode 100644 kernel/src/timer.c diff --git a/TODO b/TODO index 5db50f8..bb8c199 100644 --- a/TODO +++ b/TODO @@ -10,10 +10,18 @@ TODO [x] Virtual MM [x] Paging [x] Serial monitor -[ ] Timer interrupts +[ ] Make dedicated asm functions like lidt(), sti(), ... +[x] PIT +[ ] RTC +[ ] HPET +[ ] System calls +[ ] Userspace +[ ] Processes +[ ] Scheduler [ ] Task switching -[ ] IPC +[ ] Inter-process communication [ ] Graphics +[ ] Multicore support [ ] Networking :) [ ] Finish all the TODOs [ ] Run DOOM diff --git a/kernel/include/isr.h b/kernel/include/isr.h index 6f62238..4684542 100644 --- a/kernel/include/isr.h +++ b/kernel/include/isr.h @@ -16,7 +16,7 @@ struct isr_int_frame { typedef void (*isr_handler_ptr)(struct isr_int_frame* iframe); int isr_init(void); -void isr_register_IRQ(uint8_t i, isr_handler_ptr handler); +void isr_register(uint8_t i, isr_handler_ptr handler); int isr_handle_interrupt(struct isr_int_frame iframe); // Assembly definitions (isr.s) diff --git a/kernel/include/system.h b/kernel/include/system.h index 6cbd43d..4ac695a 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -3,6 +3,7 @@ #include +// cpuid void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx); // Ports diff --git a/kernel/include/timer.h b/kernel/include/timer.h new file mode 100644 index 0000000..872c8a8 --- /dev/null +++ b/kernel/include/timer.h @@ -0,0 +1,22 @@ +#ifndef _TIMER_H +#define _TIMER_H + +#include + +#define PIT_DIV 1193180 +#define PIT_CH0 0x40 +#define PIT_CH1 0x41 +#define PIT_CH2 0x42 +#define PIT_CMD 0x43 + +int timer_init(void); +void timer_wait(size_t ticks); + +int pit_init(void); +void pit_phase(uint8_t ch, uint8_t mode, uint32_t hz); +void pit_handler(struct isr_int_frame* iframe); + +// TODO: rtc_init(void); +// TODO: hpet_init(void); + +#endif diff --git a/kernel/src/isr.c b/kernel/src/isr.c index 500ce3b..b1593cb 100644 --- a/kernel/src/isr.c +++ b/kernel/src/isr.c @@ -75,28 +75,26 @@ int isr_init(void) { return 0; } -void isr_register_irq(uint8_t i, isr_handler_ptr handler) { +void isr_register(uint8_t i, isr_handler_ptr handler) { + if (i > 16) return; // Security irq_handlers[i] = handler; } void isr_send_eoi(uint8_t irq) { - if (irq >= 8) { - outb(0xa0, 0x20); - } + if (irq >= 8) outb(0xA0, 0x20); outb(0x20, 0x20); } +// TODO: Write fault handlers and make this more robust int isr_handle_interrupt(struct isr_int_frame iframe) { if (iframe.interrupt < 32) { // ISRs 0-31 - Exceptions - panic(exceptions[iframe.error]); + panic(exceptions[iframe.interrupt]); } else if (iframe.interrupt >= 32 && iframe.interrupt < 48) { // ISRs 32-47 - Hardware interrupts uint8_t irq = iframe.interrupt - 32; - if (irq_handlers[irq]) { - irq_handlers[irq](&iframe); - isr_send_eoi(irq); - } + if (irq_handlers[irq]) irq_handlers[irq](&iframe); + isr_send_eoi(irq); } else if (iframe.interrupt == 128) { // ISR 128 - System call return syscall_handler(&iframe); diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index aaa7c68..593cce0 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -29,13 +30,17 @@ void kmain(void* ptr, uint32_t magic) { if (tty_init() != 0) panic("Failed to initalize TTY driver."); tty_puts("kern.\n\n"); - // TODO: Timer - // TODO: Scheduler + // Timer + if (timer_init() != 0) panic("Failed to initialize timer."); + // TODO: Syscalls + // TODO: Scheduler // TODO: Interprocess communication // TODO: Tasking // TODO: Load & run /sbin/init + while (1); + panic("kmain() reached end."); } diff --git a/kernel/src/timer.c b/kernel/src/timer.c new file mode 100644 index 0000000..226e4b7 --- /dev/null +++ b/kernel/src/timer.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +#include + +size_t timer_ticks = 0; + +int timer_init(void) { + // TODO: Check what timer we can use and select the best one + return pit_init(); +} + +void timer_wait(size_t t) { + size_t req = timer_ticks + t; + while (req != timer_ticks); +} + +int pit_init(void) { + isr_register(0, pit_handler); + pit_phase(0, 2, 1000); + return 0; +} + +void pit_phase(uint8_t ch, uint8_t mode, uint32_t hz) { + if (ch > 2 || mode > 7) return; + + __asm__ volatile ("cli"); + + outb(PIT_CMD, ((ch << 6) | (3 << 4) | (mode << 1))); + + uint32_t div = PIT_DIV / hz; + debugf("[PIT] Setting PIT divisor to %d...\n", div); + outb(PIT_CH0 + ch, div & 0xFF); + outb(PIT_CH0 + ch, div >> 8); + + __asm__ volatile ("sti"); +} + +void pit_handler(struct isr_int_frame* iframe) { + timer_ticks++; + + if (timer_ticks % 1000 == 0) tty_puts("."); +} +