Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / translate.fs
diff --git a/qemu/roms/SLOF/slof/fs/translate.fs b/qemu/roms/SLOF/slof/fs/translate.fs
new file mode 100644 (file)
index 0000000..9654f24
--- /dev/null
@@ -0,0 +1,150 @@
+\ *****************************************************************************
+\ * 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
+\ ****************************************************************************/
+
+\ this is a C-to-Forth translation from the translate
+\ address code in the client
+\ with extensions to handle different sizes of #size-cells
+
+\ this tries to figure out if it is a PCI device what kind of
+\ translation is wanted
+\ if prop_type is 0, "reg" property is used, otherwise "assigned-addresses"
+: pci-address-type  ( node address prop_type -- type )
+   -rot 2 pick ( prop_type node address prop_type )
+   0= IF
+      swap s" reg" rot get-property  ( prop_type address data dlen false )
+   ELSE
+      swap s" assigned-addresses" rot get-property  ( prop_type address data dlen false )
+   THEN
+   IF  2drop -1  EXIT  THEN  4 / 5 /
+   \ advance (phys-addr(3) size(2)) steps
+   0 DO
+      \ BARs and Expansion ROM must be in assigned-addresses...
+      \ so if prop_type is 0 ("reg") and a config space offset is set
+      \ we skip this entry...
+      dup l@ FF AND 0<> ( prop_type address data cfgspace_offset? )
+      3 pick 0= ( prop_type address data cfgspace_offset? reg_prop? )
+      AND NOT IF 
+         2dup 4 + ( prop_type address data address data' )
+         2dup @ 2 pick 8 + @ + <= -rot @  >= and  IF
+            l@ 03000000 and 18 rshift nip
+            ( prop_type type )
+            swap drop ( type )
+            UNLOOP EXIT
+         THEN
+      THEN
+      \ advance in 4 byte steps and (phys-addr(3) size(2)) steps
+      4 5 * +
+   LOOP
+   3drop -1
+;
+
+: (range-read-cells)  ( range-addr #cells -- range-value )
+   \ if number of cells != 1; do 64bit read; else a 32bit read
+   1 =  IF  l@  ELSE  @  THEN
+;
+
+\ this functions tries to find a mapping for the given address
+\ it assumes that if we have #address-cells == 3 that we are trying
+\ to do a PCI translation
+
+\ nac - #address-cells
+\ nsc - #size-cells
+\ pnac - parent #address-cells
+
+: (map-one-range)  ( type range pnac nsc nac address -- address true | address false )
+   \ only check for the type if nac == 3 (PCI)
+   over 3 = 5 pick l@ 3000000 and 18 rshift 7 pick <> and  IF
+      >r 2drop 3drop r> false EXIT
+   THEN
+   \ get size
+   4 pick 4 pick 3 pick + 4 * +
+   \ get nsc
+   3 pick
+   \ read size
+   ( type range pnac nsc nac address range nsc )
+   (range-read-cells)
+   ( type range pnac nsc nac address size )
+   \ skip type if PCI
+   5 pick 3 pick 3 =  IF
+      4 +
+   THEN
+   \ get nac
+   3 pick
+   ( type range pnac nsc nac address size range nac )
+   \ read child-mapping
+   (range-read-cells)
+   ( type range pnac nsc nac address size child-mapping )
+   dup >r dup 3 pick > >r + over <= r> or  IF
+      \ address is not inside the mapping range
+      >r 2drop 3drop r> r> drop false EXIT
+   THEN
+   dup r> -
+   ( type range pnac nsc nac address offset )
+   \ add the offset on the parent mapping
+   5 pick 5 pick 3 =  IF
+      \ skip type if PCI
+      4 +
+   THEN
+   3 pick 4 * +
+   ( type range pnac nsc nac address offset parent-mapping-address )
+   \ get pnac
+   5 pick
+   \ read parent mapping
+   (range-read-cells)
+   ( type range pnac nsc nac address offset parent-mapping )
+   + >r 3drop 3drop r> true
+;
+
+\ this word translates the given address starting from the node specified
+\ in node; the word will return to the node it was started from
+: translate-address  ( node address -- address )
+   \ check for address type in "assigned-addresses"
+   2dup 1 pci-address-type  ( node address type )
+   dup -1 = IF
+      \ not found in "assigned-addresses", check in "reg"
+      drop 2dup 0 pci-address-type ( node address type )
+   THEN
+   rot parent BEGIN
+      \ check if it is the root node
+      dup parent 0=  IF  2drop EXIT  THEN
+      ( address type parent )
+      s" #address-cells" 2 pick get-property 2drop l@ >r        \ nac
+      s" #size-cells" 2 pick get-property 2drop l@ >r           \ nsc
+      s" #address-cells" 2 pick parent get-property 2drop l@ >r \ pnac
+      -rot ( node address type )
+      s" ranges" 4 pick get-property  IF
+         3drop
+         ABORT" no ranges property; not translatable"
+      THEN
+      r> r> r> 3 roll
+      ( node address type ranges pnac nsc nac length )
+      4 / >r 3dup + + >r 5 roll r> r> swap / 0 ?DO
+         ( node type ranges pnac nsc nac address )
+         6dup (map-one-range) IF
+            nip leave
+         THEN
+         nip
+         \ advance ranges
+         4 roll
+         ( node type pnac nsc nac address ranges )
+         4 pick 4 pick 4 pick + + 4 * + 4 -roll
+      LOOP
+      >r 2drop 2drop r> ( node type address )
+      swap rot parent ( address type node )
+      dup 0=
+   UNTIL
+;
+
+\ this words translates the given address starting from the current node
+: translate-my-address  ( address -- address' )
+   get-node swap translate-address
+;