summaryrefslogtreecommitdiff
path: root/kernel/include
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/include')
-rw-r--r--kernel/include/kernel/console_driver.h58
-rw-r--r--kernel/include/kernel/device.h52
-rw-r--r--kernel/include/kernel/driver.h46
-rw-r--r--kernel/include/kernel/driver_list.h34
-rw-r--r--kernel/include/kernel/early_device.h35
-rw-r--r--kernel/include/kernel/early_driver.h40
-rw-r--r--kernel/include/kernel/placement_new.h4
-rw-r--r--kernel/include/kernel/platform_bus.h22
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