diff --git a/include/apic.h b/include/apic.h index c2466f3..33e8edd 100644 --- a/include/apic.h +++ b/include/apic.h @@ -17,4 +17,8 @@ uint32_t ioapic_read(void *ioapicaddr, uint32_t reg); void ioapic_write(void *ioapicaddr, uint32_t reg, uint32_t value); void ioapic_redirect(int gsi, int vector); -void enable_symmetric_io_mode(); \ No newline at end of file +void enable_symmetric_io_mode(); + +void init_pit_timer_apic(uint32_t reload_value); +void init_apic_timer(); +void mask_pit_interrupt(); \ No newline at end of file diff --git a/include/isr.h b/include/isr.h index 1d73735..ecaec54 100644 --- a/include/isr.h +++ b/include/isr.h @@ -1,6 +1,10 @@ #ifndef ISR_H #define ISR_H +#include + +extern uint32_t timer_ticks; + void isr0(); void isr1(); void isr2(); diff --git a/src/kernel/apic.c b/src/kernel/apic.c index 9be059c..cedbd96 100644 --- a/src/kernel/apic.c +++ b/src/kernel/apic.c @@ -125,4 +125,59 @@ void ioapic_redirect(int gsi, int vector) { void enable_symmetric_io_mode() { outb(0x22, 0x70); // Select IMCR outb(0x23, 0x01); // Set to Symmetric I/O mode (bypass PIC) +} + +#include "../include/isr.h" + +#define APIC_REGISTER_TIMER_DIV 0x3E0 +#define APIC_REGISTER_TIMER_INITCNT 0x380 +#define APIC_REGISTER_LVT_TIMER 0x320 +#define APIC_LVT_INT_MASKED 0x10000 +#define APIC_REGISTER_TIMER_CURRCNT 0x390 +#define APIC_LVT_TIMER_MODE_PERIODIC (1 << 17) + +void init_pit_timer_apic(uint32_t reload_value) { + int timerFrequency = 1193182 / reload_value; + + outb(0x43, 0b00110100); + + uint8_t l = (uint8_t)(timerFrequency & 0xFF); + uint8_t h = (uint8_t)(timerFrequency >> 8 & 0xFF); + + outb(0x40, l); + outb(0x40, h); +} + +void init_apic_timer() +{ + lapic_write(APIC_REGISTER_TIMER_DIV, 0x3); + + // Prepare the PIT to sleep for 10ms (10000µs) + init_pit_timer_apic(1000); + + __asm__ __volatile__ ("sti"); + + // Set APIC init counter to -1 + lapic_write(APIC_REGISTER_TIMER_INITCNT, 0xFFFFFFFF); + + uint32_t target_ticks = timer_ticks + 10;//+10ms + while(timer_ticks < target_ticks) + {} + + // Stop the APIC timer + lapic_write(APIC_REGISTER_LVT_TIMER, APIC_LVT_INT_MASKED); + + // Now we know how often the APIC timer has ticked in 10ms + uint32_t ticksIn10ms = 0xFFFFFFFF - lapic_read(APIC_REGISTER_TIMER_CURRCNT); + + // Start timer as periodic on IRQ 0, divider 16, with the number of ticks we counted + lapic_write(APIC_REGISTER_LVT_TIMER, 32 | APIC_LVT_TIMER_MODE_PERIODIC); + lapic_write(APIC_REGISTER_TIMER_DIV, 0x3); + lapic_write(APIC_REGISTER_TIMER_INITCNT, ticksIn10ms); +} + +void mask_pit_interrupt() { + // Mask PIT interrupt (GSI 0, IRQ 0) + ioapic_write(ioapic_ptr, REG_TABLE + 2 * 0, INT_DISABLED | T_IRQ0); + ioapic_write(ioapic_ptr, REG_TABLE + 2 * 0 + 1, 0); // Clear destination field } \ No newline at end of file diff --git a/src/kernel/isr.c b/src/kernel/isr.c index 24cbffc..89c335a 100644 --- a/src/kernel/isr.c +++ b/src/kernel/isr.c @@ -110,8 +110,11 @@ __attribute__((interrupt)) void spurious(struct interrupt_frame *frame) lapic_eoi(); } +uint32_t timer_ticks = 0; + __attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame) { + timer_ticks++; if(lapic_enabled) { lapic_eoi(); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index ad81f28..6768305 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -73,6 +73,9 @@ void kmain(unsigned int magic, unsigned int info) printf("IOAPIC init done\n"); ioapic_redirect(2, 32);//timer ioapic_redirect(1, 33);//keyboard + + init_apic_timer(); + mask_pit_interrupt(); } printf("done fucking with pages and memory map!\n"); @@ -132,6 +135,11 @@ void kmain(unsigned int magic, unsigned int info) while(1) { + if(timer_ticks % 1000 == 0) + { + //printf("a second should have passed!\n"); + } + /* if(inportb(0x64) & 0x1) { unsigned char key = inportb(0x60);