initial hpet support

for now only a few wait functions are supported
This commit is contained in:
Matheus
2022-08-06 23:51:10 -03:00
parent a69310a03c
commit c94368bbc9
6 changed files with 144 additions and 2 deletions
+108
View File
@@ -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)
}
+16
View File
@@ -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);
+10
View File
@@ -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
+1 -1
View File
@@ -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
+5
View File
@@ -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();
+4 -1
View File
@@ -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(){