summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/forth/device/property.fs
blob: 1d54e3ec3f8963eecd38659028e35896229e4f0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
\ 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
  ;