aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-07-24 01:12:48 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-07-24 01:12:48 +0200
commite6d79751cd37f2cbe0d4bd721e59a4ca0d072a55 (patch)
tree922f713c9dc45274dd4c32484584ff17a2dfdaa0
parent7d241968ff4feb83bc23636df3a7ddb80f4bb4a9 (diff)
downloadkernel-e6d79751cd37f2cbe0d4bd721e59a4ca0d072a55.tar.xz
kernel-e6d79751cd37f2cbe0d4bd721e59a4ca0d072a55.zip
kapi: let drivers choose their major number
-rw-r--r--kapi/kapi/devices/device.hpp4
-rw-r--r--kapi/kapi/devices/driver.hpp3
-rw-r--r--kapi/kapi/devices/interface_registry.hpp4
-rw-r--r--kernel/kapi/devices/device.cpp5
-rw-r--r--kernel/kapi/devices/interface_registry.cpp10
-rw-r--r--kernel/kapi/devices/interface_registry.tests.cpp4
-rw-r--r--kernel/kernel/devices/storage.cpp2
-rw-r--r--kernel/kernel/filesystem/device_number_registry.cpp61
-rw-r--r--kernel/kernel/filesystem/file_type_bindings.hpp10
9 files changed, 78 insertions, 25 deletions
diff --git a/kapi/kapi/devices/device.hpp b/kapi/kapi/devices/device.hpp
index 70c5bd15..c26a4701 100644
--- a/kapi/kapi/devices/device.hpp
+++ b/kapi/kapi/devices/device.hpp
@@ -3,6 +3,7 @@
// IWYU pragma: private, include <kapi/devices.hpp>
+#include <kapi/devices/driver.hpp>
#include <kapi/devices/interface.hpp>
#include <kstd/memory.hpp>
@@ -74,6 +75,9 @@ namespace kapi::devices
//! Set the lifecycle state of this device.
auto set_state(enum state state) -> void;
+ //! Get the driver, if any, currently bound to this device.
+ [[nodiscard]] auto bound_driver() const noexcept -> driver *;
+
//! Bind this device to the given driver.
auto bind_driver(kstd::weak_ptr<struct driver> driver) -> void;
diff --git a/kapi/kapi/devices/driver.hpp b/kapi/kapi/devices/driver.hpp
index 254f7977..837b47e4 100644
--- a/kapi/kapi/devices/driver.hpp
+++ b/kapi/kapi/devices/driver.hpp
@@ -3,7 +3,6 @@
// IWYU pragma: private, include <kapi/devices.hpp>
-#include <kapi/devices/device.hpp>
#include <kapi/devices/interface.hpp>
#include <kstd/result.hpp>
@@ -17,6 +16,8 @@ namespace kapi::devices
//! @addtogroup kapi-devices-kernel-defined
//! @{
+ struct device;
+
//! The base type for all device drivers.
//!
//! Drivers model the behavior necessary to drive a device or bus. They are stateless logic and are thus never
diff --git a/kapi/kapi/devices/interface_registry.hpp b/kapi/kapi/devices/interface_registry.hpp
index 9fad91e6..ae8b5c1a 100644
--- a/kapi/kapi/devices/interface_registry.hpp
+++ b/kapi/kapi/devices/interface_registry.hpp
@@ -30,9 +30,9 @@ namespace kapi::devices
, m_implementation{implementation}
{}
- [[nodiscard]] constexpr auto device() const noexcept -> kstd::weak_ptr<device>
+ [[nodiscard]] constexpr auto device() const noexcept -> kstd::shared_ptr<device>
{
- return m_device;
+ return m_device.lock();
}
[[nodiscard]] constexpr auto name() const noexcept -> kstd::string const &
diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp
index cbbd5405..4c63f6a4 100644
--- a/kernel/kapi/devices/device.cpp
+++ b/kernel/kapi/devices/device.cpp
@@ -32,6 +32,11 @@ namespace kapi::devices
m_state = state;
}
+ auto device::bound_driver() const noexcept -> driver *
+ {
+ return m_driver.lock().get();
+ }
+
auto device::bind_driver(kstd::weak_ptr<struct driver> driver) -> void
{
m_driver = driver;
diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp
index 8882e8db..da3d080a 100644
--- a/kernel/kapi/devices/interface_registry.cpp
+++ b/kernel/kapi/devices/interface_registry.cpp
@@ -46,7 +46,7 @@ namespace kapi::devices
auto interface_registry::do_publish(kstd::shared_ptr<device> device, kstd::string name, interface interface,
void * implementation) -> kstd::result<void>
{
- erase_if(m_entries, [interface](auto e) { return e.interface() == interface && e.device().expired(); });
+ erase_if(m_entries, [interface](auto e) { return e.interface() == interface && !e.device(); });
if (!device || !implementation || name.empty())
{
@@ -54,7 +54,7 @@ namespace kapi::devices
}
auto published = std::ranges::any_of(m_entries, [&](auto const & entry) {
- return entry.interface() == interface && entry.device().lock().get() == device.get();
+ return entry.interface() == interface && entry.device().get() == device.get();
});
if (published)
@@ -70,7 +70,7 @@ namespace kapi::devices
auto interface_registry::unpublish(device const & device, interface interface) -> void
{
erase_if(m_entries, [&](auto e) {
- auto locked_device = e.device().lock();
+ auto locked_device = e.device();
return e.interface() == interface && locked_device && locked_device.get() == &device;
});
}
@@ -79,7 +79,7 @@ namespace kapi::devices
{
auto filtered = m_entries;
erase_if(filtered, [&](auto e) {
- auto locked_device = e.device().lock();
+ auto locked_device = e.device();
return !(e.interface() == interface && locked_device);
});
return filtered;
@@ -88,7 +88,7 @@ namespace kapi::devices
auto interface_registry::find(interface interface, std::string_view name) const -> kstd::result<entry>
{
auto found = std::ranges::find_if(
- m_entries, [&](auto e) { return e.interface() == interface && e.name() == name && e.device().lock(); });
+ m_entries, [&](auto e) { return e.interface() == interface && e.name() == name && e.device(); });
if (found == m_entries.cend())
{
return kstd::failure(make_error_code(kstd::errc::no_such_device));
diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/interface_registry.tests.cpp
index 78cd7ecf..100954ea 100644
--- a/kernel/kapi/devices/interface_registry.tests.cpp
+++ b/kernel/kapi/devices/interface_registry.tests.cpp
@@ -114,9 +114,9 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
REQUIRE(probeable_devices[0].name() == "probe0");
}
- THEN("the returned device pointer is lockable")
+ THEN("the returned device pointer is valid")
{
- REQUIRE(probeable_devices[0].device().lock());
+ REQUIRE(probeable_devices[0].device());
}
THEN("the returned implementation equals the result of device::as")
diff --git a/kernel/kernel/devices/storage.cpp b/kernel/kernel/devices/storage.cpp
index d5508270..cfdf3ec2 100644
--- a/kernel/kernel/devices/storage.cpp
+++ b/kernel/kernel/devices/storage.cpp
@@ -29,6 +29,6 @@ namespace kernel::devices::storage
return nullptr;
}
- return block_devices.front().device().lock();
+ return block_devices.front().device();
}
} // namespace kernel::devices::storage \ No newline at end of file
diff --git a/kernel/kernel/filesystem/device_number_registry.cpp b/kernel/kernel/filesystem/device_number_registry.cpp
index 430da00a..058ae322 100644
--- a/kernel/kernel/filesystem/device_number_registry.cpp
+++ b/kernel/kernel/filesystem/device_number_registry.cpp
@@ -12,13 +12,21 @@
#include <kstd/vector.hpp>
#include <algorithm>
+#include <cstdint>
#include <optional>
#include <ranges>
namespace
{
constinit auto static instance = std::optional<kernel::filesystem::device_number_registry>{};
-}
+
+ struct driver_group
+ {
+ kapi::devices::driver const * bound_driver;
+ std::uint8_t major;
+ kstd::vector<kapi::devices::interface_registry::entry> published;
+ };
+} // namespace
namespace kernel::filesystem
{
@@ -88,17 +96,54 @@ namespace kernel::filesystem
for (auto const & binding : file_type_bindings)
{
- auto next_minor = decltype(kapi::filesystem::device_number::minor){};
+ auto groups = kstd::vector<driver_group>{};
for (auto const & published : m_interface_registry->all(binding.interface))
{
- if (auto device = published.device().lock())
+ auto device = published.device();
+ if (!device)
+ {
+ continue;
+ }
+
+ auto bound_driver = device->bound_driver();
+ if (!bound_driver)
+ {
+ continue;
+ }
+
+ auto claimed = bound_driver->claimed_major();
+ if (!claimed)
+ {
+ continue;
+ }
+
+ auto found_group =
+ std::ranges::find_if(groups, [&](auto const & group) { return group.bound_driver == bound_driver; });
+
+ if (found_group == groups.end())
+ {
+ groups.push_back({.bound_driver = bound_driver, .major = *claimed, .published = {}});
+ found_group = groups.end() - 1;
+ }
+
+ found_group->published.push_back(published);
+ }
+
+ for (auto const & group : groups)
+ {
+ auto next_minor = decltype(kapi::filesystem::device_number::minor){};
+
+ for (auto const & published : group.published)
{
- m_entries.emplace_back(kapi::filesystem::device_number{.major = binding.major, .minor = next_minor}, //
- binding.posix_type, //
- published.name(), //
- published.device());
- ++next_minor;
+ if (auto device = published.device())
+ {
+ m_entries.emplace_back(kapi::filesystem::device_number{.major = group.major, .minor = next_minor}, //
+ binding.posix_type, //
+ published.name(), //
+ published.device());
+ ++next_minor;
+ }
}
}
}
diff --git a/kernel/kernel/filesystem/file_type_bindings.hpp b/kernel/kernel/filesystem/file_type_bindings.hpp
index e33d5086..94f6a763 100644
--- a/kernel/kernel/filesystem/file_type_bindings.hpp
+++ b/kernel/kernel/filesystem/file_type_bindings.hpp
@@ -7,24 +7,22 @@
#include <kapi/devices.hpp>
#include <array>
-#include <cstdint>
namespace kernel::filesystem
{
- //! A binding between an interface, a posix special file type, and a major number.
+ //! A binding between an interface, a posix special file type
struct file_type_binding // NOLINT(cppcoreguidelines-pro-type-member-init)
{
kapi::devices::interface interface;
file_type posix_type;
- std::uint8_t major;
};
- //! Predefined bindings for interface + file type + major number.
+ //! Predefined bindings for interface + file type
//!
- //! This array associates reserved major numbers with file types and interfaces.
+ //! This array associates published interfaces with files types.
constexpr auto inline file_type_bindings = std::array{
- file_type_binding{kapi::devices::block_device::id, file_type::block, block_major_numbers::ram_disk},
+ file_type_binding{kapi::devices::block_device::id, file_type::block},
};
} // namespace kernel::filesystem