|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.