Kernel: HPET is now used in legacy mode when PIC is forced

This commit is contained in:
Bananymous 2023-08-10 22:01:30 +03:00
parent 8b57edde6b
commit 03d4b47f63
5 changed files with 41 additions and 29 deletions

View File

@ -8,14 +8,14 @@ namespace Kernel
class HPET final : public Timer class HPET final : public Timer
{ {
public: public:
static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(); static BAN::ErrorOr<BAN::UniqPtr<HPET>> create(bool force_pic);
virtual uint64_t ms_since_boot() const override; virtual uint64_t ms_since_boot() const override;
virtual timespec time_since_boot() const override; virtual timespec time_since_boot() const override;
private: private:
HPET() = default; HPET() = default;
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize(bool force_pic);
void write_register(ptrdiff_t reg, uint64_t value) const; void write_register(ptrdiff_t reg, uint64_t value) const;
uint64_t read_register(ptrdiff_t reg) const; uint64_t read_register(ptrdiff_t reg) const;

View File

@ -18,7 +18,7 @@ namespace Kernel
class SystemTimer : public Timer class SystemTimer : public Timer
{ {
public: public:
static void initialize(); static void initialize(bool force_pic);
static SystemTimer& get(); static SystemTimer& get();
static bool is_initialized(); static bool is_initialized();
@ -32,7 +32,7 @@ namespace Kernel
private: private:
SystemTimer() = default; SystemTimer() = default;
void initialize_timers(); void initialize_timers(bool force_pic);
private: private:
uint64_t m_boot_time { 0 }; uint64_t m_boot_time { 0 };

View File

@ -31,12 +31,12 @@
namespace Kernel namespace Kernel
{ {
BAN::ErrorOr<BAN::UniqPtr<HPET>> HPET::create() BAN::ErrorOr<BAN::UniqPtr<HPET>> HPET::create(bool force_pic)
{ {
HPET* hpet = new HPET(); HPET* hpet = new HPET();
if (hpet == nullptr) if (hpet == nullptr)
return BAN::Error::from_errno(ENOMEM); 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; delete hpet;
return ret.release_error(); return ret.release_error();
@ -44,7 +44,7 @@ namespace Kernel
return BAN::UniqPtr<HPET>::adopt(hpet); return BAN::UniqPtr<HPET>::adopt(hpet);
} }
BAN::ErrorOr<void> HPET::initialize() BAN::ErrorOr<void> HPET::initialize(bool force_pic)
{ {
auto* header = (ACPI::HPET*)ACPI::get().get_header("HPET"); auto* header = (ACPI::HPET*)ACPI::get().get_header("HPET");
if (header == nullptr) if (header == nullptr)
@ -53,7 +53,7 @@ namespace Kernel
if (header->hardware_rev_id == 0) if (header->hardware_rev_id == 0)
return BAN::Error::from_errno(EINVAL); 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"); dwarnln("HPET doesn't support legacy mapping");
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
@ -92,26 +92,38 @@ namespace Kernel
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
} }
int irq = 0;
if (!force_pic)
{
uint32_t irq_cap = timer0_config >> 32; uint32_t irq_cap = timer0_config >> 32;
if (irq_cap == 0) if (irq_cap == 0)
{ {
dwarnln("HPET doesn't have any interrupts available"); dwarnln("HPET doesn't have any interrupts available");
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
for (irq = 0; irq < 32; irq++)
int irq = 0;
for (; irq < 32; irq++)
if (irq_cap & (1 << irq)) if (irq_cap & (1 << irq))
break; break;
}
unmapper.disable(); unmapper.disable();
uint64_t main_flags = HPET_CONFIG_ENABLE;
if (force_pic)
main_flags |= HPET_CONFIG_LEG_RT;
// Enable main counter // 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 // 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), read_register(HPET_REG_COUNTER) + ticks_per_ms);
write_register(HPET_REG_TIMER_COMPARATOR(0), ticks_per_ms); write_register(HPET_REG_TIMER_COMPARATOR(0), ticks_per_ms);

View File

@ -8,12 +8,12 @@ namespace Kernel
static SystemTimer* s_instance = nullptr; static SystemTimer* s_instance = nullptr;
void SystemTimer::initialize() void SystemTimer::initialize(bool force_pic)
{ {
ASSERT(s_instance == nullptr); ASSERT(s_instance == nullptr);
auto* temp = new SystemTimer; auto* temp = new SystemTimer;
ASSERT(temp); ASSERT(temp);
temp->initialize_timers(); temp->initialize_timers(force_pic);
s_instance = temp; s_instance = temp;
} }
@ -28,12 +28,12 @@ namespace Kernel
return !!s_instance; return !!s_instance;
} }
void SystemTimer::initialize_timers() void SystemTimer::initialize_timers(bool force_pic)
{ {
m_rtc = MUST(BAN::UniqPtr<RTC>::create()); m_rtc = MUST(BAN::UniqPtr<RTC>::create());
m_boot_time = BAN::to_unix_time(m_rtc->get_current_time()); 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()); dwarnln("HPET: {}", res.error());
else else
{ {

View File

@ -141,10 +141,13 @@ extern "C" void kernel_main()
MUST(ACPI::initialize()); MUST(ACPI::initialize());
dprintln("ACPI initialized"); dprintln("ACPI initialized");
parse_command_line();
dprintln("command line parsed, root='{}'", cmdline.root);
InterruptController::initialize(cmdline.force_pic); InterruptController::initialize(cmdline.force_pic);
dprintln("Interrupt controller initialized"); dprintln("Interrupt controller initialized");
SystemTimer::initialize(); SystemTimer::initialize(cmdline.force_pic);
dprintln("Timers initialized"); dprintln("Timers initialized");
DevFileSystem::initialize(); DevFileSystem::initialize();
@ -154,9 +157,6 @@ extern "C" void kernel_main()
ASSERT(tty1); ASSERT(tty1);
dprintln("TTY initialized"); dprintln("TTY initialized");
parse_command_line();
dprintln("command line parsed, root='{}'", cmdline.root);
MUST(Scheduler::initialize()); MUST(Scheduler::initialize());
dprintln("Scheduler initialized"); dprintln("Scheduler initialized");