Annotation of qemu/roms/SLOF/board-qemu/slof/pci-phb.fs, revision 1.1.1.1

1.1       root        1: \ *****************************************************************************
                      2: \ * Copyright (c) 2004, 2011 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
                      8: \ *
                      9: \ * Contributors:
                     10: \ *     IBM Corporation - initial implementation
                     11: \ ****************************************************************************/
                     12: 
                     13: \ PAPR PCI host bridge.
                     14: 
                     15: 0 VALUE phb-debug?
                     16: 
                     17: 
                     18: ." Populating " pwd cr
                     19: 
                     20: \ needed to find the right path in the device tree
                     21: : decode-unit ( addr len -- phys.lo ... phys.hi )
                     22:    2 hex-decode-unit       \ decode string
                     23:    b lshift swap           \ shift the devicenumber to the right spot
                     24:    8 lshift or             \ add the functionnumber
                     25:    \ my-bus 10 lshift or   \ add the busnumber (assume always bus 0)
                     26:    0 0 rot                 \ make phys.lo = 0 = phys.mid
                     27: ;
                     28: 
                     29: \ needed to have the right unit address in the device tree listing
                     30: \ phys.lo=phys.mid=0 , phys.hi=config-address
                     31: : encode-unit ( phys.lo phys-mid phys.hi -- unit-str unit-len )
                     32:    nip nip                     \ forget the phys.lo and phys.mid
                     33:    dup 8 rshift 7 and swap     \ calculate function number
                     34:    B rshift 1F and             \ calculate device number
                     35:    over IF 2 ELSE nip 1 THEN   \ create string with dev#,fn# or dev# only?
                     36:    hex-encode-unit
                     37: ;
                     38: 
                     39: 
                     40: 0 VALUE my-puid
                     41: 
                     42: : setup-puid
                     43:   s" reg" get-node get-property 0= IF
                     44:     decode-64 to my-puid 2drop
                     45:   THEN
                     46: ;
                     47: 
                     48: setup-puid
                     49: 
                     50: : config-b@  puid >r my-puid TO puid rtas-config-b@ r> TO puid ;
                     51: : config-w@  puid >r my-puid TO puid rtas-config-w@ r> TO puid ;
                     52: : config-l@  puid >r my-puid TO puid rtas-config-l@ r> TO puid ;
                     53: 
                     54: \ define the config writes
                     55: : config-b!  puid >r my-puid TO puid rtas-config-b! r> TO puid ;
                     56: : config-w!  puid >r my-puid TO puid rtas-config-w! r> TO puid ;
                     57: : config-l!  puid >r my-puid TO puid rtas-config-l! r> TO puid ;
                     58: 
                     59: 
                     60: : map-in ( phys.lo phys.mid phys.hi size -- virt )
                     61:    phb-debug? IF cr ." map-in called: " .s cr THEN
                     62:    \ Ignore the size, phys.lo and phys.mid, get BAR from config space
                     63:    drop nip nip                         ( phys.hi )
                     64:    \ Sanity check whether config address is in expected range:
                     65:    dup FF AND dup 10 28 WITHIN NOT swap 30 <> AND IF
                     66:       cr ." phys.hi = " . cr
                     67:       ABORT" map-in with illegal config space address"
                     68:    THEN
                     69:    00FFFFFF AND                         \ Need only bus-dev-fn+register bits
                     70:    dup config-l@                        ( phys.hi' bar.lo )
                     71:    dup 7 AND 4 = IF                     \ Is it a 64-bit BAR?
                     72:       swap 4 + config-l@ lxjoin         \ Add upper part of 64-bit BAR
                     73:    ELSE
                     74:       nip
                     75:    THEN
                     76:    F NOT AND                            \ Clear indicator bits
                     77:    translate-my-address
                     78:    phb-debug? IF ." map-in done: " .s cr THEN
                     79: ;
                     80: 
                     81: : map-out ( virt size -- )
                     82:    phb-debug? IF ." map-out called: " .s cr THEN
                     83:    2drop 
                     84: ;
                     85: 
                     86: 
                     87: : dma-alloc ( size -- virt )
                     88:    phb-debug? IF cr ." dma-alloc called: " .s cr THEN
                     89:    fff + fff not and                  \ Align size to next 4k boundary
                     90:    alloc-mem
                     91:    \ alloc-mem always returns aligned memory - double check just to be sure
                     92:    dup fff and IF
                     93:       ." Warning: dma-alloc got unaligned memory!" cr
                     94:    THEN
                     95: ;
                     96: 
                     97: : dma-free ( virt size -- )
                     98:    phb-debug? IF cr ." dma-free called: " .s cr THEN
                     99:    fff + fff not and                  \ Align size to next 4k boundary
                    100:    free-mem
                    101: ;
                    102: 
                    103: 
                    104: \ Helper variables for dma-map-in and dma-map-out
                    105: 0 VALUE dma-window-liobn        \ Logical I/O bus number
                    106: 0 VALUE dma-window-base         \ Start address of window
                    107: 0 VALUE dma-window-size         \ Size of the window
                    108: 
                    109: \ Read helper variables (LIOBN, DMA window base and size) from the
                    110: \ "ibm,dma-window" property. This property can be either located
                    111: \ in the PCI device node or in the bus node, so we've got to use the
                    112: \ "calling-child" variable here to get to the node that initiated the call.
                    113: \ XXX We should search all the way up the tree to the PHB ...
                    114: : (init-dma-window-vars)  ( -- )
                    115: \   ." Foo called in " pwd cr
                    116: \   ." calling child is " calling-child .node cr
                    117: \   ." parent is " calling-child parent .node cr
                    118:    s" ibm,dma-window" calling-child get-property IF
                    119:        s" ibm,dma-window" calling-child parent get-property 
                    120:        ABORT" no dma-window property available"
                    121:    THEN
                    122:    decode-int TO dma-window-liobn
                    123:    decode-64 TO dma-window-base
                    124:    decode-64 TO dma-window-size
                    125:    2drop
                    126: ;
                    127: 
                    128: : (clear-dma-window-vars)  ( -- )
                    129:    0 TO dma-window-liobn
                    130:    0 TO dma-window-base
                    131:    0 TO dma-window-size
                    132: ;
                    133: 
                    134: \ We assume that firmware never maps more than the whole dma-window-size
                    135: \ so we cheat by calculating the remainder of addr/windowsize instead
                    136: \ of taking care to maintain a list of assigned device addresses
                    137: : dma-virt2dev  ( virt -- devaddr )
                    138:    dma-window-size mod dma-window-base +
                    139: ;
                    140: 
                    141: : dma-map-in  ( virt size cachable? -- devaddr )
                    142:    phb-debug? IF cr ." dma-map-in called: " .s cr THEN
                    143:    (init-dma-window-vars)
                    144:    drop                               ( virt size )
                    145:    bounds dup >r                      ( v+s virt  R: virt )
                    146:    swap fff + fff not and             \ Align end to next 4k boundary
                    147:    swap fff not and                   ( v+s' virt'  R: virt )
                    148:    ?DO
                    149:       \ ." mapping " i . cr
                    150:       dma-window-liobn                \ liobn
                    151:       i dma-virt2dev                  \ ioba
                    152:       i 3 OR                          \ Make a read- & writeable TCE
                    153:       ( liobn ioba tce  R: virt )
                    154:       hv-put-tce ABORT" H_PUT_TCE failed"
                    155:    1000 +LOOP
                    156:    r> dma-virt2dev
                    157:    (clear-dma-window-vars)
                    158: ;
                    159: 
                    160: : dma-map-out  ( virt devaddr size -- )
                    161:    phb-debug? IF cr ." dma-map-out called: " .s cr THEN
                    162:    (init-dma-window-vars)
                    163:    nip                                ( virt size )
                    164:    bounds                             ( v+s virt )
                    165:    swap fff + fff not and             \ Align end to next 4k boundary
                    166:    swap fff not and                   ( v+s' virt' )
                    167:    ?DO
                    168:       \ ." unmapping " i . cr
                    169:       dma-window-liobn                \ liobn
                    170:       i dma-virt2dev                  \ ioba
                    171:       i                               \ Lowest bits not set => invalid TCE
                    172:       ( liobn ioba tce )
                    173:       hv-put-tce ABORT" H_PUT_TCE failed"
                    174:    1000 +LOOP
                    175:    (clear-dma-window-vars)
                    176: ;
                    177: 
                    178: : dma-sync  ( virt devaddr size -- )
                    179:    phb-debug? IF cr ." dma-sync called: " .s cr THEN
                    180:    \ TODO: Call flush-cache or sync here?
                    181:    3drop
                    182: ;
                    183: 
                    184: 
                    185: : open  true ;
                    186: : close ;
                    187: 
                    188: \ Parse the "ranges" property of the root pci node to decode the available
                    189: \ memory ranges. See "PCI Bus Binding to IEEE Std 1275-1994" for details.
                    190: \ The memory ranges are then used for setting up the device bars (if necessary)
                    191: : phb-parse-ranges ( -- )
                    192:    \ First clear everything, in case there is something missing in the ranges
                    193:    0  pci-next-io !
                    194:    0  pci-max-io !
                    195:    0  pci-next-mem !
                    196:    0  pci-max-mem !
                    197:    0  pci-next-mmio !
                    198:    0  pci-max-mmio !
                    199: 
                    200:    \ Now get the "ranges" property
                    201:    s" ranges" get-node get-property 0<> ABORT" ranges property not found"
                    202:    ( prop-addr prop-len )
                    203:    BEGIN
                    204:       dup
                    205:    WHILE
                    206:       decode-int                      \ Decode phys.hi
                    207:       3000000 AND                     \ Filter out address space in phys.hi
                    208:       CASE
                    209:          1000000 OF                             \ I/O space?
                    210:             decode-64 dup >r pci-next-io !      \ Decode PCI base address
                    211:             decode-64 drop                      \ Forget the parent address
                    212:             decode-64 r> + pci-max-io !         \ Decode size & calc max address
                    213:             pci-next-io @ 0= IF
                    214:                pci-next-io @ 10 + pci-next-io ! \ BARs must not be set to zero
                    215:             THEN
                    216:          ENDOF
                    217:          2000000 OF                             \ 32-bit memory space?
                    218:             decode-64 pci-next-mem !            \ Decode mem base address
                    219:             decode-64 drop                      \ Forget the parent address
                    220:             decode-64 2 / dup >r                \ Decode and calc size/2
                    221:             pci-next-mem @ + dup pci-max-mem !  \ and calc max mem address
                    222:             dup pci-next-mmio !                 \ which is the same as MMIO base
                    223:             r> + pci-max-mmio !                 \ calc max MMIO address
                    224:          ENDOF
                    225:          3000000 OF                             \ 64-bit memory space?
                    226:             cr ." Warning: 64-bit PCI space not supported yet! "
                    227:             decode-64 . decode-64 . cr
                    228:          ENDOF
                    229:       ENDCASE
                    230:    REPEAT
                    231:    ( prop-addr prop-len )
                    232:    2drop
                    233: 
                    234:    phb-debug? IF
                    235:      ." pci-next-io   = " pci-next-io @ . cr
                    236:      ." pci-max-io    = " pci-max-io  @ . cr
                    237:      ." pci-next-mem  = " pci-next-mem @ . cr
                    238:      ." pci-max-mem   = " pci-max-mem  @ . cr
                    239:      ." pci-next-mmio = " pci-next-mmio @ . cr
                    240:      ." pci-max-mmio  = " pci-max-mmio @ . cr
                    241:    THEN
                    242: ;
                    243: 
                    244: \ Scan the child nodes of the pci root node to assign bars, fixup
                    245: \ properties etc.
                    246: : phb-setup-children
                    247:    puid >r                          \ Save old value of puid
                    248:    my-puid TO puid                  \ Set current puid
                    249:    phb-parse-ranges
                    250:    1 0 (probe-pci-host-bridge)
                    251:    r> TO puid                       \ Restore previous puid
                    252: ;
                    253: phb-setup-children

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.