rewrite the device subsystem interfaces (#48)
[lunaix-os.git] / lunaix-os / includes / hal / devtree.h
1 #ifndef __LUNAIX_DEVTREE_H
2 #define __LUNAIX_DEVTREE_H
3
4 #include <lunaix/types.h>
5 #include <lunaix/ds/llist.h>
6 #include <lunaix/ds/hstr.h>
7 #include <lunaix/ds/hashtable.h>
8 #include <lunaix/boot_generic.h>
9 #include <lunaix/changeling.h>
10
11 #include <klibc/string.h>
12
13 #define le(v) ((((v) >> 24) & 0x000000ff)  |\
14                (((v) << 8)  & 0x00ff0000)  |\
15                (((v) >> 8)  & 0x0000ff00)  |\
16                (((v) << 24) & 0xff000000))
17
18 #define le64(v) (((u64_t)le(v & 0xffffffff) << 32) | le(v >> 32))
19
20 #define be(v) ((((v) << 24) & 0x000000ff)  |\
21                (((v) >> 8)  & 0x00ff0000)  |\
22                (((v) << 8)  & 0x0000ff00)  |\
23                (((v) >> 24) & 0xff000000))
24
25 #define FDT_MAGIC       be(0xd00dfeed)
26 #define FDT_NOD_BEGIN   be(0x00000001)
27 #define FDT_NOD_END     be(0x00000002)
28 #define FDT_PROP        be(0x00000003)
29 #define FDT_NOP         be(0x00000004)
30 #define FDT_END         be(0x00000009)
31
32 #define STATUS_OK       0
33 #define STATUS_DISABLE  1
34 #define STATUS_RSVD     2
35 #define STATUS_FAIL     3
36
37
38 typedef unsigned int* dt_enc_t;
39 typedef unsigned int  dt_phnd_t;
40
41 struct dt_node_base;
42 struct dt_node_iter;
43 typedef bool (*node_predicate_t)(struct dt_node_iter*, struct dt_node_base*);
44
45
46 #define PHND_NULL    ((dt_phnd_t)-1)
47
48 struct fdt_header {
49     u32_t magic;
50     u32_t totalsize;
51     u32_t off_dt_struct;
52     u32_t off_dt_strings;
53     u32_t off_mem_rsvmap;
54     u32_t version;
55     u32_t last_comp_version;
56     u32_t boot_cpuid_phys;
57     u32_t size_dt_strings;
58     u32_t size_dt_struct;
59 };
60
61 struct fdt_memrsvd_ent 
62 {
63     u64_t addr;
64     u64_t size;
65 } align(8);
66
67 struct fdt_token 
68 {
69     u32_t token;
70 } compact align(4);
71
72 struct fdt_node_head
73 {
74     struct fdt_token token;
75     char name[0];
76 };
77
78 struct fdt_prop 
79 {
80     struct fdt_token token;
81     u32_t len;
82     u32_t nameoff;
83 } compact align(4);
84
85 struct dt_prop_val
86 {
87     struct {
88         union
89         {
90             union {
91                 const char*  str_val;
92                 const char*  str_lst;
93             };
94             ptr_t        ptr_val;
95             
96             union {
97                 dt_enc_t     encoded;
98                 dt_phnd_t    phandle;
99             };
100             u32_t        u32_val;
101
102             u64_t        u64_val;
103         };
104         unsigned int size;
105     };
106 };
107
108
109 struct dt_prop
110 {
111     struct hlist_node   ht;
112     struct hstr         key;
113     struct dt_prop_val  val;
114 };
115
116 struct dt_prop_table
117 {
118     union {
119         struct hbucket    other_props[0];
120         struct hbucket    _op_bucket[8];
121     };
122 };
123
124 struct dt_node_base
125 {
126     morph_t mobj;
127
128     union {
129         struct {
130             unsigned char addr_c;
131             unsigned char sz_c;
132             unsigned char intr_c;
133             unsigned char status;
134         };
135         unsigned int _std;
136     };
137
138     union {
139         struct {
140             bool dma_coherent  : 1;
141             bool dma_ncoherent : 1;
142             bool intr_controll : 1;
143             bool intr_neuxs    : 1;
144         };
145         unsigned int    flags;
146     };
147
148     struct dt_node_base  *parent;
149     struct llist_header   nodes;
150
151     struct dt_prop_val    compat;
152     dt_phnd_t             phandle;
153
154     struct dt_prop_table* props;
155
156     void* obj;
157     morph_t* binded_dev;
158 };
159
160 struct dt_root
161 {
162     struct dt_node_base base;
163
164     const char*         serial;
165     const char*         chassis;
166 };
167
168 struct dt_intr_prop;
169
170 struct dt_intr_mapkey
171 {
172     unsigned int* val;
173     unsigned int  size;
174 };
175
176 struct dt_intr_mapent
177 {
178     struct llist_header ents;
179
180     struct dt_intr_mapkey key;
181
182     struct dt_node_base* parent;
183     struct dt_prop_val parent_props;
184 };
185
186 struct dt_intr_map 
187 {
188     struct dt_prop_val       raw;
189     struct dt_prop_val       raw_mask;
190
191     struct dt_intr_mapkey    key_mask;
192     struct llist_header      mapent;
193
194     bool resolved;
195 };
196
197 struct dt_intr_node
198 {
199     union {
200         struct dt_intr_node *parent;
201         dt_phnd_t parent_hnd;
202     };
203
204     struct {
205         bool extended;
206         bool valid;
207         union {
208             struct dt_prop_val   arr;
209             struct llist_header  values; 
210         };
211     } intr;
212
213     struct dt_intr_map* map;
214 };
215 #define INTR_TO_DTNODE(intr_node) \
216         (container_of(intr_node, struct dt_node, intr))
217
218 #define BASE_TO_DTNODE(base_node) \
219         (container_of(base_node, struct dt_node, base))
220
221 struct dt_node
222 {
223     union {
224         morph_t mobj;
225         struct dt_node_base base;
226     };
227     
228     struct dt_intr_node intr;
229     
230     struct dt_prop_val  reg;
231     struct dt_prop_val  vreg;
232
233     struct dt_prop_val  ranges;
234     struct dt_prop_val  dma_ranges;
235 };
236 #define dt_parent(node) ((node)->base.parent)
237 #define dt_morpher       morphable_attrs(dt_node, mobj)
238 #define dt_mobj(node)   (&(node)->mobj)
239
240 struct dt_intr_prop
241 {
242     struct dt_intr_node *master;
243
244     struct llist_header  props;
245     struct dt_prop_val   val;
246 };
247
248 struct dt_prop_iter
249 {
250     struct dt_prop_val     *prop;
251     struct dt_node_base    *node;
252     dt_enc_t                prop_loc;
253     dt_enc_t                prop_loc_next;
254     unsigned int            ent_sz;
255 };
256
257 struct dt_context
258 {
259     union {
260         ptr_t reloacted_dtb;
261         struct fdt_header* fdt;
262     };
263
264     struct llist_header   nodes;
265     struct dt_root       *root;
266     struct hbucket        phnds_table[16];
267     const char           *str_block;
268 };
269
270 struct fdt_iter
271 {
272     union {
273         struct fdt_token      *pos;
274         struct fdt_prop       *prop;
275         struct fdt_node_head  *node_head;
276     };
277
278     const char* str_block;
279     int depth;
280 };
281
282 struct fdt_memrsvd_iter
283 {
284     struct fdt_memrsvd_ent *block;
285 };
286
287 struct dt_node_iter
288 {
289     struct dt_node_base* head;
290     struct dt_node_base* matched;
291     void* closure;
292     node_predicate_t pred;
293 };
294
295
296
297 /****
298  * FDT Related
299  ****/
300
301 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
302 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
303 #define fdt_node_end(tok) ((tok)->token == FDT_NOD_END)
304 #define fdt_nope(tok) ((tok)->token == FDT_NOP)
305
306 void 
307 fdt_itbegin(struct fdt_iter* fdti, struct fdt_header* fdt_hdr);
308
309 void 
310 fdt_itend(struct fdt_iter* fdti);
311
312 bool 
313 fdt_itnext(struct fdt_iter* fdti);
314
315 bool 
316 fdt_itnext_at(struct fdt_iter* fdti, int level);
317
318 void
319 fdt_memrsvd_itbegin(struct fdt_memrsvd_iter* rsvdi, 
320                     struct fdt_header* fdt_hdr);
321
322 bool
323 fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi);
324
325 void
326 fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi);
327
328 static inline char*
329 fdtit_prop_key(struct fdt_iter* fdti)
330 {
331     return &fdti->str_block[fdti->prop->nameoff];
332 }
333
334
335 /****
336  * DT Main Functions: General
337  ****/
338
339 bool
340 dt_load(ptr_t dtb_dropoff);
341
342 struct dt_node*
343 dt_resolve_phandle(dt_phnd_t phandle);
344
345 struct dt_prop_val*
346 dt_getprop(struct dt_node_base* base, const char* name);
347
348 struct dt_prop_val*
349 dt_resolve_interrupt(struct dt_node* node);
350
351 void
352 dt_resolve_interrupt_map(struct dt_node* node);
353
354 static inline unsigned int
355 dt_addr_cells(struct dt_node_base* base)
356 {
357     return base->parent ? base->parent->addr_c : base->addr_c;
358 }
359
360 static inline unsigned int
361 dt_size_cells(struct dt_node_base* base)
362 {
363     return base->parent ? base->parent->sz_c : base->sz_c;
364 }
365
366
367 /****
368  * DT Main Functions: Node-finder
369  ****/
370
371 void
372 dt_begin_find_byname(struct dt_node_iter* iter, 
373                      struct dt_node* node, const char* name);
374
375 void
376 dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, 
377               node_predicate_t pred, void* closure);
378
379 static inline void
380 dt_end_find(struct dt_node_iter* iter)
381 {
382     // currently do nothing, keep only for semantic
383 }
384
385 bool
386 dt_find_next(struct dt_node_iter* iter,
387              struct dt_node_base** matched);
388
389 static inline bool
390 dt_found_any(struct dt_node_iter* iter)
391 {
392     return !!iter->matched;
393 }
394
395 struct dt_context*
396 dt_main_context();
397
398
399 /****
400  * DT Main Functions: Node-binding
401  ****/
402
403 static inline void
404 dt_bind_object(struct dt_node_base* base, void* obj)
405 {
406     base->obj = obj;
407 }
408
409 static inline bool
410 dt_has_binding(struct dt_node_base* base) 
411 {
412     return base->obj != NULL;
413 }
414
415 #define dt_binding_of(node_base, type)  \
416     ((type)(node_base)->obj)
417
418
419 /****
420  * DT Main Functions: Prop decoders
421  ****/
422
423 static inline void
424 dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, 
425                 struct dt_prop_val* val, unsigned int ent_sz)
426 {
427     *dtpi = (struct dt_prop_iter) {
428         .prop = val,
429         .node = node,
430         .prop_loc = val->encoded,
431         .prop_loc_next = val->encoded,
432         .ent_sz = ent_sz
433     };
434 }
435
436 #define dt_decode_reg(dtpi, node, field) \
437             dt_decode(dtpi, &(node)->base, &(node)->field, \
438                         dt_size_cells(&(node)->base) \
439                             + dt_addr_cells(&(node)->base))
440
441 #define dt_decode_range(dtpi, node, field) \
442             dt_decode(dtpi, &(node)->base, &(node)->field, \
443                         dt_size_cells(&(node)->base) * 2 \
444                             + dt_addr_cells(&(node)->base))
445
446 #define dt_decode_simple(dtpi, prop) \
447             dt_decode(dtpi, NULL, prop, 1);
448
449 #define dtprop_off(dtpi) \
450             (unsigned int)(\
451                 __ptr(dtpi->prop_loc_next) - __ptr(dtpi->prop->encoded) \
452             )
453
454 #define dtprop_extract(dtpi, off) \
455             ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) )
456
457 #define dtprop_strlst_foreach(pos, prop)    \
458         for (pos = (prop)->str_lst; \
459              pos <= &(prop)->str_lst[(prop)->size]; \
460              pos = &pos[strlen(pos) + 1])
461
462 static inline bool
463 dtprop_next_n(struct dt_prop_iter* dtpi, int n)
464 {
465     unsigned int off;
466
467     dtpi->prop_loc = dtpi->prop_loc_next;
468     dtpi->prop_loc_next += n;
469
470     off = dtprop_off(dtpi);
471     return off >= dtpi->prop->size;
472 }
473
474 static inline bool
475 dtprop_prev_n(struct dt_prop_iter* dtpi, int n)
476 {
477     unsigned int off;
478
479     off = dtprop_off(dtpi);
480     if (!off || off > dtpi->prop->size) {
481         return false;
482     }
483
484     dtpi->prop_loc = dtpi->prop_loc_next;
485     dtpi->prop_loc_next -= n;
486
487     return true;
488 }
489
490 static inline bool
491 dtprop_next(struct dt_prop_iter* dtpi)
492 {
493     return dtprop_next_n(dtpi, dtpi->ent_sz);
494 }
495
496 static inline bool
497 dtprop_prev(struct dt_prop_iter* dtpi)
498 {
499     return dtprop_prev_n(dtpi, dtpi->ent_sz);
500 }
501
502 static inline unsigned int
503 dtprop_to_u32(dt_enc_t enc_val)
504 {
505     return le(*enc_val);
506 }
507
508 #define dtprop_to_phnd(enc_val) \
509             (dt_phnd_t)dtprop_to_u32(enc_val)
510
511 static inline u64_t
512 dtprop_to_u64(dt_enc_t enc_val)
513 {
514     return le64(*(u64_t*)enc_val);
515 }
516
517 static inline u32_t
518 dtprop_u32_at(struct dt_prop_iter* dtpi, int index)
519 {
520     return dtprop_to_u32(dtprop_extract(dtpi, index));
521 }
522
523 static inline u32_t
524 dtprop_u64_at(struct dt_prop_iter* dtpi, int index)
525 {
526     return dtprop_to_u64(dtprop_extract(dtpi, index));
527 }
528
529 static inline dt_enc_t
530 dtprop_reg_addr(struct dt_prop_iter* dtpi)
531 {
532     return dtprop_extract(dtpi, 0);
533 }
534
535 static inline ptr_t
536 dtprop_reg_nextaddr(struct dt_prop_iter* dtpi)
537 {
538     ptr_t t;
539
540     t = (ptr_t)dtprop_to_u64(dtprop_reg_addr(dtpi));
541     dtprop_next_n(dtpi, dt_addr_cells(dtpi->node));
542
543     return t;
544 }
545
546 static inline dt_enc_t
547 dtprop_reg_len(struct dt_prop_iter* dtpi)
548 {
549     return dtprop_extract(dtpi, dtpi->node->addr_c);
550 }
551
552 static inline size_t
553 dtprop_reg_nextlen(struct dt_prop_iter* dtpi)
554 {
555     size_t t;
556
557     t = (size_t)dtprop_to_u64(dtprop_reg_len(dtpi));
558     dtprop_next_n(dtpi, dt_size_cells(dtpi->node));
559
560     return t;
561 }
562
563 static inline dt_enc_t
564 dtprop_range_childbus(struct dt_prop_iter* dtpi)
565 {
566     return dtprop_extract(dtpi, 0);
567 }
568
569 static inline dt_enc_t
570 dtprop_range_parentbus(struct dt_prop_iter* dtpi)
571 {
572     return dtprop_extract(dtpi, dt_addr_cells(dtpi->node));
573 }
574
575 static inline dt_enc_t
576 dtprop_range_len(struct dt_prop_iter* dtpi)
577 {
578     return dtprop_extract(dtpi, dt_addr_cells(dtpi->node) * 2);
579 }
580
581 #endif /* __LUNAIX_DEVTREE_H */