1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-08-25     GuEe-GUI     first version
9  */
10 
11 #ifndef __OFW_H__
12 #define __OFW_H__
13 
14 #include <rtthread.h>
15 
16 #include <ref.h>
17 #include <bitmap.h>
18 
19 #include <libfdt/libfdt.h>
20 
21 typedef rt_uint32_t rt_phandle;
22 
23 struct rt_ofw_prop
24 {
25     const char *name;
26     int length;
27     void *value;
28 
29     struct rt_ofw_prop *next;
30 };
31 
32 struct rt_ofw_node
33 {
34     const char *name;
35     /* full_name is 'path/tag' or 'path/tag@reg' */
36     const char *full_name;
37     /* phandles range from 1 to 2^32-2 (0xfffffffe) */
38     rt_phandle phandle;
39 
40     struct rt_device *dev;
41     struct rt_ofw_prop *props;
42     struct rt_ofw_node *parent;
43     struct rt_ofw_node *child;
44     struct rt_ofw_node *sibling;
45 
46     struct rt_ref ref;
47 
48 #define RT_OFW_F_SYSTEM         0   /* node is system node */
49 #define RT_OFW_F_READLY         1   /* node has driver */
50 #define RT_OFW_F_PLATFORM       2   /* node is platform device */
51 #define RT_OFW_F_OVERLAY        3   /* node is from overlay */
52     rt_bitmap_t flags;
53 
54     /* RT-Thread object prototype */
55     void *rt_data;
56 };
57 
58 #define RT_OFW_MAX_CELL_ARGS    16
59 
60 struct rt_ofw_cell_args
61 {
62     void *data;
63 
64     int args_count;
65     rt_uint32_t args[RT_OFW_MAX_CELL_ARGS];
66 };
67 
68 struct rt_ofw_node_id
69 {
70     /* The name string should consist name property (deprecated) */
71     char name[32];
72 
73     /*
74      * The type string should consist device_type property, such as pci, memory
75      * serial. Because it's deprecated in <devicetree-basics>, we can use other
76      * name (like "ttyS" or "ttyAMA" ...) to config with /chosen.
77      */
78     char type[32];
79 
80     /*
81      * The compatible string should consist only of lowercase letters, digits
82      * and dashes, and should start with a letter. A single comma is typically
83      * only used following a vendor prefix. Underscores should not be used.
84      */
85     char compatible[128];
86 
87     const void *data;
88 };
89 
90 struct rt_ofw_stub
91 {
92     const struct rt_ofw_node_id *ids;
93     rt_err_t (*handler)(struct rt_ofw_node *np, const struct rt_ofw_node_id *id);
94 };
95 
96 #define RT_OFW_SYMBOL(_class, _level) \
97     rt_section(".rt_ofw_data." #_class "." #_level)
98 
99 #define RT_OFW_SYMBOL_TYPE_RANGE(_class, _type, _start, _end) \
100 static const rt_used RT_OFW_SYMBOL(_class, 0) _type _start; \
101 static const rt_used RT_OFW_SYMBOL(_class, end) _type _end; \
102 
103 #define RT_OFW_STUB_EXPORT(_name, _ids, _class, _handler, ...) \
104 static const struct rt_ofw_stub __rt_ofw_##_name    \
105 rt_used RT_OFW_SYMBOL(_class, __VA_ARGS__ _) =      \
106 {                                                   \
107     .ids = _ids,                                    \
108     .handler = _handler,                            \
109 }
110 
111 #define RT_OFW_STUB_RANGE_EXPORT(_class, _start, _end) \
112     RT_OFW_SYMBOL_TYPE_RANGE(_class, struct rt_ofw_stub, _start = {}, _end = {})
113 
114 #define rt_ofw_data(np)  ((struct rt_ofw_node *)np)->rt_data
115 
rt_ofw_node_test_flag(const struct rt_ofw_node * np,int flag)116 rt_inline rt_bool_t rt_ofw_node_test_flag(const struct rt_ofw_node *np, int flag)
117 {
118     return rt_bitmap_test_bit((rt_bitmap_t *)&np->flags, flag);
119 }
120 
rt_ofw_node_set_flag(struct rt_ofw_node * np,int flag)121 rt_inline void rt_ofw_node_set_flag(struct rt_ofw_node *np, int flag)
122 {
123     rt_bitmap_set_bit(&np->flags, flag);
124 }
125 
rt_ofw_node_test_and_set_flag(struct rt_ofw_node * np,int flag)126 rt_inline rt_bool_t rt_ofw_node_test_and_set_flag(struct rt_ofw_node *np, int flag)
127 {
128     rt_bool_t res = rt_ofw_node_test_flag(np, flag);
129 
130     rt_ofw_node_set_flag(np, flag);
131 
132     return res;
133 }
134 
rt_ofw_node_clear_flag(struct rt_ofw_node * np,int flag)135 rt_inline void rt_ofw_node_clear_flag(struct rt_ofw_node *np, int flag)
136 {
137     rt_bitmap_clear_bit(&np->flags, flag);
138 }
139 
140 rt_err_t rt_ofw_node_destroy(struct rt_ofw_node *np);
141 
142 struct rt_ofw_node *rt_ofw_node_get(struct rt_ofw_node *np);
143 void rt_ofw_node_put(struct rt_ofw_node *np);
144 
145 rt_bool_t rt_ofw_node_tag_equ(const struct rt_ofw_node *np, const char *tag);
146 rt_bool_t rt_ofw_node_tag_prefix(const struct rt_ofw_node *np, const char *prefix);
147 
rt_ofw_node_name(const struct rt_ofw_node * np)148 rt_inline const char *rt_ofw_node_name(const struct rt_ofw_node *np)
149 {
150     return np ? np->name : "<no-node>";
151 }
152 
rt_ofw_node_full_name(const struct rt_ofw_node * np)153 rt_inline const char *rt_ofw_node_full_name(const struct rt_ofw_node *np)
154 {
155     return np ? np->full_name : "<no-node>";
156 }
157 
158 rt_bool_t rt_ofw_machine_is_compatible(const char *compatible);
159 rt_bool_t rt_ofw_node_is_available(const struct rt_ofw_node *np);
160 rt_bool_t rt_ofw_node_is_compatible(const struct rt_ofw_node *np, const char *compatible);
161 
162 struct rt_ofw_node_id *rt_ofw_prop_match(struct rt_ofw_prop *prop, const struct rt_ofw_node_id *ids);
163 struct rt_ofw_node_id *rt_ofw_node_match(struct rt_ofw_node *np, const struct rt_ofw_node_id *ids);
164 
165 struct rt_ofw_node *rt_ofw_find_node_by_tag(struct rt_ofw_node *from, const char *tag);
166 struct rt_ofw_node *rt_ofw_find_node_by_prop_r(struct rt_ofw_node *from, const char *propname,
167         const struct rt_ofw_prop **out_prop);
168 
rt_ofw_find_node_by_prop(struct rt_ofw_node * from,const char * propname)169 rt_inline struct rt_ofw_node *rt_ofw_find_node_by_prop(struct rt_ofw_node *from, const char *propname)
170 {
171     return rt_ofw_find_node_by_prop_r(from, propname, RT_NULL);
172 }
173 
174 struct rt_ofw_node *rt_ofw_find_node_by_name(struct rt_ofw_node *from, const char *name);
175 struct rt_ofw_node *rt_ofw_find_node_by_type(struct rt_ofw_node *from, const char *type);
176 struct rt_ofw_node *rt_ofw_find_node_by_compatible(struct rt_ofw_node *from, const char *compatible);
177 struct rt_ofw_node *rt_ofw_find_node_by_ids_r(struct rt_ofw_node *from, const struct rt_ofw_node_id *ids,
178         const struct rt_ofw_node_id **out_id);
179 struct rt_ofw_node *rt_ofw_find_node_by_path(const char *path);
180 struct rt_ofw_node *rt_ofw_find_node_by_phandle(rt_phandle phandle);
181 
rt_ofw_find_node_by_ids(struct rt_ofw_node * from,const struct rt_ofw_node_id * ids)182 rt_inline struct rt_ofw_node *rt_ofw_find_node_by_ids(struct rt_ofw_node *from, const struct rt_ofw_node_id *ids)
183 {
184     return rt_ofw_find_node_by_ids_r(from, ids, RT_NULL);
185 }
186 
187 struct rt_ofw_node *rt_ofw_get_parent(const struct rt_ofw_node *np);
188 struct rt_ofw_node *rt_ofw_get_child_by_tag(const struct rt_ofw_node *parent, const char *tag);
189 struct rt_ofw_node *rt_ofw_get_child_by_compatible(const struct rt_ofw_node *parent, const char *compatible);
190 
191 int rt_ofw_get_child_count(const struct rt_ofw_node *np);
192 int rt_ofw_get_available_child_count(const struct rt_ofw_node *np);
193 
194 struct rt_ofw_node *rt_ofw_get_next_node(struct rt_ofw_node *prev);
195 struct rt_ofw_node *rt_ofw_get_next_parent(struct rt_ofw_node *prev);
196 struct rt_ofw_node *rt_ofw_get_next_child(const struct rt_ofw_node *parent, struct rt_ofw_node *prev);
197 struct rt_ofw_node *rt_ofw_get_next_available_child(const struct rt_ofw_node *parent, struct rt_ofw_node *prev);
198 
199 struct rt_ofw_node *rt_ofw_get_cpu_node(int cpu, int *thread, rt_bool_t (*match_cpu_hwid)(int cpu, rt_uint64_t hwid));
200 struct rt_ofw_node *rt_ofw_get_next_cpu_node(struct rt_ofw_node *prev);
201 struct rt_ofw_node *rt_ofw_get_cpu_state_node(struct rt_ofw_node *cpu_np, int index);
202 rt_uint64_t rt_ofw_get_cpu_id(struct rt_ofw_node *cpu_np);
203 rt_uint64_t rt_ofw_get_cpu_hwid(struct rt_ofw_node *cpu_np, unsigned int thread);
204 
205 struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id);
206 int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag);
207 int rt_ofw_get_alias_last_id(const char *tag);
208 
209 rt_err_t rt_ofw_map_id(struct rt_ofw_node *np, rt_uint32_t id, const char *map_name, const char *map_mask_name,
210         struct rt_ofw_node **ref_np, rt_uint32_t *out_id);
211 
212 struct rt_ofw_node *rt_ofw_append_child(struct rt_ofw_node *parent, const char *full_name);
213 rt_err_t rt_ofw_append_prop(struct rt_ofw_node *np, const char *name, int length, void *value);
214 
215 struct rt_ofw_node *rt_ofw_parse_phandle(const struct rt_ofw_node *np, const char *phandle_name, int index);
216 rt_err_t rt_ofw_parse_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name,
217         int index, struct rt_ofw_cell_args *out_args);
218 int rt_ofw_count_phandle_cells(const struct rt_ofw_node *np, const char *list_name, const char *cells_name);
219 
220 const char *rt_ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const char *name);
221 struct rt_ofw_prop *rt_ofw_get_prop(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length);
222 
rt_ofw_prop_read_raw(const struct rt_ofw_node * np,const char * name,rt_ssize_t * out_length)223 rt_inline const void *rt_ofw_prop_read_raw(const struct rt_ofw_node *np, const char *name, rt_ssize_t *out_length)
224 {
225     struct rt_ofw_prop *prop = rt_ofw_get_prop(np, name, out_length);
226 
227     return prop ? prop->value : RT_NULL;
228 }
229 
230 int rt_ofw_prop_read_u8_array_index(const struct rt_ofw_node *np, const char *propname,
231         int index, int nr, rt_uint8_t *out_values);
232 int rt_ofw_prop_read_u16_array_index(const struct rt_ofw_node *np, const char *propname,
233         int index, int nr, rt_uint16_t *out_values);
234 int rt_ofw_prop_read_u32_array_index(const struct rt_ofw_node *np, const char *propname,
235         int index, int nr, rt_uint32_t *out_values);
236 int rt_ofw_prop_read_u64_array_index(const struct rt_ofw_node *np, const char *propname,
237         int index, int nr, rt_uint64_t *out_values);
238 int rt_ofw_prop_read_string_array_index(const struct rt_ofw_node *np, const char *propname,
239         int index, int nr, const char **out_strings);
240 
241 int rt_ofw_prop_count_of_size(const struct rt_ofw_node *np, const char *propname, int size);
242 int rt_ofw_prop_index_of_string(const struct rt_ofw_node *np, const char *propname, const char *string);
243 
244 const fdt32_t *rt_ofw_prop_next_u32(struct rt_ofw_prop *prop, const fdt32_t *cur, rt_uint32_t *out_value);
245 const char *rt_ofw_prop_next_string(struct rt_ofw_prop *prop, const char *cur);
246 
rt_ofw_prop_read_u8_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint8_t * out_value)247 rt_inline rt_err_t rt_ofw_prop_read_u8_index(const struct rt_ofw_node *np, const char *propname,
248         int index, rt_uint8_t *out_value)
249 {
250     int nr = rt_ofw_prop_read_u8_array_index(np, propname, index, 1, out_value);
251 
252     return nr > 0 ? RT_EOK : (rt_err_t)nr;
253 }
254 
rt_ofw_prop_read_u16_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint16_t * out_value)255 rt_inline rt_err_t rt_ofw_prop_read_u16_index(const struct rt_ofw_node *np, const char *propname,
256         int index, rt_uint16_t *out_value)
257 {
258     int nr = rt_ofw_prop_read_u16_array_index(np, propname, index, 1, out_value);
259 
260     return nr > 0 ? RT_EOK : (rt_err_t)nr;
261 }
262 
rt_ofw_prop_read_u32_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint32_t * out_value)263 rt_inline rt_err_t rt_ofw_prop_read_u32_index(const struct rt_ofw_node *np, const char *propname,
264         int index, rt_uint32_t *out_value)
265 {
266     int nr = rt_ofw_prop_read_u32_array_index(np, propname, index, 1, out_value);
267 
268     return nr > 0 ? RT_EOK : (rt_err_t)nr;
269 }
270 
rt_ofw_prop_read_u64_index(const struct rt_ofw_node * np,const char * propname,int index,rt_uint64_t * out_value)271 rt_inline rt_err_t rt_ofw_prop_read_u64_index(const struct rt_ofw_node *np, const char *propname,
272         int index, rt_uint64_t *out_value)
273 {
274     int nr = rt_ofw_prop_read_u64_array_index(np, propname, index, 1, out_value);
275 
276     return nr > 0 ? RT_EOK : (rt_err_t)nr;
277 }
278 
rt_ofw_prop_read_string_index(const struct rt_ofw_node * np,const char * propname,int index,const char ** out_string)279 rt_inline rt_err_t rt_ofw_prop_read_string_index(const struct rt_ofw_node *np, const char *propname,
280         int index, const char **out_string)
281 {
282     int nr = rt_ofw_prop_read_string_array_index(np, propname, index, 1, out_string);
283 
284     return nr > 0 ? RT_EOK : (rt_err_t)nr;
285 }
286 
rt_ofw_prop_read_u8(const struct rt_ofw_node * np,const char * propname,rt_uint8_t * out_value)287 rt_inline rt_err_t rt_ofw_prop_read_u8(const struct rt_ofw_node *np, const char *propname,
288         rt_uint8_t *out_value)
289 {
290     return rt_ofw_prop_read_u8_index(np, propname, 0, out_value);
291 }
292 
rt_ofw_prop_read_u16(const struct rt_ofw_node * np,const char * propname,rt_uint16_t * out_value)293 rt_inline rt_err_t rt_ofw_prop_read_u16(const struct rt_ofw_node *np, const char *propname,
294         rt_uint16_t *out_value)
295 {
296     return rt_ofw_prop_read_u16_index(np, propname, 0, out_value);
297 }
298 
rt_ofw_prop_read_u32(const struct rt_ofw_node * np,const char * propname,rt_uint32_t * out_value)299 rt_inline rt_err_t rt_ofw_prop_read_u32(const struct rt_ofw_node *np, const char *propname,
300         rt_uint32_t *out_value)
301 {
302     return rt_ofw_prop_read_u32_index(np, propname, 0, out_value);
303 }
304 
rt_ofw_prop_read_s32(const struct rt_ofw_node * np,const char * propname,rt_int32_t * out_value)305 rt_inline rt_err_t rt_ofw_prop_read_s32(const struct rt_ofw_node *np, const char *propname,
306         rt_int32_t *out_value)
307 {
308     return rt_ofw_prop_read_u32_index(np, propname, 0, (rt_uint32_t *)out_value);
309 }
310 
rt_ofw_prop_read_u64(const struct rt_ofw_node * np,const char * propname,rt_uint64_t * out_value)311 rt_inline rt_err_t rt_ofw_prop_read_u64(const struct rt_ofw_node *np, const char *propname,
312         rt_uint64_t *out_value)
313 {
314     return rt_ofw_prop_read_u64_index(np, propname, 0, out_value);
315 }
316 
rt_ofw_prop_read_string(const struct rt_ofw_node * np,const char * propname,const char ** out_string)317 rt_inline rt_err_t rt_ofw_prop_read_string(const struct rt_ofw_node *np, const char *propname,
318         const char **out_string)
319 {
320     return rt_ofw_prop_read_string_index(np, propname, 0, out_string);
321 }
322 
rt_ofw_prop_read_bool(const struct rt_ofw_node * np,const char * propname)323 rt_inline rt_bool_t rt_ofw_prop_read_bool(const struct rt_ofw_node *np, const char *propname)
324 {
325     return rt_ofw_get_prop(np, propname, RT_NULL) ? RT_TRUE : RT_FALSE;
326 }
327 
rt_ofw_prop_count_of_u8(const struct rt_ofw_node * np,const char * propname)328 rt_inline int rt_ofw_prop_count_of_u8(const struct rt_ofw_node *np, const char *propname)
329 {
330     return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint8_t));
331 }
332 
rt_ofw_prop_count_of_u16(const struct rt_ofw_node * np,const char * propname)333 rt_inline int rt_ofw_prop_count_of_u16(const struct rt_ofw_node *np, const char *propname)
334 {
335     return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint16_t));
336 }
337 
rt_ofw_prop_count_of_u32(const struct rt_ofw_node * np,const char * propname)338 rt_inline int rt_ofw_prop_count_of_u32(const struct rt_ofw_node *np, const char *propname)
339 {
340     return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint32_t));
341 }
342 
rt_ofw_prop_count_of_u64(const struct rt_ofw_node * np,const char * propname)343 rt_inline int rt_ofw_prop_count_of_u64(const struct rt_ofw_node *np, const char *propname)
344 {
345     return rt_ofw_prop_count_of_size(np, propname, sizeof(rt_uint64_t));
346 }
347 
rt_ofw_node_type(const struct rt_ofw_node * np)348 rt_inline const char *rt_ofw_node_type(const struct rt_ofw_node *np)
349 {
350     return rt_ofw_prop_read_raw(np, "device_type", RT_NULL);
351 }
352 
rt_ofw_node_is_type(const struct rt_ofw_node * np,const char * type)353 rt_inline rt_bool_t rt_ofw_node_is_type(const struct rt_ofw_node *np, const char *type)
354 {
355     const char *get_type = rt_ofw_node_type(np);
356 
357     return np && get_type && type && !rt_strcmp(get_type, type);
358 }
359 
360 #define rt_ofw_foreach_node_by_tag(np, name)                \
361     for (np = rt_ofw_find_node_by_tag(RT_NULL, name); np;   \
362          np = rt_ofw_find_node_by_tag(np, name))
363 
364 #define rt_ofw_foreach_node_by_prop(np, prop_name)          \
365     for (np = rt_ofw_find_node_by_prop(RT_NULL, prop_name); \
366         np; np = rt_ofw_find_node_by_prop(np, prop_name))
367 
368 #define rt_ofw_foreach_node_by_prop_r(np, prop_name, prop)          \
369     for (np = rt_ofw_find_node_by_prop_r(RT_NULL, prop_name, prop); \
370         np; np = rt_ofw_find_node_by_prop_r(np, prop_name, prop))
371 
372 #define rt_ofw_foreach_node_by_name(np, name)               \
373     for (np = rt_ofw_find_node_by_name(RT_NULL, name); np;  \
374          np = rt_ofw_find_node_by_name(np, name))
375 
376 #define rt_ofw_foreach_node_by_type(np, type)               \
377     for (np = rt_ofw_find_node_by_type(RT_NULL, type); np;  \
378          np = rt_ofw_find_node_by_type(np, type))
379 
380 #define rt_ofw_foreach_node_by_compatible(np, compatible)               \
381     for (np = rt_ofw_find_node_by_compatible(RT_NULL, compatible); np;  \
382          np = rt_ofw_find_node_by_compatible(np, compatible))
383 
384 #define rt_ofw_foreach_node_by_ids_r(np, id, ids)           \
385     for (np = rt_ofw_find_node_by_ids_r(RT_NULL, ids, id);  \
386         np; np = rt_ofw_find_node_by_ids_r(np, ids, id))
387 
388 #define rt_ofw_foreach_node_by_ids(np, ids)                 \
389     for (np = rt_ofw_find_node_by_ids(RT_NULL, ids); np;    \
390          np = rt_ofw_find_node_by_ids(np, ids))
391 
392 #define rt_ofw_foreach_nodes(from, np)      \
393     for (np = rt_ofw_get_next_node(from);   \
394         np; np = rt_ofw_get_next_node(np))
395 
396 #define rt_ofw_foreach_allnodes(np) \
397     rt_ofw_foreach_nodes(RT_NULL, np)
398 
399 #define rt_ofw_foreach_parent_node(np)                      \
400     for (np = rt_ofw_get_next_parent(rt_ofw_node_get(np));  \
401         np; np = rt_ofw_get_next_parent(np))
402 
403 #define rt_ofw_foreach_child_node(parent, child)            \
404     for (child = rt_ofw_get_next_child(parent, RT_NULL);    \
405         child; child = rt_ofw_get_next_child(parent, child))
406 
407 #define rt_ofw_foreach_available_child_node(parent, child)                  \
408     for (child = rt_ofw_get_next_available_child(parent, RT_NULL); child;   \
409          child = rt_ofw_get_next_available_child(parent, child))
410 
411 #define rt_ofw_foreach_cpu_node(cpu_np)                     \
412     for (cpu_np = rt_ofw_get_next_cpu_node(RT_NULL);        \
413         cpu_np; cpu_np = rt_ofw_get_next_cpu_node(cpu_np))
414 
415 #define rt_ofw_foreach_prop(np, prop)   \
416     for (prop = np->props; prop; prop = prop->next)
417 
418 #define rt_ofw_foreach_prop_u32(np, propname, prop, p, u)   \
419     for (prop = rt_ofw_get_prop(np, propname, RT_NULL),     \
420         p = rt_ofw_prop_next_u32(prop, RT_NULL, &u); p;     \
421         p = rt_ofw_prop_next_u32(prop, p, &u))
422 
423 #define rt_ofw_foreach_prop_string(np, propname, prop, s)   \
424     for (prop = rt_ofw_get_prop(np, propname, RT_NULL),     \
425         s = rt_ofw_prop_next_string(prop, RT_NULL); s;      \
426         s = rt_ofw_prop_next_string(prop, s))
427 
428 #define rt_ofw_foreach_stub(stub, stub_start, stub_end) \
429     for (stub = stub_start; stub <= stub_end; ++stub)
430 
431 struct rt_ofw_stub *rt_ofw_stub_probe_range(struct rt_ofw_node *np,
432         const struct rt_ofw_stub *stub_start, const struct rt_ofw_stub *stub_end);
433 
434 struct rt_object *rt_ofw_parse_object(struct rt_ofw_node *np, const char *obj_name, const char *cells_name);
435 
436 rt_err_t rt_ofw_console_setup(void);
437 const char *rt_ofw_bootargs_select(const char *key, int index);
438 
439 #ifdef RT_USING_CONSOLE
440 void rt_ofw_node_dump_dts(struct rt_ofw_node *np, rt_bool_t sibling_too);
441 #endif
442 
443 #endif /* __OFW_H__ */
444