diff options
Diffstat (limited to 'kapi')
| -rw-r--r-- | kapi/include/kapi/devices.hpp | 36 | ||||
| -rw-r--r-- | kapi/include/kapi/devices/bus.hpp | 95 | ||||
| -rw-r--r-- | kapi/include/kapi/devices/manager.hpp | 53 |
3 files changed, 184 insertions, 0 deletions
diff --git a/kapi/include/kapi/devices.hpp b/kapi/include/kapi/devices.hpp new file mode 100644 index 0000000..5c01b2f --- /dev/null +++ b/kapi/include/kapi/devices.hpp @@ -0,0 +1,36 @@ +#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 "kapi/devices/manager.hpp" // IWYU pragma: export + +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 &; + + //! @} + + //! @addtogroup platform-defined + //! @{ + + //! Initialize the platform's device tree. + auto init_platform_devices() -> void; + + //! @} + +} // namespace kapi::devices + +#endif
\ No newline at end of file diff --git a/kapi/include/kapi/devices/bus.hpp b/kapi/include/kapi/devices/bus.hpp new file mode 100644 index 0000000..ee774b7 --- /dev/null +++ b/kapi/include/kapi/devices/bus.hpp @@ -0,0 +1,95 @@ +#ifndef TEACHOS_KAPI_DEVICES_BUS_HPP +#define TEACHOS_KAPI_DEVICES_BUS_HPP + +#include "kapi/devices/device.hpp" +#include "kapi/devices/manager.hpp" +#include "kapi/system.hpp" + +#include <kstd/memory> +#include <kstd/print> +#include <kstd/string> +#include <kstd/vector> + +#include <algorithm> +#include <atomic> +#include <cstddef> +#include <utility> + +namespace kapi::devices +{ + //! A bus device that represents a logical/physical tree of devices and busses. + struct bus : device + { + //! Construct a bus with the given major number, minor number, and name. + //! + //! @param major The major number of the bus. + //! @param minor The minor number of the bus. + //! @param name The name of the bus. + bus(std::size_t major, std::size_t minor, kstd::string const & name) + : device(major, minor, name) + {} + + //! Initialize the bus and all of its children. + //! + //! @return true iff. the bus and all of its children are healthy, false otherwise. + auto init() -> bool final + { + if (m_initialized.test_and_set()) + { + return true; + } + + if (!probe()) + { + return false; + } + + return std::ranges::fold_left(m_devices, true, [&](bool acc, auto & child) -> bool { + kstd::println("[kAPI:BUS] Initializing child device {}@{}", child->name(), name()); + return child->init() && acc; + }); + } + + //! Attach a child device to this bus. + //! + //! Whenever a device is attached to a bus, the bus takes sole ownership of the device. + //! + //! @param child The child device to attach. + auto add_child(kstd::unique_ptr<device> child) -> void + { + auto observer = m_observers.emplace_back(child.get()); + m_devices.push_back(std::move(child)); + kapi::devices::register_device(*observer); + + if (m_initialized.test()) + { + kstd::println("[kAPI:BUS] Initializing child device {}@{}", observer->name(), name()); + if (!observer->init()) + { + kapi::system::panic("[kAPI:BUS] Failed to initialize child device"); + } + } + } + + [[nodiscard]] auto children() const -> kstd::vector<kstd::observer_ptr<device>> const & + { + return m_observers; + } + + protected: + //! Probe the bus hardware state. + //! + //! @return true iff. the bus hardware is healthy, false otherwise. + auto virtual probe() -> bool + { + return true; + } + + private: + kstd::vector<kstd::unique_ptr<device>> m_devices; + kstd::vector<kstd::observer_ptr<device>> m_observers; + std::atomic_flag m_initialized{}; + }; +} // namespace kapi::devices + +#endif
\ No newline at end of file diff --git a/kapi/include/kapi/devices/manager.hpp b/kapi/include/kapi/devices/manager.hpp new file mode 100644 index 0000000..7817fbc --- /dev/null +++ b/kapi/include/kapi/devices/manager.hpp @@ -0,0 +1,53 @@ +#ifndef TEACHOS_KAPI_DEVICES_MANAGER_HPP +#define TEACHOS_KAPI_DEVICES_MANAGER_HPP + +// IWYU pragma: private, include "kapi/devices.hpp" + +#include "kapi/devices/device.hpp" + +#include <kstd/memory> + +#include <cstddef> +#include <string_view> + +namespace kapi::devices +{ + + //! @addtogroup kernel-defined + //! @{ + + //! 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; + + //! Find a device by its major and minor numbers. + //! + //! @param major the major number of the device. + //! @param minor the minor number of the device. + //! @return a pointer to the device iff. the device was found, nullptr otherwise. + auto find_device(std::size_t major, std::size_t minor) -> kstd::observer_ptr<device>; + + //! Find a device by its name. + //! + //! @param name the name of the device. + //! @return a pointer to the device iff. the device was found, nullptr otherwise. + auto find_device(std::string_view name) -> kstd::observer_ptr<device>; + + //! @} + +} // namespace kapi::devices + +#endif
\ No newline at end of file |
