aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-23 22:34:49 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-23 22:34:49 +0200
commit7d78433e6ea80b651f80201b6c5beef799887e7f (patch)
tree09135131ee0833f99ce9b5126ea9fe4d31be1ceb
parent4a58a7c7cb1f37e0183de9b838def3a217504e7b (diff)
downloadkernel-7d78433e6ea80b651f80201b6c5beef799887e7f.tar.xz
kernel-7d78433e6ea80b651f80201b6c5beef799887e7f.zip
x86_64: port legacy PIT driver to new architecture
-rw-r--r--arch/x86_64/arch/bus/isa.cpp29
-rw-r--r--arch/x86_64/arch/bus/isa.hpp35
-rw-r--r--arch/x86_64/arch/devices/init.cpp10
-rw-r--r--arch/x86_64/arch/devices/legacy_pit.cpp85
-rw-r--r--arch/x86_64/arch/devices/legacy_pit.hpp48
-rw-r--r--kapi/kapi/devices/bus.hpp2
-rw-r--r--kapi/kapi/devices/driver.hpp10
-rw-r--r--kernel/kapi/devices/bus.cpp4
-rw-r--r--kernel/kernel/devices/storage/ram_disk/controller.cpp2
-rw-r--r--kernel/kernel/devices/storage/ram_disk/controller.hpp2
10 files changed, 199 insertions, 28 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
diff --git a/kapi/kapi/devices/bus.hpp b/kapi/kapi/devices/bus.hpp
index 0e654072..10b9c39d 100644
--- a/kapi/kapi/devices/bus.hpp
+++ b/kapi/kapi/devices/bus.hpp
@@ -50,7 +50,7 @@ namespace kapi::devices
//! Enumerate the devices on the bus.
//!
//! @return true iff. the bus hardware is healthy, false otherwise.
- auto virtual enumerate() -> bool;
+ auto virtual enumerate_old() -> bool;
private:
kstd::vector<kstd::shared_ptr<device>> m_devices;
diff --git a/kapi/kapi/devices/driver.hpp b/kapi/kapi/devices/driver.hpp
index fde5068c..254f7977 100644
--- a/kapi/kapi/devices/driver.hpp
+++ b/kapi/kapi/devices/driver.hpp
@@ -54,6 +54,16 @@ namespace kapi::devices
return static_cast<InterfaceType *>(query_interface(InterfaceType::id));
}
+ //! Retrieve this drivers implementation of a given capability interface.
+ //!
+ //! @return A pointer to this drivers implementation of the requested interface, nullptr if this driver does not
+ //! support the requested interface.
+ template<typename InterfaceType>
+ [[nodiscard]] auto as() const -> InterfaceType const *
+ {
+ return static_cast<InterfaceType *>(const_cast<driver *>(this)->query_interface(InterfaceType::id));
+ }
+
//! Check if this driver implements a given capability interface.
//!
//! @return true iff. this driver implements the requested capability interface, false otherwise.
diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp
index a63782c3..25e35733 100644
--- a/kernel/kapi/devices/bus.cpp
+++ b/kernel/kapi/devices/bus.cpp
@@ -27,7 +27,7 @@ namespace kapi::devices
return true;
}
- if (!enumerate())
+ if (!enumerate_old())
{
kstd::println(kstd::print_sink::stderr, "[OS:DEV] Bus {} enumeration failed", name());
return false;
@@ -77,7 +77,7 @@ namespace kapi::devices
return nullptr;
}
- auto bus::enumerate() -> bool
+ auto bus::enumerate_old() -> bool
{
return true;
}
diff --git a/kernel/kernel/devices/storage/ram_disk/controller.cpp b/kernel/kernel/devices/storage/ram_disk/controller.cpp
index 07ff702d..7550860e 100644
--- a/kernel/kernel/devices/storage/ram_disk/controller.cpp
+++ b/kernel/kernel/devices/storage/ram_disk/controller.cpp
@@ -17,7 +17,7 @@ namespace kernel::devices::storage::ram_disk
, m_boot_module_registry(registry)
{}
- auto controller::enumerate() -> bool
+ auto controller::enumerate_old() -> bool
{
size_t current_device_index = 0;
diff --git a/kernel/kernel/devices/storage/ram_disk/controller.hpp b/kernel/kernel/devices/storage/ram_disk/controller.hpp
index b245dc1f..165fbdbd 100644
--- a/kernel/kernel/devices/storage/ram_disk/controller.hpp
+++ b/kernel/kernel/devices/storage/ram_disk/controller.hpp
@@ -21,7 +21,7 @@ namespace kernel::devices::storage::ram_disk
/**
* @brief Probe boot modules and create RAM-disk devices.
*/
- auto enumerate() -> bool override;
+ auto enumerate_old() -> bool override;
private:
kapi::boot_modules::boot_module_registry const * m_boot_module_registry;