blob: f83ef7ac0ac1c8b44c94834a018a7d42f91ea0cb [file] [log] [blame]
\ tag: Package access.
\
\ this code implements IEEE 1275-1994 ch. 5.3.4
\
\ Copyright (C) 2003 Stefan Reinauer
\
\ See the file "COPYING" for further information about
\ the copyright and warranty status of this work.
\
\ variable last-package 0 last-package !
\ 0 value active-package
: current-device active-package ;
\
\ 5.3.4.1 Open/Close packages (part 1)
\
\ 0 value my-self ( -- ihandle )
: ?my-self
my-self dup 0= abort" no current instance."
;
: my-parent ( -- ihandle )
?my-self >in.my-parent @
;
: ihandle>non-interposed-phandle ( ihandle -- phandle )
begin dup >in.interposed @ while
>in.my-parent @
repeat
>in.device-node @
;
: instance-to-package ( ihandle -- phandle )
dup if ihandle>non-interposed-phandle then
;
: ihandle>phandle ( ihandle -- phandle )
>in.device-node @
;
\ next-property
\ defined in property.c
: peer ( phandle -- phandle.sibling )
?dup if
>dn.peer @
else
device-tree @
then
;
: child ( phandle.parent -- phandle.child )
\ Assume phandle == 0 indicates root node (not documented but similar
\ behaviour to "peer"). Used by some versions of Solaris (e.g. 9).
?dup if else device-tree @ then
>dn.child @
;
\
\ 5.3.4.2 Call methods from other packages
\
: find-method ( method-str method-len phandle -- false | xt true )
\ should we search the private wordlist too? I don't think so...
>dn.methods @ find-wordlist if
true
else
2drop false
then
;
: call-package ( ... xt ihandle -- ??? )
my-self >r
to my-self
execute
r> to my-self
;
: $call-method ( ... method-str method-len ihandle -- ??? )
dup >r >in.device-node @ find-method if
r> call-package
else
-21 throw
then
;
: $call-parent ( ... method-str method-len -- ??? )
my-parent $call-method
;
\
\ 5.3.4.1 Open/Close packages (part 2)
\
\ find-dev ( dev-str dev-len -- false | phandle true )
\ find-rel-dev ( dev-str dev-len phandle -- false | phandle true )
\
\ These function works just like find-device but without
\ any side effects (or exceptions).
\
defer find-dev
: find-rel-dev ( dev-str dev-len phandle -- false | phandle true )
active-package >r active-package!
find-dev
r> active-package!
;
: find-package ( name-str name-len -- false | phandle true )
\ Locate the support package named by name string.
\ If the package can be located, return its phandle and true; otherwise,
\ return false.
\ Interpret the name in name string relative to the "packages" device node.
\ If there are multiple packages with the same name (within the "packages"
\ node), return the phandle for the most recently created one.
\ This does the full path resolution stuff (including
\ alias expansion. If we don't want that, then we should just
\ iterade the children of /packages.
" /packages" find-dev 0= if 2drop false exit then
find-rel-dev 0= if false exit then
true
;
: open-package ( arg-str arg-len phandle -- ihandle | 0 )
\ Open the package indicated by phandle.
\ Create an instance of the package identified by phandle, save in that
\ instance the instance-argument specified by arg-string and invoke the
\ package's open method.
\ Return the instance handle ihandle of the new instance, or 0 if the package
\ could not be opened. This could occur either because that package has no
\ open method, or because its open method returned false, indicating an error.
\ The parent instance of the new instance is the instance that invoked
\ open-package. The current instance is not changed.
create-instance dup 0= if
3drop 0 exit
then
>r
\ clone arg-str
strdup r@ >in.arguments 2!
\ open the package
" open" r@ ['] $call-method catch if 3drop false then
if
r>
else
r> destroy-instance false
then
;
: $open-package ( arg-str arg-len name-str name-len -- ihandle | 0 )
\ Open the support package named by name string.
find-package if
open-package
else
2drop false
then
;
: close-package ( ihandle -- )
\ Close the instance identified by ihandle by calling the package's close
\ method and then destroying the instance.
dup " close" rot ['] $call-method catch if 3drop then
destroy-instance
;
\
\ 5.3.4.3 Get local arguments
\
: my-address ( -- phys.lo ... )
?my-self >in.device-node @
>dn.probe-addr
my-#acells tuck /l* + swap 1- 0
?do
/l - dup l@ swap
loop
drop
;
: my-space ( -- phys.hi )
?my-self >in.device-node @
>dn.probe-addr @
;
: my-unit ( -- phys.lo ... phys.hi )
?my-self >in.my-unit
my-#acells tuck /l* + swap 0 ?do
/l - dup l@ swap
loop
drop
;
: my-args ( -- arg-str arg-len )
?my-self >in.arguments 2@
;
\ char is not included. If char is not found, then R-len is zero
: left-parse-string ( str len char -- R-str R-len L-str L-len )
left-split
;
\
\ 5.3.4.4 Mapping tools
\
: map-low ( phys.lo ... size -- virt )
my-space swap s" map-in" $call-parent
;
: free-virtual ( virt size -- )
over s" address" get-my-property 0= if
decode-int -rot 2drop = if
s" address" delete-property
then
else
drop
then
s" map-out" $call-parent
;
\ Deprecated functions (required for compatibility with older loaders)
variable package-stack-pos 0 package-stack-pos !
create package-stack 8 cells allot
: push-package ( phandle -- )
\ Throw an error if we attempt to push a full stack
package-stack-pos @ 8 >= if
." cannot push-package onto full stack" cr
-99 throw
then
active-package
package-stack-pos @ /n * package-stack + !
package-stack-pos @ 1 + package-stack-pos !
active-package!
;
: pop-package ( -- )
\ Throw an error if we attempt to pop an empty stack
package-stack-pos @ 0 = if
." cannot pop-package from empty stack" cr
-99 throw
then
package-stack-pos @ 1 - package-stack-pos !
package-stack-pos @ /n * package-stack + @
active-package!
;