feat: owloysius - dynamic init function invocator
[lunaix-os.git] / lunaix-os / kernel / device / devdb.c
index cf58a9d982f3ea260e733a08eee8d6762f7ba48d..eb9e612320494db1107d9a31a06de0fa57e4eaa1 100644 (file)
@@ -2,16 +2,24 @@
 #include <lunaix/fs/twifs.h>
 #include <lunaix/status.h>
 
-#include <klibc/stdio.h>
+#include <lib/hash.h>
+
+#include <klibc/strfmt.h>
 
 static DECLARE_HASHTABLE(dev_registry, 32);
 static DECLARE_HASHTABLE(dev_byif, 8);
 static DEFINE_LLIST(dev_registry_flat);
 
-static struct device* adhoc_devcat;
+static struct device_cat* adhoc_devcat;
+
+static inline u32_t
+hash_dev(u32_t fngrp, u32_t dev)
+{
+    return (hash_32(fngrp, 16) << 16) | (hash_32(dev, 16));
+}
 
 void
-device_register_all()
+device_scan_drivers()
 {
     adhoc_devcat = device_addcat(NULL, "adhoc");
 
@@ -22,12 +30,16 @@ device_register_all()
     struct device_def* devdef;
     ldga_foreach(devdefs, struct device_def*, idx, devdef)
     {
-        u32_t hash = devclass_hash(devdef->class);
-        devdef->class.hash = hash;
+        struct devclass* devc = &devdef->class;
+        u32_t hash = hash_dev(devc->fn_grp, devc->device);
+        devc->hash = hash;
+
+        if (!devdef->name) {
+            devdef->name = "<unspecified>";
+        }
 
         hashtable_hash_in(dev_registry, &devdef->hlist, hash);
-        hashtable_hash_in(
-          dev_byif, &devdef->hlist_if, DEV_IF(devdef->class.meta));
+        hashtable_hash_in(dev_byif, &devdef->hlist_if, DEV_IF(devc->fn_grp));
 
         llist_append(&dev_registry_flat, &devdef->dev_list);
     }
@@ -36,14 +48,13 @@ device_register_all()
 static int
 devclass_eq(struct devclass* c1, struct devclass* c2)
 {
-    return c1->meta == c2->meta && c1->variant == c2->variant &&
-           c1->device == c2->device;
+    return c1->fn_grp == c2->fn_grp && c1->device == c2->device;
 }
 
 struct device_def*
-devdef_byclass(struct devclass* class)
+devdef_byclass(struct devclass* devc)
 {
-    u32_t hash = devclass_hash(*class);
+    u32_t hash = hash_dev(devc->fn_grp, devc->device);
     int errno;
 
     struct device_def *pos, *n;
@@ -52,7 +63,7 @@ devdef_byclass(struct devclass* class)
         if (pos->class.hash != hash) {
             continue;
         }
-        if (devclass_eq(class, &pos->class)) {
+        if (devclass_eq(devc, &pos->class)) {
             break;
         }
     }
@@ -60,45 +71,12 @@ devdef_byclass(struct devclass* class)
     return pos;
 }
 
-struct device*
-device_create_byclass(struct devclass* class,
-                      u32_t type,
-                      char* name,
-                      int* err_code)
+struct device_def*
+devdef_byident(struct devident* ident)
 {
-    int errno;
-    struct device_def* devdef = devdef_byclass(class);
-
-    if (!devdef) {
-        *err_code = ENOENT;
-        return NULL;
-    }
-
-    if (!devdef->init_for) {
-        if (err_code) {
-            *err_code = ENOTSUP;
-        }
-        return NULL;
-    }
-
-    struct device* dev = device_add(adhoc_devcat, NULL, type, NULL);
-
-    errno = devdef->init_for(devdef, dev);
-    if (err_code && !errno) {
-        *err_code = errno;
-        device_remove(dev);
-        return NULL;
-    }
-
-    device_setname(dev,
-                   "%s_%d:%d:%d_%d",
-                   name,
-                   class->meta,
-                   class->device,
-                   class->device,
-                   dev->dev_id);
-
-    return dev;
+    struct devclass derived = { .device = DEV_KIND_FROM(ident->unique),
+                                .fn_grp = ident->fn_grp };
+    return devdef_byclass(&derived);
 }
 
 struct hbucket*
@@ -107,32 +85,33 @@ device_definitions_byif(int if_type)
     return &dev_byif[__hashkey(dev_byif, if_type)];
 }
 
-#define device_load_on_stage(stage)                                            \
+#define __device_load_on_stage(stage)                                          \
     ({                                                                         \
         int idx = 0;                                                           \
         struct device_def* devdef;                                             \
-        ldga_foreach(dev_ld_##stage, struct device_def*, idx, devdef)          \
+        ldga_foreach(dev_##stage, struct device_def*, idx, devdef)             \
         {                                                                      \
             devdef->init(devdef);                                              \
         }                                                                      \
     })
+#define device_load_on_stage(stage) __device_load_on_stage(stage)
 
 void
-device_earlystage()
+device_onboot_load()
 {
-    device_load_on_stage(early);
+    device_load_on_stage(load_onboot);
 }
 
 void
-device_timerstage()
+device_postboot_load()
 {
-    device_load_on_stage(aftertimer);
+    device_load_on_stage(load_postboot);
 }
 
 void
-device_poststage()
+device_sysconf_load()
 {
-    device_load_on_stage(post);
+    device_load_on_stage(load_sysconf);
 }
 
 static int
@@ -150,25 +129,32 @@ __devdb_db_gonext(struct twimap* mapping)
 static void
 __devdb_twifs_lsdb(struct twimap* mapping)
 {
-    char flags[32];
+    char flags[64];
     struct device_def* def = twimap_index(mapping, struct device_def*);
 
-    int meta = def->class.meta;
-    ksnprintf(flags, 32, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta));
+    int meta = def->class.fn_grp;
+    ksnprintf(flags, 64, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta));
 
     twimap_printf(mapping,
-                  "%d:%d:%d %s (%s)\n",
-                  def->class.meta,
+                  "%08xh:%04d \"%s\" %s\n",
+                  def->class.fn_grp,
                   def->class.device,
-                  def->class.variant,
                   def->name,
                   flags);
 }
 
+void
+__devdb_reset(struct twimap* map)
+{
+    map->index =
+      container_of(dev_registry_flat.next, struct device_def, dev_list);
+}
+
 static void
 devdb_twifs_plugin()
 {
     struct twimap* map = twifs_mapping(NULL, NULL, "devtab");
+    map->reset = __devdb_reset;
     map->read = __devdb_twifs_lsdb;
     map->go_next = __devdb_db_gonext;
 }