diff options
Diffstat (limited to 'qemu/roms/SLOF/slof/fs/client.fs')
-rw-r--r-- | qemu/roms/SLOF/slof/fs/client.fs | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/slof/fs/client.fs b/qemu/roms/SLOF/slof/fs/client.fs new file mode 100644 index 000000000..1b2bb0326 --- /dev/null +++ b/qemu/roms/SLOF/slof/fs/client.fs @@ -0,0 +1,299 @@ +\ ***************************************************************************** +\ * Copyright (c) 2004, 2008 IBM Corporation +\ * All rights reserved. +\ * This program and the accompanying materials +\ * are made available under the terms of the BSD License +\ * which accompanies this distribution, and is available at +\ * http://www.opensource.org/licenses/bsd-license.php +\ * +\ * Contributors: +\ * IBM Corporation - initial implementation +\ ****************************************************************************/ + + +\ Client interface. + +0 VALUE debug-client-interface? + +\ First, the machinery. + +VOCABULARY client-voc \ We store all client-interface callable words here. + +6789 CONSTANT sc-exit +4711 CONSTANT sc-yield + +VARIABLE client-callback \ Address of client's callback function + +: client-data ciregs >r3 @ ; +: nargs client-data la1+ l@ ; +: nrets client-data la1+ la1+ l@ ; +: client-data-to-stack + client-data 3 la+ nargs 0 ?DO dup l@ swap la1+ LOOP drop ; +: stack-to-client-data + client-data nargs nrets + 2 + la+ nrets 0 ?DO tuck l! /l - LOOP drop ; + +: call-client ( args len client-entry -- ) + \ (args, len) describe the argument string, client-entry is the address of + \ the client's .entry symbol, i.e. where we eventually branch to. + \ ciregs is a variable that describes the register set of the host processor, + \ see slof/fs/exception.fs for details + \ client-entry-point maps to client_entry_point in slof/entry.S which is + \ the SLOF entry point when calling a SLOF client interface word from the + \ client. + \ We pass the arguments for the client in R6 and R7, the client interface + \ entry point address is passed in R5. + >r ciregs >r7 ! ciregs >r6 ! client-entry-point @ ciregs >r5 ! + \ Initialise client-stack-pointer + cistack ciregs >r1 ! + \ jump-client maps to call_client in slof/entry.S + \ When jump-client returns, R3 holds the address of a NUL-terminated string + \ that holds the client interface word the client wants to call, R4 holds + \ the return address. + r> jump-client drop + BEGIN + client-data-to-stack + \ Now create a Forth-style string, look it up in the client dictionary and + \ execute it, guarded by CATCH. Result of xt == 0 is stored on the return + \ stack + client-data l@ zcount + \ XXX: Should only look in client-voc... + ALSO client-voc $find PREVIOUS + dup 0= >r IF + CATCH + \ If a client interface word needs some special treatment, like exit and + \ yield, then the implementation needs to use THROW to indicate its needs + ?dup IF + dup CASE + sc-exit OF drop r> drop EXIT ENDOF + sc-yield OF drop r> drop EXIT ENDOF + ENDCASE + \ Some special call was made but we don't know that to do with it... + THROW + THEN + stack-to-client-data + ELSE + cr type ." NOT FOUND" + THEN + \ Return to the client + r> ciregs >r3 ! ciregs >r4 @ jump-client + UNTIL ; + +: flip-stack ( a1 ... an n -- an ... a1 ) ?dup IF 1 ?DO i roll LOOP THEN ; + +: (callback) ( "service-name<>" "arguments<cr>" -- ) + client-callback @ \ client-callback points to the function prolog + dup 8 + @ ciregs >r2 ! \ Set up the TOC pointer (???) + @ call-client ; \ Resolve the function's address from the prolog +' (callback) to callback + +: (continue-client) + s" " \ make call-client happy, client won't use the string anyways. + ciregs >r4 @ call-client ; +' (continue-client) to continue-client + +\ Utility. +: string-to-buffer ( str len buf len -- len' ) + 2dup erase rot min dup >r move r> ; + +\ Now come the actual client interface words. + +ALSO client-voc DEFINITIONS + +: exit sc-exit THROW ; + +: yield sc-yield THROW ; + +: test ( zstr -- missing? ) + \ XXX: Should only look in client-voc... + zcount + debug-client-interface? IF + ." ci: test " 2dup type cr + THEN + ALSO client-voc $find PREVIOUS IF + drop FALSE + ELSE + 2drop TRUE + THEN +; + +: finddevice ( zstr -- phandle ) + zcount + debug-client-interface? IF + ." ci: finddevice " 2dup type cr + THEN + 2dup " /memory" str= IF + \ Workaround: grub passes /memory instead of /memory@0 + 2drop + " /memory@0" + THEN + find-node dup 0= IF drop -1 THEN +; + +: getprop ( phandle zstr buf len -- len' ) + >r >r zcount rot ( str-adr str-len phandle R: len buf ) + debug-client-interface? IF + ." ci: getprop " 3dup . ." '" type ." '" + THEN + get-property + debug-client-interface? IF + dup IF ." ** not found **" THEN + cr + THEN + 0= IF + r> swap dup r> min swap >r move r> + ELSE + r> r> 2drop -1 + THEN +; + +: getproplen ( phandle zstr -- len ) + zcount rot get-property 0= IF nip ELSE -1 THEN ; + +: setprop ( phandle zstr buf len -- size|-1 ) + dup >r \ save len + encode-bytes ( phandle zstr prop-addr prop-len ) + 2swap zcount rot ( prop-addr prop-len name-addr name-len phandle ) + current-node @ >r \ save current node + set-node \ change to specified node + property \ set property + r> set-node \ restore original node + r> \ always return size, because we can not fail. +; + +\ VERY HACKISH +: canon ( zstr buf len -- len' ) + 2dup erase + >r >r zcount + >r dup c@ [char] / = IF + r> r> swap r> over >r min move r> + ELSE + r> find-alias ?dup 0= IF + r> r> 2drop -1 + ELSE + dup -rot r> swap r> min move + THEN + THEN +; + +: nextprop ( phandle zstr buf -- flag ) \ -1 invalid, 0 end, 1 ok + >r zcount rot next-property IF r> zplace 1 ELSE r> drop 0 THEN ; + +: open ( zstr -- ihandle ) + zcount + debug-client-interface? IF + ." ci: open " 2dup type cr + THEN + open-dev +; + +: close ( ihandle -- ) + debug-client-interface? IF + ." ci: close " dup . cr + THEN + s" stdin" get-chosen IF + decode-int nip nip over = IF + \ End of life of SLOF now, call platform quiesce as quiesce + \ is an undocumented extension and not everybody supports it + close-dev + quiesce + ELSE + close-dev + THEN + ELSE + close-dev + THEN +; + +\ Now implemented: should return -1 if no such method exists in that node +: write ( ihandle str len -- len' ) rot s" write" rot + ['] $call-method CATCH IF 2drop 3drop -1 THEN ; +: read ( ihandle str len -- len' ) rot s" read" rot + ['] $call-method CATCH IF 2drop 3drop -1 THEN ; +: seek ( ihandle hi lo -- status ) swap rot s" seek" rot + ['] $call-method CATCH IF 2drop 3drop -1 THEN ; + +\ A real claim implementation: 3.2% memory fat :-) +: claim ( addr len align -- base ) + debug-client-interface? IF + ." ci: claim " .s cr + THEN + dup IF rot drop + ['] claim CATCH IF 2drop -1 THEN + ELSE + ['] claim CATCH IF 3drop -1 THEN + THEN +; + +: release ( addr len -- ) + debug-client-interface? IF + ." ci: release " .s cr + THEN + release +; + +: instance-to-package ( ihandle -- phandle ) + ihandle>phandle ; + +: package-to-path ( phandle buf len -- len' ) + 2>r node>path 2r> string-to-buffer ; +: instance-to-path ( ihandle buf len -- len' ) + 2>r instance>path 2r> string-to-buffer ; +: instance-to-interposed-path ( ihandle buf len -- len' ) + 2>r instance>qpath 2r> string-to-buffer ; + +: call-method ( str ihandle arg ... arg -- result return ... return ) + nargs flip-stack zcount + debug-client-interface? IF + ." ci: call-method " 2dup type cr + THEN + rot ['] $call-method CATCH + nrets 0= IF drop ELSE \ if called with 0 return args do not return the catch result + dup IF nrets 1 ?DO -444 LOOP THEN + nrets flip-stack + THEN +; + +\ From the PAPR. +: test-method ( phandle str -- missing? ) + zcount + debug-client-interface? IF + ." ci: test-method " 2dup type cr + THEN + rot find-method dup IF nip THEN 0= +; + +: milliseconds milliseconds ; + +: start-cpu ( phandle addr r3 -- ) + >r >r + s" reg" rot get-property 0= IF drop l@ + ELSE true ABORT" start-cpu called with invalid phandle" THEN + r> r> of-start-cpu drop +; + +\ Quiesce firmware and assert that all hardware is in a sane state +\ (e.g. assert that no background DMA is running anymore) +: quiesce ( -- ) + debug-client-interface? IF + ." ci: quiesce" cr + THEN + \ The main quiesce call is defined in quiesce.fs + quiesce +; + +\ +\ User Interface, defined in 6.3.2.6 +\ +: interpret ( ... zstr -- result ... ) + zcount + debug-client-interface? IF + ." ci: interpret " 2dup type cr + THEN + ['] evaluate CATCH +; + +\ Allow the client to register a callback +: set-callback ( newfunc -- oldfunc ) + client-callback @ swap client-callback ! ; + +PREVIOUS DEFINITIONS |