aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kapi/include/kapi/devices.hpp46
-rw-r--r--kernel/CMakeLists.txt2
-rw-r--r--kernel/include/kernel/devices/root_bus.hpp32
-rw-r--r--kernel/kapi/devices.cpp63
-rw-r--r--kernel/src/devices/root_bus.cpp55
-rw-r--r--kernel/src/main.cpp4
-rw-r--r--libs/kstd/include/kstd/bits/observer_ptr.hpp6
7 files changed, 208 insertions, 0 deletions
diff --git a/kapi/include/kapi/devices.hpp b/kapi/include/kapi/devices.hpp
new file mode 100644
index 0000000..60a39bd
--- /dev/null
+++ b/kapi/include/kapi/devices.hpp
@@ -0,0 +1,46 @@
+#ifndef TEACHOS_KAPI_DEVICES_HPP
+#define TEACHOS_KAPI_DEVICES_HPP
+
+#include "kapi/devices/bus.hpp" // IWYU pragma: export
+#include "kapi/devices/device.hpp" // IWYU pragma: export
+
+#include <cstddef>
+
+namespace kapi::devices
+{
+
+ //! @addtogroup kernel-defined
+ //! @{
+
+ //! Initialize the kernel's device management subsystem.
+ auto init() -> void;
+
+ //! Get the virtual system root bus.
+ //!
+ //! @warning This function will panic if the root bus has not been initialized.
+ //!
+ //! @return a reference to the root bus.
+ auto get_root_bus() -> bus &;
+
+ //! Ask the kernel to allocate a new major number.
+ //!
+ //! @return a new, unused major number.
+ auto allocate_major_number() -> std::size_t;
+
+ //! Register a new device with the kernel's device manager.
+ //!
+ //! @param device The device to register.
+ //! @return true if the device was registered successfully, false otherwise.
+ auto register_device(device & device) -> bool;
+
+ //! Unregister a device from the kernel's device manager.
+ //!
+ //! @param device The device to unregister.
+ //! @return true if the device was unregistered successfully, false otherwise.
+ auto unregister_device(device & device) -> bool;
+
+ //! @}
+
+} // namespace kapi::devices
+
+#endif \ No newline at end of file
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index f283588..9868eb9 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -3,6 +3,7 @@ add_library("kernel_objs" OBJECT
"kapi/boot_modules.cpp"
"kapi/cio.cpp"
"kapi/cpu.cpp"
+ "kapi/devices.cpp"
"kapi/interrupts.cpp"
"kapi/memory.cpp"
"kapi/system.cpp"
@@ -17,6 +18,7 @@ add_library("kernel_objs" OBJECT
"src/memory.cpp"
"src/devices/block_device.cpp"
"src/devices/block_device_utils.cpp"
+ "src/devices/root_bus.cpp"
"src/devices/storage/controller.cpp"
"src/devices/storage/management.cpp"
"src/devices/storage/ram_disk/controller.cpp"
diff --git a/kernel/include/kernel/devices/root_bus.hpp b/kernel/include/kernel/devices/root_bus.hpp
new file mode 100644
index 0000000..f7bfbfb
--- /dev/null
+++ b/kernel/include/kernel/devices/root_bus.hpp
@@ -0,0 +1,32 @@
+#ifndef TEACHOS_KERNEL_DEVICES_ROOT_BUS_HPP
+#define TEACHOS_KERNEL_DEVICES_ROOT_BUS_HPP
+
+#include "kapi/devices/bus.hpp"
+#include "kapi/devices/device.hpp"
+
+#include <kstd/memory>
+#include <kstd/print>
+#include <kstd/vector>
+
+namespace kernel::devices
+{
+
+ struct root_bus final : kapi::devices::bus
+ {
+ root_bus();
+
+ auto add_child(kstd::unique_ptr<device> child) -> void override;
+
+ [[nodiscard]] auto children() const -> kstd::vector<kstd::observer_ptr<device>> const & override;
+
+ auto init() -> bool override;
+
+ private:
+ kstd::vector<kstd::unique_ptr<device>> m_children{};
+ kstd::vector<kstd::observer_ptr<device>> m_observers{};
+ bool m_initialized{};
+ };
+
+} // namespace kernel::devices
+
+#endif \ No newline at end of file
diff --git a/kernel/kapi/devices.cpp b/kernel/kapi/devices.cpp
new file mode 100644
index 0000000..dc19ab4
--- /dev/null
+++ b/kernel/kapi/devices.cpp
@@ -0,0 +1,63 @@
+#include "kapi/devices.hpp"
+
+#include "kapi/system.hpp"
+
+#include "kernel/devices/root_bus.hpp"
+
+#include <kstd/flat_map>
+#include <kstd/memory>
+#include <kstd/print>
+
+#include <atomic>
+#include <cstddef>
+#include <optional>
+#include <utility>
+
+namespace kapi::devices
+{
+
+ namespace
+ {
+ auto constinit next_major_number = std::atomic_size_t{0};
+ auto constinit root_bus = std::optional<kernel::devices::root_bus>{};
+ auto constinit device_tree = kstd::flat_map<std::pair<std::size_t, std::size_t>, kstd::observer_ptr<device>>{};
+ } // namespace
+
+ auto init() -> void
+ {
+ auto static is_initialized = std::atomic_flag{};
+ if (is_initialized.test_and_set())
+ {
+ return;
+ }
+
+ root_bus.emplace();
+ root_bus->init();
+ }
+
+ auto get_root_bus() -> bus &
+ {
+ if (!root_bus.has_value())
+ {
+ kapi::system::panic("[kernel:devices] Root bus not initialized!");
+ }
+ return *root_bus;
+ }
+
+ auto allocate_major_number() -> std::size_t
+ {
+ return next_major_number++;
+ }
+
+ auto register_device(device & device) -> bool
+ {
+ return device_tree.emplace(std::pair{device.major(), device.minor()}, &device).second;
+ }
+
+ auto unregister_device(device &) -> bool
+ {
+ kstd::println("[kernel:devices] TODO: implement device deregistration");
+ return false;
+ }
+
+} // namespace kapi::devices \ No newline at end of file
diff --git a/kernel/src/devices/root_bus.cpp b/kernel/src/devices/root_bus.cpp
new file mode 100644
index 0000000..a7f3c1a
--- /dev/null
+++ b/kernel/src/devices/root_bus.cpp
@@ -0,0 +1,55 @@
+#include "kernel/devices/root_bus.hpp"
+
+#include "kapi/devices.hpp"
+#include "kapi/devices/bus.hpp"
+#include "kapi/devices/device.hpp"
+#include "kapi/system.hpp"
+
+#include <kstd/memory>
+#include <kstd/print>
+#include <kstd/vector>
+
+#include <algorithm>
+#include <utility>
+
+namespace kernel::devices
+{
+
+ root_bus::root_bus()
+ : kapi::devices::bus{kapi::devices::allocate_major_number(), 0, "system"}
+ {}
+
+ auto root_bus::add_child(kstd::unique_ptr<device> child) -> void
+ {
+ auto observer = m_observers.emplace_back(child.get());
+ m_children.push_back(std::move(child));
+
+ if (m_initialized)
+ {
+ kstd::println("Initializing child device '{}'", observer->name());
+ if (!observer->init())
+ {
+ kapi::system::panic("[kernel:devices] Failed to initialize child device");
+ }
+ }
+ }
+
+ auto root_bus::children() const -> kstd::vector<kstd::observer_ptr<device>> const &
+ {
+ return m_observers;
+ }
+
+ auto root_bus::init() -> bool
+ {
+ if (m_initialized)
+ {
+ kapi::system::panic("[kernel:devices] Root bus already initialized!");
+ }
+
+ return std::ranges::fold_left(m_children, true, [](bool acc, auto & child) -> bool {
+ kstd::println("[kernel:devices] Initializing child device '{}'", child->name());
+ return acc && child->init();
+ });
+ }
+
+} // namespace kernel::devices \ No newline at end of file
diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp
index 37b4c5b..9d6028d 100644
--- a/kernel/src/main.cpp
+++ b/kernel/src/main.cpp
@@ -1,6 +1,7 @@
#include "kapi/boot_modules.hpp"
#include "kapi/cio.hpp"
#include "kapi/cpu.hpp"
+#include "kapi/devices.hpp"
#include "kapi/interrupts.hpp"
#include "kapi/memory.hpp"
#include "kapi/system.hpp"
@@ -179,6 +180,9 @@ auto main() -> int
kstd::println("[OS] Memory subsystem initialized.");
kapi::system::memory_initialized();
+ kapi::devices::init();
+ kstd::println("[OS] System root bus initialized.");
+
kapi::boot_modules::init();
kstd::println("[OS] Boot module registry initialized.");
diff --git a/libs/kstd/include/kstd/bits/observer_ptr.hpp b/libs/kstd/include/kstd/bits/observer_ptr.hpp
index 43ea409..1c5da15 100644
--- a/libs/kstd/include/kstd/bits/observer_ptr.hpp
+++ b/libs/kstd/include/kstd/bits/observer_ptr.hpp
@@ -44,6 +44,12 @@ namespace kstd
//! Move construct an observer pointer.
constexpr observer_ptr(observer_ptr && other) noexcept = default;
+ //! Copy assign an observer pointer.
+ constexpr auto operator=(observer_ptr const & other) noexcept -> observer_ptr & = default;
+
+ //! Move assign an observer pointer.
+ constexpr auto operator=(observer_ptr && other) noexcept -> observer_ptr & = default;
+
//! Stop watching the the watched object.
//!
//! @return The currently watched object, or nullptr if no object is being watched.