diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 4163b16..c2f7447 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -10,6 +10,7 @@ #include #include #include +#include void thread_function() { @@ -38,6 +39,7 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data) apic_init(); ioapic_init(); sse_init(); + pit_init(); process_t *p1 = process_spawn(0); diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c new file mode 100644 index 0000000..f97415e --- /dev/null +++ b/kernel/drivers/pit.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include +#include +#include +#include + +#define PIT_CH0 0x40 +#define PIT_CH2 0x42 +#define PIT_CMD 0x43 + +#define PIT_USE_CH0 0x00 +#define PIT_USE_CH2 0x80 +#define PIT_RW_LOHI 0x30 +#define PIT_MODE(M) ((M)<<1) + +#define PIT_FREQ 1193182 + +#define CH2_PORT 0x61 +#define CH2_ENABLE 0x01 +#define CH2_OUT 0x20 + + +void delay(uint8_t ms) +{ + // Turn off channel 2 + uint8_t ch2 = inb(CH2_PORT); + ch2 &= ~CH2_ENABLE; + outb(CH2_PORT, ch2); + + // Set up a countdown on channel 2 + outb(PIT_CMD, PIT_USE_CH2 | PIT_RW_LOHI | PIT_MODE(0)); + uint16_t count = PIT_FREQ * ms/1000; + outb(PIT_CH2, count & 0xFF); + outb(PIT_CH2, (count >> 8) & 0xFF); + + // Turn on channel 2 + ch2 |= CH2_ENABLE; + outb(CH2_PORT, ch2); + + // Busy wait (Ultimately, we'll only use this a few times during boot) + while(!(inb(CH2_PORT) & CH2_OUT)); +} + +void pit_delay(uint32_t ms) +{ + while(ms > 50) + { + delay(50); + ms -= 50; + } + if(ms) + delay(ms); +} + +uint64_t system_ticks = 0; +registers_t *timer_tick(registers_t *r) +{ + apic_ack(); + system_ticks ++; + return r; +} + +uint64_t get_ticks() +{ + return system_ticks; +} + +void pit_init() +{ + register_int_handler(IRQ_INT(IRQ_TIMER), timer_tick); + outb(PIT_CMD, PIT_USE_CH0 | PIT_RW_LOHI | PIT_MODE(3)); + uint16_t count = PIT_FREQ/TICK_FREQ; + outb(PIT_CH0, (count & 0xFF)); + outb(PIT_CH0, (count >> 8)); + IRQ_UNMASK(IRQ_TIMER); +} diff --git a/kernel/include/int.h b/kernel/include/int.h index 16d7d14..f342362 100644 --- a/kernel/include/int.h +++ b/kernel/include/int.h @@ -68,6 +68,7 @@ #ifndef __ASSEMBLER__ #include +#include struct int_gate_descriptor { @@ -88,7 +89,7 @@ struct idtr void pic_init(); extern unsigned int irq_map[24]; -#define IRQ_INT(irq) (INT_IRQ0 + irq) +#define IRQ_INT(irq) (INT_IRQ0 + IRQ(irq)) #define IRQ(irq) (irq_map[irq]) #define IRQ_MASK(irq) ioapic_mask(IRQ(irq)) #define IRQ_UNMASK(irq) ioapic_unmask(IRQ(irq)) diff --git a/kernel/include/pit.h b/kernel/include/pit.h new file mode 100644 index 0000000..c9f510f --- /dev/null +++ b/kernel/include/pit.h @@ -0,0 +1,5 @@ +#pragma once +#include + +void pit_delay(uint32_t ms); +void pit_init(); diff --git a/kernel/include/timer.h b/kernel/include/timer.h new file mode 100644 index 0000000..092d79f --- /dev/null +++ b/kernel/include/timer.h @@ -0,0 +1,7 @@ +#pragma once +#include + +#define TICK_FREQ 1000 + +void pit_init(); +uint64_t get_ticks();