#include "arch/devices/legacy_pit.hpp" #include "kapi/devices.hpp" #include "kapi/devices/device.hpp" #include "kapi/interrupts.hpp" #include "arch/device_io/port_io.hpp" #include #include namespace arch::devices { namespace { using command_port = io::port<0x43, std::uint8_t, io::port_write>; using channel_0_port = io::port<0x40, std::uint8_t, io::port_write>; using channel_1_port = io::port<0x41, std::uint8_t, io::port_write>; using channel_2_port = io::port<0x42, std::uint8_t, io::port_write>; constexpr auto base_frequency = 1'193'182u; constexpr auto square_wave_mode = 0x36; } // namespace legacy_pit::legacy_pit(std::size_t major, std::uint32_t frequency_in_hz) : kapi::devices::device{major, 0, "legacy_pit"} , m_irq_number{0} , m_frequency_in_hz{frequency_in_hz} {} auto legacy_pit::init() -> bool { auto divisor = static_cast(base_frequency / m_frequency_in_hz); kapi::interrupts::register_handler(m_irq_number, *this); command_port::write(square_wave_mode); io::wait(); channel_0_port::write(divisor & 0xff); io::wait(); channel_0_port::write(divisor >> 8 & 0xff); io::wait(); return true; } auto legacy_pit::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status { if (irq_number != m_irq_number) { return kapi::interrupts::status::unhandled; } ++m_ticks; return kapi::interrupts::status::handled; } } // namespace arch::devices