make irq specifier to be provided when assigining irq
[lunaix-os.git] / lunaix-os / hal / devtree / dtspec.c
1 #include "devtree.h"
2 #include <lunaix/mm/valloc.h>
3
4 #define key_mkwr(key)   \
5             (struct dtspec_key*)(key)
6 #define call_op(dtn, ops, name)    \
7             ((ops)->name ? (ops)->name(dtn) : NULL)
8
9 struct dtspec_map*
10 dtspec_create(struct dtn* node, struct dtp_val* map,
11               const struct dtspec_create_ops* ops)
12 {
13     struct dtpropi it;
14     struct dtspec_map* spec;
15     struct dtspec_mapent* ent;
16     struct dtp_val val = {}, *field;
17     int keysz, p_keysz;
18
19     assert(ops->child_keysz);
20     assert(ops->parent_keysz);
21
22     keysz = ops->child_keysz(node);
23     spec = vzalloc(sizeof(*spec));
24
25     field = call_op(node, ops, get_mask);
26     if (field) {
27         dtp_speckey(key_mkwr(&spec->mask), field);
28     }
29
30     field = call_op(node, ops, get_passthru);
31     if (field) {
32         dtp_speckey(key_mkwr(&spec->pass_thru), field);
33     }
34     
35     llist_init_head(&spec->ents);
36
37     dtpi_init(&it, map);
38     while (dtpi_has_next(&it))
39     {
40         ent = vzalloc(sizeof(*ent));
41
42         dtpi_next_val(&it, &val, keysz);
43         dtp_speckey(key_mkwr(&ent->child_spec), &val);
44
45         ent->parent = dtpi_next_hnd(&it);
46         p_keysz = ops->parent_keysz(ent->parent);
47
48         dtpi_next_val(&it, &val, p_keysz);
49         dtp_speckey(key_mkwr(&ent->parent_spec), &val);
50
51         changeling_ref(dt_mobj(ent->parent));
52         llist_append(&spec->ents, &ent->ents);
53     }
54
55     return spec;
56 }
57
58 static bool
59 __try_match(struct dtspec_key* given, struct dtspec_key* against)
60 {
61     for (unsigned int i = 0; i < given->size; i++)
62     {
63         if (given->val[i] != against->val[i])
64             return false;
65     }
66     
67     return true;
68 }
69
70 struct dtspec_mapent*
71 dtspec_lookup(struct dtspec_map* map, struct dtspec_key* key)
72 {
73     struct dtspec_mapent *pos, *n;
74     struct dtspec_key scratch = {};
75
76     dtspec_cpykey(&scratch, key);
77     dtspec_applymask(map, &scratch);
78
79     llist_for_each(pos, n, &map->ents, ents)
80     {
81         if (__try_match(&scratch, &pos->child_spec))
82         {
83             dtspec_freekey(&scratch);
84             return pos;
85         }
86     }
87
88     dtspec_freekey(&scratch);
89     return NULL;
90 }
91
92 void
93 dtspec_applymask(struct dtspec_map* map, struct dtspec_key* key)
94 {
95     for (unsigned int i = 0; i < map->mask.size; i++)
96     {
97         key->val[i] &= map->mask.val[i];
98     }
99 }
100
101 void
102 dtspec_free(struct dtspec_map* map)
103 {
104     struct dtspec_mapent *pos, *n;
105     
106     llist_for_each(pos, n, &map->ents, ents)
107     {
108         changeling_unref(dt_mobj(pos->parent));
109         vfree(pos);
110     }
111
112     vfree(map);
113 }
114
115 void
116 dtspec_cpykey(struct dtspec_key* dest, struct dtspec_key* src)
117 {    
118     if (dtspec_nullkey(src)) {
119         return;
120     }
121
122     int sz = sizeof(int) * src->size;
123
124     dest->val = valloc(sz);
125     dest->size = src->size;
126     memcpy(dest->val, src->val, sz);
127 }
128
129 void
130 dtspec_freekey(struct dtspec_key* key)
131 {
132     if (dtspec_nullkey(key)) {
133         return;
134     }
135
136     vfree(key->val);
137     key->size = 0;
138 }