diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-23 22:34:49 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-23 22:34:49 +0200 |
| commit | 7d78433e6ea80b651f80201b6c5beef799887e7f (patch) | |
| tree | 09135131ee0833f99ce9b5126ea9fe4d31be1ceb /arch/x86_64 | |
| parent | 4a58a7c7cb1f37e0183de9b838def3a217504e7b (diff) | |
| download | kernel-7d78433e6ea80b651f80201b6c5beef799887e7f.tar.xz kernel-7d78433e6ea80b651f80201b6c5beef799887e7f.zip | |
x86_64: port legacy PIT driver to new architecture
Diffstat (limited to 'arch/x86_64')
| -rw-r--r-- | arch/x86_64/arch/bus/isa.cpp | 29 | ||||
| -rw-r--r-- | arch/x86_64/arch/bus/isa.hpp | 35 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/init.cpp | 10 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/legacy_pit.cpp | 85 | ||||
| -rw-r--r-- | arch/x86_64/arch/devices/legacy_pit.hpp | 48 |
5 files changed, 184 insertions, 23 deletions
diff --git a/arch/x86_64/arch/bus/isa.cpp b/arch/x86_64/arch/bus/isa.cpp index dd248f76..573feb72 100644 --- a/arch/x86_64/arch/bus/isa.cpp +++ b/arch/x86_64/arch/bus/isa.cpp @@ -2,6 +2,11 @@ #include <kapi/devices.hpp> +#include <kstd/result.hpp> + +#include <algorithm> +#include <cstdint> + namespace arch::bus { @@ -9,4 +14,28 @@ namespace arch::bus : kapi::devices::bus{"isa"} {} + auto isa::enumerate(kapi::devices::bus &) -> void + { + // NOTE: ISA does not support enumeration, but we need to fulfill the interface. + } + + auto isa::match(kapi::devices::device const & device, kapi::devices::driver const & driver) const + -> kstd::result<std::uint32_t> + { + auto identification = device.as<isa_identification>(); + auto claims = driver.as<isa_driver_identification>(); + + if (!identification || !claims || !std::ranges::contains(claims->supported_names(), identification->isa_name())) + { + return kstd::failure(kapi::devices::driver_match_errc::no_match); + } + + return 0u; + } + + auto isa::protocol() -> kapi::devices::bus_protocol * + { + return this; + } + } // namespace arch::bus
\ No newline at end of file diff --git a/arch/x86_64/arch/bus/isa.hpp b/arch/x86_64/arch/bus/isa.hpp index 5741a640..a09127dd 100644 --- a/arch/x86_64/arch/bus/isa.hpp +++ b/arch/x86_64/arch/bus/isa.hpp @@ -1,14 +1,45 @@ #ifndef TEACHOS_X86_64_BUS_ISA_HPP #define TEACHOS_X86_64_BUS_ISA_HPP -#include <kapi/devices/bus.hpp> +#include <kapi/devices.hpp> + +#include <kstd/result.hpp> + +#include <cstdint> +#include <span> +#include <string_view> namespace arch::bus { - struct isa final : public kapi::devices::bus + struct isa_identification + { + constexpr auto static id = kapi::devices::interface{"isa_identification"}; + + virtual ~isa_identification() = default; + + [[nodiscard]] virtual auto isa_name() const -> std::string_view = 0; + }; + + struct isa_driver_identification + { + constexpr auto static id = kapi::devices::interface{"isa_driver_identification"}; + + virtual ~isa_driver_identification() = default; + + [[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0; + }; + + struct isa final : public kapi::devices::bus, kapi::devices::bus_protocol { isa(); + + auto enumerate(kapi::devices::bus & self) -> void override; + + [[nodiscard]] auto match(kapi::devices::device const & device, kapi::devices::driver const & driver) const + -> kstd::result<std::uint32_t> override; + + [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override; }; } // namespace arch::bus diff --git a/arch/x86_64/arch/devices/init.cpp b/arch/x86_64/arch/devices/init.cpp index 2c4fb3c3..f6adcbcf 100644 --- a/arch/x86_64/arch/devices/init.cpp +++ b/arch/x86_64/arch/devices/init.cpp @@ -7,6 +7,7 @@ #include <kapi/acpi.hpp> #include <kapi/cpu.hpp> #include <kapi/devices.hpp> +#include <kapi/devices/driver_registry.hpp> #include <acpi/acpi.hpp> @@ -14,7 +15,6 @@ #include <kstd/print.hpp> #include <cstdint> -#include <utility> namespace arch::devices { @@ -63,12 +63,12 @@ namespace arch::devices kstd::println("[x86_64:DEV] Initializing ISA bus..."); auto isa_bus = kstd::make_shared<arch::bus::isa>(); + auto root_bus = kapi::devices::get_root_bus(); - auto pit = kstd::make_shared<arch::devices::legacy_pit>(pit_frequency_in_hz); - isa_bus->add_child(std::move(pit)); + root_bus->add_child(isa_bus); - auto root_bus = kapi::devices::get_root_bus(); - root_bus->add_child(std::move(isa_bus)); + kapi::devices::driver_registry::get().add(kstd::make_shared<pit_driver>(pit_frequency_in_hz)); + isa_bus->add_child(kstd::make_shared<pit_device>()); } } // namespace arch::devices diff --git a/arch/x86_64/arch/devices/legacy_pit.cpp b/arch/x86_64/arch/devices/legacy_pit.cpp index d93b38fd..5e968a6b 100644 --- a/arch/x86_64/arch/devices/legacy_pit.cpp +++ b/arch/x86_64/arch/devices/legacy_pit.cpp @@ -1,16 +1,25 @@ #include <arch/devices/legacy_pit.hpp> +#include <arch/bus/isa.hpp> #include <arch/device_io/port_io.hpp> #include <kapi/devices.hpp> #include <kapi/devices/device.hpp> #include <kapi/interrupts.hpp> +#include <kstd/memory.hpp> +#include <kstd/result.hpp> + +#include <array> #include <cstdint> +#include <span> +#include <string_view> namespace arch::devices { + using namespace std::string_view_literals; + namespace { using command_port = io::port<0x43, std::uint8_t, io::port_write>; @@ -20,19 +29,46 @@ namespace arch::devices constexpr auto base_frequency = 1'193'182u; constexpr auto square_wave_mode = 0x36; + + constexpr auto pit_names = std::array{"pit"sv}; } // namespace - legacy_pit::legacy_pit(std::uint32_t frequency_in_hz) - : kapi::devices::device{"legacy_pit"} - , m_irq_number{0} - , m_frequency_in_hz{frequency_in_hz} + pit_device::pit_device() + : device{"legacy_pit"} + {} + + auto pit_device::isa_name() const -> std::string_view + { + return "pit"; + } + + auto pit_device::init() -> bool + { + return true; + } + + auto pit_device::query_interface(kapi::devices::interface interface) -> void * + { + if (interface == arch::bus::isa_identification::id) + { + return static_cast<arch::bus::isa_identification *>(this); + } + + return kapi::devices::device::query_interface(interface); + } + + pit_driver::pit_driver(std::uint32_t frequency_in_hz) + : m_frequency_in_hz{frequency_in_hz} {} - auto legacy_pit::init() -> bool + auto pit_driver::probe(kapi::devices::device & device) -> kstd::result<void> { - auto divisor = static_cast<std::uint16_t>(base_frequency / m_frequency_in_hz); + auto data = kstd::make_shared<driver_data>(0, m_frequency_in_hz, 0); + device.set_driver_data(data); - kapi::interrupts::register_handler(m_irq_number, *this); + auto divisor = static_cast<std::uint16_t>(base_frequency / data->frequency_in_hz); + + kapi::interrupts::register_handler(data->irq_number, *this); command_port::write<std::uint8_t>(square_wave_mode); io::wait(); @@ -41,19 +77,46 @@ namespace arch::devices channel_0_port::write<std::uint8_t>(divisor >> 8 & 0xff); io::wait(); - return true; + return kstd::success(); } - auto legacy_pit::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status + auto pit_driver::unbind(kapi::devices::device & device) -> void { - if (irq_number != m_irq_number) + auto data = static_pointer_cast<driver_data>(device.driver_data()); + + kapi::interrupts::unregister_handler(data->irq_number, *this); + + device.set_driver_data(nullptr); + } + + auto pit_driver::supported_names() const -> std::span<std::string_view const> + { + return pit_names; + } + + auto pit_driver::handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status + { + // auto data = static_pointer_cast<driver_data>(device.driver_data()); + + if (irq_number != 0) { return kapi::interrupts::status::unhandled; } - ++m_ticks; + // TODO: upgrade kapi interrupts to gain access to the device. + // ++m_ticks; return kapi::interrupts::status::handled; } + auto pit_driver::query_interface(kapi::devices::interface interface) -> void * + { + if (interface == arch::bus::isa_driver_identification::id) + { + return static_cast<arch::bus::isa_driver_identification *>(this); + } + + return kapi::devices::driver::query_interface(interface); + } + } // namespace arch::devices
\ No newline at end of file diff --git a/arch/x86_64/arch/devices/legacy_pit.hpp b/arch/x86_64/arch/devices/legacy_pit.hpp index 7a74144e..1bb41e2b 100644 --- a/arch/x86_64/arch/devices/legacy_pit.hpp +++ b/arch/x86_64/arch/devices/legacy_pit.hpp @@ -1,26 +1,64 @@ #ifndef TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP #define TEACHOS_ARCH_X86_64_DEVICES_LEGACY_PIT_HPP -#include <kapi/devices/device.hpp> +#include <arch/bus/isa.hpp> + +#include <kapi/devices.hpp> #include <kapi/interrupts.hpp> +#include <kstd/result.hpp> + #include <cstdint> +#include <span> +#include <string_view> namespace arch::devices { - struct legacy_pit : kapi::devices::device, kapi::interrupts::handler + //! The ISA device for the legacy Programmable Interrupt Timer. + //! + //! This type identifies the PIT device node to the driver, so the driver can be matched successfully. + struct pit_device final : kapi::devices::device, arch::bus::isa_identification { - explicit legacy_pit(std::uint32_t frequency_in_hz); + pit_device(); + // TODO: remove auto init() -> bool override; + //! Get the synthetic ISA identifier for this device. + //! + //! @return the string "pit" + [[nodiscard]] auto isa_name() const -> std::string_view override; + + protected: + auto query_interface(kapi::devices::interface interface) -> void * override; + }; + + //! The driver for the legacy, ISA-connected Programmable Interrupt Timer. + struct pit_driver final : kapi::devices::driver, arch::bus::isa_driver_identification, kapi::interrupts::handler + { + explicit pit_driver(std::uint32_t frequency_in_hz); + + [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result<void> override; + + auto unbind(kapi::devices::device & device) -> void override; + + [[nodiscard]] auto supported_names() const -> std::span<std::string_view const> override; + auto handle_interrupt(std::uint32_t irq_number) -> kapi::interrupts::status override; + protected: + auto query_interface(kapi::devices::interface interface) -> void * override; + private: - std::uint32_t m_irq_number{}; + struct driver_data + { + std::uint32_t irq_number{}; + std::uint32_t frequency_in_hz{}; + std::uint64_t ticks{}; + }; + std::uint32_t m_frequency_in_hz{}; - std::uint64_t m_ticks{}; }; } // namespace arch::devices |
