3 #include <lunaix/mm/valloc.h>
5 #include <klibc/string.h>
7 static struct dt_intr_map*
8 __get_map(struct dt_intr_node* node)
11 node->map = valloc(sizeof(struct dt_intr_map));
13 node->map->resolved = false;
14 llist_init_head(&node->map->mapent);
16 INTR_TO_DTNODE(node)->base.intr_neuxs = true;
23 __prepare_key(struct dt_intr_mapkey* key,
24 dt_enc_t key_raw, unsigned int keylen)
26 *key = (struct dt_intr_mapkey) {
27 .val = valloc(keylen * sizeof(int)),
31 memcpy(key->val, key_raw, keylen * sizeof(int));
35 __destory_key(struct dt_intr_mapkey* key)
40 static inline unsigned int
41 __interrupt_keysize(struct dt_node_base* base)
43 return base->addr_c + base->intr_c;
47 __mask_key(struct dt_intr_mapkey* k, struct dt_intr_mapkey* mask)
49 for (int i = 0; i < k->size; i++)
51 k->val[i] &= mask->val[i];
56 __compare_key(struct dt_intr_mapkey* k1, struct dt_intr_mapkey* k2)
58 if (k1->size != k2->size) {
62 for (int i = 0; i < k1->size; i++)
64 if (k1->val[i] != k2->val[i]) {
72 static struct dt_node_base*
73 __get_connected_nexus(struct dt_node_base* base)
75 struct dt_node_base* current;
78 while (current && !current->intr_neuxs) {
79 current = current->parent;
86 resolve_interrupt_map(struct dt_node* node)
88 struct dt_intr_node* inode;
89 struct dt_intr_map* imap;
90 struct dt_prop_iter iter;
92 struct dt_intr_mapent *ent;
94 unsigned int keysize, parent_keysize;
99 if (likely(!inode->map)) {
104 keysize = __interrupt_keysize(&node->base);
106 __prepare_key(&imap->key_mask, imap->raw_mask.encoded, keysize);
108 dt_decode(&iter, &node->base, &imap->raw, 1);
114 ent = valloc(sizeof(*ent));
116 __prepare_key(&ent->key, iter.prop_loc, advance);
117 __mask_key(&ent->key, &imap->key_mask);
119 parent_hnd = dtprop_to_phnd(dtprop_extract(&iter, advance));
120 ent->parent = &dt_resolve_phandle(parent_hnd)->base;
123 parent_keysize = __interrupt_keysize(ent->parent);
125 ent->parent_props.encoded = dtprop_extract(&iter, advance);
126 ent->parent_props.size = parent_keysize;
128 advance += parent_keysize;
130 llist_append(&imap->mapent, &ent->ents);
132 } while (dtprop_next_n(&iter, advance));
134 imap->resolved = true;
138 resolve_interrupt(struct dt_node* node)
140 struct dt_node_base* nexus;
141 struct dt_intr_node* i_nexus, *i_node;
142 struct dt_intr_mapkey key;
145 if (!node->intr.intr.valid) {
149 nexus = __get_connected_nexus(&node->base);
150 i_nexus = &BASE_TO_DTNODE(nexus)->intr;
151 i_node = &node->intr;
154 return &i_node->intr.arr;
157 keylen = nexus->addr_c + nexus->intr_c;
158 key = (struct dt_intr_mapkey) {
159 .val = valloc(keylen * sizeof(int)),
164 node->reg.encoded, nexus->addr_c * sizeof(int));
166 memcpy(&key.val[nexus->addr_c],
167 i_node->intr.arr.encoded, nexus->intr_c * sizeof(int));
169 __mask_key(&key, &i_nexus->map->key_mask);
171 struct dt_intr_mapent *pos, *n;
173 llist_for_each(pos, n, &i_nexus->map->mapent, ents) {
174 if (__compare_key(&pos->key, &key))
176 return &pos->parent_props;
182 parse_stdintr_prop(struct fdt_iter* it, struct dt_intr_node* node)
184 struct dt_intr_map* map;
186 if (propeq(it, "interrupt-map")) {
187 map = __get_map(node);
188 __mkprop_ptr(it, &map->raw);
191 else if (propeq(it, "interrupt-map-mask")) {
192 map = __get_map(node);
193 __mkprop_ptr(it, &map->raw_mask);
196 else if (propeq(it, "interrupt-parent")) {
197 node->parent_hnd = __prop_getu32(it);
200 else if (propeq(it, "interrupt-extended")) {
201 node->intr.extended = true;
202 __mkprop_ptr(it, &node->intr.arr);
205 else if (!node->intr.extended && propeq(it, "interrupts")) {
206 node->intr.valid = true;
207 __mkprop_ptr(it, &node->intr.arr);