diff options
Diffstat (limited to 'kernel/include')
| -rw-r--r-- | kernel/include/kernel/console_driver.h | 58 | ||||
| -rw-r--r-- | kernel/include/kernel/device.h | 52 | ||||
| -rw-r--r-- | kernel/include/kernel/driver.h | 46 | ||||
| -rw-r--r-- | kernel/include/kernel/driver_list.h | 34 | ||||
| -rw-r--r-- | kernel/include/kernel/early_device.h | 35 | ||||
| -rw-r--r-- | kernel/include/kernel/early_driver.h | 40 | ||||
| -rw-r--r-- | kernel/include/kernel/placement_new.h | 4 | ||||
| -rw-r--r-- | kernel/include/kernel/platform_bus.h | 22 |
8 files changed, 291 insertions, 0 deletions
diff --git a/kernel/include/kernel/console_driver.h b/kernel/include/kernel/console_driver.h new file mode 100644 index 0000000..f34c4e0 --- /dev/null +++ b/kernel/include/kernel/console_driver.h @@ -0,0 +1,58 @@ +#pragma once + +// ============================================================================ +// kernel/console_driver.h — Console driver category + registry +// +// ConsoleDriver is the category base for all text output devices +// (framebuffer, UART, etc.). The console:: namespace provides the global +// registry and active-console tracking. +// ============================================================================ + +#include <stdint.h> +#include <stddef.h> +#include <kernel/driver.h> +#include <kernel/driver_list.h> + +struct FramebufferInfo; // forward declaration (defined in boot/boot_info.h) + +class ConsoleDriver : public Driver { +public: + // Write a single character (handles newline, cursor, scrolling). + virtual void putchar(char c) = 0; + + // Write a buffer of characters. Default: loops over putchar(). + virtual void write(const char* s, size_t len); + + // Clear the screen / output buffer. + virtual void clear() = 0; +}; + +namespace console { + +// Register a console driver in the global list. +void register_driver(ConsoleDriver* driver); + +// Set the active console (the one kcon:: delegates to). +void set_active(ConsoleDriver* driver); + +// Get the current active console (nullptr before any console is initialized). +ConsoleDriver* active(); + +// Get the driver list for enumeration. +DriverList<ConsoleDriver>& drivers(); + +// ── Per-driver init functions (guarded by config) ───────────────────────── + +#ifdef CONFIG_DRIVER_FBCON +void init_framebuffer(const FramebufferInfo& fb); +#endif + +#ifdef CONFIG_DRIVER_UART_16550 +void init_uart_16550(uint16_t port = 0x3F8); +#endif + +#ifdef CONFIG_DRIVER_PL011_UART +void init_pl011(uintptr_t base_addr = 0x09000000); +#endif + +} // namespace console diff --git a/kernel/include/kernel/device.h b/kernel/include/kernel/device.h new file mode 100644 index 0000000..222ff9e --- /dev/null +++ b/kernel/include/kernel/device.h @@ -0,0 +1,52 @@ +#pragma once + +// ============================================================================ +// kernel/device.h — Device and Bus base classes +// +// A Device represents a piece of hardware. Devices form a tree via +// intrusive parent-child pointers (no heap needed). Each Device can be +// bound to a Driver that knows how to operate it. +// +// A Bus is a Device that can have child devices. It serves as a grouping +// point for device enumeration and driver matching (future: PCI, DT). +// ============================================================================ + +#include <stdint.h> + +class Driver; + +class Device { +public: + virtual ~Device() = default; + + virtual const char* name() const = 0; + + // ── Hierarchy ───────────────────────────────────────────────────────── + Device* parent() const { return parent_; } + Device* first_child() const { return first_child_; } + Device* next_sibling() const { return next_sibling_; } + + void add_child(Device* child) { + child->parent_ = this; + child->next_sibling_ = first_child_; + first_child_ = child; + } + + // ── Driver binding ──────────────────────────────────────────────────── + Driver* driver() const { return driver_; } + void set_driver(Driver* drv) { driver_ = drv; } + +protected: + Device* parent_ = nullptr; + Device* first_child_ = nullptr; + Device* next_sibling_ = nullptr; + Driver* driver_ = nullptr; +}; + +// ── Bus — a Device that groups child devices ────────────────────────────── +// Future: enumerate() discovers children, match() pairs devices with drivers. + +class Bus : public Device { +public: + void add_device(Device* dev) { add_child(dev); } +}; diff --git a/kernel/include/kernel/driver.h b/kernel/include/kernel/driver.h new file mode 100644 index 0000000..564590b --- /dev/null +++ b/kernel/include/kernel/driver.h @@ -0,0 +1,46 @@ +#pragma once + +// ============================================================================ +// kernel/driver.h - Base driver class +// +// Abstract root of the driver hierarchy. Every driver inherits from this. +// Registration uses an intrusive singly-linked list (next_ pointer). +// A driver can be bound to a Device via bind(). +// ============================================================================ + +#include <stdint.h> +#include <kernel/device.h> + +template <typename T> +class DriverList; + +class Driver { +public: + virtual ~Driver() = default; + + // Human-readable name, e.g. "framebuffer-console", "uart-16550" + virtual const char* name() const = 0; + + // Initialize driver hardware/state. Returns true on success. + // Called after bind() — device() is available for reading hw info. + virtual bool init() = 0; + + // Shut down driver (release resources, disable hardware). + virtual void shutdown() = 0; + + // ── Device binding ──────────────────────────────────────────────────── + // Links this driver to a device. Sets bidirectional pointers. + void bind(Device* dev) { + device_ = dev; + dev->set_driver(this); + } + + Device* device() const { return device_; } + +protected: + Driver* next_ = nullptr; + Device* device_ = nullptr; + + template <typename T> + friend class DriverList; +}; diff --git a/kernel/include/kernel/driver_list.h b/kernel/include/kernel/driver_list.h new file mode 100644 index 0000000..1ba9ab2 --- /dev/null +++ b/kernel/include/kernel/driver_list.h @@ -0,0 +1,34 @@ +#pragma once + +// ============================================================================ +// kernel/driver_list.h — Typed intrusive singly-linked list for drivers +// +// Each driver category (console, block, etc.) maintains its own DriverList. +// Insertion is O(1) prepend. No heap allocation — the list node is the +// driver's own next_ pointer inherited from Driver. +// ============================================================================ + +#include <kernel/driver.h> + +template <typename T> +class DriverList { +public: + // Prepend a driver to the list. + void add(T* driver) { + driver->next_ = head_; + head_ = driver; + } + + // Iterate all drivers. fn(T*) returns true to stop early. + template <typename Fn> + void for_each(Fn fn) const { + for (auto* d = head_; d != nullptr; d = static_cast<T*>(d->next_)) { + if (fn(d)) return; + } + } + + T* head() const { return head_; } + +private: + T* head_ = nullptr; +}; diff --git a/kernel/include/kernel/early_device.h b/kernel/include/kernel/early_device.h new file mode 100644 index 0000000..5ddec7b --- /dev/null +++ b/kernel/include/kernel/early_device.h @@ -0,0 +1,35 @@ +#pragma once + +// ============================================================================ +// kernel/early_device.h — CRTP mixin for pre-heap device allocation +// +// Same pattern as EarlyDriver<T>, but for Device subclasses. Provides +// static storage for exactly one instance of the derived device type. +// +// Usage: +// class MyDevice : public Device, public EarlyDevice<MyDevice> { }; +// auto* dev = MyDevice::create(args...); +// MyDevice::instance(); +// ============================================================================ + +#include <stdint.h> +#include <stddef.h> +#include <kernel/placement_new.h> + +template <typename Derived> +class EarlyDevice { +public: + template <typename... Args> + static Derived* create(Args&&... args) { + alignas(Derived) static char storage[sizeof(Derived)]; + instance_ = new (storage) Derived(static_cast<Args&&>(args)...); + return instance_; + } + + static Derived* instance() { + return instance_; + } + +private: + static inline Derived* instance_ = nullptr; +}; diff --git a/kernel/include/kernel/early_driver.h b/kernel/include/kernel/early_driver.h new file mode 100644 index 0000000..ff1b3b9 --- /dev/null +++ b/kernel/include/kernel/early_driver.h @@ -0,0 +1,40 @@ +#pragma once + +// ============================================================================ +// kernel/early_driver.h — CRTP mixin for pre-heap driver allocation +// +// Early drivers (framebuffer console, serial UART) must work before kmalloc +// exists. This template provides static storage for exactly one instance of +// the derived driver, constructed via placement new. +// +// Usage: +// class MyDriver : public SomeCategory, public EarlyDriver<MyDriver> { }; +// auto* drv = MyDriver::create(args...); // placement new into BSS +// MyDriver::instance(); // get the singleton +// ============================================================================ + +#include <stdint.h> +#include <stddef.h> +#include <kernel/placement_new.h> + +template <typename Derived> +class EarlyDriver { +public: + // Construct the driver in static storage. Call exactly once. + // sizeof(Derived) is evaluated here, not at class definition time, + // so Derived is guaranteed to be complete. + template <typename... Args> + static Derived* create(Args&&... args) { + alignas(Derived) static char storage[sizeof(Derived)]; + instance_ = new (storage) Derived(static_cast<Args&&>(args)...); + return instance_; + } + + // Returns the instance, or nullptr if create() hasn't been called. + static Derived* instance() { + return instance_; + } + +private: + static inline Derived* instance_ = nullptr; +}; diff --git a/kernel/include/kernel/placement_new.h b/kernel/include/kernel/placement_new.h new file mode 100644 index 0000000..6f7f1f3 --- /dev/null +++ b/kernel/include/kernel/placement_new.h @@ -0,0 +1,4 @@ +#pragma once + +// Placement new for freestanding C++ (no <new> header available). +inline void* operator new(size_t, void* ptr) noexcept { return ptr; } diff --git a/kernel/include/kernel/platform_bus.h b/kernel/include/kernel/platform_bus.h new file mode 100644 index 0000000..8561ca6 --- /dev/null +++ b/kernel/include/kernel/platform_bus.h @@ -0,0 +1,22 @@ +#pragma once + +// ============================================================================ +// kernel/platform_bus.h — Platform bus for fixed-address devices +// +// The PlatformBus is the root of the device hierarchy. Non-discoverable +// devices (framebuffer, UART at fixed addresses) are registered here. +// Future buses (PCI, device-tree) will be added as siblings or children. +// ============================================================================ + +#include <kernel/device.h> +#include <kernel/early_device.h> + +class PlatformBus : public Bus, public EarlyDevice<PlatformBus> { +public: + const char* name() const override { return "platform"; } +}; + +// Lazy-initialized singleton accessor for the platform bus. +namespace platform { + Bus& bus(); +} // namespace platform |
