forked from Bananymous/banan-os
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
|
||||
{
|
||||
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 timespec time_since_boot() const override;
|
||||
|
||||
private:
|
||||
HPET() = default;
|
||||
BAN::ErrorOr<void> initialize();
|
||||
BAN::ErrorOr<void> initialize(bool force_pic);
|
||||
|
||||
void write_register(ptrdiff_t reg, uint64_t value) const;
|
||||
uint64_t read_register(ptrdiff_t reg) const;
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -31,12 +31,12 @@
|
|||
namespace Kernel
|
||||
{
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<HPET>> HPET::create()
|
||||
BAN::ErrorOr<BAN::UniqPtr<HPET>> 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<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");
|
||||
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);
|
||||
|
||||
|
|
|
@ -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<RTC>::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
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue