|
|
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.