diff options
Diffstat (limited to 'qemu/roms/openbios/libopenbios/bindings.c')
-rw-r--r-- | qemu/roms/openbios/libopenbios/bindings.c | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/qemu/roms/openbios/libopenbios/bindings.c b/qemu/roms/openbios/libopenbios/bindings.c new file mode 100644 index 000000000..5323421f5 --- /dev/null +++ b/qemu/roms/openbios/libopenbios/bindings.c @@ -0,0 +1,524 @@ +/* + * Creation Date: <2003/11/24 12:30:18 samuel> + * Time-stamp: <2004/01/07 19:37:38 samuel> + * + * <bindings.c> + * + * Forth bindings + * + * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 + * + */ + +#include "config.h" +#include "libopenbios/bindings.h" +#include "libc/string.h" +#include "libc/stdlib.h" +#include "libc/byteorder.h" + + +/************************************************************************/ +/* forth interface glue */ +/************************************************************************/ + +void +push_str( const char *str ) +{ + PUSH( pointer2cell(str) ); + PUSH( str ? strlen(str) : 0 ); +} + +/* WARNING: sloooow - AVOID */ +cell +feval( const char *str ) +{ + push_str( str ); + return eword("evaluate", 2); +} + +cell +_eword( const char *word, xt_t *cache_xt, int nargs ) +{ + static xt_t catch_xt = 0; + cell ret = -1; + + if( !catch_xt ) + catch_xt = findword("catch"); + if( !*cache_xt ) + *cache_xt = findword( (char*)word ); + + if( *cache_xt ) { + PUSH_xt( *cache_xt ); + enterforth( catch_xt ); + if( (ret=POP()) ) + dstackcnt -= nargs; + } + return ret; +} + +/* note: only the built-in dictionary is searched */ +int +_fword( const char *word, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = findword( (char*)word ); + + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +int +_selfword( const char *method, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = find_ih_method( method, my_self() ); + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +int +_parword( const char *method, xt_t *cache_xt ) +{ + if( !*cache_xt ) + *cache_xt = find_ih_method( method, my_parent() ); + if( *cache_xt ) { + enterforth( *cache_xt ); + return 0; + } + return -1; +} + +void +bind_func( const char *name, void (*func)(void) ) +{ + PUSH( pointer2cell(func) ); + push_str( name ); + fword("is-cfunc"); +} + +void +bind_xtfunc( const char *name, xt_t xt, ucell arg, void (*func)(void) ) +{ + PUSH_xt( xt ); + PUSH( arg ); + PUSH( pointer2cell(func) ); + push_str( name ); + fword("is-xt-cfunc"); +} + +xt_t +bind_noname_func( void (*func)(void) ) +{ + PUSH( pointer2cell(func) ); + fword("is-noname-cfunc"); + return POP_xt(); +} + +void +throw( int error ) +{ + PUSH( error ); + fword("throw"); +} + + +/************************************************************************/ +/* ihandle related */ +/************************************************************************/ + +phandle_t +ih_to_phandle( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("ihandle>phandle"); + return POP_ph(); +} + +ihandle_t +my_parent( void ) +{ + fword("my-parent"); + return POP_ih(); +} + +ihandle_t +my_self( void ) +{ + fword("my-self"); + return POP_ih(); +} + +xt_t +find_package_method( const char *method, phandle_t ph ) +{ + push_str( method ); + PUSH_ph( ph ); + fword("find-method"); + if( POP() ) + return POP_xt(); + return 0; +} + +xt_t +find_ih_method( const char *method, ihandle_t ih ) +{ + return find_package_method( method, ih_to_phandle(ih) ); +} + + +xt_t +find_parent_method( const char *method ) +{ + return find_ih_method( method, my_parent() ); +} + +void +call_package( xt_t xt, ihandle_t ihandle ) +{ + PUSH_xt( xt ); + PUSH_ih( ihandle ); + fword("call-package"); +} + +void +call_parent( xt_t xt ) +{ + PUSH_xt( xt ); + fword("call-parent"); +} + +void +call_parent_method( const char *method ) +{ + push_str( method ); + fword("$call-parent"); +} + + +/************************************************************************/ +/* open/close package/dev */ +/************************************************************************/ + +ihandle_t +open_dev( const char *spec ) +{ + push_str( spec ); + fword("open-dev"); + return POP_ih(); +} + +void +close_dev( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("close-dev"); +} + +ihandle_t +open_package( const char *argstr, phandle_t ph ) +{ + push_str( argstr ); + PUSH_ph( ph ); + fword("open-package"); + return POP_ih(); +} + +void +close_package( ihandle_t ih ) +{ + PUSH_ih( ih ); + fword("close-package"); +} + + +/************************************************************************/ +/* ihandle arguments */ +/************************************************************************/ + +char * +pop_fstr_copy( void ) +{ + int len = POP(); + char *str, *p = (char*)cell2pointer(POP()); + if( !len ) + return NULL; + str = malloc( len + 1 ); + if( !str ) + return NULL; + memcpy( str, p, len ); + str[len] = 0; + return str; +} + +char * +my_args_copy( void ) +{ + fword("my-args"); + return pop_fstr_copy(); +} + + +/************************************************************************/ +/* properties */ +/************************************************************************/ + +void +set_property( phandle_t ph, const char *name, const char *buf, int len ) +{ + if( !ph ) { + printk("set_property: NULL phandle\n"); + return; + } + PUSH(pointer2cell(buf)); + PUSH(len); + push_str( name ); + PUSH_ph(ph); + fword("set-property"); +} + +void +set_int_property( phandle_t ph, const char *name, u32 val ) +{ + u32 swapped=__cpu_to_be32(val); + set_property( ph, name, (char*)&swapped, sizeof(swapped) ); +} + +char * +get_property( phandle_t ph, const char *name, int *retlen ) +{ + int len; + + if( retlen ) + *retlen = -1; + + push_str( name ); + PUSH_ph( ph ); + fword("get-package-property"); + if( POP() ) + return NULL; + len = POP(); + if( retlen ) + *retlen = len; + return (char*)cell2pointer(POP()); +} + +u32 +get_int_property( phandle_t ph, const char *name, int *retlen ) +{ + u32 *p; + + if( !(p=(u32 *)get_property(ph, name, retlen)) ) + return 0; + return __be32_to_cpu(*p); +} + + +/************************************************************************/ +/* device selection / iteration */ +/************************************************************************/ + +void +activate_dev( phandle_t ph ) +{ + PUSH_ph( ph ); + fword("active-package!"); +} + +phandle_t +activate_device( const char *str ) +{ + phandle_t ph = find_dev( str ); + activate_dev( ph ); + return ph; +} + +void +device_end( void ) +{ + fword("device-end"); +} + +phandle_t +get_cur_dev( void ) +{ + fword("active-package"); + return POP_ph(); +} + +phandle_t +find_dev( const char *path ) +{ + phandle_t ret = 0; + push_str( path ); + fword("(find-dev)"); + if( POP() ) + return POP_ph(); + return ret; +} + +phandle_t +dt_iter_begin( void ) +{ + fword("iterate-tree-begin"); + return POP_ph(); +} + +phandle_t +dt_iterate( phandle_t last_tree ) +{ + if( !last_tree ) + return dt_iter_begin(); + + PUSH_ph( last_tree ); + fword("iterate-tree"); + return POP_ph(); +} + +phandle_t +dt_iterate_type( phandle_t last_tree, const char *type ) +{ + if( !last_tree ) + last_tree = dt_iter_begin(); + + /* root node is never matched but we don't care about that */ + while( (last_tree = dt_iterate(last_tree)) ) { + char *s = get_property( last_tree, "device_type", NULL ); + if( s && !strcmp(type, s) ) + break; + } + return last_tree; +} + + +/************************************************************************/ +/* node methods */ +/************************************************************************/ + +void +make_openable( int only_parents ) +{ + phandle_t ph, save_ph = get_cur_dev(); + PUSH_ph( save_ph ); + + for( ;; ) { + if( only_parents++ ) + fword("parent"); + if( !(ph=POP_ph()) ) + break; + activate_dev( ph ); + PUSH_ph( ph ); + fword("is-open"); + } + activate_dev( save_ph ); +} + +static void +call1_func( void ) +{ + void (*func)(cell v); + func = (void*)cell2pointer(POP()); + + (*func)( POP() ); +} + + +static void +add_methods( int flags, int size, const method_t *methods, int nmet ) +{ + xt_t xt=0; + int i; + + /* nodes might be matched multiple times */ + if( find_package_method(methods[0].name, get_cur_dev()) ) + return; + + if( size ) { + PUSH( size ); + fword("is-ibuf"); + xt = POP_xt(); + } + + for( i=0; i<nmet; i++ ) { + /* null-name methods specify static initializers */ + if( !methods[i].name ) { + typedef void (*initfunc)( void *p ); + char *buf = NULL; + if( xt ) { + enterforth( xt ); + buf = (char*)cell2pointer(POP()); + } + (*(initfunc)methods[i].func)( buf ); + continue; + } + if( !size ) + bind_func( methods[i].name, methods[i].func ); + else + bind_xtfunc( methods[i].name, xt, pointer2cell(methods[i].func), + &call1_func ); + } + + if( flags & INSTALL_OPEN ) + make_openable(0); +} + +void +bind_node( int flags, int size, const char * const *paths, int npaths, + const method_t *methods, int nmet ) +{ + phandle_t save_ph = get_cur_dev(); + int i; + + for( i=0; i<npaths; i++ ) { + const char *name = paths[i]; + + /* type matching? */ + if( *name == 'T' ) { + phandle_t ph = 0; + name++; + while( (ph=dt_iterate_type(ph, name)) ) { + activate_dev( ph ); + add_methods( flags, size, methods, nmet ); + } + continue; + } + + /* path patching */ + if( activate_device(name) ) + add_methods( flags, size, methods, nmet ); + else if( *name == '+' ) { + /* create node (and missing parents) */ + if( !activate_device(++name) ) { + push_str( name ); + fword("create-node"); + } + add_methods( flags, size, methods, nmet ); + } + } + activate_dev( save_ph ); +} + +phandle_t +bind_new_node( int flags, int size, const char *name, + const method_t *methods, int nmet ) +{ + phandle_t save_ph = get_cur_dev(); + phandle_t new_ph; + /* create node */ + push_str( name ); + fword("create-node"); + add_methods( flags, size, methods, nmet ); + new_ph = get_cur_dev(); + + activate_dev( save_ph ); + return new_ph; +} |