diff --git a/kernel/include/kernel/Timer/HPET.h b/kernel/include/kernel/Timer/HPET.h index 69b261016..fcf99c59b 100644 --- a/kernel/include/kernel/Timer/HPET.h +++ b/kernel/include/kernel/Timer/HPET.h @@ -8,14 +8,14 @@ namespace Kernel class HPET final : public Timer { public: - static BAN::ErrorOr> create(); + static BAN::ErrorOr> create(bool force_pic); virtual uint64_t ms_since_boot() const override; virtual timespec time_since_boot() const override; private: HPET() = default; - BAN::ErrorOr initialize(); + BAN::ErrorOr initialize(bool force_pic); void write_register(ptrdiff_t reg, uint64_t value) const; uint64_t read_register(ptrdiff_t reg) const; diff --git a/kernel/include/kernel/Timer/Timer.h b/kernel/include/kernel/Timer/Timer.h index f3058925e..4ab412e7e 100644 --- a/kernel/include/kernel/Timer/Timer.h +++ b/kernel/include/kernel/Timer/Timer.h @@ -18,7 +18,7 @@ namespace Kernel class SystemTimer : public Timer { public: - static void initialize(); + static void initialize(bool force_pic); static SystemTimer& get(); static bool is_initialized(); @@ -32,7 +32,7 @@ namespace Kernel private: SystemTimer() = default; - void initialize_timers(); + void initialize_timers(bool force_pic); private: uint64_t m_boot_time { 0 }; diff --git a/kernel/kernel/Timer/HPET.cpp b/kernel/kernel/Timer/HPET.cpp index 9065df419..130e79759 100644 --- a/kernel/kernel/Timer/HPET.cpp +++ b/kernel/kernel/Timer/HPET.cpp @@ -31,12 +31,12 @@ namespace Kernel { - BAN::ErrorOr> HPET::create() + BAN::ErrorOr> HPET::create(bool force_pic) { HPET* hpet = new HPET(); if (hpet == nullptr) return BAN::Error::from_errno(ENOMEM); - if (auto ret = hpet->initialize(); ret.is_error()) + if (auto ret = hpet->initialize(force_pic); ret.is_error()) { delete hpet; return ret.release_error(); @@ -44,7 +44,7 @@ namespace Kernel return BAN::UniqPtr::adopt(hpet); } - BAN::ErrorOr HPET::initialize() + BAN::ErrorOr HPET::initialize(bool force_pic) { auto* header = (ACPI::HPET*)ACPI::get().get_header("HPET"); if (header == nullptr) @@ -53,7 +53,7 @@ namespace Kernel if (header->hardware_rev_id == 0) return BAN::Error::from_errno(EINVAL); - if (!header->legacy_replacement_irq_routing_cable) + if (force_pic && !header->legacy_replacement_irq_routing_cable) { dwarnln("HPET doesn't support legacy mapping"); return BAN::Error::from_errno(ENOTSUP); @@ -92,26 +92,38 @@ 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; + if (!force_pic) + { + 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); + } + for (irq = 0; irq < 32; irq++) + if (irq_cap & (1 << irq)) + break; + } unmapper.disable(); + uint64_t main_flags = HPET_CONFIG_ENABLE; + if (force_pic) + main_flags |= HPET_CONFIG_LEG_RT; + // Enable main counter - write_register(HPET_REG_CONFIG, read_register(HPET_REG_CONFIG) | HPET_CONFIG_ENABLE); + write_register(HPET_REG_CONFIG, read_register(HPET_REG_CONFIG) | main_flags); + + uint64_t timer0_flags = 0; + timer0_flags |= HPET_Tn_INT_ENB_CNF; + timer0_flags |= HPET_Tn_TYPE_CNF; + timer0_flags |= HPET_Tn_VAL_SET_CNF; + if (!force_pic) + timer0_flags |= irq << HPET_Tn_INT_ROUTE_CNF_SHIFT; // 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 | (irq << HPET_Tn_INT_ROUTE_CNF_SHIFT)); + write_register(HPET_REG_TIMER_CONFIG(0), timer0_flags); 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); diff --git a/kernel/kernel/Timer/Timer.cpp b/kernel/kernel/Timer/Timer.cpp index e866af38b..d1cbb9620 100644 --- a/kernel/kernel/Timer/Timer.cpp +++ b/kernel/kernel/Timer/Timer.cpp @@ -8,12 +8,12 @@ namespace Kernel static SystemTimer* s_instance = nullptr; - void SystemTimer::initialize() + void SystemTimer::initialize(bool force_pic) { ASSERT(s_instance == nullptr); auto* temp = new SystemTimer; ASSERT(temp); - temp->initialize_timers(); + temp->initialize_timers(force_pic); s_instance = temp; } @@ -28,12 +28,12 @@ namespace Kernel return !!s_instance; } - void SystemTimer::initialize_timers() + void SystemTimer::initialize_timers(bool force_pic) { m_rtc = MUST(BAN::UniqPtr::create()); m_boot_time = BAN::to_unix_time(m_rtc->get_current_time()); - if (auto res = HPET::create(); res.is_error()) + if (auto res = HPET::create(force_pic); res.is_error()) dwarnln("HPET: {}", res.error()); else { diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index b3ffc5b6c..f85ab2341 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -141,10 +141,13 @@ extern "C" void kernel_main() MUST(ACPI::initialize()); dprintln("ACPI initialized"); + parse_command_line(); + dprintln("command line parsed, root='{}'", cmdline.root); + InterruptController::initialize(cmdline.force_pic); dprintln("Interrupt controller initialized"); - SystemTimer::initialize(); + SystemTimer::initialize(cmdline.force_pic); dprintln("Timers initialized"); DevFileSystem::initialize(); @@ -154,9 +157,6 @@ extern "C" void kernel_main() ASSERT(tty1); dprintln("TTY initialized"); - parse_command_line(); - dprintln("command line parsed, root='{}'", cmdline.root); - MUST(Scheduler::initialize()); dprintln("Scheduler initialized");