summaryrefslogtreecommitdiff
path: root/na/drivers/base
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:31:46 +0800
commite90b72ec3082588b296956730bd2930cf8d5d671 (patch)
tree36ff6916af9b4176ea5a9662219d11e721f0b691 /na/drivers/base
parent1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (diff)
downloadlume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.gz
lume-e90b72ec3082588b296956730bd2930cf8d5d671.tar.xz
refactor: promote new architecture to repository root
Archive the deprecated implementation under lume-legacy, make the new kernel the default root-level build, and update repository entry points without changing kernel behavior.
Diffstat (limited to 'na/drivers/base')
-rw-r--r--na/drivers/base/bus.cc32
-rw-r--r--na/drivers/base/core.cc156
-rw-r--r--na/drivers/base/driver.cc72
-rw-r--r--na/drivers/base/module.mk9
-rw-r--r--na/drivers/base/platform.cc231
5 files changed, 0 insertions, 500 deletions
diff --git a/na/drivers/base/bus.cc b/na/drivers/base/bus.cc
deleted file mode 100644
index 975f676..0000000
--- a/na/drivers/base/bus.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * drivers/base/bus.cc — bus_type registration.
- *
- * Mirrors Linux drivers/base/bus.c. Trivial in this iteration:
- * initialize the device/driver lists and the per-bus spinlock.
- *
- * Reference: docs/specs/storage_stack.md §4.3
- */
-
-#include <lume/device.h>
-#include <lume/klog.h>
-#include <lume/kprintf.h>
-#include <lume/errno.h>
-
-int bus_register(bus_type* bus)
-{
- if (bus == nullptr || bus->name == nullptr) {
- return -EINVAL;
- }
- if (bus->registered) {
- return 0;
- }
- bus->devices.init();
- bus->drivers.init();
- bus->lock.init(bus->name);
- bus->registered = true;
- kprintf("[bus] '%s' registered\n", bus->name);
- return 0;
-}
diff --git a/na/drivers/base/core.cc b/na/drivers/base/core.cc
deleted file mode 100644
index f92b2a4..0000000
--- a/na/drivers/base/core.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * drivers/base/core.cc — device core.
- *
- * Mirrors Linux drivers/base/core.c (greatly simplified). Provides
- * device_initialize, device_register, device_unregister, and the
- * try_bind helper shared with driver registration.
- *
- * Reference: docs/specs/storage_stack.md §4.3
- */
-
-#include <lume/device.h>
-#include <lume/container_of.h>
-#include <lume/klog.h>
-#include <lume/kprintf.h>
-#include <lume/errno.h>
-#include <lume/list.h>
-
-/* ------------------------------------------------------------------ */
-/* device ktype — generic release (no-op; subclasses override) */
-/* ------------------------------------------------------------------ */
-
-static void device_release(kobject* kobj)
-{
- /* Concrete device flavors (platform_device, virtio_device, ...) are
- * expected to allocate via kmalloc and free in their own release
- * paths after device_unregister + final kobject_put. The generic
- * device kobj_type only fires for stack-allocated devices used in
- * tests — nothing to do. */
- (void)kobj;
-}
-
-static const kobj_type device_ktype = {
- .release = device_release,
-};
-
-/* ------------------------------------------------------------------ */
-/* device_initialize / device_register */
-/* ------------------------------------------------------------------ */
-
-void device_initialize(device* dev)
-{
- if (dev == nullptr) {
- return;
- }
- kobject_init(&dev->kobj, &device_ktype);
- dev->parent = nullptr;
- dev->driver = nullptr;
- dev->driver_data = nullptr;
- dev->platform_data = nullptr;
- dev->devt = 0;
- dev->bus_list.init();
- dev->driver_list.init();
-}
-
-const char* dev_name(const device* dev)
-{
- if (dev == nullptr) {
- return "(null)";
- }
- if (dev->kobj.name != nullptr) {
- return dev->kobj.name;
- }
- if (dev->init_name != nullptr) {
- return dev->init_name;
- }
- return "(unnamed)";
-}
-
-/* try_bind: attempt to match `dev` against `drv` and probe.
- * Returns 1 on successful bind, 0 otherwise.
- * Caller must hold bus->lock. */
-int device_try_bind(device* dev, device_driver* drv);
-
-int device_try_bind(device* dev, device_driver* drv)
-{
- bus_type* bus = dev->bus;
-
- if (bus->match != nullptr && bus->match(dev, drv) == 0) {
- return 0;
- }
-
- dev->driver = drv;
-
- int rc = 0;
- if (bus->probe != nullptr) {
- rc = bus->probe(dev);
- } else if (drv->probe != nullptr) {
- rc = drv->probe(dev);
- }
-
- if (rc == 0) {
- list_add_tail(&dev->driver_list, &drv->devices);
- return 1;
- }
- dev->driver = nullptr;
- return 0;
-}
-
-int device_register(device* dev)
-{
- if (dev == nullptr || dev->bus == nullptr) {
- return -EINVAL;
- }
- if (!dev->bus->registered) {
- kprintf("[device] register '%s' fail: bus '%s' not registered\n",
- dev_name(dev),
- dev->bus->name != nullptr ? dev->bus->name : "?");
- return -ENODEV;
- }
-
- /* device_initialize is idempotent — safe to call again, but most
- * paths will already have initialized. Detect via ktype set. */
- if (dev->kobj.ktype == nullptr) {
- device_initialize(dev);
- }
- if (dev->kobj.name == nullptr) {
- kobject_add(&dev->kobj, nullptr, dev->init_name);
- }
- dev->bus_list.init();
- dev->driver_list.init();
-
- LockGuard g(dev->bus->lock);
- list_add_tail(&dev->bus_list, &dev->bus->devices);
-
- list_node* cur = dev->bus->drivers.next;
- while (cur != &dev->bus->drivers) {
- device_driver* drv =
- list_entry<device_driver, &device_driver::bus_node>(cur);
- cur = cur->next;
- if (device_try_bind(dev, drv) != 0) {
- break;
- }
- }
- return 0;
-}
-
-void device_unregister(device* dev)
-{
- if (dev == nullptr || dev->bus == nullptr) {
- return;
- }
-
- LockGuard g(dev->bus->lock);
-
- if (dev->driver != nullptr) {
- if (dev->driver->remove != nullptr) {
- dev->driver->remove(dev);
- }
- list_del_init(&dev->driver_list);
- dev->driver = nullptr;
- }
- list_del_init(&dev->bus_list);
-}
diff --git a/na/drivers/base/driver.cc b/na/drivers/base/driver.cc
deleted file mode 100644
index ce15b6d..0000000
--- a/na/drivers/base/driver.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * drivers/base/driver.cc — driver_register / driver_unregister.
- *
- * Mirrors Linux drivers/base/driver.c. Registers a device_driver on
- * its bus and tries to bind any unbound matching devices.
- *
- * Reference: docs/specs/storage_stack.md §4.3
- */
-
-#include <lume/device.h>
-#include <lume/container_of.h>
-#include <lume/klog.h>
-#include <lume/kprintf.h>
-#include <lume/errno.h>
-
-/* Implemented in core.cc — bind a device to a driver on its bus.
- * Returns 1 on success, 0 on no-match-or-probe-fail. */
-int device_try_bind(device* dev, device_driver* drv);
-
-int driver_register(device_driver* drv)
-{
- if (drv == nullptr || drv->bus == nullptr) {
- return -EINVAL;
- }
- if (!drv->bus->registered) {
- kprintf("[driver] register '%s' fail: bus '%s' not registered\n",
- drv->name != nullptr ? drv->name : "?",
- drv->bus->name != nullptr ? drv->bus->name : "?");
- return -ENODEV;
- }
-
- drv->bus_node.init();
- drv->devices.init();
-
- LockGuard g(drv->bus->lock);
- list_add_tail(&drv->bus_node, &drv->bus->drivers);
-
- /* Try to bind any unbound devices already on the bus. */
- list_node* cur = drv->bus->devices.next;
- while (cur != &drv->bus->devices) {
- device* dev = list_entry<device, &device::bus_list>(cur);
- cur = cur->next;
- if (dev->driver == nullptr) {
- device_try_bind(dev, drv);
- }
- }
- return 0;
-}
-
-void driver_unregister(device_driver* drv)
-{
- if (drv == nullptr || drv->bus == nullptr) {
- return;
- }
-
- LockGuard g(drv->bus->lock);
-
- /* Unbind every device bound to this driver. */
- while (!drv->devices.is_empty()) {
- list_node* first = drv->devices.next;
- device* dev = list_entry<device, &device::driver_list>(first);
- if (drv->remove != nullptr) {
- drv->remove(dev);
- }
- list_del_init(&dev->driver_list);
- dev->driver = nullptr;
- }
- list_del_init(&drv->bus_node);
-}
diff --git a/na/drivers/base/module.mk b/na/drivers/base/module.mk
deleted file mode 100644
index 1d8fb05..0000000
--- a/na/drivers/base/module.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (C) 2026 Richard Qin
-#
-# Driver model core (mirrors Linux drivers/base/)
-
-SRCS_CC += drivers/base/bus.cc
-SRCS_CC += drivers/base/core.cc
-SRCS_CC += drivers/base/driver.cc
-SRCS_CC += drivers/base/platform.cc
diff --git a/na/drivers/base/platform.cc b/na/drivers/base/platform.cc
deleted file mode 100644
index 65ec21e..0000000
--- a/na/drivers/base/platform.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (C) 2026 Richard Qin */
-
-/*
- * drivers/base/platform.cc — platform bus + FDT-driven device creation.
- *
- * Mirrors Linux drivers/base/platform.c. Provides:
- * - platform_bus — the bus_type instance
- * - platform_match — compatible-string matching via of_match_table
- * - platform_dispatch — bus->probe forwarder that down-casts and calls
- * platform_driver::probe(platform_device*)
- * - driver_probe_all() — boot entry: register bus, register linker-set
- * drivers, walk FDT, register platform_devices
- *
- * Reference: docs/specs/storage_stack.md §4.3
- */
-
-#include <lume/platform_device.h>
-#include <lume/driver.h>
-#include <lume/device_node.h>
-#include <lume/fdt.h>
-#include <string.h>
-
-/* kmalloc is declared extern "C" in <lume/slab.h>, but mm/slab.cc defines
- * it WITHOUT extern "C" (i.e. C++-mangled). Declare locally with C++
- * linkage so the symbol matches what mm/slab.o exports. */
-void* kmalloc(uint32 size);
-#include <lume/klog.h>
-#include <lume/kprintf.h>
-#include <lume/errno.h>
-#include <lume/container_of.h>
-
-/* ------------------------------------------------------------------ */
-/* Linker-section registry */
-/* ------------------------------------------------------------------ */
-
-extern "C" {
- extern platform_driver* __drivers_start[];
- extern platform_driver* __drivers_end[];
-}
-
-/* ------------------------------------------------------------------ */
-/* platform_bus_type */
-/* ------------------------------------------------------------------ */
-
-static int platform_match(device* dev, device_driver* drv)
-{
- platform_device* pdev = to_platform_device(dev);
- platform_driver* pdrv = to_platform_driver(drv);
-
- if (pdrv->of_match_table == nullptr || pdev->of_node == nullptr) {
- return 0;
- }
- const char* node_compat = pdev->of_node->get_prop_string("compatible");
- if (node_compat == nullptr) {
- return 0;
- }
- for (const of_device_id* id = pdrv->of_match_table;
- id->compatible != nullptr; ++id) {
- if (strcmp(id->compatible, node_compat) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-static int platform_dispatch(device* dev)
-{
- platform_device* pdev = to_platform_device(dev);
- platform_driver* pdrv = to_platform_driver(dev->driver);
- if (pdrv->probe == nullptr) {
- return 0;
- }
- return pdrv->probe(pdev);
-}
-
-bus_type platform_bus = {
- .name = "platform",
- .match = platform_match,
- .probe = platform_dispatch,
- .devices = {},
- .drivers = {},
- .lock = {},
- .registered = false,
-};
-
-void platform_bus_init()
-{
- bus_register(&platform_bus);
-}
-
-/* ------------------------------------------------------------------ */
-/* platform_driver_register / platform_device_register */
-/* ------------------------------------------------------------------ */
-
-int platform_driver_register(platform_driver* pdrv)
-{
- if (pdrv == nullptr) {
- return -EINVAL;
- }
- pdrv->driver.bus = &platform_bus;
- /* driver.probe is unused — we route through bus->probe. Set name
- * from the first of_match if not already provided. */
- if (pdrv->driver.name == nullptr && pdrv->of_match_table != nullptr) {
- pdrv->driver.name = pdrv->of_match_table[0].compatible;
- }
- return driver_register(&pdrv->driver);
-}
-
-int platform_device_register(platform_device* pdev)
-{
- if (pdev == nullptr) {
- return -EINVAL;
- }
- pdev->dev.bus = &platform_bus;
- if (pdev->dev.init_name == nullptr && pdev->of_node != nullptr) {
- pdev->dev.init_name = pdev->of_node->get_prop_string("compatible");
- }
- device_initialize(&pdev->dev);
- return device_register(&pdev->dev);
-}
-
-/* ------------------------------------------------------------------ */
-/* FDT-driven device instantiation */
-/* ------------------------------------------------------------------ */
-
-static platform_device* alloc_platform_device_from_node(DeviceNode* node,
- const char* compat)
-{
- auto* pdev = static_cast<platform_device*>(
- kmalloc(static_cast<uint32>(sizeof(platform_device))));
- if (pdev == nullptr) {
- return nullptr;
- }
- memset(pdev, 0, sizeof(*pdev));
- pdev->of_node = node;
- pdev->mmio_base = node->get_prop_u64("reg", 0);
- /* "reg" second cell is size — for now we don't bother parsing it
- * separately; drivers that need it pull from of_node directly. */
- pdev->mmio_size = 0;
- pdev->irq = -1;
- pdev->dev.init_name = compat;
- return pdev;
-}
-
-/* For each registered platform_driver, walk its of_match_table and
- * spawn a platform_device for each FDT compatible match found.
- *
- * NOTE: This is a simplified FDT walker — it only finds the FIRST FDT
- * node matching each compatible string (delegating to
- * fdt_find_compatible). Devices with multiple FDT instances of the
- * same compatible will only see one bound here. A full FDT tree walk
- * is left for when virtio-mmio or multi-instance UART arrives.
- */
-static void instantiate_devices_for_driver(platform_driver* pdrv)
-{
- if (pdrv == nullptr || pdrv->of_match_table == nullptr) {
- return;
- }
- for (const of_device_id* id = pdrv->of_match_table;
- id->compatible != nullptr; ++id) {
- DeviceNode* node = fdt_find_compatible(id->compatible);
- if (node == nullptr) {
- continue;
- }
- platform_device* pdev =
- alloc_platform_device_from_node(node, id->compatible);
- if (pdev == nullptr) {
- kprintf("[platform] OOM allocating pdev for %s\n", id->compatible);
- continue;
- }
- kprintf("[platform] instantiating '%s' -> pdev mmio=0x%llx\n",
- id->compatible, pdev->mmio_base);
- platform_device_register(pdev);
- }
-}
-
-/* ------------------------------------------------------------------ */
-/* Boot entry — replaces the old driver_probe_all() */
-/* ------------------------------------------------------------------ */
-
-void driver_probe_all()
-{
- kprintf("[dpa] step 1: &platform_bus=%p (link 0xffffffc08033a0a8)\n",
- &platform_bus);
- kprintf("[dpa] step 1: pre-touch platform_bus.name slot...\n");
- const char** name_slot = &platform_bus.name;
- kprintf("[dpa] step 1: name_slot=%p\n", name_slot);
- kprintf("[dpa] step 1: about to deref *name_slot\n");
- const char* nm = *name_slot;
- kprintf("[dpa] step 1: *name_slot=%p\n", nm);
- kprintf("[dpa] step 1: about to read first byte of nm\n");
- char first = nm != nullptr ? nm[0] : '!';
- kprintf("[dpa] step 1: nm[0]='%c'\n", first);
-
- kprintf("[dpa] step 1: platform_bus_init enter\n");
- platform_bus_init();
- kprintf("[dpa] step 1: platform_bus_init done\n");
-
- platform_driver** start = __drivers_start;
- platform_driver** end = __drivers_end;
- kprintf("[dpa] step 2: __drivers_start=%p __drivers_end=%p count=%lld\n",
- start, end, (long long)(end - start));
-
- for (platform_driver** slot = start; slot < end; ++slot) {
- kprintf("[dpa] step 2: slot=%p *slot=%p\n", slot, *slot);
- if (*slot != nullptr) {
- platform_driver* pdrv = *slot;
- kprintf("[dpa] step 2: pdrv->of_match_table=%p\n",
- pdrv->of_match_table);
- if (pdrv->of_match_table != nullptr) {
- kprintf("[dpa] step 2: pdrv->of_match_table[0].compatible=%p\n",
- pdrv->of_match_table[0].compatible);
- if (pdrv->of_match_table[0].compatible != nullptr) {
- kprintf("[dpa] step 2: compatible='%s'\n",
- pdrv->of_match_table[0].compatible);
- }
- }
- platform_driver_register(pdrv);
- kprintf("[dpa] step 2: registered\n");
- }
- }
-
- kprintf("[dpa] step 3: instantiate devices\n");
- for (platform_driver** slot = start; slot < end; ++slot) {
- if (*slot != nullptr) {
- instantiate_devices_for_driver(*slot);
- }
- }
- kprintf("[dpa] done\n");
-}