Annotation of qemu/roms/SLOF/board-qemu/slof/pci-phb.fs, revision 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.