1 \ *****************************************************************************
2 \ * Copyright (c) 2004, 2008 IBM Corporation
3 \ * All rights reserved.
4 \ * This program and the accompanying materials
5 \ * are made available under the terms of the BSD License
6 \ * which accompanies this distribution, and is available at
7 \ * http://www.opensource.org/licenses/bsd-license.php
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
16 0 VALUE debug-client-interface?
18 \ First, the machinery.
20 VOCABULARY client-voc \ We store all client-interface callable words here.
23 4711 CONSTANT sc-yield
25 VARIABLE client-callback \ Address of client's callback function
27 : client-data ciregs >r3 @ ;
28 : nargs client-data la1+ l@ ;
29 : nrets client-data la1+ la1+ l@ ;
30 : client-data-to-stack
31 client-data 3 la+ nargs 0 ?DO dup l@ swap la1+ LOOP drop ;
32 : stack-to-client-data
33 client-data nargs nrets + 2 + la+ nrets 0 ?DO tuck l! /l - LOOP drop ;
35 : call-client ( args len client-entry -- )
36 \ (args, len) describe the argument string, client-entry is the address of
37 \ the client's .entry symbol, i.e. where we eventually branch to.
38 \ ciregs is a variable that describes the register set of the host processor,
39 \ see slof/fs/exception.fs for details
40 \ client-entry-point maps to client_entry_point in slof/entry.S which is
41 \ the SLOF entry point when calling a SLOF client interface word from the
43 \ We pass the arguments for the client in R6 and R7, the client interface
44 \ entry point address is passed in R5.
45 >r ciregs >r7 ! ciregs >r6 ! client-entry-point @ ciregs >r5 !
46 \ Initialise client-stack-pointer
48 \ jump-client maps to call_client in slof/entry.S
49 \ When jump-client returns, R3 holds the address of a NUL-terminated string
50 \ that holds the client interface word the client wants to call, R4 holds
55 \ Now create a Forth-style string, look it up in the client dictionary and
56 \ execute it, guarded by CATCH. Result of xt == 0 is stored on the return
59 \ XXX: Should only look in client-voc...
60 ALSO client-voc $find PREVIOUS
63 \ If a client interface word needs some special treatment, like exit and
64 \ yield, then the implementation needs to use THROW to indicate its needs
67 sc-exit OF drop r> drop EXIT ENDOF
68 sc-yield OF drop r> drop EXIT ENDOF
70 \ Some special call was made but we don't know that to do with it...
77 \ Return to the client
78 r> ciregs >r3 ! ciregs >r4 @ jump-client
81 : flip-stack ( a1 ... an n -- an ... a1 ) ?dup IF 1 ?DO i roll LOOP THEN ;
83 : (callback) ( "service-name<>" "arguments<cr>" -- )
84 client-callback @ \ client-callback points to the function prolog
85 dup 8 + @ ciregs >r2 ! \ Set up the TOC pointer (???)
86 @ call-client ; \ Resolve the function's address from the prolog
87 ' (callback) to callback
90 s" " \ make call-client happy, client won't use the string anyways.
91 ciregs >r4 @ call-client ;
92 ' (continue-client) to continue-client
95 : string-to-buffer ( str len buf len -- len' )
96 2dup erase rot min dup >r move r> ;
98 \ Now come the actual client interface words.
100 ALSO client-voc DEFINITIONS
102 : exit sc-exit THROW ;
104 : yield sc-yield THROW ;
106 : test ( zstr -- missing? )
107 \ XXX: Should only look in client-voc...
109 debug-client-interface? IF
110 ." ci: test " 2dup type cr
112 ALSO client-voc $find PREVIOUS IF
119 : finddevice ( zstr -- phandle )
121 debug-client-interface? IF
122 ." ci: finddevice " 2dup type cr
124 2dup " /memory" str= IF
125 \ Workaround: grub passes /memory instead of /memory@0
129 find-node dup 0= IF drop -1 THEN
132 : getprop ( phandle zstr buf len -- len' )
133 >r >r zcount rot ( str-adr str-len phandle R: len buf )
134 debug-client-interface? IF
135 ." ci: getprop " 3dup . ." '" type ." '"
138 debug-client-interface? IF
139 dup IF ." ** not found **" THEN
143 r> swap dup r> min swap >r move r>
149 : getproplen ( phandle zstr -- len )
150 zcount rot get-property 0= IF nip ELSE -1 THEN ;
152 : setprop ( phandle zstr buf len -- size|-1 )
154 encode-bytes ( phandle zstr prop-addr prop-len )
155 2swap zcount rot ( prop-addr prop-len name-addr name-len phandle )
156 current-node @ >r \ save current node
157 set-node \ change to specified node
158 property \ set property
159 r> set-node \ restore original node
160 r> \ always return size, because we can not fail.
164 : canon ( zstr buf len -- len' )
167 >r dup c@ [char] / = IF
168 r> r> swap r> over >r min move r>
170 r> find-alias ?dup 0= IF
173 dup -rot r> swap r> min move
178 : nextprop ( phandle zstr buf -- flag ) \ -1 invalid, 0 end, 1 ok
179 >r zcount rot next-property IF r> zplace 1 ELSE r> drop 0 THEN ;
181 : open ( zstr -- ihandle )
183 debug-client-interface? IF
184 ." ci: open " 2dup type cr
189 : close ( ihandle -- )
190 debug-client-interface? IF
191 ." ci: close " dup . cr
193 s" stdin" get-chosen IF
194 decode-int nip nip over = IF
195 \ End of life of SLOF now, call platform quiesce as quiesce
196 \ is an undocumented extension and not everybody supports it
207 \ Now implemented: should return -1 if no such method exists in that node
208 : write ( ihandle str len -- len' ) rot s" write" rot
209 ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
210 : read ( ihandle str len -- len' ) rot s" read" rot
211 ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
212 : seek ( ihandle hi lo -- status ) swap rot s" seek" rot
213 ['] $call-method CATCH IF 2drop 3drop -1 THEN ;
215 \ A real claim implementation: 3.2% memory fat :-)
216 : claim ( addr len align -- base )
217 debug-client-interface? IF
221 ['] claim CATCH IF 2drop -1 THEN
223 ['] claim CATCH IF 3drop -1 THEN
227 : release ( addr len -- )
228 debug-client-interface? IF
229 ." ci: release " .s cr
234 : instance-to-package ( ihandle -- phandle )
237 : package-to-path ( phandle buf len -- len' )
238 2>r node>path 2r> string-to-buffer ;
239 : instance-to-path ( ihandle buf len -- len' )
240 2>r instance>path 2r> string-to-buffer ;
241 : instance-to-interposed-path ( ihandle buf len -- len' )
242 2>r instance>qpath 2r> string-to-buffer ;
244 : call-method ( str ihandle arg ... arg -- result return ... return )
245 nargs flip-stack zcount
246 debug-client-interface? IF
247 ." ci: call-method " 2dup type cr
249 rot ['] $call-method CATCH
250 nrets 0= IF drop ELSE \ if called with 0 return args do not return the catch result
251 dup IF nrets 1 ?DO -444 LOOP THEN
257 : test-method ( phandle str -- missing? )
259 debug-client-interface? IF
260 ." ci: test-method " 2dup type cr
262 rot find-method dup IF nip THEN 0=
265 : milliseconds milliseconds ;
267 : start-cpu ( phandle addr r3 -- )
269 s" reg" rot get-property 0= IF drop l@
270 ELSE true ABORT" start-cpu called with invalid phandle" THEN
271 r> r> of-start-cpu drop
274 \ Quiesce firmware and assert that all hardware is in a sane state
275 \ (e.g. assert that no background DMA is running anymore)
277 debug-client-interface? IF
280 \ The main quiesce call is defined in quiesce.fs
285 \ User Interface, defined in 6.3.2.6
287 : interpret ( ... zstr -- result ... )
289 debug-client-interface? IF
290 ." ci: interpret " 2dup type cr
295 \ Allow the client to register a callback
296 : set-callback ( newfunc -- oldfunc )
297 client-callback @ swap client-callback ! ;