| \ tag: Property management |
| \ |
| \ this code implements IEEE 1275-1994 ch. 5.3.5 |
| \ |
| \ Copyright (C) 2003 Stefan Reinauer |
| \ |
| \ See the file "COPYING" for further information about |
| \ the copyright and warranty status of this work. |
| \ |
| |
| \ small helpers.. these should go elsewhere. |
| : bigendian? |
| 10 here ! here c@ 10 <> |
| ; |
| |
| : l!-be ( val addr ) |
| 3 bounds swap do |
| dup ff and i c! |
| 8 rshift |
| -1 +loop |
| drop |
| ; |
| |
| : l@-be ( addr ) |
| 0 swap 4 bounds do |
| i c@ swap 8 << or |
| loop |
| ; |
| |
| \ allocate n bytes for device tree information |
| \ until I know where to put this, I put it in the |
| \ dictionary. |
| |
| : alloc-tree ( n -- addr ) |
| dup >r \ save len |
| here swap allot |
| dup r> 0 fill \ clear memory |
| ; |
| |
| : align-tree ( -- ) |
| null-align |
| ; |
| |
| : no-active true abort" no active package." ; |
| |
| \ |
| \ 5.3.5 Property management |
| \ |
| |
| \ Helper function |
| : find-property ( name len phandle -- &&prop|0 ) |
| >dn.properties |
| begin |
| dup @ |
| while |
| dup @ >prop.name @ ( name len prop propname ) |
| 2over comp0 ( name len prop equal? ) |
| 0= if nip nip exit then |
| >prop.next @ |
| repeat |
| ( name len false ) |
| 3drop false |
| ; |
| |
| \ From package (5.3.4.1) |
| : next-property |
| ( previous-str previous-len phandle -- false | name-str name-len true ) |
| >r |
| 2dup 0= swap 0= or if |
| 2drop r> >dn.properties @ |
| else |
| r> find-property dup if @ then |
| dup if >prop.next @ then |
| then |
| |
| ?dup if |
| >prop.name @ dup cstrlen true |
| ( phandle name-str name-len true ) |
| else |
| false |
| then |
| ; |
| |
| |
| \ |
| \ 5.3.5.4 Property value access |
| \ |
| |
| \ Return value for name string property in package phandle. |
| : get-package-property |
| ( name-str name-len phandle -- true | prop-addr prop-len false ) |
| find-property ?dup if |
| @ dup >prop.addr @ |
| swap >prop.len @ |
| false |
| else |
| true |
| then |
| ; |
| |
| \ Return value for given property in the current instance or its parents. |
| : get-inherited-property |
| ( name-str name-len -- true | prop-addr prop-len false ) |
| my-self |
| begin |
| ?dup |
| while |
| dup >in.device-node @ ( str len ihandle phandle ) |
| 2over rot find-property ?dup if |
| @ |
| ( str len ihandle prop ) |
| nip nip nip ( prop ) |
| dup >prop.addr @ swap >prop.len @ |
| false |
| exit |
| then |
| ( str len ihandle ) |
| >in.my-parent @ |
| repeat |
| 2drop |
| true |
| ; |
| |
| \ Return value for given property in this package. |
| : get-my-property ( name-str name-len -- true | prop-addr prop-len false ) |
| my-self >in.device-node @ ( -- phandle ) |
| get-package-property |
| ; |
| |
| |
| \ |
| \ 5.3.5.2 Property array decoding |
| \ |
| |
| : decode-int ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 n ) |
| dup 0> if |
| dup 4 min >r ( addr1 len1 R:minlen ) |
| over r@ + swap ( addr1 addr2 len1 R:minlen ) |
| r> - ( addr1 addr2 len2 ) |
| rot l@-be |
| else |
| 0 |
| then |
| ; |
| |
| \ HELPER: get #address-cell value (from parent) |
| \ Legal values are 1..4 (we may optionally support longer addresses) |
| : my-#acells ( -- #address-cells ) |
| my-self ?dup if >in.device-node @ else active-package then |
| ?dup if >dn.parent @ then |
| ?dup if |
| " #address-cells" rot get-package-property if 2 exit then |
| \ we don't have to support more than 4 (and 0 is illegal) |
| decode-int nip nip 4 min 1 max |
| else |
| 2 |
| then |
| ; |
| |
| \ HELPER: get #size-cells value (from parent) |
| : my-#scells ( -- #size-cells ) |
| my-self ?dup if >in.device-node @ else active-package then |
| ?dup if >dn.parent @ then |
| ?dup if |
| " #size-cells" rot get-package-property if 1 exit then |
| decode-int nip nip |
| else |
| 1 |
| then |
| ; |
| |
| : decode-string ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 str len ) |
| dup 0> if |
| 2dup bounds \ check property for 0 bytes |
| 0 -rot \ initial string len is 0 |
| do |
| i c@ 0= if |
| leave |
| then |
| 1+ |
| loop ( prop-addr1 prop-len1 len ) |
| 1+ rot >r ( prop-len1 len R: prop-addr1 ) |
| over min 2dup - ( prop-len1 nlen prop-len2 R: prop-addr1 ) |
| r@ 2 pick + ( prop-len1 nlen prop-len2 prop-addr2 ) |
| >r >r >r ( R: prop-addr1 prop-addr2 prop-len2 nlen ) |
| drop |
| r> r> r> ( nlen prop-len2 prop-addr2 ) |
| -rot swap 1- ( prop-addr2 prop-len2 nlen ) |
| r> swap ( prop-addr2 prop-len2 str len ) |
| else |
| 0 0 |
| then |
| ; |
| |
| : decode-bytes ( addr1 len1 #bytes -- addr len2 addr1 #bytes ) |
| tuck - ( addr1 #bytes len2 ) |
| r> 2dup + ( addr1 #bytes addr2 ) ( R: len2 ) |
| r> 2swap |
| ; |
| |
| : decode-phys |
| ( prop-addr1 prop-len1 -- prop-addr2 prop-len2 phys.lo ... phys.hi ) |
| my-#acells 0 ?do |
| decode-int r> r> rot >r >r >r |
| loop |
| my-#acells 0 ?do |
| r> r> r> -rot >r >r |
| loop |
| ; |
| |
| |
| \ |
| \ 5.3.5.1 Property array encoding |
| \ |
| |
| : encode-int ( n -- prop-addr prop-len ) |
| /l alloc-tree tuck l!-be /l |
| ; |
| |
| : encode-string ( str len -- prop-addr prop-len ) |
| \ we trust len here. should probably check string? |
| tuck char+ alloc-tree ( len str prop-addr ) |
| tuck 3 pick move ( len prop-addr ) |
| swap 1+ |
| ; |
| |
| : encode-bytes ( data-addr data-len -- prop-addr prop-len ) |
| tuck alloc-tree ( len str prop-addr ) |
| tuck 3 pick move |
| swap |
| ; |
| |
| : encode+ ( prop-addr1 prop-len1 prop-addr2 prop-len2 -- prop-addr3 prop-len3 ) |
| nip + |
| ; |
| |
| : encode-phys ( phys.lo ... phys.hi -- prop-addr prop-len ) |
| encode-int my-#acells 1- 0 ?do |
| rot encode-int encode+ |
| loop |
| ; |
| |
| defer sbus-intr>cpu ( sbus-intr# -- cpu-intr# ) |
| : (sbus-intr>cpu) ." No SBUS present on this machine." cr ; |
| ['] (sbus-intr>cpu) to sbus-intr>cpu |
| |
| |
| \ |
| \ 5.3.5.3 Property declaration |
| \ |
| |
| : (property) ( prop-addr prop-len name-str name-len dnode -- ) |
| >r 2dup r@ |
| align-tree |
| find-property ?dup if |
| \ If a property with that property name already exists in the |
| \ package in which the property would be created, replace its |
| \ value with the new value. |
| @ r> drop \ don't need the device node anymore. |
| -rot 2drop tuck \ drop property name |
| >prop.len ! \ overwrite old values |
| >prop.addr ! |
| exit |
| then |
| |
| ( prop-addr prop-len name-str name-len R: dn ) |
| prop-node.size alloc-tree |
| dup >prop.next off |
| |
| dup r> >dn.properties |
| begin dup @ while @ >prop.next repeat ! |
| >r |
| |
| ( prop-addr prop-len name-str name-len R: prop ) |
| |
| \ create copy of property name |
| dup char+ alloc-tree |
| dup >r swap move r> |
| ( prop-addr prop-len new-name R: prop ) |
| r@ >prop.name ! |
| r@ >prop.len ! |
| r> >prop.addr ! |
| align-tree |
| ; |
| |
| : property ( prop-addr prop-len name-str name-len -- ) |
| my-self ?dup if |
| >in.device-node @ |
| else |
| active-package |
| then |
| dup if |
| (property) |
| else |
| no-active |
| then |
| ; |
| |
| : (delete-property) ( name len dnode -- ) |
| find-property ?dup if |
| dup @ >prop.next @ swap ! |
| \ maybe we should try to reclaim the space? |
| then |
| ; |
| |
| : delete-property ( name-str name-len -- ) |
| active-package ?dup if |
| (delete-property) |
| else |
| 2drop |
| then |
| ; |
| |
| \ Create the "name" property; value is indicated string. |
| : device-name ( str len -- ) |
| encode-string " name" property |
| ; |
| |
| \ Create "device_type" property, value is indicated string. |
| : device-type ( str len -- ) |
| encode-string " device_type" property |
| ; |
| |
| \ Create the "reg" property with the given values. |
| : reg ( phys.lo ... phys.hi size -- ) |
| >r ( phys.lo ... phys.hi ) encode-phys ( addr len ) |
| r> ( addr1 len1 size ) encode-int ( addr1 len1 addr2 len2 ) |
| encode+ ( addr len ) |
| " reg" property |
| ; |
| |
| \ Create the "model" property; value is indicated string. |
| : model ( str len -- ) |
| encode-string " model" property |
| ; |