These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / pci-scan.fs
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
8 \ *
9 \ * Contributors:
10 \ *     IBM Corporation - initial implementation
11 \ ****************************************************************************/
12
13 \ ----------------------------------------------------------
14 \ **********  Variables to be set by host bridge  **********
15 \ ----------------------------------------------------------
16
17 \ Values of the next free memory area
18 VARIABLE pci-next-mem           \ prefetchable memory mapped
19 VARIABLE pci-max-mem
20 VARIABLE pci-next-mmio          \ non-prefetchable memory
21 VARIABLE pci-max-mmio
22 VARIABLE pci-next-io            \ I/O space
23 VARIABLE pci-max-io
24 VARIABLE pci-next-mem64           \ prefetchable 64-bit memory mapped
25 VARIABLE pci-max-mem64
26
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
35 \ 3,4,5 means
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
43
44
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 ;
49
50
51 #include "pci-helper.fs"
52
53 \ Dump out the pci device-slot vector
54 : pci-vec ( -- )
55         cr s" device-vec(" type
56         pci-device-vec-len dup 2 0.r s" ):" type
57         1+ 0 DO
58                 pci-device-vec i + c@
59                 space 2 0.r
60         LOOP
61         cr
62 ;
63
64 \ prints out all relevant pci variables
65 : pci-var-out ( -- )
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
69 ;
70
71
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
81 ;
82
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
92 ;
93
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
103 ;
104
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                 pci-next-mem64 @ 100000000 #aligned \ | read the current Value of 64-bit and align to 4GB boundary
114                 dup 100000000 + pci-next-mem64 x!   \ | and write back with 1GB for bridge
115                 2 pick swap                         \ |
116                 20 rshift                           \ | keep upper 32 bits
117                 swap 28 + rtas-config-l!            \ | and write it into the Base-Upper32-bits
118                 pci-max-mem64 @ 20 rshift           \ | fetch max Limit address and keep upper 32 bits
119                 2 pick 2C + rtas-config-l!          \ | and set the Limit
120         THEN                                    \ FI
121         10 rshift                               \ keep upper 16 bits
122         pci-max-mem @ 1- FFFF0000 and or        \ and Insert mmem Limit (set it to max)
123         swap 24 + rtas-config-l!                \ and write it into the bridge
124 ;
125
126 \ Update pci-next-mem to be 1MB aligned and set the mem-limit register
127 \ The Limit Value is one less then the upper boundary
128 \ If the limit is less than the base the mem is disabled
129 : pci-bridge-set-mem-limit ( addr -- )
130         pci-next-mem @ 100000 #aligned          \ read the current Value and align to 1MB boundary
131         dup pci-next-mem !                      \ and write it back
132         1-                                      \ make limit one less than boundary
133         over 24 + rtas-config-w@                \ check if 64bit support
134         1 and IF                                \ IF 64 bit support
135                 pci-next-mem64 @ 100000000 #aligned \ | Reat current value of 64-bar and align at 4GB
136                 dup pci-next-mem64 x!               \ | and write it back
137                 1-                                  \ | make limite one less than boundary
138                 2 pick swap                         \ |
139                 20 rshift                           \ | keep upper 32 bits
140                 swap 2C + rtas-config-l!            \ | and write it into the Limit-Upper32-bits
141         THEN                                    \ FI
142         FFFF0000 and                            \ keep upper 16 bits
143         over 24 + rtas-config-l@ 0000FFFF and   \ fetch original Value
144         or swap 24 + rtas-config-l!             \ and write it into the bridge
145 ;
146
147 \ Update pci-next-io to be 4KB aligned and set the io-base and io-base-upper register
148 \ and set the Limit register to the maximum available address space
149 \ needed for scanning possible devices behind the bridge
150 : pci-bridge-set-io-base ( addr -- )
151         pci-next-io @ 1000 #aligned             \ read the current Value and align to 4KB boundary
152         dup 1000 + pci-next-io !                \ and write back with 4K for bridge
153         over 1C + rtas-config-l@                \ check if 32bit support
154         1 and IF                                \ IF 32 bit support
155                 2dup 10 rshift                  \ | keep upper 16 bits
156                 pci-max-io @ FFFF0000 and or    \ | insert upper 16 bits of Max-Limit
157                 swap 30 + rtas-config-l!        \ | and write it into the Base-Upper16-bits
158         THEN                                    \ FI
159         8 rshift 000000FF and                   \ keep upper 8 bits
160         pci-max-io @ 1- 0000FF00 and or         \ insert upper 8 bits of Max-Limit
161         over rtas-config-l@ FFFF0000 and        \ fetch original Value
162         or swap 1C + rtas-config-l!             \ and write it into the bridge
163 ;
164
165 \ Update pci-next-io to be 4KB aligned and set the io-limit register
166 \ The Limit Value is one less then the upper boundary
167 \ If the limit is less than the base the io is disabled
168 : pci-bridge-set-io-limit ( addr -- )
169         pci-next-io @ 1000 #aligned             \ read the current Value and align to 4KB boundary
170         dup pci-next-io !                       \ and write it back
171         1-                                      \ make limit one less than boundary
172         over 1D + rtas-config-b@                \ check if 32bit support
173         1 and IF                                \ IF 32 bit support
174                 2dup FFFF0000 and               \ | keep upper 16 bits
175                 over 30 + rtas-config-l@        \ | fetch original Value
176                 or swap 30 + rtas-config-l!     \ | and write it into the Limit-Upper16-bits
177         THEN                                    \ FI
178         0000FF00 and                            \ keep upper 8 bits
179         over 1C + rtas-config-l@ FFFF00FF and   \ fetch original Value
180         or swap 1C + rtas-config-l!             \ and write it into the bridge
181 ;
182
183 \ set up all base registers to the current variable Values
184 : pci-bridge-set-bases ( addr -- )
185         dup pci-bridge-set-mmio-base
186         dup pci-bridge-set-mem-base
187             pci-bridge-set-io-base
188 ;
189
190 \ set up all limit registers to the current variable Values
191 : pci-bridge-set-limits ( addr -- )
192         dup pci-bridge-set-mmio-limit
193         dup pci-bridge-set-mem-limit
194             pci-bridge-set-io-limit
195 ;
196
197 \ ----------------------------------------------------------
198 \ ******************  PCI Scan functions  ******************
199 \ ----------------------------------------------------------
200
201 \ define function pointer as forward declaration of pci-probe-bus
202 DEFER func-pci-probe-bus
203 DEFER func-pci-bridge-range-props
204
205 \ Setup the Base and Limits in the Bridge
206 \ and scan the bus(es) beyond that Bridge
207 : pci-bridge-probe ( addr -- )
208         dup pci-bridge-set-bases                        \ SetUp all Base Registers
209         dup func-pci-bridge-range-props                 \ Setup temporary "range
210         pci-bus-number 1+ TO pci-bus-number             \ increase number of busses found
211         pci-device-vec-len 1+ TO pci-device-vec-len     \ increase the device-slot vector depth
212         dup                                             \ stack config-addr for pci-bus!
213         FF swap                                         \ Subordinate Bus Number ( for now to max to open all subbusses )
214         pci-bus-number swap                             \ Secondary   Bus Number ( the new busnumber )
215         dup pci-addr2bus swap                           \ Primary     Bus Number ( the current bus )
216         pci-bus!                                        \ and set them into the bridge
217         pci-enable                                      \ enable mem/IO transactions
218         dup pci-bus-scnd@ func-pci-probe-bus            \ and probe the secondary bus
219         dup pci-bus-number swap pci-bus-subo!           \ set SubOrdinate Bus Number to current number of busses
220         pci-device-vec-len 1- TO pci-device-vec-len     \ decrease the device-slot vector depth
221         dup pci-bridge-set-limits                       \ SetUp all Limit Registers
222         drop                                            \ forget the config-addr
223 ;
224
225 \ set up the pci-device
226 : pci-device-setup ( addr -- )
227         drop                            \ since the config-addr is coded in my-space, drop it here
228         s" pci-device.fs" included      \ and setup the device as node in the device tree
229 ;
230
231 \ set up the pci bridge
232 : pci-bridge-setup ( addr -- )
233         drop                            \ since the config-addr is coded in my-space, drop it here
234         s" pci-bridge.fs" included      \ and setup the bridge as node in the device tree
235 ;
236
237 \ add the new found device/bridge to the device tree and set it up
238 : pci-add-device ( addr -- )
239         new-device                      \ create a new device-tree node
240             dup set-space               \ set the config addr for this device tree entry
241             dup pci-set-slot            \ set the slot bit
242             dup pci-htype@              \ read HEADER-Type
243             7f and                      \ Mask bit 7 - multifunction device
244             CASE
245                0 OF pci-device-setup ENDOF  \ | set up the device
246                1 OF pci-bridge-setup ENDOF  \ | set up the bridge
247                dup OF dup pci-htype@ pci-out ENDOF
248            ENDCASE
249         finish-device                   \ and close the device-tree node
250 ;
251
252 \ check for multifunction and for each function
253 \ (dependig from header type) call device or bridge setup
254 : pci-setup-device ( addr -- )
255         dup pci-htype@                      \ read HEADER-Type
256         80 and IF 8 ELSE 1 THEN             \ check for multifunction
257         0 DO                                \ LOOP over all possible functions (either 8 or only 1)
258                 dup
259                 i 8 lshift +                \ calc device-function-config-addr
260                 dup pci-vendor@             \ check if valid function
261                 FFFF = IF
262                         drop                \ non-valid so forget the address
263                 ELSE
264                     pci-device-number 1+    \ increase the number of devices
265                     TO pci-device-number    \ and store it
266                     pci-add-device          \ and add the device to the device tree and set it up
267                 THEN
268         LOOP                                \ next function
269         drop                                \ forget the device-addr
270 ;
271
272 \ check if a device is plugged into this bus at this device number
273 : pci-probe-device ( busnr devicenr -- )
274         pci-bus2addr                                    \ calc pci-address
275         dup pci-vendor@                                 \ fetch Vendor-ID
276         FFFF = IF                                       \ check if valid
277                 drop                                    \ if not forget it
278         ELSE
279                 pci-setup-device                        \ if valid setup the device
280         THEN
281 ;
282
283 \ walk through all 32 possible pci devices on this bus and probe them
284 : pci-probe-bus ( busnr -- )
285         0 TO pci-device-slots           \ reset slot array to unpoppulated
286         20 0 DO
287                 dup
288                 i pci-probe-device
289         LOOP
290         drop
291 ;
292
293 \ setup the function pointer used in pci-bridge-setup
294 ' pci-probe-bus TO func-pci-probe-bus
295
296 \ ----------------------------------------------------------
297 \ ******************  System functions  ********************
298 \ ----------------------------------------------------------
299 \ Setup the whole system for pci devices
300 \ start with the bus-min and try all busses
301 \ until at least 1 device was found
302 \ ( needed for HostBridges that don't start with Bus 0 )
303 : pci-probe-all ( bus-max bus-min -- )                  \ Check all busses from bus-min up to bus-max if needed
304         0 TO pci-device-vec-len                         \ reset the device-slot vector
305         DO
306                 i TO pci-bus-number                     \ set current Busnumber
307                 0 TO pci-device-number                  \ reset Device Number
308                 pci-bus-number pci-probe-bus            \ and probe this bus
309                 pci-device-number 0 > IF LEAVE THEN     \ if we found a device we're done
310         LOOP                                            \ else next bus
311 ;
312
313 : (probe-pci-host-bridge) ( bus-max bus-min -- )
314         0d emit ."  Adapters on " puid 10 0.r cr        \ print the puid we're looking at
315         ( bus-max bus-min ) pci-probe-all               \ and walk the bus
316         pci-device-number 0= IF                         \ IF no devices found
317                 15 spaces                               \ | indent the output
318                 ." None" cr                             \ | tell the world our result
319         THEN                                            \ FI
320 ;
321
322 \ probe the hostbridge that is specified in my-puid
323 \ for the mmio mem and io addresses:
324 \ base is the least available address
325 \ max is the highest available address
326 : probe-pci-host-bridge ( bus-max bus-min mmio-max mmio-base mem-max mem-base io-max io-base my-puid -- )
327         puid >r TO puid                                 \ save puid and set the new
328         pci-next-io !                                   \ save the next io-base address
329         pci-max-io !                                    \ save the max io-space address
330         pci-next-mem !                                  \ save the next mem-base address
331         pci-max-mem !                                   \ save the max mem-space address
332         pci-next-mmio !                                 \ save the next mmio-base address
333         pci-max-mmio !                                  \ save the max mmio-space address
334         (probe-pci-host-bridge)
335         r> TO  puid                                     \ restore puid
336 ;
337
338 \ provide the device-alias definition words
339 #include <pci-aliases.fs>
340
341 \ provide all words for the interrupts settings
342 #include <pci-interrupts.fs>
343
344 \ provide all words for the pci capabilities init
345 #include <pci-capabilities.fs>
346
347 \ provide all words needed to generate the properties and/or assign BAR values
348 #include "pci-properties.fs"
349
350 \ setup the function pointer for bridge ranges
351 ' pci-bridge-range-props TO func-pci-bridge-range-props