mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: initial hpet support
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
#include <arch/acpi.h>
|
||||
#include <time.h>
|
||||
#include <logging.h>
|
||||
#include <arch/hpet.h>
|
||||
#include <kernel/vmm.h>
|
||||
|
||||
#define HPET_REG_CAPS 0
|
||||
#define HPET_REG_CONFIG 2
|
||||
#define HPET_REG_INTSTATUS 4
|
||||
#define HPET_REG_COUNTER 0x1e
|
||||
|
||||
#define CAP_FSPERTICK(x) (((x) >> 32) & 0xffffffff)
|
||||
|
||||
// XXX there might be several hpets in a system.
|
||||
static volatile uint64_t *hpet;
|
||||
static time_t ticksperus;
|
||||
|
||||
static uint64_t read64(int reg) {
|
||||
return hpet[reg];
|
||||
}
|
||||
|
||||
static void write64(int reg, uint64_t v) {
|
||||
hpet[reg] = v;
|
||||
}
|
||||
|
||||
void arch_hpet_waitticks(time_t ticks) {
|
||||
uint64_t target = read64(HPET_REG_COUNTER) + ticks;
|
||||
while (target > read64(HPET_REG_COUNTER)) asm volatile("pause");
|
||||
}
|
||||
|
||||
void arch_hpet_waitus(time_t us) {
|
||||
arch_hpet_waitticks(us * ticksperus);
|
||||
}
|
||||
|
||||
bool arch_hpet_exists() {
|
||||
return arch_acpi_findtable("HPET", 0) != NULL;
|
||||
}
|
||||
|
||||
void arch_hpet_init() {
|
||||
__assert(arch_hpet_exists());
|
||||
hpet_t *table = arch_acpi_findtable("HPET", 0);
|
||||
printf("hpet%lu: %lu bits %lu comparators\n", table->hpetnum, 32 + table->countersize * 32, table->comparatorcount);
|
||||
__assert(table->countersize); // XXX not rely on hpet being 64 bits
|
||||
__assert(table->addrid == 0);
|
||||
__assert((table->addr & PAGE_SIZE) == 0);
|
||||
hpet = vmm_map(NULL, PAGE_SIZE, VMM_FLAGS_PHYSICAL, ARCH_MMU_FLAGS_READ | ARCH_MMU_FLAGS_WRITE | ARCH_MMU_FLAGS_NOEXEC, (void *)table->addr);
|
||||
__assert(hpet);
|
||||
ticksperus = 1000000000 / CAP_FSPERTICK(read64(HPET_REG_CAPS));
|
||||
printf("hpet%lu: %lu ticks per us (%lu fs per tick)\n", table->hpetnum, ticksperus, CAP_FSPERTICK(read64(HPET_REG_CAPS)));
|
||||
__assert(ticksperus);
|
||||
|
||||
write64(HPET_REG_CONFIG, 0);
|
||||
write64(HPET_REG_COUNTER, 0);
|
||||
write64(HPET_REG_CONFIG, 1);
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <kernel/alloc.h>
|
||||
#include <arch/acpi.h>
|
||||
#include <arch/apic.h>
|
||||
#include <arch/hpet.h>
|
||||
|
||||
static cpu_t bsp_cpu;
|
||||
|
||||
@@ -29,5 +30,6 @@ void kernel_entry() {
|
||||
arch_acpi_init();
|
||||
arch_apic_init();
|
||||
arch_apic_initap();
|
||||
arch_hpet_init();
|
||||
__assert(!"kernel entry end");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
typedef struct {
|
||||
time_t s;
|
||||
time_t ns;
|
||||
} timespec_t;
|
||||
|
||||
#endif
|
||||
@@ -45,6 +45,24 @@ typedef struct {
|
||||
uint32_t flags;
|
||||
} __attribute__((packed)) madt_t;
|
||||
|
||||
typedef struct {
|
||||
sdtheader_t header;
|
||||
uint8_t hwrev;
|
||||
uint8_t comparatorcount:5;
|
||||
uint8_t countersize:1;
|
||||
uint8_t reserved:1;
|
||||
uint8_t legacy_replacement:1;
|
||||
uint16_t pcivendor;
|
||||
uint8_t addrid;
|
||||
uint8_t bitwidth;
|
||||
uint8_t bitoffset;
|
||||
uint8_t reserved2;
|
||||
uint64_t addr;
|
||||
uint8_t hpetnum;
|
||||
uint16_t mintick;
|
||||
uint8_t pageprot;
|
||||
} __attribute__((packed)) hpet_t;
|
||||
|
||||
#define ACPI_MADT_TYPE_LAPIC 0
|
||||
#define ACPI_MADT_TYPE_IOAPIC 1
|
||||
#define ACPI_MADT_TYPE_OVERRIDE 2
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _HPET_H
|
||||
#define _HPET_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
void arch_hpet_waitticks(time_t ticks);
|
||||
void arch_hpet_waitus(time_t us);
|
||||
bool arch_hpet_exists();
|
||||
void arch_hpet_init();
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user