From ebe0adb3b5da0ec773935adf19578d331525ec2a Mon Sep 17 00:00:00 2001 From: Bananymous Date: Thu, 10 Aug 2023 21:04:01 +0300 Subject: [PATCH] Kernel: HPET doesn't use the legacy mapping anymore --- kernel/kernel/Timer/HPET.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/kernel/kernel/Timer/HPET.cpp b/kernel/kernel/Timer/HPET.cpp index fa226699..9065df41 100644 --- a/kernel/kernel/Timer/HPET.cpp +++ b/kernel/kernel/Timer/HPET.cpp @@ -21,6 +21,7 @@ #define HPET_Tn_TYPE_CNF (1 << 3) #define HPET_Tn_PER_INT_CAP (1 << 4) #define HPET_Tn_VAL_SET_CNF (1 << 6) +#define HPET_Tn_INT_ROUTE_CNF_SHIFT 9 #define FS_PER_S 1'000'000'000'000'000 #define FS_PER_MS 1'000'000'000'000 @@ -30,8 +31,6 @@ namespace Kernel { - static uint64_t s_system_time = 0; - BAN::ErrorOr> HPET::create() { HPET* hpet = new HPET(); @@ -93,13 +92,26 @@ namespace Kernel return BAN::Error::from_errno(ENOTSUP); } + uint32_t irq_cap = timer0_config >> 32; + + if (irq_cap == 0) + { + dwarnln("HPET doesn't have any interrupts available"); + return BAN::Error::from_errno(EINVAL); + } + + int irq = 0; + for (; irq < 32; irq++) + if (irq_cap & (1 << irq)) + break; + unmapper.disable(); // Enable main counter - write_register(HPET_REG_CONFIG, read_register(HPET_REG_CONFIG) | HPET_CONFIG_LEG_RT | HPET_CONFIG_ENABLE); + write_register(HPET_REG_CONFIG, read_register(HPET_REG_CONFIG) | HPET_CONFIG_ENABLE); // Enable timer 0 as 1 ms periodic - write_register(HPET_REG_TIMER_CONFIG(0), HPET_Tn_INT_ENB_CNF | HPET_Tn_TYPE_CNF | HPET_Tn_VAL_SET_CNF); + write_register(HPET_REG_TIMER_CONFIG(0), HPET_Tn_INT_ENB_CNF | HPET_Tn_TYPE_CNF | HPET_Tn_VAL_SET_CNF | (irq << HPET_Tn_INT_ROUTE_CNF_SHIFT)); write_register(HPET_REG_TIMER_COMPARATOR(0), read_register(HPET_REG_COUNTER) + ticks_per_ms); write_register(HPET_REG_TIMER_COMPARATOR(0), ticks_per_ms); @@ -107,8 +119,8 @@ namespace Kernel for (int i = 1; i <= header->comparator_count; i++) write_register(HPET_REG_TIMER_CONFIG(i), 0); - IDT::register_irq_handler(0, [] { s_system_time++; Scheduler::get().timer_reschedule(); }); - InterruptController::get().enable_irq(0); + IDT::register_irq_handler(irq, [] { Scheduler::get().timer_reschedule(); }); + InterruptController::get().enable_irq(irq); return {}; }