apic: init apic timer using pit, not precise on qemu
This commit is contained in:
+5
-1
@@ -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_write(void *ioapicaddr, uint32_t reg, uint32_t value);
|
||||||
void ioapic_redirect(int gsi, int vector);
|
void ioapic_redirect(int gsi, int vector);
|
||||||
|
|
||||||
void enable_symmetric_io_mode();
|
void enable_symmetric_io_mode();
|
||||||
|
|
||||||
|
void init_pit_timer_apic(uint32_t reload_value);
|
||||||
|
void init_apic_timer();
|
||||||
|
void mask_pit_interrupt();
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
#ifndef ISR_H
|
#ifndef ISR_H
|
||||||
#define ISR_H
|
#define ISR_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern uint32_t timer_ticks;
|
||||||
|
|
||||||
void isr0();
|
void isr0();
|
||||||
void isr1();
|
void isr1();
|
||||||
void isr2();
|
void isr2();
|
||||||
|
|||||||
@@ -125,4 +125,59 @@ void ioapic_redirect(int gsi, int vector) {
|
|||||||
void enable_symmetric_io_mode() {
|
void enable_symmetric_io_mode() {
|
||||||
outb(0x22, 0x70); // Select IMCR
|
outb(0x22, 0x70); // Select IMCR
|
||||||
outb(0x23, 0x01); // Set to Symmetric I/O mode (bypass PIC)
|
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
|
||||||
}
|
}
|
||||||
@@ -110,8 +110,11 @@ __attribute__((interrupt)) void spurious(struct interrupt_frame *frame)
|
|||||||
lapic_eoi();
|
lapic_eoi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t timer_ticks = 0;
|
||||||
|
|
||||||
__attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame)
|
__attribute__((interrupt)) void isr_timer(struct interrupt_frame *frame)
|
||||||
{
|
{
|
||||||
|
timer_ticks++;
|
||||||
if(lapic_enabled)
|
if(lapic_enabled)
|
||||||
{
|
{
|
||||||
lapic_eoi();
|
lapic_eoi();
|
||||||
|
|||||||
@@ -73,6 +73,9 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
printf("IOAPIC init done\n");
|
printf("IOAPIC init done\n");
|
||||||
ioapic_redirect(2, 32);//timer
|
ioapic_redirect(2, 32);//timer
|
||||||
ioapic_redirect(1, 33);//keyboard
|
ioapic_redirect(1, 33);//keyboard
|
||||||
|
|
||||||
|
init_apic_timer();
|
||||||
|
mask_pit_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("done fucking with pages and memory map!\n");
|
printf("done fucking with pages and memory map!\n");
|
||||||
@@ -132,6 +135,11 @@ void kmain(unsigned int magic, unsigned int info)
|
|||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
|
if(timer_ticks % 1000 == 0)
|
||||||
|
{
|
||||||
|
//printf("a second should have passed!\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* if(inportb(0x64) & 0x1)
|
/* if(inportb(0x64) & 0x1)
|
||||||
{
|
{
|
||||||
unsigned char key = inportb(0x60);
|
unsigned char key = inportb(0x60);
|
||||||
|
|||||||
Reference in New Issue
Block a user