xref: /onnv-gate/usr/src/psm/stand/boot/sparc/common/ramdisk.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/param.h>
30*0Sstevel@tonic-gate #include <sys/promif.h>
31*0Sstevel@tonic-gate #include <sys/salib.h>
32*0Sstevel@tonic-gate /* EXPORT DELETE START */
33*0Sstevel@tonic-gate #include <bootlog.h>
34*0Sstevel@tonic-gate /* EXPORT DELETE END */
35*0Sstevel@tonic-gate #include "ramdisk.h"
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate /*
38*0Sstevel@tonic-gate  * This is a chunk of Forth delivered by the OBP group.  When loaded
39*0Sstevel@tonic-gate  * into OBP it creates a ramdisk device node whose functionality is
40*0Sstevel@tonic-gate  * defined in FWARC 2002/299.
41*0Sstevel@tonic-gate  *
42*0Sstevel@tonic-gate  * Note the %s in the line following " new-device" - this is where we
43*0Sstevel@tonic-gate  * plug the name of the node in.
44*0Sstevel@tonic-gate  */
45*0Sstevel@tonic-gate static const char ramdisk_fth[] =
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate "headerless "
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate "\" /\" find-package 0= if"
50*0Sstevel@tonic-gate "   .\" Can't find /\" abort "
51*0Sstevel@tonic-gate "then  push-package "
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate "new-device"
54*0Sstevel@tonic-gate "   \" %s\"		device-name"
55*0Sstevel@tonic-gate "   \" block\"		encode-string \" device_type\" property"
56*0Sstevel@tonic-gate /* CSTYLED */
57*0Sstevel@tonic-gate "   \" SUNW,ramdisk\"	encode-string \" compatible\"  property"
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate "   hex"
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate "   headerless"
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate "   0 value mmu-ihandle"
64*0Sstevel@tonic-gate "   0 value mem-ihandle"
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate "   : get-memory-ihandles" /* ( -- ) */
67*0Sstevel@tonic-gate "      \" /chosen\" find-package drop dup \" mmu\" rot"
68*0Sstevel@tonic-gate "      get-package-property if"
69*0Sstevel@tonic-gate "	  .\" Can't find chosen mmu property\" cr abort"
70*0Sstevel@tonic-gate "      then"
71*0Sstevel@tonic-gate "      decode-int to mmu-ihandle 2drop"
72*0Sstevel@tonic-gate "      \" memory\" rot get-package-property if"
73*0Sstevel@tonic-gate " 	  .\" Can't find chosen memory property\" cr abort"
74*0Sstevel@tonic-gate "      then"
75*0Sstevel@tonic-gate "      decode-int to mem-ihandle 2drop"
76*0Sstevel@tonic-gate "   ;"
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate "   : get-page-size" /* ( -- page-size ) */
79*0Sstevel@tonic-gate "     mmu-ihandle ihandle>phandle \" page-size\" rot get-package-property"
80*0Sstevel@tonic-gate "      if  h# 2000  else  decode-int nip nip  then "
81*0Sstevel@tonic-gate "   ;"
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate "   : get-mode" /* ( -- rw-mode ) */
84*0Sstevel@tonic-gate "      here \" translate\" mmu-ihandle $call-method if"
85*0Sstevel@tonic-gate " 	  nip nip"
86*0Sstevel@tonic-gate "      else"
87*0Sstevel@tonic-gate " 	  h# 27"
88*0Sstevel@tonic-gate "      then"
89*0Sstevel@tonic-gate "   ;"
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate "   : 64>32bit-phys" /* ( 64bit.lo 64bit.hi -- 32bit.lo 32bit.hi ) */
92*0Sstevel@tonic-gate "      drop xlsplit"
93*0Sstevel@tonic-gate "   ;"
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate "   : 32>64bit-phys" /* ( 32bit.lo 32bit.hi -- 64bit.lo 64bit.hi ) */
96*0Sstevel@tonic-gate "      lxjoin 0"
97*0Sstevel@tonic-gate "   ;"
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate "   : phy-claim" /* ( size align -- base.lo base.hi 0 | error ) */
100*0Sstevel@tonic-gate "       \" claim\" mem-ihandle ['] $call-method catch if"
101*0Sstevel@tonic-gate "	    drop 2drop 2drop -1"
102*0Sstevel@tonic-gate "	else"
103*0Sstevel@tonic-gate "	   64>32bit-phys 0"
104*0Sstevel@tonic-gate "	then"
105*0Sstevel@tonic-gate "   ;"
106*0Sstevel@tonic-gate 
107*0Sstevel@tonic-gate "   : phy-release" /* ( phys.lo phys.hi size -- ) */
108*0Sstevel@tonic-gate "      >r 32>64bit-phys r> \" release\" mem-ihandle $call-method"
109*0Sstevel@tonic-gate "   ;"
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate "   : vir-claim" /* ( [ virt ] size align -- base ) */
112*0Sstevel@tonic-gate "      \" claim\" mmu-ihandle $call-method"
113*0Sstevel@tonic-gate "   ;"
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate "   : vir-release" /* ( virt size -- ) */
116*0Sstevel@tonic-gate "      \" release\" mmu-ihandle $call-method"
117*0Sstevel@tonic-gate "   ;"
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate "   : vir-map" /* ( phys-lo phys-hi virt size mode -- ) */
120*0Sstevel@tonic-gate "      >r >r >r 32>64bit-phys r> r> r>"
121*0Sstevel@tonic-gate "      \" map\" mmu-ihandle $call-method"
122*0Sstevel@tonic-gate "   ;"
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate "   : vir-unmap" /* ( virt size -- ) */
125*0Sstevel@tonic-gate "      \" unmap\" mmu-ihandle $call-method"
126*0Sstevel@tonic-gate "   ;"
127*0Sstevel@tonic-gate "   headers"
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate /*  \ This structure represents a physical "chunk" of ramdisk memory */
130*0Sstevel@tonic-gate "   struct"
131*0Sstevel@tonic-gate "      /l field >res-pa.lo"		/* \ lower 32bits of physical address */
132*0Sstevel@tonic-gate "      /l field >res-pa.hi"		/* \ upper 32bits of physical address */
133*0Sstevel@tonic-gate "      /l field >res-len.lo"		/* \ lower 32bits of chunk size */
134*0Sstevel@tonic-gate "      /l field >res-len.hi"		/* \ upper 32bits of chunk size */
135*0Sstevel@tonic-gate "   constant /res-entry"
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate "   4	value    max-res-entries"	/* \ Max # of non-contig phys chunks */
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate "   max-res-entries /res-entry *"	/* \ size of resource buffer */
140*0Sstevel@tonic-gate "   ( value ) buffer: my-resources"	/* \ resource buffer label */
141*0Sstevel@tonic-gate "   0      value      num-res-entries"	/* \ current # of chunks allocated */
142*0Sstevel@tonic-gate "   h# 10 constant    label-size"	/* \ size of disk-label buffer */
143*0Sstevel@tonic-gate "   label-size instance buffer: my-label" /* \ for disk-label argument string */
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate "   get-memory-ihandles"		/* \ So we can claim/map/free memory */
146*0Sstevel@tonic-gate "   get-page-size value pagesize"	/* \ get virt pagesize from vmem node */
147*0Sstevel@tonic-gate "   get-mode	value	 mode"		/* \ get mode to map virt memory with */
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate "   0 instance	value	 window-mapped?" /* \ just in case for pa's near 0 */
150*0Sstevel@tonic-gate "   0 instance	value	 window-pa"	/* \ physical base of virtual window */
151*0Sstevel@tonic-gate "   0 instance	value	 window-base"	/* \ virtual window base */
152*0Sstevel@tonic-gate "   h# 10000	constant window-size"	/* \ virtual window size */
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate "   0 instance	value	 filepos"	/* \ file position marker */
155*0Sstevel@tonic-gate "   -1		value	 new-disk?"	/* \ need to alloc new resources? */
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate "   0 instance	value	 offset-low"	/* \ Offset to start of partition */
158*0Sstevel@tonic-gate "   0 instance	value	 offset-high"	/* \ For partition relative seeks */
159*0Sstevel@tonic-gate "   0 instance	value	 label-package"	/* \ ihandle for disk-label package */
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate "   external"				/* \ Because device_type = block */
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate "   0		value	 size"		/* \ size of disk */
164*0Sstevel@tonic-gate "   0		value	 #blocks"	/* \ size of disk / decimal 512 */
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate "   headerless"
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate "   : round-up"	/* ( n -- n' ) */
169*0Sstevel@tonic-gate "      1- tuck + swap invert and"
170*0Sstevel@tonic-gate "   ;"
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate "   : init-label-package" /* ( adr len -- okay? ) */
173*0Sstevel@tonic-gate "      0 to offset-high  0 to offset-low"
174*0Sstevel@tonic-gate "      \" disk-label\"  $open-package to label-package"
175*0Sstevel@tonic-gate "      label-package  if"
176*0Sstevel@tonic-gate "	  0 0  \" offset\" label-package $call-method"
177*0Sstevel@tonic-gate "	  to offset-high to offset-low"
178*0Sstevel@tonic-gate " 	  true"
179*0Sstevel@tonic-gate "      else"
180*0Sstevel@tonic-gate " 	  .\" Can't open disk label package\"  cr  false"
181*0Sstevel@tonic-gate "      then"
182*0Sstevel@tonic-gate "   ;"
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate "   : res-entry-len" /* ( n -- 64bit-len | 0 )	\ Get length of chunk n */
185*0Sstevel@tonic-gate "      dup num-res-entries > if"
186*0Sstevel@tonic-gate "	  drop 0"
187*0Sstevel@tonic-gate "      else"
188*0Sstevel@tonic-gate " 	  /res-entry * my-resources +"
189*0Sstevel@tonic-gate " 	  dup >res-len.lo l@ swap >res-len.hi l@"
190*0Sstevel@tonic-gate " 	  lxjoin"
191*0Sstevel@tonic-gate "      then"
192*0Sstevel@tonic-gate "   ;"
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate "   : res-entry-pa" /* ( n -- 64bit-pa | 0 )	\ Get phys address of chunk n */
195*0Sstevel@tonic-gate "      dup num-res-entries > if"		/* ( n ) */
196*0Sstevel@tonic-gate " 	  drop 0"				/* ( 0 ) */
197*0Sstevel@tonic-gate "      else"					/* ( n ) */
198*0Sstevel@tonic-gate " 	  /res-entry * my-resources +"		/* ( chunk-adr ) */
199*0Sstevel@tonic-gate " 	  dup >res-pa.lo l@ swap >res-pa.hi l@"	/* ( pa.lo pa.hi ) */
200*0Sstevel@tonic-gate " 	  lxjoin"				/* ( 64bit-pa ) */
201*0Sstevel@tonic-gate "      then"					/* ( 64bit-pa ) */
202*0Sstevel@tonic-gate "   ;"
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate "   : claim-window" /* ( -- )			\ Claim mem for virt window */
205*0Sstevel@tonic-gate "      window-size pagesize vir-claim to window-base"
206*0Sstevel@tonic-gate "   ;"
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate "   : release-window" /* ( -- )			\ Free virt window memory */
209*0Sstevel@tonic-gate "      window-base window-size"
210*0Sstevel@tonic-gate "      2dup vir-unmap"
211*0Sstevel@tonic-gate "      vir-release"
212*0Sstevel@tonic-gate "   ;"
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate "   : map-window" /* ( 64bit-pa -- ) \ Map a physical address to the v-window */
215*0Sstevel@tonic-gate "      dup to window-pa"
216*0Sstevel@tonic-gate "      xlsplit window-base window-size mode vir-map"
217*0Sstevel@tonic-gate "      -1 to window-mapped?"
218*0Sstevel@tonic-gate "   ;"
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate "   : unmap-window" /* ( -- )			\ Unmap the virtual window */
221*0Sstevel@tonic-gate "      window-base window-size vir-unmap"
222*0Sstevel@tonic-gate "      0 to window-mapped?"
223*0Sstevel@tonic-gate "   ;"
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate "   : in-window?" /* ( pa -- in-window? ) */
226*0Sstevel@tonic-gate "      window-mapped? if"
227*0Sstevel@tonic-gate "	  window-pa dup window-size + 1- between"
228*0Sstevel@tonic-gate "      else"
229*0Sstevel@tonic-gate "	  drop 0"
230*0Sstevel@tonic-gate "      then"
231*0Sstevel@tonic-gate "   ;"
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate "   : window-left" /* ( offset -- space-left-in-window ) */
234*0Sstevel@tonic-gate "     window-size mod"
235*0Sstevel@tonic-gate "     window-size swap -"
236*0Sstevel@tonic-gate "   ;"
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate "   : release-resources" /* ( -- )  \ release previously claimed phys addrs */
239*0Sstevel@tonic-gate "      num-res-entries 0 2dup = if"			/* ( res-entries 0 ) */
240*0Sstevel@tonic-gate "	 2drop exit"					/* ( ) */
241*0Sstevel@tonic-gate "      then"						/* ( res-entries 0 ) */
242*0Sstevel@tonic-gate "      do"						/* ( ) */
243*0Sstevel@tonic-gate " 	  i res-entry-pa xlsplit"			/* ( pa.lo pa.hi ) */
244*0Sstevel@tonic-gate " 	  i res-entry-len phy-release"			/* ( ) */
245*0Sstevel@tonic-gate "      loop"						/* ( ) */
246*0Sstevel@tonic-gate "      0 to num-res-entries"				/* ( ) */
247*0Sstevel@tonic-gate "      my-resources max-res-entries /res-entry * erase"	/* ( ) */
248*0Sstevel@tonic-gate "   ;"
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate "   : fill-entry" /* ( pa.lo pa.hi size.lo size.hi  -- )    \ fill chunk buf */
251*0Sstevel@tonic-gate "      num-res-entries /res-entry * my-resources +"
252*0Sstevel@tonic-gate "      tuck >res-len.hi l!"
253*0Sstevel@tonic-gate "      tuck >res-len.lo l!"
254*0Sstevel@tonic-gate "      tuck >res-pa.hi  l!"
255*0Sstevel@tonic-gate "      >res-pa.lo	l!"
256*0Sstevel@tonic-gate "      num-res-entries 1+ to num-res-entries"
257*0Sstevel@tonic-gate "   ;"
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate /*  \ First attempt to claim the whole ramdisk contiguously. */
260*0Sstevel@tonic-gate /*  \ If that doesn't work, try to claim it in smaller chunks */
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate "   : attempt-claim" /* ( size -- error? ) */
263*0Sstevel@tonic-gate "      size 0 begin"			/* ( next totcl ) */
264*0Sstevel@tonic-gate "	  over pagesize phy-claim if"	/* ( next totcl ) */
265*0Sstevel@tonic-gate "	     swap 2 / window-size"	/* ( totcl next' ) */
266*0Sstevel@tonic-gate " 	     round-up swap"		/* ( next' totcl ) */
267*0Sstevel@tonic-gate "	  else"				/* ( next totcl pa.lo,hi ) */
268*0Sstevel@tonic-gate " 	     2over drop xlsplit"	/* ( next totcl pa.lo,hi len.lo,hi ) */
269*0Sstevel@tonic-gate " 	     fill-entry"		/* ( next totcl ) */
270*0Sstevel@tonic-gate " 	     over +"			/* ( next totcl ) */
271*0Sstevel@tonic-gate " 	  then"				/* ( next totcl ) */
272*0Sstevel@tonic-gate " 	  2dup size - 0>="		/* ( next totcl next comp? ) */
273*0Sstevel@tonic-gate " 	  swap size max-res-entries /"	/* ( next totcl comp? next smallest ) */
274*0Sstevel@tonic-gate " 	  - 0< or"			/* ( next totcl ) */
275*0Sstevel@tonic-gate "      until"				/* ( next totcl ) */
276*0Sstevel@tonic-gate "      nip size - 0< if  -1  else  0  then"
277*0Sstevel@tonic-gate "   ;"
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate "   : claim-resources" /* ( -- error? ) */
280*0Sstevel@tonic-gate "      attempt-claim if  release-resources -1  else  0  then"
281*0Sstevel@tonic-gate "   ;"
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate /*  \ Given a 0-relative disk offset compute the proper physical address */
284*0Sstevel@tonic-gate "   : offset>pa" /* ( disk-offset -- 64bit-pa error? ) */
285*0Sstevel@tonic-gate "      0 num-res-entries 0 do"		/* ( disk-offset 0 ) */
286*0Sstevel@tonic-gate "	  i res-entry-len +"		/* ( disk-offset len' ) */
287*0Sstevel@tonic-gate " 	  2dup - 0< if"			/* ( disk-offset len' ) */
288*0Sstevel@tonic-gate "	     - i res-entry-len +"	/* ( offset-into-pa ) \ briefly -ve */
289*0Sstevel@tonic-gate " 	     i res-entry-pa + 0"	/* ( pa 0 ) */
290*0Sstevel@tonic-gate " 	     unloop exit"		/* ( pa 0 ) */
291*0Sstevel@tonic-gate " 	  then"				/* ( disk-offset len' ) */
292*0Sstevel@tonic-gate "      loop"				/* ( disk-offset len' ) */
293*0Sstevel@tonic-gate "      drop -1"				/* ( offset error ) */
294*0Sstevel@tonic-gate "   ;"
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate /*  \ Map the virtual window to the physical-address corresponding to the */
297*0Sstevel@tonic-gate /*  \ given 0-relative disk offset */
298*0Sstevel@tonic-gate "   : get-window" /* ( offset -- va len error? ) */
299*0Sstevel@tonic-gate "      dup offset>pa if"			/* ( offset pa ) */
300*0Sstevel@tonic-gate " 	  -1"					/* ( offset pa -1 ) */
301*0Sstevel@tonic-gate "      else"					/* ( offset pa ) */
302*0Sstevel@tonic-gate " 	  dup in-window? 0= if"			/* ( offset pa ) */
303*0Sstevel@tonic-gate " 	     unmap-window"			/* ( offset pa ) */
304*0Sstevel@tonic-gate " 	     over window-size mod - map-window"	/* ( offset ) */
305*0Sstevel@tonic-gate " 	  else"
306*0Sstevel@tonic-gate " 	     drop"
307*0Sstevel@tonic-gate " 	  then"
308*0Sstevel@tonic-gate " 	   window-base over window-size mod +"	/* ( offset va ) */
309*0Sstevel@tonic-gate " 	  swap window-left 0"			/* ( va len 0 ) */
310*0Sstevel@tonic-gate "      then"					/* ( va len error? ) */
311*0Sstevel@tonic-gate "   ;"
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate "   headers"
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate /*  \ Write len1 bytes from src into va. */
316*0Sstevel@tonic-gate "   : partial-write" /* ( src len0 va len1 -- len' ) */
317*0Sstevel@tonic-gate "      rot min dup >r move r>"
318*0Sstevel@tonic-gate "   ;"
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate /*  \ Read len1 bytes from src into va. */
321*0Sstevel@tonic-gate "   : partial-read" /* ( src len0 va len1 -- len' ) */
322*0Sstevel@tonic-gate "      rot min dup >r >r swap r> move r>"
323*0Sstevel@tonic-gate "   ;"
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate "   defer operation ' partial-write is operation"
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate /*  \ Write or Read len given the src address.  The block-operation word */
328*0Sstevel@tonic-gate /*  \ determines the physical address that corresponds to the current file */
329*0Sstevel@tonic-gate /*  \ position, and maps/unmaps the 64K virtual window */
330*0Sstevel@tonic-gate "   : block-operation" /* ( src len acf -- len' ) */
331*0Sstevel@tonic-gate "      is operation"
332*0Sstevel@tonic-gate "      0 -rot begin"			/* ( 0 src len ) */
333*0Sstevel@tonic-gate " 	  dup 0>"			/* ( len' src len more? ) */
334*0Sstevel@tonic-gate "      while"				/* ( len' src len  ) */
335*0Sstevel@tonic-gate " 	  2dup filepos"			/* ( len' src len src len filepos ) */
336*0Sstevel@tonic-gate " 	  get-window if"		/* ( len' src len src len va len ) */
337*0Sstevel@tonic-gate " 	     2drop 2drop 2drop exit"	/* ( len' ) */
338*0Sstevel@tonic-gate " 	  then"				/* ( len src len src len va len ) */
339*0Sstevel@tonic-gate " 	  operation"			/* ( len src len len' ) */
340*0Sstevel@tonic-gate " 	  dup filepos + to filepos"	/* ( len src len len' ) */
341*0Sstevel@tonic-gate " 	  >r r@ - rot r@ + rot r> + rot" /* ( len' src' len' ) */
342*0Sstevel@tonic-gate "      repeat"				/* ( len' src' len' ) */
343*0Sstevel@tonic-gate "      2drop"				/* ( len' ) */
344*0Sstevel@tonic-gate "   ;"
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate "   : range-bad?" /* ( adr -- range-bad? ) */
347*0Sstevel@tonic-gate "      0 size between 0="
348*0Sstevel@tonic-gate "   ;"
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate "   : space-left" /* ( -- space-left ) */
351*0Sstevel@tonic-gate "      size filepos -"
352*0Sstevel@tonic-gate "   ;"
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate "   : hex-number" /* ( adr,len -- true | n false ) */
355*0Sstevel@tonic-gate "      base @ >r hex $number r> base !"
356*0Sstevel@tonic-gate "   ;"
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate "   : parse-size" /* ( $nums -- 64bit-size | 0 )  \ poss ',' seperated ints */
359*0Sstevel@tonic-gate "      ascii , left-parse-string"		/* ( $num $num ) */
360*0Sstevel@tonic-gate "      hex-number if  2drop 0 exit  then"	/* ( $num n ) */
361*0Sstevel@tonic-gate "      over 0= if  nip nip exit  then"		/* ( $num n ) */
362*0Sstevel@tonic-gate "      -rot hex-number if  drop 0 exit  then"	/* ( hi lo ) */
363*0Sstevel@tonic-gate "      swap lxjoin"
364*0Sstevel@tonic-gate "   ;"
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate "   : set-size" /* ( adr len -- error? ) */
367*0Sstevel@tonic-gate "      parse-size dup 0= if"		/* ( size ) */
368*0Sstevel@tonic-gate "	  drop -1"			/* ( -1 ) */
369*0Sstevel@tonic-gate "      else"				/* ( size ) */
370*0Sstevel@tonic-gate " 	  window-size round-up"		/* ( size' ) */
371*0Sstevel@tonic-gate " 	  dup to size"			/* ( size' ) */
372*0Sstevel@tonic-gate " 	  d# 512 / to #blocks"		/* ( ) */
373*0Sstevel@tonic-gate " 	  \" nolabel\" my-label pack"	/* \ first open cannot have a label */
374*0Sstevel@tonic-gate " 	  drop 0"			/* ( 0 ) */
375*0Sstevel@tonic-gate "      then"				/* ( error? ) */
376*0Sstevel@tonic-gate "   ;"
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate "   : $=" /* (s adr1 len1 adr2 len2 -- same? ) */
379*0Sstevel@tonic-gate "      rot tuck  <>  if  3drop false exit  then"	/* ( adr1 adr2 len1 ) */
380*0Sstevel@tonic-gate "      comp 0="						/* ( same? ) */
381*0Sstevel@tonic-gate "   ;"
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate "   : is-label?" /* ( adr len -- is-label? )	\ $= "nolabel" or <a-z> */
384*0Sstevel@tonic-gate "      dup 1 = if"				/* ( adr len ) */
385*0Sstevel@tonic-gate " 	  drop c@ ascii a ascii z between"	/* ( is-label? ) */
386*0Sstevel@tonic-gate "      else"					/* ( adr len ) */
387*0Sstevel@tonic-gate " 	  \" nolabel\" $="			/* ( is-label? ) */
388*0Sstevel@tonic-gate "      then"					/* ( is-label? ) */
389*0Sstevel@tonic-gate "   ;"
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate "   : set-label" /* ( adr len -- error? ) */
392*0Sstevel@tonic-gate "      my-label label-size erase"
393*0Sstevel@tonic-gate "      dup 1+ label-size > if"
394*0Sstevel@tonic-gate "	  2drop -1"
395*0Sstevel@tonic-gate "      else"
396*0Sstevel@tonic-gate "	  my-label pack drop 0"
397*0Sstevel@tonic-gate "      then"
398*0Sstevel@tonic-gate "   ;"
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate "   : process-args" /* ( arg$ -- error? ) */
401*0Sstevel@tonic-gate "      ascii = left-parse-string"		/* ( value$ key$ ) */
402*0Sstevel@tonic-gate "      new-disk? if"				/* ( value$ key$ ) */
403*0Sstevel@tonic-gate " 	  2dup \" size\" $= if"			/* ( value$ key$ ) */
404*0Sstevel@tonic-gate " 	    2drop set-size exit"		/* ( error? ) */
405*0Sstevel@tonic-gate " 	  then"					/* ( value$ key$ ) */
406*0Sstevel@tonic-gate "      else"					/* ( value$ key$ ) */
407*0Sstevel@tonic-gate " 	  2dup is-label? if"			/* ( value$ key$ ) */
408*0Sstevel@tonic-gate " 	    2swap 2drop set-label exit"		/* ( error? ) */
409*0Sstevel@tonic-gate " 	  then"					/* ( value$ key$ ) */
410*0Sstevel@tonic-gate "      then"					/* ( value$ key$ ) */
411*0Sstevel@tonic-gate "     .\" Inappropriate argument \" type cr  2drop -1"	/* ( -1 ) */
412*0Sstevel@tonic-gate "   ;"
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate /*  \ Publish the physical chunks that make up the ramdisk in the */
415*0Sstevel@tonic-gate /*  \ existing property */
416*0Sstevel@tonic-gate "   : create-existing-prop" /* ( -- ) */
417*0Sstevel@tonic-gate "     0 0 encode-bytes"				/* ( adr 0 ) */
418*0Sstevel@tonic-gate "     num-res-entries 0 do"			/* ( adr 0 ) */
419*0Sstevel@tonic-gate "       i /res-entry * my-resources + >r"	/* ( adr len ) */
420*0Sstevel@tonic-gate "       r@ >res-pa.hi l@  encode-int encode+"	/* ( adr len ) */
421*0Sstevel@tonic-gate "       r@ >res-pa.lo l@  encode-int encode+"	/* ( adr len ) */
422*0Sstevel@tonic-gate "       r@ >res-len.hi l@ encode-int encode+"	/* ( adr len ) */
423*0Sstevel@tonic-gate "       r> >res-len.lo l@ encode-int encode+"	/* ( adr len ) */
424*0Sstevel@tonic-gate "     loop"					/* ( adr len ) */
425*0Sstevel@tonic-gate "     \" existing\" property"			/* ( ) */
426*0Sstevel@tonic-gate "   ;"
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate "   external"
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate "   : read" /* ( adr,len -- len' ) */
431*0Sstevel@tonic-gate "      space-left"			/* ( adr len space-left ) */
432*0Sstevel@tonic-gate "      min ['] partial-read"		/* ( adr len' read-acf ) */
433*0Sstevel@tonic-gate "      block-operation"			/* ( len' ) */
434*0Sstevel@tonic-gate "   ;"
435*0Sstevel@tonic-gate 
436*0Sstevel@tonic-gate "   : write" /* ( adr,len -- len' ) */
437*0Sstevel@tonic-gate "      space-left"			/* ( adr len space-left ) */
438*0Sstevel@tonic-gate "      min ['] partial-write"		/* ( adr len' write-acf ) */
439*0Sstevel@tonic-gate "      block-operation"			/* ( len' ) */
440*0Sstevel@tonic-gate "   ;"
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate "   : seek" /* ( offset other -- error? ) */
443*0Sstevel@tonic-gate "      offset-high + swap offset-low + swap drop"  /* \ "other" arg unused */
444*0Sstevel@tonic-gate "      dup 0< if"			/* ( offset ) */
445*0Sstevel@tonic-gate "	  size +"			/* ( offset' ) */
446*0Sstevel@tonic-gate "      then"				/* ( offset' ) */
447*0Sstevel@tonic-gate "	  0 + dup range-bad? if"	/* ( offset' ) */
448*0Sstevel@tonic-gate " 	  drop -1"			/* ( -1 ) */
449*0Sstevel@tonic-gate "      else"				/* ( offset' ) */
450*0Sstevel@tonic-gate " 	  to filepos false"		/* ( 0 ) */
451*0Sstevel@tonic-gate "      then"				/* ( error? ) */
452*0Sstevel@tonic-gate "   ;"
453*0Sstevel@tonic-gate 
454*0Sstevel@tonic-gate "   : load" /* ( addr -- size ) */
455*0Sstevel@tonic-gate "      \" load\"  label-package $call-method"
456*0Sstevel@tonic-gate "   ;"
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate "   : offset" /* ( rel -- abs )  \ needed for device_type = block */
459*0Sstevel@tonic-gate "      offset-low +"
460*0Sstevel@tonic-gate "   ;"
461*0Sstevel@tonic-gate 
462*0Sstevel@tonic-gate /*  \ release resources, initialize data, remove existing property */
463*0Sstevel@tonic-gate /*  \ Can be called with no instance data */
464*0Sstevel@tonic-gate "   : destroy" /* ( -- ) */
465*0Sstevel@tonic-gate "      \" existing\" delete-property"
466*0Sstevel@tonic-gate "      0 to size"
467*0Sstevel@tonic-gate "      -1 to new-disk?"
468*0Sstevel@tonic-gate "      release-resources"
469*0Sstevel@tonic-gate "   ;"
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate "   : open" /* ( -- flag ) */
472*0Sstevel@tonic-gate "      my-args process-args if"
473*0Sstevel@tonic-gate "	  0 exit"				/* \ unrecognized arguments */
474*0Sstevel@tonic-gate "      then"
475*0Sstevel@tonic-gate "      new-disk? if"
476*0Sstevel@tonic-gate "	  claim-resources if  0 exit  then"	/* \ can't claim */
477*0Sstevel@tonic-gate "	  create-existing-prop"			/* \ advertise resources */
478*0Sstevel@tonic-gate "	  0 to new-disk?"			/* \ no longer a new-disk */
479*0Sstevel@tonic-gate "      then"
480*0Sstevel@tonic-gate "      claim-window"				/* \ claim virtual window */
481*0Sstevel@tonic-gate "      my-label count init-label-package 0= if  0 exit  then"
482*0Sstevel@tonic-gate "      -1"
483*0Sstevel@tonic-gate "   ;"
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate "   : close" /* ( -- ) */
486*0Sstevel@tonic-gate "      window-base if "
487*0Sstevel@tonic-gate "	  release-window"
488*0Sstevel@tonic-gate "      then"
489*0Sstevel@tonic-gate "   ; "
490*0Sstevel@tonic-gate "finish-device "
491*0Sstevel@tonic-gate 
492*0Sstevel@tonic-gate "pop-package"
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate ;	/* end of ramdisk_fth[] initialization */
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate /*
498*0Sstevel@tonic-gate  * Create an actual ramdisk instance.
499*0Sstevel@tonic-gate  */
500*0Sstevel@tonic-gate static void
501*0Sstevel@tonic-gate create_ramdisk_node(const char *ramdisk_name)
502*0Sstevel@tonic-gate {
503*0Sstevel@tonic-gate 	char	*fth_buf;
504*0Sstevel@tonic-gate 	size_t	buf_size;
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 	buf_size = sizeof (ramdisk_fth) + strlen(ramdisk_name);
507*0Sstevel@tonic-gate 
508*0Sstevel@tonic-gate 	fth_buf = bkmem_alloc(buf_size);
509*0Sstevel@tonic-gate 	if (fth_buf == NULL) {
510*0Sstevel@tonic-gate 		prom_panic("unable to allocate Forth buffer for ramdisk");
511*0Sstevel@tonic-gate 	}
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	(void) snprintf(fth_buf, buf_size, ramdisk_fth, ramdisk_name);
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	prom_interpret(fth_buf, 0, 0, 0, 0, 0);
516*0Sstevel@tonic-gate 
517*0Sstevel@tonic-gate 	bkmem_free(fth_buf, buf_size);
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate int
521*0Sstevel@tonic-gate create_ramdisk(const char *ramdisk_name, size_t size, char **device_path)
522*0Sstevel@tonic-gate {
523*0Sstevel@tonic-gate 	static int	first_time = 1;
524*0Sstevel@tonic-gate 	char		buf[OBP_MAXPATHLEN];
525*0Sstevel@tonic-gate 	ihandle_t	ih;
526*0Sstevel@tonic-gate 
527*0Sstevel@tonic-gate 	/*
528*0Sstevel@tonic-gate 	 * Ensure that size is a multiple of page size (rounded up).
529*0Sstevel@tonic-gate 	 */
530*0Sstevel@tonic-gate 	size = ptob(btopr(size));
531*0Sstevel@tonic-gate 
532*0Sstevel@tonic-gate /* EXPORT DELETE START */
533*0Sstevel@tonic-gate 	bootlog("wanboot", BOOTLOG_VERBOSE, "Creating ramdisk, size=0x%lx",
534*0Sstevel@tonic-gate 	    size);
535*0Sstevel@tonic-gate /* EXPORT DELETE END */
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate 	if (strcmp(ramdisk_name, RD_ROOTFS) == 0 ||
538*0Sstevel@tonic-gate 	    strcmp(ramdisk_name, RD_BOOTFS) == 0) {
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate 		if (first_time) {
541*0Sstevel@tonic-gate 			first_time = 0;
542*0Sstevel@tonic-gate 
543*0Sstevel@tonic-gate 			create_ramdisk_node(RD_ROOTFS);
544*0Sstevel@tonic-gate 			create_ramdisk_node(RD_BOOTFS);
545*0Sstevel@tonic-gate 		}
546*0Sstevel@tonic-gate 
547*0Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "/%s:nolabel", ramdisk_name);
548*0Sstevel@tonic-gate 		*device_path = strdup(buf);
549*0Sstevel@tonic-gate 
550*0Sstevel@tonic-gate 		if (*device_path != NULL) {
551*0Sstevel@tonic-gate 			(void) snprintf(buf, sizeof (buf), "/%s:size=%x,%x",
552*0Sstevel@tonic-gate 			    ramdisk_name,
553*0Sstevel@tonic-gate 			    (uint32_t)(size >> 32), (uint32_t)size);
554*0Sstevel@tonic-gate 
555*0Sstevel@tonic-gate 			if ((ih = prom_open(buf)) != 0) {
556*0Sstevel@tonic-gate 				return (ih);
557*0Sstevel@tonic-gate 			}
558*0Sstevel@tonic-gate 		}
559*0Sstevel@tonic-gate 	}
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate /* EXPORT DELETE START */
562*0Sstevel@tonic-gate 	bootlog("wanboot", BOOTLOG_CRIT, "Cannot create ramdisk \"%s\"",
563*0Sstevel@tonic-gate 	    ramdisk_name);
564*0Sstevel@tonic-gate /* EXPORT DELETE END */
565*0Sstevel@tonic-gate 	prom_panic("create_ramdisk: fatal error");
566*0Sstevel@tonic-gate 	/* NOTREACHED */
567*0Sstevel@tonic-gate }
568