Create an OFW device tree by parsing the LinuxBIOS device tree.
To create a device tree call create-lb-devices

Signed-off-by: Jens Freimann <jens@freimann.org>

Index: cpu/x86/pc/biosload/lbdevtree.fth
===================================================================
--- cpu/x86/pc/biosload/lbdevtree.fth	(Revision 0)
+++ cpu/x86/pc/biosload/lbdevtree.fth	(Revision 0)
@@ -0,0 +1,455 @@
+purpose: Create device tree by parsing the LinuxBIOS device tree
+
+\  defines from LinuxBIOS
+00000100 constant LB_IORESOURCE_IO
+00000200 constant LB_IORESOURCE_MEM32
+00000300 constant LB_IORESOURCE_MEM64
+00001000 constant LB_IORESOURCE_PREFETCH
+
+\ device datastructure in LinuxBIOS
+struct
+h# 5c   field >device-something  \ TODO: add remaining fields
+h# 4    field >device-vendor-id
+h# 4    field >device-id
+h# 20   field >device-something2 \ TODO: add remaining fields
+h# 1b0  field >device-resources
+h# 4    field >device-numberof
+constant /device
+
+\ resource datastructure in LinuxBIOS
+struct
+h#  0 field >resource-baseaddr
+h#  8 field >resource-size
+h# 10 field >resource-limit
+h# 18 field >resource-flags
+h# 1c field >resource-index
+h# 20 field >resource-align
+h# 21 field >resource-gran
+constant /resource
+\ -------------------------------------
+
+\ Variables
+create lb-stringbuf 11 allot
+create lb-dev-addr   4 allot
+create lb-devfn      4 allot
+create lb-resource-offset 4 allot
+
+: devsel-mask 3 h# 8 << ;
+: fbtb-mask   1 h# 6 << ;
+: 66mhz-mask  1 h# 5 << ;
+: udf-mask    1 h# 4 << ;
+: prefetchable-mask 1 h# 1e << ;
+
+: make-string ( n index  -- )
+    dup 0> if 1 - then
+    lb-stringbuf +     ( n addr index )
+    swap 30 + swap c!
+;
+
+: clear-lb-stringbuf ( addr -- )
+    lb-stringbuf 11 0 fill
+;
+
+: num>str ( n -- str-addr str-len )
+    clear-lb-stringbuf
+    0 h# a            ( n limit index )
+    do
+        h# a u/mod   ( rem div )
+        dup 0=
+        if   swap I make-string h# a I - nip dup h# a swap - lb-stringbuf + 1 - swap 1 + leave
+        else swap I make-string
+        then
+    -1
+    +loop
+;
+
+: my-+i  ( adr len n -- adr' len' )  encode-int encode+  ;
+: my-0+i  ( adr len -- adr' len' )  0 my-+i  ;
+
+
+
+: find-devtree ( -- addr )
+    find-lbtable drop
+    lbt-header-start /lbt-header-size +
+    begin
+        dup                      ( addr-entry addr-entry )
+        dup l@ h# e =            ( addr-entry addr-entry true|false)
+        if true
+        else
+            swap
+            lbt-table-end
+            >=                   \ current addr < than lbt-table-end?
+        swap next-lbtrecord swap
+        then
+    until
+    drop
+    8 + l@
+;
+
+\ read data from LinuxBIOS device-tree
+: pci-vendor@ ( dev-addr -- ) h# 5c + l@ ;
+: pci-device@ ( dev-addr -- ) h# 60 + l@ ;
+: pci-status@ ( dev-addr -- ) h# 64 + w@ ;
+: pci-revision@ ( dev-addr -- ) h# 66 + c@ ;
+: pci-cacheline-size@ ( dev-addr -- ) h# 67 + c@ ;
+: pci-interrupt-pin@ ( dev-addr -- ) h# 69 + c@ ;
+: pci-mingrant@ ( dev-addr -- ) h# 6a + c@ ;
+: pci-maxlat@ ( dev-addr -- ) h# 6b + c@ ;
+: pci-subsystem-vid@ ( dev-addr -- ) h# 6c + w@ ;
+: pci-subsystem-id@ ( dev-addr -- ) h# 6e + w@ ;
+: pci-classcode@  ( dev-addr -- ) h# 70 + l@ ;
+: pci-headertype@ ( dev-addr -- ) h# 74 + w@ ;
+: pci-devfn@ ( dev-addr -- ) h# 10 + l@ ;
+
+: ?bridge-lb ;
+: ?cardbus-lb ;
+
+: pci-name ( dev-addr -- str-addr ) h# 1c + ;
+
+: devsel@  devsel-mask and 8 >> ;
+: fbtb@    fbtb-mask and 6 >> ;
+: 66mhz@   66mhz-mask and 5 >> ;
+: udf@     udf-mask and 4 >> ;
+
+: dev-print-vendor ( dev-addr -- )
+    pci-vendor@
+    l@ . cr                 \ print-name
+;
+
+: dev-print-device ( dev-addr -- )
+    pci-device@
+    l@ . cr
+;
+
+: dev-print-name ( dev-addr -- )
+    pci-name
+    40 type cr              \ print-name
+;
+
+: next-device ( addr - addr-next-dev )
+    8 + l@          \ next device
+
+;
+
+: $hold  ( adr len -- )
+   dup  if  bounds swap 1-  ?do  i c@ hold  -1 +loop  else  2drop  then
+;
+
+: ascii-vendor-id  ( device/vendor-id -- adr len )
+   lwsplit
+   push-hex
+   <# u#s drop ascii , hold u#s  " pci" $hold  u#> string2 $save
+   pop-base
+;
+
+: class-name: ( code "name" --- )  ,  parse-word ",  align  ;
+
+create class-names
+
+h# ffffff ,  \ Mask
+h# 000100 class-name: display
+h# 0 , 	  \ No more entries for this mask
+
+h# ff0000 ,  \ Mask
+h# 030000 class-name: display
+h# 0a0000 class-name: dock
+h# 0b0000 class-name: cpu
+h# 0 , 	  \ No more entries for this mask
+
+h# ffff00 ,  \ Mask
+h# 010000 class-name: scsi
+h# 010100 class-name: ide
+h# 010200 class-name: fdc
+h# 010300 class-name: ipi
+h# 010400 class-name: raid
+h# 020000 class-name: ethernet
+h# 020100 class-name: token
+h# 020200 class-name: fddi
+h# 020300 class-name: atm
+h# 040000 class-name: video
+h# 040100 class-name: sound
+h# 050000 class-name: memory
+h# 050100 class-name: flash
+h# 060000 class-name: host
+h# 060100 class-name: isa
+h# 060200 class-name: eisa
+h# 060300 class-name: mca
+h# 060400 class-name: pci
+h# 060500 class-name: pcmcia
+h# 060600 class-name: nubus
+h# 060700 class-name: cardbus
+h# 070000 class-name: serial
+h# 070100 class-name: parallel
+h# 080000 class-name: interrupt
+h# 080100 class-name: dma
+h# 080200 class-name: timer
+h# 080300 class-name: rtc
+h# 090000 class-name: keyboard
+h# 090100 class-name: pen
+h# 090200 class-name: mouse
+h# 0c0000 class-name: firewire
+h# 0c0100 class-name: access
+h# 0c0200 class-name: ssa
+h# 0c0300 class-name: usb
+h# 0c0300 class-name: fibre
+h# 0 ,       \ No more entries for this mask
+h# 0 ,       \ End of table
+
+: @+  ( adr -- adr' n )  dup na1+ swap @  ;
+
+: unknown-class?  ( class-code -- true | class-name$ false )
+   \ The outer loop executes once for each distinct mask value
+   class-names  begin  @+  dup  while        ( code adr mask )
+      2 pick and >r                          ( code adr r: masked-code )
+
+      \ The inner loop searches all entries with that mask value
+      begin  @+  dup  while                  ( code adr match )
+
+         r@ =  if                            ( code adr )
+            \ A match under the mask was found; return the string
+            r> drop nip  count false  exit   ( class-name$ false )
+         then                                ( code adr )
+
+         \ Skip the string and proceed to the next entry
+         count + 1+ aligned
+      repeat                                 ( code adr 0 )
+
+      \ Proceed to the next mask value
+      r> 2drop                               ( code adr )
+   repeat                                    ( code adr 0 )
+
+   \ No match was found
+   3drop true                                ( true )
+;
+
+\ 
+: name-property-value  ( dev-addr str-addr str-lenstr-addr str-len  -- adr len )
+    2 pick dup pci-vendor@ swap pci-device@ wljoin ascii-vendor-id
+;
+
+: my-+string  ( prop-adr,len string-adr,len -- prop-adr,len' )
+    encode-string  encode+
+;
+
+: <#class  ( dev-addr -- arguments-to-u#> )
+    pci-classcode@ 8 rshift push-hex <# u# u# u# u# u# u#  pop-base
+;
+
+: prefetchable? ( flags -- true|false )
+    LB_IORESOURCE_PREFETCH and
+;
+
+: resource-flags@ ( resource-addr -- flags )
+    >resource-flags l@
+;
+
+\ Can be either Configuration Space
+\ I/O Space, 32-bit-address Memory Space or
+\ 64-bit-address Memory Space
+: space-code@ ( resource-addr -- space-code )
+    resource-flags@ h# 3 and
+;
+
+: address-aliased? ( resource-addr flags -- true|false )
+    \ FIXME
+;
+
+: relocatable? ( resource-addr flags -- true|false )
+    \ FIXME
+;
+
+: resource-phys-addr@ ( resource-addr -- phys-addr )
+    >resource-baseaddr l@ \ FIXME: its actually 8 bit not 4 but how to join them?
+;
+
+: resource-size@ ( resource-addr -- space-size )
+    >resource-baseaddr 8 + l@
+;
+
+\ take devfn and add some flags we get a phys.hi
+: encode-phys-hi ( resource-addr devfn -- phys.hi )
+    >r                                                  ( r: devfn ) ( resource-addr )
+    dup >resource-flags l@                                       ( resource-addr flags )
+    prefetchable? if r> prefetchable-mask or >r then    \ set prefetchable bit
+                                                        ( resource-addr flags  )
+    space-code@ 18 << r> or >r                          \ set space-code
+    \ FIXME address-aliased?
+    \ FIXME relocatable?
+    r>                                                  ( phys.hi )
+;
+
+\ returns number of resources for given device
+\ dev-addr is address of struct device as defined in LinuxBIOS
+: resources# ( dev-addr -- resources# )
+    >device-numberof l@
+;
+
+: set-compatible-property  ( dev-addr -- )
+   0 0 encode-bytes
+   rot pci-subsystem-vid@ ?dup  if  ascii-vendor-id my-+string  then
+   name-property-value my-+string rot dup >r rot rot r> \ 2 pick
+   <#class " pciclass," $hold u#>  my-+string
+   " compatible" property
+;
+
+: resource-offset! lb-resource-offset l! ;
+: resource-offset@ lb-resource-offset l@ ;
+
+: lb-add-reg-entry ( devfn dev-addr -- )
+    resource-offset!
+    dup >r >device-resources resource-offset@ + swap
+    \ add register to flags
+    encode-phys-hi                                      ( dev-addr devfn phys.hi )
+    encode-int
+    r@ >device-resources resource-offset@ + resource-phys-addr@ encode-int 0      ( dev-addr devfn phys.hi phys.mid )
+    encode-int encode+ encode+
+    r@ >device-resources resource-offset@ + resource-size@ encode-int 0           ( dev-addr devfn phys.hi phys.mid phys.lo )
+    encode-int encode+ encode+
+    r> drop
+;
+
+: dev-addr@ lb-dev-addr l@ ;
+: dev-addr! lb-dev-addr l! ;
+: devfn@ lb-devfn l@ ;
+: devfn! lb-devfn l! ;
+
+: encode-configspace ( dev-addr -- )
+    dev-addr!
+    dev-addr@ pci-devfn@ 8 << devfn!                 ( )
+    devfn@ encode-int my-0+i my-0+i my-0+i my-0+i    ( addr len )
+    devfn@ 8 << devfn!                               ( addr len )
+;
+
+: set-reg-property ( dev-addr -- )
+    encode-configspace
+    devfn@ dev-addr@ dup                             ( addr len devfn dev-addr dev-addr )
+    resources#
+    dup if
+        0 do                                         ( addr len )
+            I 24 * 
+            lb-add-reg-entry 
+            encode+
+            devfn@ dev-addr@                         ( addr len devfn dev-addr dev-addr )
+        loop
+        2drop
+    else
+        3drop
+    then
+    " reg" property
+;
+
+: set-name-property ( dev-addr -- )
+    dup pci-classcode@ unknown-class? if dup pci-vendor@ swap pci-device@ wljoin ascii-vendor-id
+    else rot drop then
+    encode-string " name" property
+;
+
+: set-vendor-property ( dev-addr -- )
+    pci-vendor@ encode-int " vendor-id" property
+;
+
+: set-device-property ( dev-addr -- )
+    pci-device@ encode-int " device-id" property
+;
+
+: set-devselspeed-property ( dev-addr -- )
+    pci-status@ devsel@ encode-int " devsel-speed" property
+;
+
+: set-fast-back-to-back-property ( dev-addr -- )
+    pci-status@ fbtb@ dup
+    if 0 0 encode-int " fast-back-to-back" property
+    else drop then
+;
+
+: set-udf-supported-property ( dev-addr -- )
+    pci-status@ udf@ dup
+    if 0 0 encode-int " udf-supported" property
+    else drop then
+;
+
+: set-classcode ( dev-addr -- )
+    pci-classcode@ encode-int " class-code" property
+;
+
+: set-subsystem-vid ( dev-addr -- )
+    pci-subsystem-vid@ dup
+    if encode-int " subsystem-vendor-id" property
+    else drop then
+;
+
+: set-subsystem-id ( dev-addr -- )
+    pci-subsystem-id@  dup
+    if encode-int " subsystem-id" property
+    else drop then
+;
+
+: set-max-latency ( dev-addr -- )
+    pci-maxlat@ encode-int " max-latency" property
+;
+
+: set-min-grant ( dev-addr -- )
+    pci-mingrant@ encode-int " min-grant" property
+;
+
+: set-revision ( dev-addr -- )
+    pci-revision@ encode-int " revision-id" property
+;
+
+: set-cacheline-size ( dev-addr -- )
+    pci-cacheline-size@ encode-int " cache-line-size" property
+;
+
+: set-interrupt ( dev-addr -- )
+    pci-interrupt-pin@ dup if encode-int " interrupt" property else drop then
+;
+
+: make-lbdev-properties ( dev-addr -- )
+    set-reg-property dup
+    set-name-property dup
+    set-vendor-property dup
+    set-device-property dup
+    set-devselspeed-property dup
+    set-fast-back-to-back-property dup
+    set-udf-supported-property dup
+    set-classcode dup
+    set-subsystem-vid dup
+    set-subsystem-id dup
+    set-max-latency dup
+    set-min-grant dup
+    set-revision dup
+    set-cacheline-size dup
+    set-interrupt dup
+    set-compatible-property
+;
+
+\ Check if device has a vendor-id and device id
+: pci-dev? ( dev-addr -- true|false )
+  dup >device-vendor-id l@ swap       ( vendor-id dev-addr )
+  >device-id l@  +             ( true|false )
+;
+
+: make-lb-device ( dev-addr -- )
+    dup pci-dev?
+    if
+        " /pci" select-dev
+        new-device
+        make-lbdev-properties
+        finish-device
+        device-end
+    else
+        drop
+    then
+;
+
+: create-lb-devices ( dev-addr -- )
+    " /pci" select-dev
+    9 0                    ( dev-addr limit index )
+    do
+            dup
+            make-lb-device
+            next-device
+    loop
+    ." Ende"
+;
+
