mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-23 08:00:20 +00:00
Kernel: Use map_typed() in HPET code and add a register access helper
This commit is contained in:
parent
1d59053494
commit
8d6910b78e
Notes:
sideshowbarker
2024-07-19 05:31:09 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/8d6910b78e1
2 changed files with 59 additions and 62 deletions
|
@ -31,6 +31,7 @@
|
|||
#include <Kernel/Time/HPETComparator.h>
|
||||
#include <Kernel/Time/TimeManagement.h>
|
||||
#include <Kernel/VM/MemoryManager.h>
|
||||
#include <Kernel/VM/TypedMapping.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -123,8 +124,7 @@ bool HPET::test_and_initialize()
|
|||
return false;
|
||||
klog() << "HPET @ " << hpet;
|
||||
|
||||
auto region = MM.allocate_kernel_region(hpet.page_base(), (PAGE_SIZE * 2), "HPET Initialization", Region::Access::Read);
|
||||
auto* sdt = (ACPI::Structures::HPET*)region->vaddr().offset(hpet.offset_in_page()).as_ptr();
|
||||
auto sdt = map_typed<ACPI::Structures::HPET>(hpet);
|
||||
|
||||
// Note: HPET is only usable from System Memory
|
||||
ASSERT(sdt->event_timer_block.address_space == (u8)ACPI::GenericAddressStructure::AddressSpace::SystemMemory);
|
||||
|
@ -144,14 +144,10 @@ bool HPET::check_for_exisiting_periodic_timers()
|
|||
auto hpet = ACPI::Parser::the()->find_table("HPET");
|
||||
if (hpet.is_null())
|
||||
return false;
|
||||
auto region = MM.allocate_kernel_region(hpet.page_base(), (PAGE_SIZE * 2), "HPET Initialization", Region::Access::Read);
|
||||
auto* sdt = (ACPI::Structures::HPET*)region->vaddr().offset(hpet.offset_in_page()).as_ptr();
|
||||
|
||||
auto sdt = map_typed<ACPI::Structures::HPET>(hpet);
|
||||
ASSERT(sdt->event_timer_block.address_space == 0);
|
||||
|
||||
auto p_block = PhysicalAddress(sdt->event_timer_block.address);
|
||||
auto block_region = MM.allocate_kernel_region(p_block, (PAGE_SIZE * 2), "HPET Initialization", Region::Access::Read);
|
||||
auto* registers = (volatile HPETRegistersBlock*)block_region->vaddr().offset(p_block.offset_in_page()).as_ptr();
|
||||
auto registers = map_typed<volatile HPETRegistersBlock>(PhysicalAddress(sdt->event_timer_block.address));
|
||||
|
||||
size_t timers_count = ((registers->raw_capabilites.reg >> 8) & 0x1f) + 1;
|
||||
for (size_t index = 0; index < timers_count; index++) {
|
||||
|
@ -163,13 +159,11 @@ bool HPET::check_for_exisiting_periodic_timers()
|
|||
|
||||
void HPET::global_disable()
|
||||
{
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
registers_block->configuration.reg = registers_block->configuration.reg & ~(u32)HPETFlags::Configuration::Enable;
|
||||
registers().configuration.reg = registers().configuration.reg & ~(u32)HPETFlags::Configuration::Enable;
|
||||
}
|
||||
void HPET::global_enable()
|
||||
{
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
registers_block->configuration.reg = registers_block->configuration.reg | (u32)HPETFlags::Configuration::Enable;
|
||||
registers().configuration.reg = registers().configuration.reg | (u32)HPETFlags::Configuration::Enable;
|
||||
}
|
||||
|
||||
void HPET::set_periodic_comparator_value(const HPETComparator& comparator, u64 value)
|
||||
|
@ -177,10 +171,9 @@ void HPET::set_periodic_comparator_value(const HPETComparator& comparator, u64 v
|
|||
disable(comparator);
|
||||
ASSERT(comparator.is_periodic());
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
volatile auto* timer = ®isters_block->timers[comparator.comparator_number()];
|
||||
timer->configuration_and_capability = timer->configuration_and_capability | (u32)HPETFlags::TimerConfiguration::ValueSet;
|
||||
timer->comparator_value = value;
|
||||
volatile auto& timer = registers().timers[comparator.comparator_number()];
|
||||
timer.configuration_and_capability = timer.configuration_and_capability | (u32)HPETFlags::TimerConfiguration::ValueSet;
|
||||
timer.comparator_value = value;
|
||||
enable(comparator);
|
||||
}
|
||||
|
||||
|
@ -189,9 +182,9 @@ void HPET::set_non_periodic_comparator_value(const HPETComparator& comparator, u
|
|||
ASSERT_INTERRUPTS_DISABLED();
|
||||
ASSERT(!comparator.is_periodic());
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
registers_block->timers[comparator.comparator_number()].comparator_value = main_counter_value() + value;
|
||||
registers().timers[comparator.comparator_number()].comparator_value = main_counter_value() + value;
|
||||
}
|
||||
|
||||
void HPET::enable_periodic_interrupt(const HPETComparator& comparator)
|
||||
{
|
||||
#ifdef HPET_DEBUG
|
||||
|
@ -199,11 +192,10 @@ void HPET::enable_periodic_interrupt(const HPETComparator& comparator)
|
|||
#endif
|
||||
disable(comparator);
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
volatile auto* timer = ®isters_block->timers[comparator.comparator_number()];
|
||||
auto configuration_and_capability = timer->configuration_and_capability;
|
||||
volatile auto& timer = registers().timers[comparator.comparator_number()];
|
||||
auto configuration_and_capability = timer.configuration_and_capability;
|
||||
ASSERT(configuration_and_capability & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable);
|
||||
timer->configuration_and_capability = configuration_and_capability | (u32)HPETFlags::TimerConfiguration::TimerType;
|
||||
timer.configuration_and_capability = configuration_and_capability | (u32)HPETFlags::TimerConfiguration::TimerType;
|
||||
enable(comparator);
|
||||
}
|
||||
void HPET::disable_periodic_interrupt(const HPETComparator& comparator)
|
||||
|
@ -213,11 +205,10 @@ void HPET::disable_periodic_interrupt(const HPETComparator& comparator)
|
|||
#endif
|
||||
disable(comparator);
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
auto volatile* timer = ®isters_block->timers[comparator.comparator_number()];
|
||||
auto configuration_and_capability = timer->configuration_and_capability;
|
||||
auto volatile& timer = registers().timers[comparator.comparator_number()];
|
||||
auto configuration_and_capability = timer.configuration_and_capability;
|
||||
ASSERT(configuration_and_capability & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable);
|
||||
timer->configuration_and_capability = configuration_and_capability & ~(u32)HPETFlags::TimerConfiguration::TimerType;
|
||||
timer.configuration_and_capability = configuration_and_capability & ~(u32)HPETFlags::TimerConfiguration::TimerType;
|
||||
enable(comparator);
|
||||
}
|
||||
|
||||
|
@ -227,9 +218,8 @@ void HPET::disable(const HPETComparator& comparator)
|
|||
klog() << "HPET: Disable comparator " << comparator.comparator_number() << ".";
|
||||
#endif
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
volatile auto* timer = ®isters_block->timers[comparator.comparator_number()];
|
||||
timer->configuration_and_capability = timer->configuration_and_capability & ~(u32)HPETFlags::TimerConfiguration::InterruptEnable;
|
||||
volatile auto& timer = registers().timers[comparator.comparator_number()];
|
||||
timer.configuration_and_capability = timer.configuration_and_capability & ~(u32)HPETFlags::TimerConfiguration::InterruptEnable;
|
||||
}
|
||||
void HPET::enable(const HPETComparator& comparator)
|
||||
{
|
||||
|
@ -237,16 +227,15 @@ void HPET::enable(const HPETComparator& comparator)
|
|||
klog() << "HPET: Enable comparator " << comparator.comparator_number() << ".";
|
||||
#endif
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
volatile auto* timer = ®isters_block->timers[comparator.comparator_number()];
|
||||
timer->configuration_and_capability = timer->configuration_and_capability | (u32)HPETFlags::TimerConfiguration::InterruptEnable;
|
||||
volatile auto& timer = registers().timers[comparator.comparator_number()];
|
||||
timer.configuration_and_capability = timer.configuration_and_capability | (u32)HPETFlags::TimerConfiguration::InterruptEnable;
|
||||
}
|
||||
|
||||
u64 HPET::main_counter_value() const
|
||||
{
|
||||
auto* registers_block = (const volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
return registers_block->main_counter_value.reg;
|
||||
return registers().main_counter_value.reg;
|
||||
}
|
||||
|
||||
u64 HPET::frequency() const
|
||||
{
|
||||
return m_frequency;
|
||||
|
@ -256,9 +245,8 @@ Vector<unsigned> HPET::capable_interrupt_numbers(const HPETComparator& comparato
|
|||
{
|
||||
ASSERT(comparator.comparator_number() <= m_comparators.size());
|
||||
Vector<unsigned> capable_interrupts;
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
auto* comparator_registers = (const volatile TimerStructure*)®isters_block->timers[comparator.comparator_number()];
|
||||
u32 interrupt_bitfield = comparator_registers->configuration_and_capability >> 32;
|
||||
auto& comparator_registers = (const volatile TimerStructure&)registers().timers[comparator.comparator_number()];
|
||||
u32 interrupt_bitfield = comparator_registers.configuration_and_capability >> 32;
|
||||
for (size_t index = 0; index < 32; index++) {
|
||||
if (interrupt_bitfield & 1)
|
||||
capable_interrupts.append(index);
|
||||
|
@ -271,9 +259,8 @@ Vector<unsigned> HPET::capable_interrupt_numbers(u8 comparator_number)
|
|||
{
|
||||
ASSERT(comparator_number <= m_comparators.size());
|
||||
Vector<unsigned> capable_interrupts;
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
auto* comparator_registers = (const volatile TimerStructure*)®isters_block->timers[comparator_number];
|
||||
u32 interrupt_bitfield = comparator_registers->configuration_and_capability >> 32;
|
||||
auto& comparator_registers = (const volatile TimerStructure&)registers().timers[comparator_number];
|
||||
u32 interrupt_bitfield = comparator_registers.configuration_and_capability >> 32;
|
||||
for (size_t index = 0; index < 32; index++) {
|
||||
if (interrupt_bitfield & 1)
|
||||
capable_interrupts.append(index);
|
||||
|
@ -285,17 +272,15 @@ Vector<unsigned> HPET::capable_interrupt_numbers(u8 comparator_number)
|
|||
void HPET::set_comparator_irq_vector(u8 comparator_number, u8 irq_vector)
|
||||
{
|
||||
ASSERT(comparator_number <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
auto* comparator_registers = (volatile TimerStructure*)®isters_block->timers[comparator_number];
|
||||
comparator_registers->configuration_and_capability = comparator_registers->configuration_and_capability | (irq_vector << 9);
|
||||
auto& comparator_registers = (volatile TimerStructure&)registers().timers[comparator_number];
|
||||
comparator_registers.configuration_and_capability = comparator_registers.configuration_and_capability | (irq_vector << 9);
|
||||
}
|
||||
|
||||
bool HPET::is_periodic_capable(u8 comparator_number) const
|
||||
{
|
||||
ASSERT(comparator_number <= m_comparators.size());
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
auto* comparator_registers = (const volatile TimerStructure*)®isters_block->timers[comparator_number];
|
||||
return comparator_registers->configuration_and_capability & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable;
|
||||
auto& comparator_registers = (const volatile TimerStructure&)registers().timers[comparator_number];
|
||||
return comparator_registers.configuration_and_capability & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable;
|
||||
}
|
||||
|
||||
void HPET::set_comparators_to_optimal_interrupt_state(size_t)
|
||||
|
@ -304,36 +289,43 @@ void HPET::set_comparators_to_optimal_interrupt_state(size_t)
|
|||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
PhysicalAddress HPET::find_acpi_hept_registers_block()
|
||||
PhysicalAddress HPET::find_acpi_hpet_registers_block()
|
||||
{
|
||||
auto region = MM.allocate_kernel_region(m_physical_acpi_hpet_table.page_base(), (PAGE_SIZE * 2), "HPET Initialization", Region::Access::Read);
|
||||
auto* sdt = (const volatile ACPI::Structures::HPET*)region->vaddr().offset(m_physical_acpi_hpet_table.offset_in_page()).as_ptr();
|
||||
auto sdt = map_typed<const volatile ACPI::Structures::HPET>(m_physical_acpi_hpet_table);
|
||||
ASSERT(sdt->event_timer_block.address_space == (u8)ACPI::GenericAddressStructure::AddressSpace::SystemMemory);
|
||||
return PhysicalAddress(sdt->event_timer_block.address);
|
||||
}
|
||||
|
||||
const volatile HPETRegistersBlock& HPET::registers() const
|
||||
{
|
||||
return *(const volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
}
|
||||
|
||||
volatile HPETRegistersBlock& HPET::registers()
|
||||
{
|
||||
return *(volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
}
|
||||
|
||||
u64 HPET::calculate_ticks_in_nanoseconds() const
|
||||
{
|
||||
auto* registers_block = (const volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
return ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD / registers_block->capabilities.main_counter_tick_period;
|
||||
return ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD / registers().capabilities.main_counter_tick_period;
|
||||
}
|
||||
|
||||
HPET::HPET(PhysicalAddress acpi_hpet)
|
||||
: m_physical_acpi_hpet_table(acpi_hpet)
|
||||
, m_physical_acpi_hpet_registers(find_acpi_hept_registers_block())
|
||||
, m_physical_acpi_hpet_registers(find_acpi_hpet_registers_block())
|
||||
, m_hpet_mmio_region(MM.allocate_kernel_region(m_physical_acpi_hpet_registers.page_base(), PAGE_SIZE, "HPET MMIO", Region::Access::Read | Region::Access::Write))
|
||||
{
|
||||
auto region = MM.allocate_kernel_region(m_physical_acpi_hpet_table.page_base(), (PAGE_SIZE * 2), "HPET Initialization", Region::Access::Read);
|
||||
auto* sdt = (const volatile ACPI::Structures::HPET*)region->vaddr().offset(m_physical_acpi_hpet_table.offset_in_page()).as_ptr();
|
||||
auto sdt = map_typed<const volatile ACPI::Structures::HPET>(m_physical_acpi_hpet_table);
|
||||
m_vendor_id = sdt->pci_vendor_id;
|
||||
m_minimum_tick = sdt->mininum_clock_tick;
|
||||
klog() << "HPET: Minimum clock tick - " << m_minimum_tick;
|
||||
|
||||
auto* registers_block = (volatile HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
|
||||
|
||||
// Note: We must do a 32 bit access to offsets 0x0, or 0x4 only.
|
||||
size_t timers_count = ((registers_block->raw_capabilites.reg >> 8) & 0x1f) + 1;
|
||||
size_t timers_count = ((registers().raw_capabilites.reg >> 8) & 0x1f) + 1;
|
||||
klog() << "HPET: Timers count - " << timers_count;
|
||||
ASSERT(timers_count >= 2);
|
||||
auto* capabilities_register = (const volatile HPETCapabilityRegister*)®isters_block->raw_capabilites.reg;
|
||||
auto* capabilities_register = (const volatile HPETCapabilityRegister*)®isters().raw_capabilites.reg;
|
||||
|
||||
global_disable();
|
||||
|
||||
|
@ -342,9 +334,9 @@ HPET::HPET(PhysicalAddress acpi_hpet)
|
|||
ASSERT(capabilities_register->main_counter_tick_period <= ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD);
|
||||
|
||||
// Reset the counter, just in case...
|
||||
registers_block->main_counter_value.reg = 0;
|
||||
if (registers_block->raw_capabilites.reg & (u32)HPETFlags::Attributes::LegacyReplacementRouteCapable)
|
||||
registers_block->configuration.reg = registers_block->configuration.reg | (u32)HPETFlags::Configuration::LegacyReplacementRoute;
|
||||
registers().main_counter_value.reg = 0;
|
||||
if (registers().raw_capabilites.reg & (u32)HPETFlags::Attributes::LegacyReplacementRouteCapable)
|
||||
registers().configuration.reg = registers().configuration.reg | (u32)HPETFlags::Configuration::LegacyReplacementRoute;
|
||||
|
||||
m_comparators.append(HPETComparator::create(0, 0, is_periodic_capable(0)));
|
||||
m_comparators.append(HPETComparator::create(1, 8, is_periodic_capable(1)));
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
namespace Kernel {
|
||||
|
||||
class HPETComparator;
|
||||
struct HPETRegistersBlock;
|
||||
|
||||
class HPET {
|
||||
public:
|
||||
static bool initialized();
|
||||
|
@ -63,6 +65,9 @@ public:
|
|||
Vector<unsigned> capable_interrupt_numbers(const HPETComparator&);
|
||||
|
||||
private:
|
||||
const volatile HPETRegistersBlock& registers() const;
|
||||
volatile HPETRegistersBlock& registers();
|
||||
|
||||
void global_disable();
|
||||
void global_enable();
|
||||
|
||||
|
@ -71,7 +76,7 @@ private:
|
|||
|
||||
u64 calculate_ticks_in_nanoseconds() const;
|
||||
|
||||
PhysicalAddress find_acpi_hept_registers_block();
|
||||
PhysicalAddress find_acpi_hpet_registers_block();
|
||||
explicit HPET(PhysicalAddress acpi_hpet);
|
||||
PhysicalAddress m_physical_acpi_hpet_table;
|
||||
PhysicalAddress m_physical_acpi_hpet_registers;
|
||||
|
|
Loading…
Reference in a new issue