Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / os / bootprom / devtree.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: devtree.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42id: @(#)devtree.fth 3.23 06/02/16 19:19:51
43purpose:
44copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47headerless
48
49headers
50: get ( acf -- value ) 0 perform-action ;
51: set ( value acf -- ) 1 perform-action ;
52: decode ( value acf -- adr len ) 3 perform-action ;
53: encode ( adr len acf -- true | value false )
54 4 ['] perform-action catch if
55 2drop 2drop true
56 else
57 false
58 then
59;
60
61\ TODO
62\ Don't use the system search order; use a private stack
63\ $find searches through the private stack
64\ Change names back from "regprop" to "reg", etc.
65\ Either implement a true breadth-first search or don't specify it.
66
672 actions
68action: drop context token@ ;
69action: drop context token! definitions ;
70create current-device use-actions
71
72: >node-offset ( apf -- addr ) @ current-device >body >user + ;
73
741 actions
75action: >node-offset ;
76
77transient
78
79: (ufield) \ name ( offset size -- offset' )
80 create over , +
81;
82
83: ufield \ name ( offset size -- offset' )
84 (ufield) use-actions
85;
86
87resident
88
893 actions
90action: >node-offset token@ execute ;
91action: >node-offset token! ;
92action: >node-offset ;
93
94transient
95: node-defer \ name ( offset -- offset' )
96 /token (ufield) use-actions
97;
98resident
99
100\ Notes for a more abstract searching mechanism:
101\ Instead of the child and peer links in the device node, packages
102\ with children have "search", "create", and "enumerate" methods.
103\ To search a level, call that package's search method. Those
104\ methods probably need to work from a phandle, not an ihandle.
105
106\ The 'check-user-size' below enables user space to grow on demand.
107
108: unaligned-ualloc ( size -- user# )
109 check-user-size #user @ swap #user +! ( user# )
110;
111
112struct ( devnode )
113/link #threads * ufield 'threads \ Package methods
114dup \ These fields will be "ualloc"ed
115 /token ufield 'child \ Pointer to first child
116 /token ufield 'peer \ Pointer to next peer
117 /token ufield 'properties \ Pointer to properties vocabulary
118 /n ufield '#adr-cells \ Size of a parent address
119 /n ufield '#buffers
120 /n ufield '#values
121 /token ufield 'values
122 /n ufield support-node? \ is this a support node?
123 /n ufield inherit-node-flags? \ inherit parent props?
124 node-defer (encode-unit) \ encode-unit method
125 node-defer (decode-unit) \ decode-unit method
126( starting-offset ending-offset ) swap - ( size-to-ualloc )
127constant /devnode-extra
128
129headers
130: >parent ( node -- parent-node ) >voc-link link@ ;
131
132: push-package ( phandle -- ) also execute definitions ;
133: pop-package ( -- ) previous definitions ;
134: push-device ( acf -- ) to current-device ;
135
136: pop-device ( -- )
137 current-device >parent ( parent-voc )
138 non-null? if push-device then
139;
140
141\ Each package instance has its own private data storage area.
142\ The data creation words "value", "variable", and "buffer:",
143\ when used during compilation of a package, allocate memory
144\ relative to a base pointer. The package definition includes the
145\ initial values for the words created with "value" and "variable".
146\ When a package instance is created, memory is allocated for the
147\ package's data and the portion used for values and variables is
148\ initialized from the values stored in the package definition.
149\
150\ While the package is being defined (i.e. its code is being compiled),
151\ a "dummy" instance is created with space for data, so that
152\ data words may be used as soon as they are created. The "dummy"
153\ instance data area is given a "generous" default size (for 100 * cellsize
154\ bytes of initialized data, 700 * cellsize for buffers).
155\ Hopefully this won't be exceeded.
156
157headerless
158variable package-level package-level off
159variable next-is-instance next-is-instance off
160headers
161variable instance-mode instance-mode off
162headerless
163: instance? ( -- flag )
164
165\ \ Debugging code. Keep this in until we have "sanitized" the drivers.
166\ package-level @ 0<> next-is-instance @ 0= and instance-mode @ and if
167\ ." Instance problem " where ??cr
168\ then
169
170 package-level @ 0<> next-is-instance @ instance-mode @ or and
171 next-is-instance off
172;
173headers
174: instance ( -- ) next-is-instance on ;
175headerless
176
177\ Now in machine code in obp/os/bootprom/sparc/instance.fth
178\ : >instance-data ( pfa -- adr ) @ my-self + ;
179
180: value#, ( size -- adr )
181 '#values @ dup , ( size offset )
182 tuck + '#values ! ( offset )
183 my-self + ( adr )
184;
185
186headers
187overload: value \ name ( initial-value -- )
188 header noop \ Will patch with (value)
189;
190headerless
1913 actions
192action: >instance-data @ ;
193action: >instance-data ! ;
194action: >instance-data ;
195
196: (value) ( initial-value -- )
197 instance? if
198 create-cf use-actions /n value#,
199 else
200 value-cf /n user#,
201 then ( value adr )
202 !
203; patch (value) noop value
204
205\ Create fields which are present in every instance record.
206\ "fixed instance value"
207
208headers
209transient
210: fibuf: \ name ( offset -- offset' )
211 create -1 na+ dup , ( offset' )
212 use-actions
213;
214: fival: \ name ( offset -- offset' )
215 create dup , na1+ ( offset' )
216 use-actions
217;
218resident
219
220headers
221overload: buffer: \ name ( size -- )
222 header noop \ Will patch with (buffer:)
223;
224
2253 actions
226action: >instance-data ;
227action: >instance-data ! ;
228action: >instance-data ;
229
230headerless
231overload: (buffer:) ( #bytes -- )
232 instance? if
233 create-cf
234 \ The address computation should use "#dalign round-up", but
235 \ #dalign (8) is defined later, in the "allocator" vocabulary.
236 '#buffers @ swap 8 round-up - dup , '#buffers ! use-actions
237 else
238 (buffer:)
239 then
240; patch (buffer:) noop buffer:
241
242headers
243overload: variable \ name ( -- )
244 header noop \ Will patch with (variable)
245;
246
2473 actions
248action: >instance-data ;
249action: >instance-data ! ;
250action: >instance-data ;
251
252headerless
253: (variable) ( -- )
254 instance? if
255 create-cf use-actions 0 /n value#, else user-cf 0 /n user#,
256 then
257 !
258; patch (variable) noop variable
259
260headers
261overload: defer \ name ( -- )
262 header noop \ Will patch with (defer)
263;
264
2653 actions
266action: >instance-data token@ execute ;
267action: >instance-data token! ;
268action: >instance-data token@ ;
269
270headerless
271: (defer) ( -- )
272 instance? if
273 create-cf ['] crash /token ( value data-size )
274 use-actions value#,
275 else
276 defer-cf ['] crash /token ( value data-size )
277 user#,
278 then ( value adr )
279 token!
280; patch (defer) noop defer
281
282headers
283\ Instance values that are automatically created for every package instance.
284
2850
286fival: my-adr0 \ F: First component of device probe address
287fival: my-adr1 \ F: Intermediate component of device probe address
288fival: my-adr2 \ F: Intermediate component of device probe address
289fival: my-space \ F: Last component of device probe address
290fival: frame-buffer-adr \ F: Frame buffer address. Strictly speaking, this
291 \ should not be in every package, but we put it
292 \ here as a work-around for some old CG6 FCode
293 \ drivers whose selftest routines use frame-buffer-adr
294 \ for diagnostics mappings. If frame-buffer-adr is
295 \ global, that would cause dual-cg6 systems to break.
296fival: my-termemu
297fival: interposed? \ Was this instance interposed?
298headerless
299constant #fixed-vals
300headers
301
3020
303fibuf: my-voc \ Package definition (code) for this instance
304fibuf: my-parent \ Current instance just before this one was created
305fibuf: my-args-adr \ Argument string - base address
306fibuf: my-args-len \ Argument string - length
307fibuf: my-unit-3 \ Fourth component of device instance address
308fibuf: my-unit-2 \ Third component of device instance address
309fibuf: my-unit-1 \ Second component of device instance address
310fibuf: my-unit-low \ First component of device instance address
311
312headerless
313constant #fixed-bufs
314
315headers
316: my-args ( -- adr len ) my-args-adr my-args-len ;
317
318headerless
319: allocate-instance ( value-size variable-size -- )
320 \ Allocate instance record
321 my-self >r ( val-size var-size )
322 tuck + alloc-mem ( var-size base-adr )
323 + is my-self ( )
324
325 \ Set the fixed fields
326 r> to my-parent ( )
327 current-device to my-voc ( )
328
329 0 to my-args-len 0 to my-args-adr ( ) \ May be changed later
330 0 to interposed? ( )
331 0 to my-unit-low 0 to my-unit-1 ( )
332 0 to my-unit-2 0 to my-unit-3 ( )
333;
334
335: initial-values ( -- adr ) 'values token@ ;
336
337\ Returns the address of the initial value of the named instance data.
338: (initial-addr) ( adr -- adr' ) my-self - initial-values + ;
339: initial-addr \ name ( -- addr )
340 [compile] addr
341 state @ if compile (initial-addr) else (initial-addr) then
342; immediate
343
344headers
345: copy-args ( args-adr,len -- )
346 dup if
347 dup alloc-mem to my-args-adr ( args-adr,len )
348 to my-args-len ( args-adr )
349 my-args-adr my-args-len move ( )
350 else
351 2drop
352 then
353;
354
355\ my-self points to a position in the middle of the instance record.
356\ Initialized data ("values") is at positive offsets from my-self,
357\ and uninitialized data ("variables" and "buffers") is at negative offsets.
358: new-instance ( args-adr args-len -- )
359 '#values @ '#buffers @ negate allocate-instance
360
361 \ Copy in the initialized data
362 initial-values my-self '#values @ move ( args-adr args-len )
363
364 copy-args
365;
366
367headerless
368: deallocate-instance ( value-size variabled-size -- )
369 my-args-len if my-args-adr my-args-len free-mem then
370 my-self my-parent is my-self ( val-size var-size self )
371 over - ( val-size var-size base-adr )
372 -rot + free-mem ( )
373;
374
375\ Destroy instance has the side effect of setting my-self to the parent
376\ of the node that is being destroyed. This prevents my-self from referring
377\ to a non-existent instance.
378
379headers
380: destroy-instance ( -- )
381 also my-voc execute ( )
382 '#values @ '#buffers @ negate ( value-size variable-size )
383 previous ( value-size variable-size )
384 deallocate-instance
385;
386
387headerless
388\ When creating a package definition, we initialize the buffer
389\ (unitialized data) allocation pointer and the value (initialized data)
390\ allocation pointer.
391
392\ Size of the buffer that is used as the instance data when the package
393\ is being created. This allows variables, buffers, and values to be
394\ used while the package is being created.
395
396: initial-sizes ( -- value-size variable-size )
397 d# 100 /n* d# 700 /n*
398;
399
400: extend-package ( -- )
401 next-is-instance off
402 1 package-level +! initial-sizes allocate-instance
403;
404
405: allot-package-data ( -- )
406 acf-align here dup 'values token! '#values @ dup allot erase
407;
408: finish-package-data ( -- )
409 \ Copy the initialized data into the dictionary and set up the
410 \ pointer to it.
411 '#values @ if allot-package-data then
412 my-self initial-values '#values @ move ( )
413
414 initial-addr frame-buffer-adr off
415 initial-addr my-termemu off
416
417 initial-sizes deallocate-instance ( )
418 package-level @ 1- 0 max package-level !
419;
420
421\ Internal factor used to implement first-child and next-child
422: set-child? ( link-adr -- flag )
423 get-token? if push-device true else false then
424;
425
426\ Interface to searching code in breadth.fth:
427: first-child ( -- another? ) 'child set-child? ;
428: next-child ( -- another? ) 'peer pop-device set-child? ;
429
430\ Removes the voc-link field from the most-recently-created vocabulary
431: erase-voc-link ( -- )
432 voc-link link@ >voc-link link@ voc-link link!
433 /link na1+ negate allot
434;
435
436\ Creates an unnamed vocabulary
437: (vocabulary) ( -- )
438 ['] acf-align is header
439 vocabulary
440 ['] (header) is header
441
442 erase-voc-link
443;
444
445: allocate-node-record ( -- )
446 \ Allocate user (RAM) space for properties, "last" field, children, peers
447 /devnode-extra unaligned-ualloc drop
448
449 lastacf push-device ( parent's-child-field )
450;
451: init-properties ( -- ) (vocabulary) lastacf 'properties token! ;
452
453headerless
454
455\ this was moved from finddev because the encode/decode unit recovery
456\ mechanism needs it, and in order to only complain once about missing
457\ methods and to accelerate the device tree parsing these were moved here.
458
4592variable saved-method$
460variable saved-method-package
461defer no-proc ' true is no-proc \ definition requires forward references..
462
463: setup-method$ ( adr len phandle -- adr len phandle )
464 >r r@ saved-method-package ! ( adr len )
465 2dup saved-method$ 2! ( adr len )
466 r> ( adr len phandle )
467;
468headers
469
470: current-properties ( -- ) 'properties token@ ;
471
472: $vexecute? ( adr len voc-acf -- true | ??? false)
473 (search-wordlist) if execute false else true then
474;
475
476: $vexecute ( adr len voc-acf -- ?? ) $vexecute? drop ;
477
478\ Used during compilation (probing), when the search order includes
479\ the current vocabulary as well as the parent vocabularies.
480: get-property ( name-adr,len -- true | value-adr,len false )
481 current-properties $vexecute?
482;
483headerless
484: #adr-cells ( -- n )
485 " #address-cells" get-property if 2 else get-encoded-int then
486;
487
488\ this routine will only execute once per node, unless the device tree
489\ changes (via cd, device-end or finish-device) it looks up the static
490\ acf for the encode/decode method substituting the default 2cell form
491\ and complaining once, if the method does not exist.
492: (lookup-method) ( ? ? def-acf ptr method$ -- ? ? )
493 current-device setup-method$ (search-wordlist) if ( ? ? def-acf ptr acf )
494 >r ( ? ? default-acf ptr )
495 nip ( ? ? ptr )
496 else ( ? ? default-acf ptr )
497 swap >r ( ? ? ptr )
498 no-proc ( ? ? ptr -2 )
499 2 #adr-cells tuck ( ? ? ptr -2 n 2 n )
500 <> swap 0<> and if throw else drop then ( ? ? ptr )
501 diagnostic-mode? if ( ? ? ptr )
502 ??cr ." Notice: " abort-message type cr
503 then ( ? ? ptr )
504 then ( ? ? ptr )
505 r> tuck swap ( ? ? acf acf ptr )
506 set ( ? ? acf )
507 execute ( ? ? )
508;
509
510\ Moved from findev.fth because the device tree depends upon
511\ encode-unit and decode-unit, and because some cards are missing those
512\ methods and we have to workaround them this becomes a fundamental part
513\ of the device tree operation now.
514
515create bad-number ," Bad number syntax"
516: safe->number ( adr len -- n ) $hnumber if bad-number throw then ;
517
518headers
519
520: parse-int ( adr len -- n ) dup if safe->number else 2drop 0 then ;
521
522: parse-2int ( adr len -- address space )
523 ascii , left-parse-string ( after-str before-str )
524 parse-int >r ( after-str )
525 parse-int r> ( address space )
526;
527
528headerless
529
530: (encode-2ints) ( l h -- adr,len ) swap <# u#s drop ascii , hold u#s u#> ;
531
532: lookup-decode-unit ( unit$ -- pa.lo .. pa.hi )
533 ['] parse-2int ['] (decode-unit) " decode-unit" (lookup-method)
534;
535
536: lookup-encode-unit ( pa.lo .. pa.hi -- unit$ )
537 ['] (encode-2ints) ['] (encode-unit) " encode-unit" (lookup-method)
538;
539
540\ reset the current device cached encode/decode methods
541: reset-xxcoders ( -- )
542 ['] lookup-decode-unit is (decode-unit)
543 ['] lookup-encode-unit is (encode-unit)
544;
545
546: init-node ( #address-cells -- )
547 allocate-node-record
548
549 '#adr-cells !
550 'child !null-token \ No children yet
551 'peer !null-token \ Null peer
552
553 #fixed-vals '#values ! \ Initialize data sizes
554 #fixed-bufs '#buffers !
555
556 'values !null-token \ No initial data values yet
557
558 init-properties
559
560 0 support-node? ! \ Not a support node by default
561 true inherit-node-flags? ! \ inherit by default
562 reset-xxcoders
563;
564
565: link-to-peer ( parent's-child-field -- )
566 dup token@ 'peer token! ( parent's-child-field )
567 current-device swap token! ( )
568;
569: device-node? ( voc -- flag )
570 voc-link begin another-link? while ( voc link )
571 2dup voc> = if 2drop false exit then ( voc link )
572 >voc-link
573 repeat ( voc )
574 drop true
575;
576
577headers
578
579: new-node ( -- )
580 (vocabulary) current-device link, ( ) \ Up-link to parent device
581
582 \ Save parent linkage address on stack for later use
583 inherit-node-flags? @ ( in? )
584 support-node? @ over and ( in? support? )
585 'child ( in? support? parent's-child-field )
586 #adr-cells init-node ( in? support? parent's-child-field )
587 link-to-peer ( in? support? )
588 support-node? ! ( in? )
589 inherit-node-flags? ! ( )
590;
591
592: new-device ( -- ) new-node extend-package ;
593
594: device-end ( -- )
595 \ The false will be patched later with device-context?
596 false if reset-xxcoders then
597 only forth also definitions package-level off
598;
599
600: my-#adr-cells ( -- n )
601 my-self if \ Use current instance's package if there is a current instance
602 my-voc also execute '#adr-cells @ previous
603 else \ Otherwise use the active package
604 '#adr-cells @
605 then
606;
607
608\ my-address applies to the current instance, regardless of whether or
609\ not the active package corresponds to the current instance, thus it must
610\ use my-#adr-cells, which explicitly refers to the current instance's
611\ package.
612
613: my-address ( -- phys.lo .. )
614 addr my-adr0 my-#adr-cells 1- 1 max /n* bounds ?do i @ /n +loop
615;
616: my-unit ( -- phys.lo .. )
617 addr my-unit-low my-#adr-cells /n* bounds ?do i @ /n +loop
618;
619
620vocabulary root-node
621 erase-voc-link null link, \ Root has no parent
622 0 init-node
623 allot-package-data
624device-end
625
626: root-device ( -- ) only forth also ['] root-node push-device ;
627
628: finish-device ( -- ) reset-xxcoders finish-package-data pop-device ;
629
630\ The magic-device-types vocabulary contains words whose names are the
631\ same as the names of the device_type property values that we wish to
632\ recognize as special cases. "device_type" in the "magic-properties"
633\ vocabulary searches this vocabulary every time that a "device_type"
634\ property is created, and executes the corresponding word if a match
635\ is found. That word may look at the property name and value on the
636\ stack, but it must not remove them. However, it might wish to alter
637\ the value!
638
639vocabulary magic-device-types
640
641\ The magic-properties vocabulary contains words whose names are the
642\ same as the names of properties that we wish to recognize as special
643\ cases. "property" searches this vocabulary every time that an
644\ property is created, and executes the corresponding word if a match
645\ is found. That word may look at the property name and value on the
646\ stack, but it must not remove them. However, it might wish to alter
647\ either the name or the value!
648
649vocabulary magic-properties
650also magic-properties definitions
651: device_type ( value-str name-str -- value-str name-str )
652 2over get-encoded-string ['] magic-device-types $vexecute
653;
654previous definitions
655
656
657\ The parameter field of a property word contains:
658\ offset size
659\ Offset is the 32-bit positive distance from the beginning of the
660\ property-encoded byte array to the parameter field address. size is the
661\ 16-bit size of the property value array. This representation depends on
662\ the fact that property-encoded arrays are stored in the dictionary.
663
664headerless
665: make-property-name ( name-adr,len -- )
666 current token@ >r current-properties current token!
667 ['] $header behavior >r
668 ['] ($header) to $header
669 $create
670 r> to $header
671 r> current token!
672;
673
674headers
6755 actions
676action: dup dup unaligned-l@ l->n - swap la1+ w@ ;
677action: ( adr,len apf -- )
678 tuck la1+ w! ( adr apf )
679 dup rot - swap unaligned-l! ( )
680;
681action: ;
682action: drop ;
683action: drop ;
684
685: (property) ( value-adr,len name-adr,len -- )
686 2dup ['] magic-properties $vexecute ( value-str name-str )
687 2dup current-properties (search-wordlist) if ( value-str name-str acf )
688 nip nip set ( )
689 else ( value-str name-str )
690 make-property-name ( value-str )
691 here rot - l, w, align use-actions ( )
692 then ( )
693;
694
695: property ( value-adr,len name-adr,len -- )
696 my-self if
697 context token@ >r my-voc execute
698 (property)
699 r> context token!
700 else
701 (property)
702 then
703;
704
705: delete-property ( name-adr,len -- )
706 current-properties (search-wordlist) if
707 >link current-properties remove-word
708 then
709;
710overload: forget \ name ( -- )
711 current token@ device-node? abort" Can't forget device methods"
712 forget
713;
714
715headerless
716: get-unit ( -- true | adr len false ) " reg" get-property ;
717
718: unit-str>phys- ( adr len -- phys.hi .. phys.lo )
719 '#adr-cells @ 0 ?do decode-int -rot loop 2drop ( phys.hi .. phys.lo )
720;
721
722: reorder ( xn .. x1 n -- x1 .. xn ) 0 ?do i roll loop ;
723
724: unit-str>phys ( adr len -- phys.lo .. phys.hi )
725 unit-str>phys- ( phys.hi .. phys.lo )
726 '#adr-cells @ reorder ( phys.lo .. phys.hi )
727;
728headers