rewrite the device subsystem interfaces (#48)
[lunaix-os.git] / lunaix-os / includes / hal / devtree.h
index 3a92116eeb4fc744be07297c6b0664b49591b3cb..7b02ca5810a026c0942f4366b09c2e51f4ec8063 100644 (file)
@@ -6,6 +6,9 @@
 #include <lunaix/ds/hstr.h>
 #include <lunaix/ds/hashtable.h>
 #include <lunaix/boot_generic.h>
+#include <lunaix/changeling.h>
+
+#include <klibc/string.h>
 
 #define le(v) ((((v) >> 24) & 0x000000ff)  |\
                (((v) << 8)  & 0x00ff0000)  |\
 typedef unsigned int* dt_enc_t;
 typedef unsigned int  dt_phnd_t;
 
+struct dt_node_base;
+struct dt_node_iter;
+typedef bool (*node_predicate_t)(struct dt_node_iter*, struct dt_node_base*);
+
+
 #define PHND_NULL    ((dt_phnd_t)-1)
 
 struct fdt_header {
@@ -81,7 +89,7 @@ struct dt_prop_val
         {
             union {
                 const char*  str_val;
-                const char** str_lst;
+                const char*  str_lst;
             };
             ptr_t        ptr_val;
             
@@ -105,8 +113,18 @@ struct dt_prop
     struct dt_prop_val  val;
 };
 
+struct dt_prop_table
+{
+    union {
+        struct hbucket    other_props[0];
+        struct hbucket    _op_bucket[8];
+    };
+};
+
 struct dt_node_base
 {
+    morph_t mobj;
+
     union {
         struct {
             unsigned char addr_c;
@@ -122,27 +140,21 @@ struct dt_node_base
             bool dma_coherent  : 1;
             bool dma_ncoherent : 1;
             bool intr_controll : 1;
-            unsigned int other : 29;
+            bool intr_neuxs    : 1;
         };
         unsigned int    flags;
     };
 
     struct dt_node_base  *parent;
-    struct llist_header   children;
-    struct llist_header   siblings;
     struct llist_header   nodes;
-    struct hlist_node     phnd_link;
-
-    const char*           name;
 
     struct dt_prop_val    compat;
-    const char*           model;
     dt_phnd_t             phandle;
 
-    union {
-        struct hbucket    other_props[0];
-        struct hbucket    _op_bucket[8];
-    };
+    struct dt_prop_table* props;
+
+    void* obj;
+    morph_t* binded_dev;
 };
 
 struct dt_root
@@ -155,6 +167,33 @@ struct dt_root
 
 struct dt_intr_prop;
 
+struct dt_intr_mapkey
+{
+    unsigned int* val;
+    unsigned int  size;
+};
+
+struct dt_intr_mapent
+{
+    struct llist_header ents;
+
+    struct dt_intr_mapkey key;
+
+    struct dt_node_base* parent;
+    struct dt_prop_val parent_props;
+};
+
+struct dt_intr_map 
+{
+    struct dt_prop_val       raw;
+    struct dt_prop_val       raw_mask;
+
+    struct dt_intr_mapkey    key_mask;
+    struct llist_header      mapent;
+
+    bool resolved;
+};
+
 struct dt_intr_node
 {
     union {
@@ -164,22 +203,28 @@ struct dt_intr_node
 
     struct {
         bool extended;
+        bool valid;
         union {
             struct dt_prop_val   arr;
             struct llist_header  values; 
         };
     } intr;
 
-    struct dt_prop_val       intr_map;
-    struct dt_prop_val       intr_map_mask;
+    struct dt_intr_map* map;
 };
-#define DT_NODE(intr_node) \
+#define INTR_TO_DTNODE(intr_node) \
         (container_of(intr_node, struct dt_node, intr))
 
+#define BASE_TO_DTNODE(base_node) \
+        (container_of(base_node, struct dt_node, base))
 
 struct dt_node
 {
-    struct dt_node_base base;
+    union {
+        morph_t mobj;
+        struct dt_node_base base;
+    };
+    
     struct dt_intr_node intr;
     
     struct dt_prop_val  reg;
@@ -188,7 +233,9 @@ struct dt_node
     struct dt_prop_val  ranges;
     struct dt_prop_val  dma_ranges;
 };
-
+#define dt_parent(node) ((node)->base.parent)
+#define dt_morpher       morphable_attrs(dt_node, mobj)
+#define dt_mobj(node)   (&(node)->mobj)
 
 struct dt_intr_prop
 {
@@ -241,11 +288,15 @@ struct dt_node_iter
 {
     struct dt_node_base* head;
     struct dt_node_base* matched;
-    const char *name;
+    void* closure;
+    node_predicate_t pred;
 };
 
-#define dtnode_child_foreach(node_base, pos, n)  \
-        llist_for_each(pos, n, &(node_base)->children, siblings)
+
+
+/****
+ * FDT Related
+ ****/
 
 #define fdt_prop(tok) ((tok)->token == FDT_PROP)
 #define fdt_node(tok) ((tok)->token == FDT_NOD_BEGIN)
@@ -274,6 +325,16 @@ fdt_memrsvd_itnext(struct fdt_memrsvd_iter* rsvdi);
 void
 fdt_memrsvd_itend(struct fdt_memrsvd_iter* rsvdi);
 
+static inline char*
+fdtit_prop_key(struct fdt_iter* fdti)
+{
+    return &fdti->str_block[fdti->prop->nameoff];
+}
+
+
+/****
+ * DT Main Functions: General
+ ****/
 
 bool
 dt_load(ptr_t dtb_dropoff);
@@ -282,11 +343,44 @@ struct dt_node*
 dt_resolve_phandle(dt_phnd_t phandle);
 
 struct dt_prop_val*
-dt_getprop(struct dt_node* node, const char* name);
+dt_getprop(struct dt_node_base* base, const char* name);
+
+struct dt_prop_val*
+dt_resolve_interrupt(struct dt_node* node);
 
 void
-dt_begin_find(struct dt_node_iter* iter, 
-              struct dt_node* node, const char* name);
+dt_resolve_interrupt_map(struct dt_node* node);
+
+static inline unsigned int
+dt_addr_cells(struct dt_node_base* base)
+{
+    return base->parent ? base->parent->addr_c : base->addr_c;
+}
+
+static inline unsigned int
+dt_size_cells(struct dt_node_base* base)
+{
+    return base->parent ? base->parent->sz_c : base->sz_c;
+}
+
+
+/****
+ * DT Main Functions: Node-finder
+ ****/
+
+void
+dt_begin_find_byname(struct dt_node_iter* iter, 
+                     struct dt_node* node, const char* name);
+
+void
+dt_begin_find(struct dt_node_iter* iter, struct dt_node* node, 
+              node_predicate_t pred, void* closure);
+
+static inline void
+dt_end_find(struct dt_node_iter* iter)
+{
+    // currently do nothing, keep only for semantic
+}
 
 bool
 dt_find_next(struct dt_node_iter* iter,
@@ -298,13 +392,34 @@ dt_found_any(struct dt_node_iter* iter)
     return !!iter->matched;
 }
 
+struct dt_context*
+dt_main_context();
 
-static inline char*
-fdtit_prop_key(struct fdt_iter* fdti)
+
+/****
+ * DT Main Functions: Node-binding
+ ****/
+
+static inline void
+dt_bind_object(struct dt_node_base* base, void* obj)
 {
-    return &fdti->str_block[fdti->prop->nameoff];
+    base->obj = obj;
+}
+
+static inline bool
+dt_has_binding(struct dt_node_base* base) 
+{
+    return base->obj != NULL;
 }
 
+#define dt_binding_of(node_base, type)  \
+    ((type)(node_base)->obj)
+
+
+/****
+ * DT Main Functions: Prop decoders
+ ****/
+
 static inline void
 dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node, 
                 struct dt_prop_val* val, unsigned int ent_sz)
@@ -319,27 +434,17 @@ dt_decode(struct dt_prop_iter* dtpi, struct dt_node_base* node,
 }
 
 #define dt_decode_reg(dtpi, node, field) \
-            dt_decode(dtpi, &(node)->base, (node)->(field), \
-                            (node)->base.sz_c + (node)->base.addr_c);
+            dt_decode(dtpi, &(node)->base, &(node)->field, \
+                        dt_size_cells(&(node)->base) \
+                            + dt_addr_cells(&(node)->base))
 
 #define dt_decode_range(dtpi, node, field) \
-            dt_decode(dtpi, &(node)->base, (node)->field, \
-                            (node)->base.sz_c * 2 + (node)->base.addr_c);
-
-static inline void
-dt_decode_intrmap(struct dt_prop_iter* dtpi, 
-                  struct dt_intr_node* intr_node)
-{
-    unsigned int size;
-    struct dt_node* node;
-    struct dt_node_base* base;
-    
-    node = DT_NODE(intr_node);
-    base = &node->base;
-    size = (base->addr_c + base->intr_c) * 2 + 1;
+            dt_decode(dtpi, &(node)->base, &(node)->field, \
+                        dt_size_cells(&(node)->base) * 2 \
+                            + dt_addr_cells(&(node)->base))
 
-    dt_decode(dtpi, base, &intr_node->intr_map, size);
-}
+#define dt_decode_simple(dtpi, prop) \
+            dt_decode(dtpi, NULL, prop, 1);
 
 #define dtprop_off(dtpi) \
             (unsigned int)(\
@@ -349,6 +454,11 @@ dt_decode_intrmap(struct dt_prop_iter* dtpi,
 #define dtprop_extract(dtpi, off) \
             ( (dt_enc_t) (&(dtpi)->prop_loc[(off)]) )
 
+#define dtprop_strlst_foreach(pos, prop)    \
+        for (pos = (prop)->str_lst; \
+             pos <= &(prop)->str_lst[(prop)->size]; \
+             pos = &pos[strlen(pos) + 1])
+
 static inline bool
 dtprop_next_n(struct dt_prop_iter* dtpi, int n)
 {
@@ -404,78 +514,68 @@ dtprop_to_u64(dt_enc_t enc_val)
     return le64(*(u64_t*)enc_val);
 }
 
-static inline dt_enc_t
-dtprop_reg_addr(struct dt_prop_iter* dtpi)
+static inline u32_t
+dtprop_u32_at(struct dt_prop_iter* dtpi, int index)
 {
-    return dtprop_extract(dtpi, 0);
+    return dtprop_to_u32(dtprop_extract(dtpi, index));
 }
 
-static inline dt_enc_t
-dtprop_reg_len(struct dt_prop_iter* dtpi)
+static inline u32_t
+dtprop_u64_at(struct dt_prop_iter* dtpi, int index)
 {
-    return dtprop_extract(dtpi, dtpi->node->addr_c);
+    return dtprop_to_u64(dtprop_extract(dtpi, index));
 }
 
 static inline dt_enc_t
-dtprop_range_childbus(struct dt_prop_iter* dtpi)
+dtprop_reg_addr(struct dt_prop_iter* dtpi)
 {
     return dtprop_extract(dtpi, 0);
 }
 
-static inline dt_enc_t
-dtprop_range_parentbus(struct dt_prop_iter* dtpi)
+static inline ptr_t
+dtprop_reg_nextaddr(struct dt_prop_iter* dtpi)
 {
-    return dtprop_extract(dtpi, dtpi->node->addr_c);
-}
+    ptr_t t;
 
-static inline dt_enc_t
-dtprop_range_len(struct dt_prop_iter* dtpi)
-{
-    return dtprop_extract(dtpi, dtpi->node->addr_c * 2);
-}
+    t = (ptr_t)dtprop_to_u64(dtprop_reg_addr(dtpi));
+    dtprop_next_n(dtpi, dt_addr_cells(dtpi->node));
 
-static inline dt_enc_t
-dtprop_intr_cuaddr(struct dt_prop_iter* dtpi)
-{
-    return dtprop_extract(dtpi, 0);
+    return t;
 }
 
 static inline dt_enc_t
-dtprop_intr_cispec(struct dt_prop_iter* dtpi)
+dtprop_reg_len(struct dt_prop_iter* dtpi)
 {
     return dtprop_extract(dtpi, dtpi->node->addr_c);
 }
 
-static inline struct dt_intr_node*
-dtprop_intr_parent(struct dt_prop_iter* dtpi)
+static inline size_t
+dtprop_reg_nextlen(struct dt_prop_iter* dtpi)
 {
-    unsigned off;
-    struct dt_node* node;
-    dt_enc_t enc_val;
+    size_t t;
 
-    off = dtpi->node->addr_c + dtpi->node->intr_c;
-    enc_val = dtprop_extract(dtpi, off);
-    node = dt_resolve_phandle(dtprop_to_phnd(enc_val));
-    
-    return &node->intr;
+    t = (size_t)dtprop_to_u64(dtprop_reg_len(dtpi));
+    dtprop_next_n(dtpi, dt_size_cells(dtpi->node));
+
+    return t;
 }
 
 static inline dt_enc_t
-dtprop_intr_puaddr(struct dt_prop_iter* dtpi)
+dtprop_range_childbus(struct dt_prop_iter* dtpi)
 {
-    unsigned off;
-
-    off = dtpi->node->addr_c + dtpi->node->intr_c + 1;
-    return dtprop_extract(dtpi, off);
+    return dtprop_extract(dtpi, 0);
 }
 
 static inline dt_enc_t
-dtprop_intr_pispec(struct dt_prop_iter* dtpi)
+dtprop_range_parentbus(struct dt_prop_iter* dtpi)
 {
-    unsigned off;
+    return dtprop_extract(dtpi, dt_addr_cells(dtpi->node));
+}
 
-    off = dtpi->node->addr_c * 2 + dtpi->node->intr_c + 1;
-    return dtprop_extract(dtpi, off);
+static inline dt_enc_t
+dtprop_range_len(struct dt_prop_iter* dtpi)
+{
+    return dtprop_extract(dtpi, dt_addr_cells(dtpi->node) * 2);
 }
 
 #endif /* __LUNAIX_DEVTREE_H */