diff options
Diffstat (limited to 'kernel/drivers')
| -rw-r--r-- | kernel/drivers/char/pl011.cpp | 83 | ||||
| -rw-r--r-- | kernel/drivers/char/uart_16550.cpp | 85 | ||||
| -rw-r--r-- | kernel/drivers/console/framebuffer.cpp | 328 | ||||
| -rw-r--r-- | kernel/drivers/driver_registry.cpp | 55 |
4 files changed, 551 insertions, 0 deletions
diff --git a/kernel/drivers/char/pl011.cpp b/kernel/drivers/char/pl011.cpp new file mode 100644 index 0000000..7615370 --- /dev/null +++ b/kernel/drivers/char/pl011.cpp @@ -0,0 +1,83 @@ +// ============================================================================ +// drivers/char/pl011.cpp — PL011 UART console driver + device (aarch64) +// +// Stub implementation that compiles but does no real I/O yet. +// TODO: Program IBRD, FBRD, LCR_H, CR registers for actual UART output. +// ============================================================================ + +#include <kernel/console_driver.h> +#include <kernel/early_driver.h> +#include <kernel/early_device.h> +#include <kernel/platform_bus.h> + +// ── PL011Device ─────────────────────────────────────────────────────────── + +class PL011Device : public Device, public EarlyDevice<PL011Device> { +public: + explicit PL011Device(uintptr_t base_addr) : base_(base_addr) {} + + const char* name() const override { return "uart0"; } + uintptr_t base() const { return base_; } + +private: + uintptr_t base_; +}; + +// ── PL011Console driver ────────────────────────────────────────────────── + +class PL011Console : public ConsoleDriver, + public EarlyDriver<PL011Console> { +public: + PL011Console() = default; + + const char* name() const override { return "pl011-uart"; } + + bool init() override { + auto* dev = static_cast<PL011Device*>(device()); + base_ = dev->base(); + + // TODO: Configure UART registers at base_: + // UARTIBRD (offset 0x24) — integer baud rate divisor + // UARTFBRD (offset 0x28) — fractional baud rate divisor + // UARTLCR_H (offset 0x2C) — line control (8N1, FIFO enable) + // UARTCR (offset 0x30) — control register (TX enable, UART enable) + initialized_ = true; + return true; + } + + void shutdown() override { + initialized_ = false; + } + + void putchar(char c) override { + if (!initialized_) return; + // TODO: while (*(volatile uint32_t*)(base_ + 0x18) & (1 << 5)) {} + // *(volatile uint32_t*)(base_ + 0x00) = c; + (void)c; + } + + void clear() override { + // UART has no screen to clear + } + +private: + uintptr_t base_ = 0; + bool initialized_ = false; +}; + +// ── Driver init function ────────────────────────────────────────────────── + +namespace console { + +void init_pl011(uintptr_t base_addr) { + auto* dev = PL011Device::create(base_addr); + platform::bus().add_device(dev); + + auto* drv = PL011Console::create(); + drv->bind(dev); + drv->init(); + + console::register_driver(drv); +} + +} // namespace console diff --git a/kernel/drivers/char/uart_16550.cpp b/kernel/drivers/char/uart_16550.cpp new file mode 100644 index 0000000..a85b5e7 --- /dev/null +++ b/kernel/drivers/char/uart_16550.cpp @@ -0,0 +1,85 @@ +// ============================================================================ +// drivers/char/uart_16550.cpp — 16550 UART console driver + device (x86_64) +// +// Stub implementation that compiles but does no real I/O yet. +// TODO: Program divisor latch, 8N1, FIFO, implement actual port I/O. +// ============================================================================ + +#include <kernel/console_driver.h> +#include <kernel/early_driver.h> +#include <kernel/early_device.h> +#include <kernel/platform_bus.h> + +// ── UART16550Device ─────────────────────────────────────────────────────── + +class UART16550Device : public Device, public EarlyDevice<UART16550Device> { +public: + explicit UART16550Device(uint16_t port) : port_(port) {} + + const char* name() const override { return "uart0"; } + uint16_t port() const { return port_; } + +private: + uint16_t port_; +}; + +// ── UART16550Console driver ─────────────────────────────────────────────── + +class UART16550Console : public ConsoleDriver, + public EarlyDriver<UART16550Console> { +public: + UART16550Console() = default; + + const char* name() const override { return "uart-16550"; } + + bool init() override { + auto* dev = static_cast<UART16550Device*>(device()); + port_ = dev->port(); + + // TODO: outb(port_ + 1, 0x00) — disable interrupts + // TODO: outb(port_ + 3, 0x80) — enable DLAB + // TODO: outb(port_ + 0, 0x03) — set divisor (lo) 38400 baud + // TODO: outb(port_ + 1, 0x00) — set divisor (hi) + // TODO: outb(port_ + 3, 0x03) — 8 bits, no parity, one stop + // TODO: outb(port_ + 2, 0xC7) — enable FIFO, clear, 14-byte threshold + // TODO: outb(port_ + 4, 0x0B) — IRQs enabled, RTS/DSR set + initialized_ = true; + return true; + } + + void shutdown() override { + initialized_ = false; + } + + void putchar(char c) override { + if (!initialized_) return; + // TODO: while (!(inb(port_ + 5) & 0x20)) {} — wait for THR empty + // TODO: outb(port_, c) + (void)c; + } + + void clear() override { + // UART has no screen to clear + } + +private: + uint16_t port_ = 0; + bool initialized_ = false; +}; + +// ── Driver init function ────────────────────────────────────────────────── + +namespace console { + +void init_uart_16550(uint16_t port) { + auto* dev = UART16550Device::create(port); + platform::bus().add_device(dev); + + auto* drv = UART16550Console::create(); + drv->bind(dev); + drv->init(); + + console::register_driver(drv); +} + +} // namespace console diff --git a/kernel/drivers/console/framebuffer.cpp b/kernel/drivers/console/framebuffer.cpp new file mode 100644 index 0000000..e7f0577 --- /dev/null +++ b/kernel/drivers/console/framebuffer.cpp @@ -0,0 +1,328 @@ +// ============================================================================ +// drivers/console/framebuffer.cpp — Framebuffer console driver + device +// +// FramebufferDevice describes the GOP framebuffer hardware (base address, +// resolution, pixel format). FramebufferConsole is the driver that renders +// text to it using a built-in 8x16 VGA bitmap font. +// +// Both are early-allocated (static storage, no heap). +// ============================================================================ + +#include <kernel/console_driver.h> +#include <kernel/early_driver.h> +#include <kernel/early_device.h> +#include <kernel/platform_bus.h> +#include <boot/boot_info.h> + +// ── Minimal 8x16 bitmap font (ASCII 32-126) ────────────────────────────── + +static constexpr int FONT_FIRST = 32; +static constexpr int FONT_LAST = 126; + +// clang-format off +static const uint8_t g_font[][16] = { + // 32: space + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 33: ! + {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 34: " + {0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 35: # + {0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, + // 36: $ + {0x00,0x10,0x10,0x7C,0xD6,0xD0,0x7C,0x16,0xD6,0x7C,0x10,0x10,0x00,0x00,0x00,0x00}, + // 37: % + {0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00}, + // 38: & + {0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + // 39: ' + {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 40: ( + {0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00}, + // 41: ) + {0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00}, + // 42: * + {0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00}, + // 43: + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00}, + // 44: , + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00}, + // 45: - + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 46: . + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 47: / + {0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00}, + // 48-57: 0-9 + {0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xDE,0xF6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00}, + // 58: : + {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, + // 59: ; + {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00}, + // 60: < + {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, + // 61: = + {0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 62: > + {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, + // 63: ? + {0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, + // 64: @ + {0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0xC0,0x7C,0x00,0x00,0x00,0x00}, + // 65-90: A-Z + {0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00}, + {0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00}, + // 91: [ + {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, + // 92: backslash + {0x00,0x00,0x00,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00,0x00,0x00}, + // 93: ] + {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, + // 94: ^ + {0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 95: _ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, + // 96: ` + {0x00,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + // 97-122: a-z + {0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, + {0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}, + {0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00}, + // 123: { + {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, + // 124: | + {0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, + // 125: } + {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, + // 126: ~ + {0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +}; +// clang-format on + +// ── FramebufferDevice ───────────────────────────────────────────────────── + +class FramebufferDevice : public Device, public EarlyDevice<FramebufferDevice> { +public: + explicit FramebufferDevice(const FramebufferInfo& fb) + : base_(fb.base), width_(fb.width), height_(fb.height) + , pitch_(fb.pitch), format_(fb.format) + {} + + const char* name() const override { return "framebuffer0"; } + + uint64_t base() const { return base_; } + uint32_t width() const { return width_; } + uint32_t height() const { return height_; } + uint32_t pitch() const { return pitch_; } + PixelFormat format() const { return format_; } + +private: + uint64_t base_; + uint32_t width_; + uint32_t height_; + uint32_t pitch_; + PixelFormat format_; +}; + +// ── FramebufferConsole driver ───────────────────────────────────────────── + +class FramebufferConsole : public ConsoleDriver, + public EarlyDriver<FramebufferConsole> { +public: + FramebufferConsole() = default; + + const char* name() const override { return "framebuffer-console"; } + + bool init() override { + auto* dev = static_cast<FramebufferDevice*>(device()); + fb_ = reinterpret_cast<uint32_t*>(dev->base()); + width_ = dev->width(); + height_ = dev->height(); + pitch_ = dev->pitch(); + is_bgr_ = (dev->format() == PixelFormat::BGR); + clear(); + return true; + } + + void shutdown() override {} + + void putchar(char c) override { + uint32_t max_cols = width_ / CHAR_W; + uint32_t max_rows = height_ / CHAR_H; + + if (c == '\n') { + col_ = 0; + row_++; + } else if (c == '\r') { + col_ = 0; + } else if (c == '\t') { + col_ = (col_ + 4) & ~3u; + } else { + render_char(col_, row_, c); + col_++; + } + + if (col_ >= max_cols) { + col_ = 0; + row_++; + } + + if (row_ >= max_rows) { + scroll(); + row_ = max_rows - 1; + } + } + + void clear() override { + for (uint32_t y = 0; y < height_; y++) { + for (uint32_t x = 0; x < width_; x++) { + put_pixel(x, y, BG_COLOR); + } + } + col_ = 0; + row_ = 0; + } + +private: + uint32_t* fb_ = nullptr; + uint32_t width_ = 0; + uint32_t height_ = 0; + uint32_t pitch_ = 0; + bool is_bgr_ = false; + uint32_t col_ = 0; + uint32_t row_ = 0; + + static constexpr uint32_t CHAR_W = 8; + static constexpr uint32_t CHAR_H = 16; + static constexpr uint32_t FG_COLOR = CONFIG_FBCON_FG_COLOR; + static constexpr uint32_t BG_COLOR = CONFIG_FBCON_BG_COLOR; + + void put_pixel(uint32_t x, uint32_t y, uint32_t rgb) { + if (x >= width_ || y >= height_) return; + + uint32_t color; + if (is_bgr_) { + color = ((rgb & 0xFF) << 16) | (rgb & 0xFF00) | ((rgb >> 16) & 0xFF); + } else { + color = rgb; + } + + auto* row = reinterpret_cast<uint32_t*>( + reinterpret_cast<uint8_t*>(fb_) + y * pitch_); + row[x] = color; + } + + void scroll() { + uint32_t row_bytes = pitch_; + uint32_t shift = CHAR_H * row_bytes; + uint32_t total = height_ * row_bytes; + + auto* fb = reinterpret_cast<uint8_t*>(fb_); + + for (uint32_t i = 0; i < total - shift; i++) { + fb[i] = fb[i + shift]; + } + for (uint32_t i = total - shift; i < total; i++) { + fb[i] = 0; + } + uint32_t start_y = height_ - CHAR_H; + for (uint32_t y = start_y; y < height_; y++) { + for (uint32_t x = 0; x < width_; x++) { + put_pixel(x, y, BG_COLOR); + } + } + } + + void render_char(uint32_t col, uint32_t row, char c) { + int idx = static_cast<int>(c) - FONT_FIRST; + if (idx < 0 || idx > (FONT_LAST - FONT_FIRST)) idx = 0; + + uint32_t px = col * CHAR_W; + uint32_t py = row * CHAR_H; + + for (uint32_t y = 0; y < CHAR_H; y++) { + uint8_t bits = g_font[idx][y]; + for (uint32_t x = 0; x < CHAR_W; x++) { + uint32_t color = (bits & (0x80 >> x)) ? FG_COLOR : BG_COLOR; + put_pixel(px + x, py + y, color); + } + } + } +}; + +// ── Driver init function ────────────────────────────────────────────────── + +namespace console { + +void init_framebuffer(const FramebufferInfo& fb) { + // Create device on the platform bus + auto* dev = FramebufferDevice::create(fb); + platform::bus().add_device(dev); + + // Create driver and bind to device + auto* drv = FramebufferConsole::create(); + drv->bind(dev); + drv->init(); + + // Register as active console + console::register_driver(drv); + console::set_active(drv); +} + +} // namespace console diff --git a/kernel/drivers/driver_registry.cpp b/kernel/drivers/driver_registry.cpp new file mode 100644 index 0000000..43b2b5a --- /dev/null +++ b/kernel/drivers/driver_registry.cpp @@ -0,0 +1,55 @@ +// ============================================================================ +// drivers/driver_registry.cpp — Driver/device registry globals +// +// Provides storage for per-category driver lists, the active console +// pointer, and the platform bus singleton. Always compiled. +// ============================================================================ + +#include <kernel/console_driver.h> +#include <kernel/platform_bus.h> + +// ── ConsoleDriver default write implementation ──────────────────────────── + +void ConsoleDriver::write(const char* s, size_t len) { + for (size_t i = 0; i < len; ++i) { + putchar(s[i]); + } +} + +// ── Console registry ────────────────────────────────────────────────────── + +static DriverList<ConsoleDriver> g_console_drivers; +static ConsoleDriver* g_active_console = nullptr; + +namespace console { + +void register_driver(ConsoleDriver* driver) { + g_console_drivers.add(driver); +} + +void set_active(ConsoleDriver* driver) { + g_active_console = driver; +} + +ConsoleDriver* active() { + return g_active_console; +} + +DriverList<ConsoleDriver>& drivers() { + return g_console_drivers; +} + +} // namespace console + +// ── Platform bus (lazy singleton) ───────────────────────────────────────── + +namespace platform { + +Bus& bus() { + if (!PlatformBus::instance()) { + PlatformBus::create(); + } + return *PlatformBus::instance(); +} + +} // namespace platform |
