ld-tool portability fix: MacOS build experience
[lunaix-os.git] / lunaix-os / kernel / device / devdb.c
1 #include <lunaix/device.h>
2 #include <lunaix/fs/twifs.h>
3 #include <lunaix/status.h>
4
5 #include <klibc/hash.h>
6
7 #include <klibc/strfmt.h>
8
9 static DECLARE_HASHTABLE(dev_registry, 32);
10 static DECLARE_HASHTABLE(dev_byif, 8);
11 static DEFINE_LLIST(dev_registry_flat);
12
13 static struct device_cat* adhoc_devcat;
14
15 static inline u32_t
16 hash_dev(u32_t fngrp, u32_t dev)
17 {
18     return (hash_32(fngrp, 16) << 16) | (hash_32(dev, 16));
19 }
20
21 void
22 device_scan_drivers()
23 {
24     adhoc_devcat = device_addcat(NULL, "adhoc");
25
26     hashtable_init(dev_registry);
27     hashtable_init(dev_byif);
28
29     int idx = 0;
30     struct device_def* devdef;
31     ldga_foreach(devdefs, struct device_def*, idx, devdef)
32     {
33         struct devclass* devc = &devdef->class;
34         u32_t hash = hash_dev(devc->fn_grp, devc->device);
35         devc->hash = hash;
36
37         if (!devdef->name) {
38             devdef->name = "<unspecified>";
39         }
40
41         hashtable_hash_in(dev_registry, &devdef->hlist, hash);
42         hashtable_hash_in(dev_byif, &devdef->hlist_if, DEV_IF(devc->fn_grp));
43
44         llist_append(&dev_registry_flat, &devdef->dev_list);
45     }
46 }
47
48 static int
49 devclass_eq(struct devclass* c1, struct devclass* c2)
50 {
51     return c1->fn_grp == c2->fn_grp && c1->device == c2->device;
52 }
53
54 struct device_def*
55 devdef_byclass(struct devclass* devc)
56 {
57     u32_t hash = hash_dev(devc->fn_grp, devc->device);
58     int errno;
59
60     struct device_def *pos, *n;
61     hashtable_hash_foreach(dev_registry, hash, pos, n, hlist)
62     {
63         if (pos->class.hash != hash) {
64             continue;
65         }
66         if (devclass_eq(devc, &pos->class)) {
67             break;
68         }
69     }
70
71     return pos;
72 }
73
74 struct device_def*
75 devdef_byident(struct devident* ident)
76 {
77     struct devclass derived = { .device = DEV_KIND_FROM(ident->unique),
78                                 .fn_grp = ident->fn_grp };
79     return devdef_byclass(&derived);
80 }
81
82 struct hbucket*
83 device_definitions_byif(int if_type)
84 {
85     return &dev_byif[__hashkey(dev_byif, if_type)];
86 }
87
88 #define __device_load_on_stage(stage)                                          \
89     ({                                                                         \
90         int idx = 0;                                                           \
91         struct device_def* devdef;                                             \
92         ldga_foreach(dev_##stage, struct device_def*, idx, devdef)             \
93         {                                                                      \
94             devdef->init(devdef);                                              \
95         }                                                                      \
96     })
97 #define device_load_on_stage(stage) __device_load_on_stage(stage)
98
99 void
100 device_onboot_load()
101 {
102     device_load_on_stage(load_onboot);
103 }
104
105 void
106 device_postboot_load()
107 {
108     device_load_on_stage(load_postboot);
109 }
110
111 void
112 device_sysconf_load()
113 {
114     device_load_on_stage(load_sysconf);
115 }
116
117 static int
118 __devdb_db_gonext(struct twimap* mapping)
119 {
120     struct device_def* current = twimap_index(mapping, struct device_def*);
121     if (current->dev_list.next == &dev_registry_flat) {
122         return 0;
123     }
124     mapping->index =
125       list_entry(current->dev_list.next, struct device_def, dev_list);
126     return 1;
127 }
128
129 static void
130 __devdb_twifs_lsdb(struct twimap* mapping)
131 {
132     char flags[64];
133     struct device_def* def = twimap_index(mapping, struct device_def*);
134
135     int meta = def->class.fn_grp;
136     ksnprintf(flags, 64, "if=%x,fn=%x", DEV_IF(meta), DEV_FN(meta));
137
138     twimap_printf(mapping,
139                   "%08xh:%04d \"%s\" %s\n",
140                   def->class.fn_grp,
141                   def->class.device,
142                   def->name,
143                   flags);
144 }
145
146 void
147 __devdb_reset(struct twimap* map)
148 {
149     map->index =
150       container_of(dev_registry_flat.next, struct device_def, dev_list);
151 }
152
153 static void
154 devdb_twifs_plugin()
155 {
156     struct twimap* map = twifs_mapping(NULL, NULL, "devtab");
157     map->reset = __devdb_reset;
158     map->read = __devdb_twifs_lsdb;
159     map->go_next = __devdb_db_gonext;
160 }
161 EXPORT_TWIFS_PLUGIN(devdb, devdb_twifs_plugin);