| \ tag: Package creation and deletion |
| \ |
| \ this code implements IEEE 1275-1994 |
| \ |
| \ Copyright (C) 2003, 2004 Samuel Rydh |
| \ |
| \ See the file "COPYING" for further information about |
| \ the copyright and warranty status of this work. |
| \ |
| |
| variable device-tree |
| |
| \ make defined words globally visible |
| \ |
| : external ( -- ) |
| active-package ?dup if |
| >dn.methods @ set-current |
| then |
| ; |
| |
| \ make the private wordlist active (not an OF word) |
| \ |
| : private ( -- ) |
| active-package ?dup if |
| >r |
| forth-wordlist r@ >dn.methods @ r@ >dn.priv-methods @ 3 set-order |
| r> >dn.priv-methods @ set-current |
| then |
| ; |
| |
| \ set activate package and make the world visible package wordlist |
| \ the current one. |
| \ |
| : active-package! ( phandle -- ) |
| dup to active-package |
| \ locally defined words are not available |
| ?dup if |
| forth-wordlist over >dn.methods @ 2 set-order |
| >dn.methods @ set-current |
| else |
| forth-wordlist dup 1 set-order set-current |
| then |
| ; |
| |
| |
| \ new-device ( -- ) |
| \ |
| \ Start new package, as child of active package. |
| \ Create a new device node as a child of the active package and make the |
| \ new node the active package. Create a new instance and make it the current |
| \ instance; the instance that invoked new-device becomes the parent instance |
| \ of the new instance. |
| \ Subsequently, newly defined Forth words become the methods of the new node |
| \ and newly defined data items (such as types variable, value, buffer:, and |
| \ defer) are allocated and stored within the new instance. |
| |
| : new-device ( -- ) |
| align-tree dev-node.size alloc-tree >r |
| active-package |
| dup r@ >dn.parent ! |
| |
| \ ( parent ) hook up at the end of the peer list |
| ?dup if |
| >dn.child |
| begin dup @ while @ >dn.peer repeat |
| r@ swap ! |
| else |
| \ we are the root node! |
| r@ to device-tree |
| then |
| |
| \ ( -- ) fill in device node stuff |
| inst-node.size r@ >dn.isize ! |
| |
| \ create two wordlists |
| wordlist r@ >dn.methods ! |
| wordlist r@ >dn.priv-methods ! |
| |
| \ initialize template data |
| r@ >dn.itemplate |
| r@ over >in.device-node ! |
| my-self over >in.my-parent ! |
| |
| \ make it the active package and current instance |
| to my-self |
| r@ active-package! |
| |
| \ swtich to public wordlist |
| external |
| r> drop |
| ; |
| |
| \ helpers for finish-device (OF does not actually define words |
| \ for device node deletion) |
| |
| : (delete-device) \ ( phandle ) |
| >r |
| r@ >dn.parent @ |
| ?dup if |
| >dn.child \ ( &first-child ) |
| begin dup @ r@ <> while @ >dn.peer repeat |
| r@ >dn.peer @ swap ! |
| else |
| \ root node |
| 0 to device-tree |
| then |
| |
| \ XXX: free any memory related to this node. |
| \ we could have a list with free device-node headers... |
| r> drop |
| ; |
| |
| : delete-device \ ( phandle ) |
| >r |
| \ first, get rid of any children |
| begin r@ >dn.child @ dup while |
| (delete-device) |
| repeat |
| drop |
| |
| \ then free this node |
| r> (delete-device) |
| ; |
| |
| \ finish-device ( -- ) |
| \ |
| \ Finish this package, set active package to parent. |
| \ Complete a device node that was created by new-device, as follows: If the |
| \ device node has no "name" property, remove the device node from the device |
| \ tree. Otherwise, save the current values of the current instance's |
| \ initialized data items within the active package for later use in |
| \ initializing the data items of instances created from that node. In any |
| \ case, destroy the current instance, make its parent instance the current |
| \ instance, and select the parent node of the device node just completed, |
| \ making the parent node the active package again. |
| |
| : finish-device \ ( -- ) |
| my-self |
| dup >in.device-node @ >r |
| >in.my-parent @ to my-self |
| |
| ( -- ) |
| r@ >dn.parent @ active-package! |
| s" name" r@ get-package-property if |
| \ delete the node (and any children) |
| r@ delete-device |
| else |
| 2drop |
| \ node OK |
| then |
| r> drop |
| ; |
| |
| |
| \ helper function which creates and initializes an instance. |
| \ open is not called. The current instance is not changed. |
| \ |
| : create-instance ( phandle -- ihandle|0 ) |
| dup >dn.isize @ ['] alloc-mem catch if 2drop 0 exit then |
| >r |
| \ we need to save the size in order to be able to release it properly |
| dup >dn.isize @ r@ >in.alloced-size ! |
| |
| \ clear memory (we only need to clear the head; all other data is copied) |
| r@ inst-node.size 0 fill |
| |
| ( phandle R: ihandle ) |
| |
| \ instantiate data |
| dup >dn.methods @ r@ instance-init |
| dup >dn.priv-methods @ r@ instance-init |
| |
| \ instantiate |
| dup >dn.itemplate r@ inst-node.size move |
| r@ r@ >in.instance-data ! |
| my-self r@ >in.my-parent ! |
| drop |
| |
| r> |
| ; |
| |
| \ helper function which tears down and frees an instance |
| : destroy-instance ( ihandle ) |
| ?dup if |
| \ free arguments |
| dup >in.arguments 2@ free-mem |
| \ and the instance block |
| dup >in.alloced-size @ |
| free-mem |
| then |
| ; |
| |
| \ Redefine to word so that statements of the form "0 to active-package" |
| \ are supported for bootloaders that require it |
| : to |
| ['] ' execute |
| dup ['] active-package = if |
| drop active-package! |
| else |
| (to-xt) |
| then |
| ; immediate |