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