|
|
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.