mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
initial hpet support
for now only a few wait functions are supported
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#include <arch/hpet.h>
|
||||
#include <arch/acpi.h>
|
||||
#include <arch/pci.h>
|
||||
#include <arch/panic.h>
|
||||
#include <kernel/vmm.h>
|
||||
#include <arch/mmu.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define REGISTER_CAPABILITIES 0
|
||||
#define REGISTER_CONFIGURATION 0x10
|
||||
#define REGISTER_INTERRUPT 0x20
|
||||
#define REGISTER_COUNTER 0xF0
|
||||
#define REGISTER_N_CONFIG 0x100
|
||||
#define REGISTER_N_COMPARATOR 0x108
|
||||
#define REGISTER_N_FSB 0x110
|
||||
|
||||
static uint16_t mintick;
|
||||
static void* volatile hpetaddr;
|
||||
static uint32_t period;
|
||||
static uint64_t nsperiod;
|
||||
static uint8_t compcount;
|
||||
static uint64_t ticksper100ns;
|
||||
|
||||
static inline void writetocompn(size_t n, size_t offset, uint64_t data){
|
||||
*(uint64_t* volatile)(hpetaddr + 0x20*n + offset) = data;
|
||||
}
|
||||
|
||||
static inline uint64_t readfromcompn(size_t n, size_t offset){
|
||||
return *(uint64_t* volatile)(hpetaddr + 0x100 + 0x20*n + offset);
|
||||
}
|
||||
|
||||
static inline uint64_t readfromreg(size_t offset){
|
||||
return *(uint64_t* volatile)(hpetaddr + offset);
|
||||
}
|
||||
|
||||
static inline void writetoreg(size_t offset, uint64_t data){
|
||||
*(uint64_t* volatile)(hpetaddr + offset) = data;
|
||||
}
|
||||
|
||||
static void wait_ticks(size_t ticks){
|
||||
|
||||
size_t end = readfromreg(REGISTER_COUNTER) + ticks;
|
||||
|
||||
while(readfromreg(REGISTER_COUNTER) < end) asm("pause");
|
||||
}
|
||||
|
||||
void hpet_wait_us(size_t us){
|
||||
|
||||
size_t usticks = ticksper100ns*10;
|
||||
|
||||
wait_ticks(usticks*us);
|
||||
|
||||
}
|
||||
|
||||
void hpet_wait_ms(size_t ms){
|
||||
size_t msticks = ticksper100ns*10000;
|
||||
|
||||
wait_ticks(ms*msticks);
|
||||
|
||||
}
|
||||
|
||||
void hpet_wait_s(size_t s){
|
||||
size_t sticks = ticksper100ns*10000000;
|
||||
|
||||
wait_ticks(s*sticks);
|
||||
|
||||
}
|
||||
|
||||
void hpet_init(){
|
||||
|
||||
hpet_t* hpet = acpi_gettable("HPET", 0);
|
||||
|
||||
if(!hpet)
|
||||
_panic("No HPET found!\n", 0);
|
||||
|
||||
printf("HPET table at %p\n", hpet);
|
||||
|
||||
mintick = hpet->mintick;
|
||||
|
||||
if(hpet->spacetype == 1) _panic("I/O space hpet not supported", 0);
|
||||
|
||||
printf("HPET configuration space is at %p\n", hpet->address);
|
||||
|
||||
// seabios doesn't report this in the memory map.....
|
||||
|
||||
hpetaddr = vmm_alloc(1, 0);
|
||||
vmm_map((void*)hpet->address, hpetaddr, 1, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE);
|
||||
|
||||
uint64_t capabilities = readfromreg(REGISTER_CAPABILITIES);
|
||||
|
||||
compcount = (capabilities >> 8) & 0b11111;
|
||||
period = (capabilities >> 32) & 0xFFFFFFFF;
|
||||
nsperiod = period / 1000000;
|
||||
ticksper100ns = 100000000 / period;
|
||||
|
||||
printf("%lu comparators at %lu femtosecond ticks (%lu ns, %lu ticks per 100 ns)\n", compcount, period, nsperiod, ticksper100ns);
|
||||
|
||||
// configure so we don't use legacy replacement and clear the counter
|
||||
|
||||
writetoreg(REGISTER_CONFIGURATION, 0); // stop it
|
||||
writetoreg(REGISTER_COUNTER, 0);
|
||||
writetoreg(REGISTER_CONFIGURATION, 1); // turn it back on
|
||||
|
||||
// TODO add interrupt support. for now only direct reads to the
|
||||
// counter will be supported.
|
||||
// (this should be enough for calibrating the CPU specific timers)
|
||||
|
||||
}
|
||||
@@ -60,6 +60,22 @@ typedef struct {
|
||||
mcfgentry entries[];
|
||||
} __attribute__((packed)) mcfg_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
sdt_t header;
|
||||
uint8_t revid;
|
||||
uint8_t flags;
|
||||
uint16_t vendor;
|
||||
uint8_t spacetype;
|
||||
uint8_t bitwidth;
|
||||
uint8_t bitoffset;
|
||||
uint8_t reserved;
|
||||
uint64_t address;
|
||||
uint8_t hpetnum;
|
||||
uint16_t mintick;
|
||||
uint8_t protection;
|
||||
} __attribute__((packed)) hpet_t;
|
||||
|
||||
void* acpi_gettable(char* sig, size_t n);
|
||||
void acpi_init();
|
||||
bool acpi_checksumok(sdt_t* table);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _HPET_H_INCLUDE
|
||||
#define _HPET_H_INCLUDE
|
||||
|
||||
void hpet_init();
|
||||
|
||||
void hpet_wait_us(size_t us);
|
||||
void hpet_wait_ms(size_t ms);
|
||||
void hpet_wait_s(size_t s);
|
||||
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ typedef struct _pci_enumeration{
|
||||
pci_common* header;
|
||||
} pci_enumeration;
|
||||
|
||||
|
||||
uint64_t pci_msi_build(uint64_t* data, uint8_t vector, uint8_t processor, uint8_t edgetrigger, uint8_t deassert);
|
||||
void pci_enumerate();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <kernel/initrd.h>
|
||||
#include <arch/spinlock.h>
|
||||
#include <stdio.h>
|
||||
#include <arch/pci.h>
|
||||
#include <arch/hpet.h>
|
||||
#include <arch/smp.h>
|
||||
|
||||
static volatile struct limine_terminal_request liminettyr = {
|
||||
.id = LIMINE_TERMINAL_REQUEST,
|
||||
@@ -67,6 +70,8 @@ void kmain(){
|
||||
apic_lapicinit();
|
||||
|
||||
pci_enumerate();
|
||||
|
||||
hpet_init();
|
||||
|
||||
smp_init();
|
||||
|
||||
|
||||
@@ -122,7 +122,10 @@ static void legacy_enumeration(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint64_t pci_msi_build(uint64_t* data, uint8_t vector, uint8_t processor, uint8_t edgetrigger, uint8_t deassert){
|
||||
*data = vector | (edgetrigger << 15) | (deassert << 14);
|
||||
return (0xFEE00000 | (processor << 12));
|
||||
}
|
||||
|
||||
void pci_enumerate(){
|
||||
|
||||
|
||||
Reference in New Issue
Block a user