|
|
1.1 root 1: /*
2: * Creation Date: <2003/11/24 12:30:18 samuel>
3: * Time-stamp: <2004/01/07 19:37:38 samuel>
4: *
5: * <bindings.c>
6: *
7: * Forth bindings
8: *
9: * Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
10: *
11: * This program is free software; you can redistribute it and/or
12: * modify it under the terms of the GNU General Public License
13: * version 2
14: *
15: */
16:
17: #include "config.h"
18: #include "libopenbios/bindings.h"
19: #include "libc/string.h"
20: #include "libc/stdlib.h"
21: #include "libc/byteorder.h"
22:
23:
24: /************************************************************************/
25: /* forth interface glue */
26: /************************************************************************/
27:
28: void
29: push_str( const char *str )
30: {
31: PUSH( pointer2cell(str) );
32: PUSH( str ? strlen(str) : 0 );
33: }
34:
35: /* WARNING: sloooow - AVOID */
36: cell
37: feval( const char *str )
38: {
39: push_str( str );
40: return eword("evaluate", 2);
41: }
42:
43: cell
44: _eword( const char *word, xt_t *cache_xt, int nargs )
45: {
46: static xt_t catch_xt = 0;
47: cell ret = -1;
48:
49: if( !catch_xt )
50: catch_xt = findword("catch");
51: if( !*cache_xt )
52: *cache_xt = findword( (char*)word );
53:
54: if( *cache_xt ) {
55: PUSH_xt( *cache_xt );
56: enterforth( catch_xt );
57: if( (ret=POP()) )
58: dstackcnt -= nargs;
59: }
60: return ret;
61: }
62:
63: /* note: only the built-in dictionary is searched */
64: int
65: _fword( const char *word, xt_t *cache_xt )
66: {
67: if( !*cache_xt )
68: *cache_xt = findword( (char*)word );
69:
70: if( *cache_xt ) {
71: enterforth( *cache_xt );
72: return 0;
73: }
74: return -1;
75: }
76:
77: int
78: _selfword( const char *method, xt_t *cache_xt )
79: {
80: if( !*cache_xt )
81: *cache_xt = find_ih_method( method, my_self() );
82: if( *cache_xt ) {
83: enterforth( *cache_xt );
84: return 0;
85: }
86: return -1;
87: }
88:
89: int
90: _parword( const char *method, xt_t *cache_xt )
91: {
92: if( !*cache_xt )
93: *cache_xt = find_ih_method( method, my_parent() );
94: if( *cache_xt ) {
95: enterforth( *cache_xt );
96: return 0;
97: }
98: return -1;
99: }
100:
101: void
102: bind_func( const char *name, void (*func)(void) )
103: {
104: PUSH( pointer2cell(func) );
105: push_str( name );
106: fword("is-cfunc");
107: }
108:
109: void
110: bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) )
111: {
112: PUSH_xt( xt );
113: PUSH( arg );
114: PUSH( pointer2cell(func) );
115: push_str( name );
116: fword("is-xt-cfunc");
117: }
118:
119: xt_t
120: bind_noname_func( void (*func)(void) )
121: {
122: PUSH( pointer2cell(func) );
123: fword("is-noname-cfunc");
124: return POP_xt();
125: }
126:
127: void
128: throw( int error )
129: {
130: PUSH( error );
131: fword("throw");
132: }
133:
134:
135: /************************************************************************/
136: /* ihandle related */
137: /************************************************************************/
138:
139: phandle_t
140: ih_to_phandle( ihandle_t ih )
141: {
142: PUSH_ih( ih );
143: fword("ihandle>phandle");
144: return POP_ph();
145: }
146:
147: ihandle_t
148: my_parent( void )
149: {
150: fword("my-parent");
151: return POP_ih();
152: }
153:
154: ihandle_t
155: my_self( void )
156: {
157: fword("my-self");
158: return POP_ih();
159: }
160:
161: xt_t
162: find_package_method( const char *method, phandle_t ph )
163: {
164: push_str( method );
165: PUSH_ph( ph );
166: fword("find-method");
167: if( POP() )
168: return POP_xt();
169: return 0;
170: }
171:
172: xt_t
173: find_ih_method( const char *method, ihandle_t ih )
174: {
175: return find_package_method( method, ih_to_phandle(ih) );
176: }
177:
178:
179: xt_t
180: find_parent_method( const char *method )
181: {
182: return find_ih_method( method, my_parent() );
183: }
184:
185: void
186: call_package( xt_t xt, ihandle_t ihandle )
187: {
188: PUSH_xt( xt );
189: PUSH_ih( ihandle );
190: fword("call-package");
191: }
192:
193: void
194: call_parent( xt_t xt )
195: {
196: PUSH_xt( xt );
197: fword("call-parent");
198: }
199:
200: void
201: call_parent_method( const char *method )
202: {
203: push_str( method );
204: fword("$call-parent");
205: }
206:
207:
208: /************************************************************************/
209: /* open/close package/dev */
210: /************************************************************************/
211:
212: ihandle_t
213: open_dev( const char *spec )
214: {
215: push_str( spec );
216: fword("open-dev");
217: return POP_ih();
218: }
219:
220: void
221: close_dev( ihandle_t ih )
222: {
223: PUSH_ih( ih );
224: fword("close-dev");
225: }
226:
227: ihandle_t
228: open_package( const char *argstr, phandle_t ph )
229: {
230: push_str( argstr );
231: PUSH_ph( ph );
232: fword("open-package");
233: return POP_ih();
234: }
235:
236: void
237: close_package( ihandle_t ih )
238: {
239: PUSH_ih( ih );
240: fword("close-package");
241: }
242:
243:
244: /************************************************************************/
245: /* ihandle arguments */
246: /************************************************************************/
247:
248: char *
249: pop_fstr_copy( void )
250: {
251: int len = POP();
252: char *str, *p = (char*)cell2pointer(POP());
253: if( !len )
254: return NULL;
255: str = malloc( len + 1 );
256: if( !str )
257: return NULL;
258: memcpy( str, p, len );
259: str[len] = 0;
260: return str;
261: }
262:
263: char *
264: my_args_copy( void )
265: {
266: fword("my-args");
267: return pop_fstr_copy();
268: }
269:
270:
271: /************************************************************************/
272: /* properties */
273: /************************************************************************/
274:
275: void
276: set_property( phandle_t ph, const char *name, const char *buf, int len )
277: {
278: if( !ph ) {
279: printk("set_property: NULL phandle\n");
280: return;
281: }
282: PUSH(pointer2cell(buf));
283: PUSH(len);
284: push_str( name );
285: PUSH_ph(ph);
286: fword("set-property");
287: }
288:
289: void
290: set_int_property( phandle_t ph, const char *name, u32 val )
291: {
292: u32 swapped=__cpu_to_be32(val);
293: set_property( ph, name, (char*)&swapped, sizeof(swapped) );
294: }
295:
296: char *
297: get_property( phandle_t ph, const char *name, int *retlen )
298: {
299: int len;
300:
301: if( retlen )
302: *retlen = -1;
303:
304: push_str( name );
305: PUSH_ph( ph );
306: fword("get-package-property");
307: if( POP() )
308: return NULL;
309: len = POP();
310: if( retlen )
311: *retlen = len;
312: return (char*)cell2pointer(POP());
313: }
314:
315: u32
316: get_int_property( phandle_t ph, const char *name, int *retlen )
317: {
318: u32 *p;
319:
320: if( !(p=(u32 *)get_property(ph, name, retlen)) )
321: return 0;
322: return __be32_to_cpu(*p);
323: }
324:
325:
326: /************************************************************************/
327: /* device selection / iteration */
328: /************************************************************************/
329:
330: void
331: activate_dev( phandle_t ph )
332: {
333: PUSH_ph( ph );
334: fword("active-package!");
335: }
336:
337: phandle_t
338: activate_device( const char *str )
339: {
340: phandle_t ph = find_dev( str );
341: activate_dev( ph );
342: return ph;
343: }
344:
345: void
346: device_end( void )
347: {
348: fword("device-end");
349: }
350:
351: phandle_t
352: get_cur_dev( void )
353: {
354: fword("active-package");
355: return POP_ph();
356: }
357:
358: phandle_t
359: find_dev( const char *path )
360: {
361: phandle_t ret = 0;
362: push_str( path );
363: fword("(find-dev)");
364: if( POP() )
365: return POP_ph();
366: return ret;
367: }
368:
369: phandle_t
370: dt_iter_begin( void )
371: {
372: fword("iterate-tree-begin");
373: return POP_ph();
374: }
375:
376: phandle_t
377: dt_iterate( phandle_t last_tree )
378: {
379: if( !last_tree )
380: return dt_iter_begin();
381:
382: PUSH_ph( last_tree );
383: fword("iterate-tree");
384: return POP_ph();
385: }
386:
387: phandle_t
388: dt_iterate_type( phandle_t last_tree, const char *type )
389: {
390: if( !last_tree )
391: last_tree = dt_iter_begin();
392:
393: /* root node is never matched but we don't care about that */
394: while( (last_tree = dt_iterate(last_tree)) ) {
395: char *s = get_property( last_tree, "device_type", NULL );
396: if( s && !strcmp(type, s) )
397: break;
398: }
399: return last_tree;
400: }
401:
402:
403: /************************************************************************/
404: /* node methods */
405: /************************************************************************/
406:
407: void
408: make_openable( int only_parents )
409: {
410: phandle_t ph, save_ph = get_cur_dev();
411: PUSH_ph( save_ph );
412:
413: for( ;; ) {
414: if( only_parents++ )
415: fword("parent");
416: if( !(ph=POP_ph()) )
417: break;
418: activate_dev( ph );
419: PUSH_ph( ph );
420: fword("is-open");
421: }
422: activate_dev( save_ph );
423: }
424:
425: static void
426: call1_func( void )
427: {
428: void (*func)(cell v);
429: func = (void*)cell2pointer(POP());
430:
431: (*func)( POP() );
432: }
433:
434:
435: static void
436: add_methods( int flags, int size, const method_t *methods, int nmet )
437: {
438: xt_t xt=0;
439: int i;
440:
441: /* nodes might be matched multiple times */
442: if( find_package_method(methods[0].name, get_cur_dev()) )
443: return;
444:
445: if( size ) {
446: PUSH( size );
447: fword("is-ibuf");
448: xt = POP_xt();
449: }
450:
451: for( i=0; i<nmet; i++ ) {
452: /* null-name methods specify static initializers */
453: if( !methods[i].name ) {
454: typedef void (*initfunc)( void *p );
455: char *buf = NULL;
456: if( xt ) {
457: enterforth( xt );
458: buf = (char*)cell2pointer(POP());
459: }
460: (*(initfunc)methods[i].func)( buf );
461: continue;
462: }
463: if( !size )
464: bind_func( methods[i].name, methods[i].func );
465: else
466: bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func),
467: &call1_func );
468: }
469:
470: if( flags & INSTALL_OPEN )
471: make_openable(0);
472: }
473:
474: void
475: bind_node( int flags, int size, const char * const *paths, int npaths,
476: const method_t *methods, int nmet )
477: {
478: phandle_t save_ph = get_cur_dev();
479: int i;
480:
481: for( i=0; i<npaths; i++ ) {
482: const char *name = paths[i];
483:
484: /* type matching? */
485: if( *name == 'T' ) {
486: phandle_t ph = 0;
487: name++;
488: while( (ph=dt_iterate_type(ph, name)) ) {
489: activate_dev( ph );
490: add_methods( flags, size, methods, nmet );
491: }
492: continue;
493: }
494:
495: /* path patching */
496: if( activate_device(name) )
497: add_methods( flags, size, methods, nmet );
498: else if( *name == '+' ) {
499: /* create node (and missing parents) */
500: if( !activate_device(++name) ) {
501: push_str( name );
502: fword("create-node");
503: }
504: add_methods( flags, size, methods, nmet );
505: }
506: }
507: activate_dev( save_ph );
508: }
509:
510: phandle_t
511: bind_new_node( int flags, int size, const char *name,
512: const method_t *methods, int nmet )
513: {
514: phandle_t save_ph = get_cur_dev();
515: phandle_t new_ph;
516: /* create node */
517: push_str( name );
518: fword("create-node");
519: add_methods( flags, size, methods, nmet );
520: new_ph = get_cur_dev();
521:
522: activate_dev( save_ph );
523: return new_ph;
524: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.