1 \ *****************************************************************************
2 \ * Copyright (c) 2004, 2008 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
10 \ * IBM Corporation - initial implementation
11 \ ****************************************************************************/
13 \ ----------------------------------------------------------
14 \ ********** Variables to be set by host bridge **********
15 \ ----------------------------------------------------------
17 \ Values of the next free memory area
18 VARIABLE pci-next-mem \ prefetchable memory mapped
20 VARIABLE pci-next-mmio \ non-prefetchable memory
22 VARIABLE pci-next-io \ I/O space
24 VARIABLE pci-next-mem64 \ prefetchable 64-bit memory mapped
25 VARIABLE pci-max-mem64
27 \ Counter of busses found
28 0 VALUE pci-bus-number
29 \ Counter of devices found
30 0 VALUE pci-device-number
31 \ bit field of devices plugged into this bridge
32 0 VALUE pci-device-slots
33 \ byte field holding the device-slot number vector of the current device
34 \ the vector can be as deep as the max depth of bridges possible
36 \ the 5th slot on the bus of the bridge in
37 \ the 4th slot on the bus of the bridge in
38 \ the 3rd slot on the HostBridge bus
39 here 100 allot CONSTANT pci-device-vec
40 0 VALUE pci-device-vec-len
41 \ enable/disable creation of hotplug-specific properties
42 0 VALUE pci-hotplug-enabled
45 \ Fixme Glue to the pci-devices ... remove this later
46 : next-pci-mem ( addr -- addr ) pci-next-mem ;
47 : next-pci-mmio ( addr -- addr ) pci-next-mmio ;
48 : next-pci-io ( addr -- addr ) pci-next-io ;
51 #include "pci-helper.fs"
53 \ Dump out the pci device-slot vector
55 cr s" device-vec(" type
56 pci-device-vec-len dup 2 0.r s" ):" type
64 \ prints out all relevant pci variables
66 s" mem:" type pci-next-mem @ 16 0.r cr
67 s" mmio:" type pci-next-mmio @ 16 0.r cr
68 s" io:" type pci-next-io @ 16 0.r cr
72 \ Update the device-slot number vector
73 \ Set the bit of the DeviceSlot in the Slot array
74 : pci-set-slot ( addr -- )
75 pci-addr2dev dup \ calc slot number
76 pci-device-vec-len \ the end of the vector
77 pci-device-vec + c! \ and update the vector
78 80000000 swap rshift \ calc bit position of the device slot
79 pci-device-slots or \ set this bit
80 TO pci-device-slots \ and write it back
83 \ Update pci-next-mmio to be 1MB aligned and set the mmio-base register
84 \ and set the Limit register to the maximum available address space
85 \ needed for scanning possible devices behind the bridge
86 : pci-bridge-set-mmio-base ( addr -- )
87 pci-next-mmio @ 100000 #aligned \ read the current Value and align to 1MB boundary
88 dup 100000 + pci-next-mmio ! \ and write back with 1MB for bridge
89 10 rshift \ mmio-base reg is only the upper 16 bits
90 pci-max-mmio @ 1- FFFF0000 and or \ and Insert mmio Limit (set it to max)
91 swap 20 + rtas-config-l! \ and write it into the bridge
94 \ Update pci-next-mmio to be 1MB aligned and set the mmio-limit register
95 \ The Limit Value is one less then the upper boundary
96 \ If the limit is less than the base the mmio is disabled
97 : pci-bridge-set-mmio-limit ( addr -- )
98 pci-next-mmio @ 100000 #aligned \ fetch current value and align to 1MB
99 dup pci-next-mmio ! \ and write it back
100 1- FFFF0000 and \ make it one less and keep upper 16 bits
101 over 20 + rtas-config-l@ 0000FFFF and \ fetch original value
102 or swap 20 + rtas-config-l! \ and write it into the Reg
105 \ Update pci-next-mem to be 1MB aligned and set the mem-base and mem-base-upper register
106 \ and set the Limit register to the maximum available address space
107 \ needed for scanning possible devices behind the bridge
108 : pci-bridge-set-mem-base ( addr -- )
109 pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary
110 dup 100000 + pci-next-mem ! \ and write back with 1MB for bridge
111 over 24 + rtas-config-w@ \ check if 64bit support
112 1 and IF \ IF 64 bit support
113 2dup 20 rshift \ | keep upper 32 bits
114 swap 28 + rtas-config-l! \ | and write it into the Base-Upper32-bits
115 pci-max-mem @ 20 rshift \ | fetch max Limit address and keep upper 32 bits
116 2 pick 2C + rtas-config-l! \ | and set the Limit
118 10 rshift \ keep upper 16 bits
119 pci-max-mem @ 1- FFFF0000 and or \ and Insert mmem Limit (set it to max)
120 swap 24 + rtas-config-l! \ and write it into the bridge
123 \ Update pci-next-mem to be 1MB aligned and set the mem-limit register
124 \ The Limit Value is one less then the upper boundary
125 \ If the limit is less than the base the mem is disabled
126 : pci-bridge-set-mem-limit ( addr -- )
127 pci-next-mem @ 100000 #aligned \ read the current Value and align to 1MB boundary
128 dup pci-next-mem ! \ and write it back
129 1- \ make limit one less than boundary
130 over 24 + rtas-config-w@ \ check if 64bit support
131 1 and IF \ IF 64 bit support
132 2dup 20 rshift \ | keep upper 32 bits
133 swap 2C + rtas-config-l! \ | and write it into the Limit-Upper32-bits
135 FFFF0000 and \ keep upper 16 bits
136 over 24 + rtas-config-l@ 0000FFFF and \ fetch original Value
137 or swap 24 + rtas-config-l! \ and write it into the bridge
140 \ Update pci-next-io to be 4KB aligned and set the io-base and io-base-upper register
141 \ and set the Limit register to the maximum available address space
142 \ needed for scanning possible devices behind the bridge
143 : pci-bridge-set-io-base ( addr -- )
144 pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary
145 dup 1000 + pci-next-io ! \ and write back with 4K for bridge
146 over 1C + rtas-config-l@ \ check if 32bit support
147 1 and IF \ IF 32 bit support
148 2dup 10 rshift \ | keep upper 16 bits
149 pci-max-io @ FFFF0000 and or \ | insert upper 16 bits of Max-Limit
150 swap 30 + rtas-config-l! \ | and write it into the Base-Upper16-bits
152 8 rshift 000000FF and \ keep upper 8 bits
153 pci-max-io @ 1- 0000FF00 and or \ insert upper 8 bits of Max-Limit
154 over rtas-config-l@ FFFF0000 and \ fetch original Value
155 or swap 1C + rtas-config-l! \ and write it into the bridge
158 \ Update pci-next-io to be 4KB aligned and set the io-limit register
159 \ The Limit Value is one less then the upper boundary
160 \ If the limit is less than the base the io is disabled
161 : pci-bridge-set-io-limit ( addr -- )
162 pci-next-io @ 1000 #aligned \ read the current Value and align to 4KB boundary
163 dup pci-next-io ! \ and write it back
164 1- \ make limit one less than boundary
165 over 1D + rtas-config-b@ \ check if 32bit support
166 1 and IF \ IF 32 bit support
167 2dup FFFF0000 and \ | keep upper 16 bits
168 over 30 + rtas-config-l@ \ | fetch original Value
169 or swap 30 + rtas-config-l! \ | and write it into the Limit-Upper16-bits
171 0000FF00 and \ keep upper 8 bits
172 over 1C + rtas-config-l@ FFFF00FF and \ fetch original Value
173 or swap 1C + rtas-config-l! \ and write it into the bridge
176 \ set up all base registers to the current variable Values
177 : pci-bridge-set-bases ( addr -- )
178 dup pci-bridge-set-mmio-base
179 dup pci-bridge-set-mem-base
180 pci-bridge-set-io-base
183 \ set up all limit registers to the current variable Values
184 : pci-bridge-set-limits ( addr -- )
185 dup pci-bridge-set-mmio-limit
186 dup pci-bridge-set-mem-limit
187 pci-bridge-set-io-limit
190 \ ----------------------------------------------------------
191 \ ****************** PCI Scan functions ******************
192 \ ----------------------------------------------------------
194 \ define function pointer as forward declaration of pci-probe-bus
195 DEFER func-pci-probe-bus
196 DEFER func-pci-bridge-range-props
198 \ Setup the Base and Limits in the Bridge
199 \ and scan the bus(es) beyond that Bridge
200 : pci-bridge-probe ( addr -- )
201 dup pci-bridge-set-bases \ SetUp all Base Registers
202 dup func-pci-bridge-range-props \ Setup temporary "range
203 pci-bus-number 1+ TO pci-bus-number \ increase number of busses found
204 pci-device-vec-len 1+ TO pci-device-vec-len \ increase the device-slot vector depth
205 dup \ stack config-addr for pci-bus!
206 FF swap \ Subordinate Bus Number ( for now to max to open all subbusses )
207 pci-bus-number swap \ Secondary Bus Number ( the new busnumber )
208 dup pci-addr2bus swap \ Primary Bus Number ( the current bus )
209 pci-bus! \ and set them into the bridge
210 pci-enable \ enable mem/IO transactions
211 dup pci-bus-scnd@ func-pci-probe-bus \ and probe the secondary bus
212 dup pci-bus-number swap pci-bus-subo! \ set SubOrdinate Bus Number to current number of busses
213 pci-device-vec-len 1- TO pci-device-vec-len \ decrease the device-slot vector depth
214 dup pci-bridge-set-limits \ SetUp all Limit Registers
215 drop \ forget the config-addr
218 \ set up the pci-device
219 : pci-device-setup ( addr -- )
220 drop \ since the config-addr is coded in my-space, drop it here
221 s" pci-device.fs" included \ and setup the device as node in the device tree
224 \ set up the pci bridge
225 : pci-bridge-setup ( addr -- )
226 drop \ since the config-addr is coded in my-space, drop it here
227 s" pci-bridge.fs" included \ and setup the bridge as node in the device tree
230 \ add the new found device/bridge to the device tree and set it up
231 : pci-add-device ( addr -- )
232 new-device \ create a new device-tree node
233 dup set-space \ set the config addr for this device tree entry
234 dup pci-set-slot \ set the slot bit
235 dup pci-htype@ \ read HEADER-Type
236 7f and \ Mask bit 7 - multifunction device
238 0 OF pci-device-setup ENDOF \ | set up the device
239 1 OF pci-bridge-setup ENDOF \ | set up the bridge
240 dup OF dup pci-htype@ pci-out ENDOF
242 finish-device \ and close the device-tree node
245 \ check for multifunction and for each function
246 \ (dependig from header type) call device or bridge setup
247 : pci-setup-device ( addr -- )
248 dup pci-htype@ \ read HEADER-Type
249 80 and IF 8 ELSE 1 THEN \ check for multifunction
250 0 DO \ LOOP over all possible functions (either 8 or only 1)
252 i 8 lshift + \ calc device-function-config-addr
253 dup pci-vendor@ \ check if valid function
255 drop \ non-valid so forget the address
257 pci-device-number 1+ \ increase the number of devices
258 TO pci-device-number \ and store it
259 pci-add-device \ and add the device to the device tree and set it up
262 drop \ forget the device-addr
265 \ check if a device is plugged into this bus at this device number
266 : pci-probe-device ( busnr devicenr -- )
267 pci-bus2addr \ calc pci-address
268 dup pci-vendor@ \ fetch Vendor-ID
269 FFFF = IF \ check if valid
270 drop \ if not forget it
272 pci-setup-device \ if valid setup the device
276 \ walk through all 32 possible pci devices on this bus and probe them
277 : pci-probe-bus ( busnr -- )
278 0 TO pci-device-slots \ reset slot array to unpoppulated
286 \ setup the function pointer used in pci-bridge-setup
287 ' pci-probe-bus TO func-pci-probe-bus
289 \ ----------------------------------------------------------
290 \ ****************** System functions ********************
291 \ ----------------------------------------------------------
292 \ Setup the whole system for pci devices
293 \ start with the bus-min and try all busses
294 \ until at least 1 device was found
295 \ ( needed for HostBridges that don't start with Bus 0 )
296 : pci-probe-all ( bus-max bus-min -- ) \ Check all busses from bus-min up to bus-max if needed
297 0 TO pci-device-vec-len \ reset the device-slot vector
299 i TO pci-bus-number \ set current Busnumber
300 0 TO pci-device-number \ reset Device Number
301 pci-bus-number pci-probe-bus \ and probe this bus
302 pci-device-number 0 > IF LEAVE THEN \ if we found a device we're done
306 : (probe-pci-host-bridge) ( bus-max bus-min -- )
307 0d emit ." Adapters on " puid 10 0.r cr \ print the puid we're looking at
308 ( bus-max bus-min ) pci-probe-all \ and walk the bus
309 pci-device-number 0= IF \ IF no devices found
310 15 spaces \ | indent the output
311 ." None" cr \ | tell the world our result
315 \ probe the hostbridge that is specified in my-puid
316 \ for the mmio mem and io addresses:
317 \ base is the least available address
318 \ max is the highest available address
319 : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- )
320 puid >r TO puid \ save puid and set the new
321 pci-next-io ! \ save the next io-base address
322 pci-max-io ! \ save the max io-space address
323 pci-next-mem ! \ save the next mem-base address
324 pci-max-mem ! \ save the max mem-space address
325 pci-next-mmio ! \ save the next mmio-base address
326 pci-max-mmio ! \ save the max mmio-space address
327 (probe-pci-host-bridge)
328 r> TO puid \ restore puid
331 \ provide the device-alias definition words
332 #include <pci-aliases.fs>
334 \ provide all words for the interrupts settings
335 #include <pci-interrupts.fs>
337 \ provide all words for the pci capabilities init
338 #include <pci-capabilities.fs>
340 \ provide all words needed to generate the properties and/or assign BAR values
341 #include "pci-properties.fs"
343 \ setup the function pointer for bridge ranges
344 ' pci-bridge-range-props TO func-pci-bridge-range-props