Kernel: HPET is now used in legacy mode when PIC is forced
This commit is contained in:
parent
8b57edde6b
commit
03d4b47f63
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue