aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-23 21:09:34 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-23 21:46:16 +0200
commitfbc31c3e385363f9eaba93238756a739e09ce873 (patch)
tree05343a458fb1e40df5babb46bca4a217fe6d1503 /kernel/kapi
parentcb87b4dd8e874d5d7b219487ca38f55756c205df (diff)
downloadkernel-fbc31c3e385363f9eaba93238756a739e09ce873.tar.xz
kernel-fbc31c3e385363f9eaba93238756a739e09ce873.zip
kapi: add driver registry
Diffstat (limited to 'kernel/kapi')
-rw-r--r--kernel/kapi/devices.cpp19
-rw-r--r--kernel/kapi/devices/bus.cpp5
-rw-r--r--kernel/kapi/devices/device.cpp29
-rw-r--r--kernel/kapi/devices/driver_registry.cpp135
4 files changed, 186 insertions, 2 deletions
diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp
index 8f3011fe..5eed1b87 100644
--- a/kernel/kapi/devices.cpp
+++ b/kernel/kapi/devices.cpp
@@ -2,6 +2,7 @@
#include <kernel/devices/root_bus.hpp>
+#include <kapi/devices/driver_registry.hpp>
#include <kapi/system.hpp>
#include <kapi/test_support/devices.hpp>
@@ -9,6 +10,7 @@
#include <kstd/memory.hpp>
#include <kstd/print.hpp>
#include <kstd/string.hpp>
+#include <kstd/vector.hpp>
#include <string_view>
#include <utility>
@@ -29,6 +31,7 @@ namespace kapi::devices
}
interface_registry::init();
+ driver_registry::init();
root_bus = kstd::make_shared<kernel::devices::root_bus>();
register_device(root_bus);
@@ -85,6 +88,21 @@ namespace kapi::devices
return found->second.lock();
}
+ auto all() -> kstd::vector<kstd::shared_ptr<device>>
+ {
+ auto result = kstd::vector<kstd::shared_ptr<device>>{};
+
+ for (auto const & [name, weak_device] : device_tree)
+ {
+ if (auto device = weak_device.lock())
+ {
+ result.push_back(std::move(device));
+ }
+ }
+
+ return result;
+ }
+
} // namespace kapi::devices
namespace kapi::test_support::devices
@@ -92,6 +110,7 @@ namespace kapi::test_support::devices
auto deinit() -> void
{
deinit_interface_registry();
+ deinit_driver_registry();
kapi::devices::root_bus.reset();
}
diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp
index 179a04a8..6c659ef5 100644
--- a/kernel/kapi/devices/bus.cpp
+++ b/kernel/kapi/devices/bus.cpp
@@ -68,6 +68,11 @@ namespace kapi::devices
return {m_devices.data(), m_devices.size()};
}
+ auto bus::protocol() -> struct bus_protocol *
+ {
+ return nullptr;
+ }
+
auto bus::enumerate() -> bool
{
return true;
diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp
index 540d37b7..cbbd5405 100644
--- a/kernel/kapi/devices/device.cpp
+++ b/kernel/kapi/devices/device.cpp
@@ -22,9 +22,29 @@ namespace kapi::devices
return m_parent.lock();
}
- auto device::set_parent(kstd::weak_ptr<bus> parent) -> void
+ auto device::state() const noexcept -> enum state
{
- m_parent = parent;
+ return m_state;
+ }
+
+ auto device::set_state(enum state state) -> void
+ {
+ m_state = state;
+ }
+
+ auto device::bind_driver(kstd::weak_ptr<struct driver> driver) -> void
+ {
+ m_driver = driver;
+ }
+
+ auto device::driver_data() const -> kstd::shared_ptr<void> const &
+ {
+ return m_driver_data;
+ }
+
+ auto device::set_driver_data(kstd::shared_ptr<void> data) -> void
+ {
+ m_driver_data = data;
}
auto device::query_interface(interface) -> void *
@@ -32,4 +52,9 @@ namespace kapi::devices
return nullptr;
}
+ auto device::set_parent(kstd::weak_ptr<bus> parent) -> void
+ {
+ m_parent = parent;
+ }
+
} // namespace kapi::devices \ No newline at end of file
diff --git a/kernel/kapi/devices/driver_registry.cpp b/kernel/kapi/devices/driver_registry.cpp
new file mode 100644
index 00000000..67da9877
--- /dev/null
+++ b/kernel/kapi/devices/driver_registry.cpp
@@ -0,0 +1,135 @@
+#include <kapi/devices/driver_registry.hpp>
+
+#include <kapi/devices/bus.hpp>
+#include <kapi/devices/bus_protocol.hpp>
+#include <kapi/devices/device.hpp>
+#include <kapi/devices/driver.hpp>
+#include <kapi/devices/manager.hpp>
+#include <kapi/system.hpp>
+#include <kapi/test_support/devices.hpp>
+
+#include <kstd/memory.hpp>
+#include <kstd/print.hpp>
+#include <kstd/system_error.hpp>
+#include <kstd/vector.hpp>
+
+#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <optional>
+#include <utility>
+
+namespace kapi::devices
+{
+
+ namespace
+ {
+ constinit auto static registry = std::optional<driver_registry>{};
+
+ struct candidate
+ {
+ std::uint32_t priority;
+ kstd::shared_ptr<driver> driver_handle;
+ };
+ } // namespace
+
+ auto driver_registry::init() -> void
+ {
+ if (registry.has_value())
+ {
+ system::panic("[kernel] Device driver registry has already been initialized.");
+ }
+
+ registry.emplace();
+ }
+
+ auto driver_registry::get() -> driver_registry &
+ {
+ if (!registry)
+ {
+ system::panic("[kernel] Device driver registry has not been initialized.");
+ }
+
+ return *registry;
+ }
+
+ auto driver_registry::add(kstd::shared_ptr<driver> driver) -> void
+ {
+ m_drivers.emplace_back(std::move(driver));
+
+ for (auto const & device : kapi::devices::all())
+ {
+ if (device->state() != state::bound)
+ {
+ try_bind(device);
+ }
+ }
+ }
+
+ auto driver_registry::device_attached(kstd::shared_ptr<device> const & device) -> void
+ {
+ try_bind(device);
+ }
+
+ auto driver_registry::try_bind(kstd::shared_ptr<device> const & device) -> void
+ {
+ if (!device || device->state() == state::bound)
+ {
+ return;
+ }
+
+ auto parent = device->parent();
+ auto protocol = parent ? parent->protocol() : nullptr;
+ if (!protocol)
+ {
+ return;
+ }
+
+ auto candidates = kstd::vector<candidate>{};
+
+ for (auto const & driver : m_drivers)
+ {
+ auto match = protocol->match(*device, *driver);
+ if (match)
+ {
+ candidates.push_back({.priority = *match, .driver_handle = driver});
+ }
+ else if (match.error() != kstd::errc::not_supported)
+ {
+ kstd::println(kstd::print_sink::stderr, "[OS:DRV] match() failed for device {}: {}", device->name(),
+ match.error().message());
+ }
+ }
+
+ std::ranges::stable_sort(candidates, std::ranges::greater{}, &candidate::priority);
+
+ for (auto const & candidate : candidates)
+ {
+ auto probed = candidate.driver_handle->probe(*device);
+ if (probed)
+ {
+ device->bind_driver(candidate.driver_handle);
+ device->set_state(state::bound);
+ kstd::println("[OS:DRV] Bound device {} (priority {})", device->name(), candidate.priority);
+ return;
+ }
+
+ kstd::println(kstd::print_sink::stderr, "[OS:DRV] probe() failed for device {} (priority {}): {}", device->name(),
+ candidate.priority, probed.error().message());
+ }
+
+ if (!candidates.empty())
+ {
+ device->set_state(state::failed);
+ }
+ }
+
+} // namespace kapi::devices
+
+namespace kapi::test_support::devices
+{
+ auto deinit_driver_registry() -> void
+ {
+ kapi::devices::registry.reset();
+ }
+} // namespace kapi::test_support::devices \ No newline at end of file