summaryrefslogtreecommitdiff
path: root/na/drivers/base/driver.cc
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:24:56 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:24:56 +0800
commit1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (patch)
tree0f5e01cd7c7a05abb6b1c7472d7f00f49caf02cc /na/drivers/base/driver.cc
parent63dc025705f6533b91fb1a7d26e6ed864efd9900 (diff)
downloadlume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.gz
lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.xz
feat: establish bootable new architecture checkpoint
Replace the compressed boot path with a relocatable higher-half RISC-V entry, expand memory and SMP support, and add the driver, TTY, VFS, exec, signal, syscall, initramfs, and self-test infrastructure needed for a bootable kernel checkpoint.
Diffstat (limited to 'na/drivers/base/driver.cc')
-rw-r--r--na/drivers/base/driver.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/na/drivers/base/driver.cc b/na/drivers/base/driver.cc
new file mode 100644
index 0000000..ce15b6d
--- /dev/null
+++ b/na/drivers/base/driver.cc
@@ -0,0 +1,72 @@
+/* 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);
+}