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 #include "pci-class-code-names.fs"
15 \ read the various bar type sizes
16 : pci-bar-size@ ( bar-addr -- bar-size ) -1 over rtas-config-l! rtas-config-l@ ;
17 : pci-bar-size-mem@ ( bar-addr -- mem-size ) pci-bar-size@ -10 and invert 1+ FFFFFFFF and ;
18 : pci-bar-size-io@ ( bar-addr -- io-size ) pci-bar-size@ -4 and invert 1+ FFFFFFFF and ;
20 \ fetch raw bar size but keep original BAR value
21 : pci-bar-size ( bar-addr -- bar-size-raw )
22 dup rtas-config-l@ swap \ fetch original Value ( bval baddr )
23 -1 over rtas-config-l! \ make BAR show size ( bval baddr )
24 dup rtas-config-l@ \ and fetch the size ( bval baddr bsize )
25 -rot rtas-config-l! \ restore Value
28 \ calc 32 bit MEM BAR size
29 : pci-bar-size-mem32 ( bar-addr -- bar-size )
30 pci-bar-size \ fetch raw size
31 -10 and invert 1+ \ calc size
32 FFFFFFFF and \ keep lower 32 bits
35 \ calc 32 bit ROM BAR size
36 : pci-bar-size-rom ( bar-addr -- bar-size )
37 pci-bar-size \ fetch raw size
38 FFFFF800 and invert 1+ \ calc size
39 FFFFFFFF and \ keep lower 32 bits
42 \ calc 64 bit MEM BAR size
43 : pci-bar-size-mem64 ( bar-addr -- bar-size )
44 dup pci-bar-size \ fetch raw size lower 32 bits
45 swap 4 + pci-bar-size \ fetch raw size upper 32 bits
46 20 lshift + \ and put them together
47 -10 and invert 1+ \ calc size
51 : pci-bar-size-io ( bar-addr -- bar-size )
52 pci-bar-size \ fetch raw size
53 -4 and invert 1+ \ calc size
54 FFFFFFFF and \ keep lower 32 bits
59 \ +----------------------------------------------------------------------------------------+
61 \ | +----------------------------+-+--+-+ |
62 \ | MEM-BAR : | Base Address |P|TT|0| P - prefechtable ; TT - 00 : 32 Bit |
63 \ | +----------------------------+-+--+-+ 10 : 64 Bit |
64 \ | +-------------------------------+-+-+ |
65 \ | IO-BAR : | Base Address |0|1| |
66 \ | +-------------------------------+-+-+ |
67 \ | That is: 0 - no encoded BarType |
69 \ | 2 - Memory 32 Bit |
70 \ | 3 - Memory 32 Bit prefetchable |
71 \ | 4 - Memory 64 Bit |
72 \ | 5 - Memory 64 Bit prefetchable |
73 \ +----------------------------------------------------------------------------------------+
74 : pci-bar-code@ ( bar-addr -- 0|1..4|5 )
75 rtas-config-l@ dup \ fetch the BaseAddressRegister
77 2 and IF 0 ELSE 1 THEN \ only '01' is valid
80 0 OF 2 ENDOF \ Memory 32 Bit Non-Prefetchable
81 8 OF 3 ENDOF \ Memory 32 Bit Prefetchable
82 4 OF 4 ENDOF \ Memory 64 Bit Non-Prefetchable
83 C OF 5 ENDOF \ Memory 64 Bit Prefechtable
84 dup OF 0 ENDOF \ Not a valid BarType
89 \ ***************************************************************************************
90 \ Assigning the new Value to the BARs
91 \ ***************************************************************************************
92 \ align the current mem and set var to next mem
93 \ align with a size of 0 returns 0 !!!
94 : assign-var ( size var -- al-mem )
95 2dup @ \ ( size var size cur-mem ) read current free mem
96 swap #aligned \ ( size var al-mem ) align the mem to the size
97 dup 2swap -rot + \ ( al-mem var new-mem ) add size to aligned mem
98 swap ! \ ( al-mem ) set variable to new mem
101 \ set bar to current free mem ( in variable ) and set variable to next free mem
102 : assign-bar-value32 ( bar size var -- 4 )
103 over IF \ IF size > 0
104 assign-var \ | ( bar al-mem ) set variable to next mem
105 swap rtas-config-l! \ | ( -- ) set the bar to al-mem
107 2drop drop \ | clear stack
109 4 \ size of the base-address-register
112 \ set bar to current free mem ( in variable ) and set variable to next free mem
113 : assign-bar-value64 ( bar size var -- 8 )
114 over IF \ IF size > 0
115 assign-var \ | ( bar al-mem ) set variable to next mem
116 swap \ | ( al-mem addr ) calc config-addr of this bar
117 2dup rtas-config-l! \ | ( al-mem addr ) set the Lower part of the bar to al-mem
118 4 + swap 20 rshift \ | ( al-mem>>32 addr ) prepare the upper part of the al-mem
119 swap rtas-config-l! \ | ( -- ) and set the upper part of the bar
121 2drop drop \ | clear stack
123 8 \ size of the base-address-register
126 \ Setup a prefetchable 64bit BAR and return its size
127 : assign-mem64-bar ( bar-addr -- 8 )
128 dup pci-bar-size-mem64 \ fetch size
129 pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range
134 assign-bar-value64 \ and set it all
137 \ Setup a prefetchable 32bit BAR and return its size
138 : assign-mem32-bar ( bar-addr -- 4 )
139 dup pci-bar-size-mem32 \ fetch size
140 pci-next-mem \ var to change
141 assign-bar-value32 \ and set it all
144 \ Setup a non-prefetchable 64bit BAR and return its size
145 : assign-mmio64-bar ( bar-addr -- 8 )
146 dup pci-bar-size-mem64 \ fetch size
147 pci-next-mem64 @ 0 = IF \ Check if we have 64-bit memory range
150 pci-next-mem64 \ for board-qemu we will use same range
152 assign-bar-value64 \ and set it all
155 \ Setup a non-prefetchable 32bit BAR and return its size
156 : assign-mmio32-bar ( bar-addr -- 4 )
157 dup pci-bar-size-mem32 \ fetch size
158 pci-next-mmio \ var to change
159 assign-bar-value32 \ and set it all
162 \ Setup an IO-Bar and return the size of the base-address-register
163 : assign-io-bar ( bar-addr -- 4 )
164 dup pci-bar-size-io \ fetch size
165 pci-next-io \ var to change
166 assign-bar-value32 \ and set it all
169 \ Setup an Expansion ROM bar
170 : assign-rom-bar ( bar-addr -- )
171 dup pci-bar-size-rom \ fetch size
173 over >r \ | save bar addr for enable
174 pci-next-mmio \ | var to change
175 assign-bar-value32 \ | and set it
176 drop \ | forget the BAR length
177 r@ rtas-config-l@ \ | fetch BAR
178 1 or r> rtas-config-l! \ | and enable the ROM
180 2drop \ | clear stack
184 \ Setup the BAR due to its type and return the size of the register (4 or 8 Bytes ) used as increment for the BAR-Loop
185 : assign-bar ( bar-addr -- reg-size )
186 dup pci-bar-code@ \ calc BAR type
188 CASE \ | CASE Setup the right type
189 1 OF assign-io-bar ENDOF \ | - set up an IO-Bar
190 2 OF assign-mmio32-bar ENDOF \ | - set up an 32bit MMIO-Bar
191 3 OF assign-mem32-bar ENDOF \ | - set up an 32bit MEM-Bar (prefetchable)
192 4 OF assign-mmio64-bar ENDOF \ | - set up an 64bit MMIO-Bar
193 5 OF assign-mem64-bar ENDOF \ | - set up an 64bit MEM-Bar (prefetchable)
196 ABORT \ | Throw an exception
200 \ Setup all the bars of a pci device
201 : assign-all-device-bars ( configaddr -- )
202 28 10 DO \ BARs start at 10 and end at 27
203 dup i + \ calc config-addr of the BAR
204 assign-bar \ and set it up
205 +LOOP \ add 4 or 8 to the index and loop
206 30 + assign-rom-bar \ set up the ROM if available
209 \ Setup all the bars of a pci device
210 : assign-all-bridge-bars ( configaddr -- )
211 18 10 DO \ BARs start at 10 and end at 17
212 dup i + \ calc config-addr of the BAR
213 assign-bar \ and set it up
214 +LOOP \ add 4 or 8 to the index and loop
215 38 + assign-rom-bar \ set up the ROM if available
218 \ +---------------------------------------------------------------------------------------+
219 \ | Numerical Representaton of a PCI address (PCI Bus Binding 2.2.1.1) |
221 \ | 31 24 16 11 8 0 |
222 \ | +--------+--------+-----+---+--------+ |
223 \ | phys.hi: |npt000ss| bus | dev |fnc| reg | n - 0 relocatable |
224 \ | +--------+--------+-----+---+--------+ p - 1 prefetchable |
225 \ | t - 1 aliased or <1MB or <64KB |
226 \ | ss - 00 Configuration Space |
228 \ | 10 Memory Space 32bits |
229 \ | 11 Memory Space 64bits |
230 \ +---------------------------------------------------------------------------------------+
232 \ ***************************************************************************************
233 \ Generating the assigned-addresses property
234 \ ***************************************************************************************
235 \ generate assigned-addresses property for 64Bit MEM-BAR and return BAR-reg-size
236 : gen-mem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
237 dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize )
239 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
240 over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size)
241 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val )
242 83000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
243 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
244 r> encode-64+ \ | Encode size ( paddr plen )
246 2drop \ | don't do anything
248 8 \ sizeof(BAR) = 8 Bytes
251 \ generate assigned-addresses property for prefetchable 64Bit MEM-BAR and return BAR-reg-size
252 : gen-pmem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
253 dup pci-bar-size-mem64 \ fetch BAR Size ( paddr plen baddr bsize )
255 >r dup rtas-config-l@ \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
256 over 4 + rtas-config-l@ \ | fetch upper 32 bits ( paddr plen baddr val.lo val.hi R: size)
257 20 lshift + -10 and >r \ | calc 64 bit value and save it ( paddr plen baddr R: size val )
258 C3000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
259 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
260 r> encode-64+ \ | Encode size ( paddr plen )
262 2drop \ | don't do anything
264 8 \ sizeof(BAR) = 8 Bytes
267 \ generate assigned-addresses property for 32Bit MEM-BAR and return BAR-reg-size
268 : gen-mem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
269 dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize )
271 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
272 -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
273 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
274 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
275 r> encode-64+ \ | Encode size ( paddr plen )
277 2drop \ | don't do anything
279 4 \ sizeof(BAR) = 4 Bytes
282 \ generate assigned-addresses property for prefetchable 32Bit MEM-BAR and return BAR-reg-size
283 : gen-pmem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
284 dup pci-bar-size-mem32 \ fetch BAR Size ( paddr plen baddr bsize )
286 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
287 -10 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
288 C2000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
289 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
290 r> encode-64+ \ | Encode size ( paddr plen )
292 2drop \ | don't do anything
294 4 \ sizeof(BAR) = 4 Bytes
297 \ generate assigned-addresses property for IO-BAR and return BAR-reg-size
298 : gen-io-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
299 dup pci-bar-size-io \ fetch BAR Size ( paddr plen baddr bsize )
301 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
302 -4 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
303 81000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
304 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
305 r> encode-64+ \ | Encode size ( paddr plen )
307 2drop \ | don't do anything
309 4 \ sizeof(BAR) = 4 Bytes
312 \ generate assigned-addresses property for ROM-BAR
313 : gen-rom-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len )
314 dup pci-bar-size-rom \ fetch BAR Size ( paddr plen baddr bsize )
316 >r dup rtas-config-l@ \ | save size and fetch value ( paddr plen baddr val R: size)
317 FFFFF800 and >r \ | calc 32 bit value and save it ( paddr plen baddr R: size val )
318 82000000 or encode-int+ \ | Encode config addr ( paddr plen R: size val )
319 r> encode-64+ \ | Encode assigned addr ( paddr plen R: size )
320 r> encode-64+ \ | Encode size ( paddr plen )
322 2drop \ | don't do anything
326 \ add another BAR to the assigned addresses property and return the size of the encoded register
327 : pci-add-assigned-address ( prop-addr prop-len bar-addr -- prop-addr prop-len bsize )
328 dup pci-bar-code@ \ calc BAR type ( paddr plen baddr btype)
329 CASE \ CASE for the BAR types ( paddr plen baddr )
330 0 OF drop 4 ENDOF \ - not a valid type so do nothing
331 1 OF gen-io-bar-prop ENDOF \ - IO-BAR
332 2 OF gen-mem32-bar-prop ENDOF \ - MEM32
333 3 OF gen-pmem32-bar-prop ENDOF \ - MEM32 prefetchable
334 4 OF gen-mem64-bar-prop ENDOF \ - MEM64
335 5 OF gen-pmem64-bar-prop ENDOF \ - MEM64 prefetchable
336 ENDCASE \ ESAC ( paddr plen bsize )
339 \ generate the assigned address property for a PCI device
340 : pci-device-assigned-addresses-prop ( addr -- )
341 encode-start \ provide mem for property ( addr paddr plen )
342 2 pick 30 + gen-rom-bar-prop \ assign the rom bar
343 28 10 DO \ we have 6 possible BARs
344 2 pick i + \ calc BAR address ( addr paddr plen bar-addr )
345 pci-add-assigned-address \ and generate the props for the BAR
346 +LOOP \ increase Index by returned len
347 s" assigned-addresses" property drop \ and write it into the device tree
350 \ generate the assigned address property for a PCI bridge
351 : pci-bridge-assigned-addresses-prop ( addr -- )
352 encode-start \ provide mem for property
353 2 pick 38 + gen-rom-bar-prop \ assign the rom bar
354 18 10 DO \ we have 2 possible BARs
355 2 pick i + \ ( addr paddr plen current-addr )
356 pci-add-assigned-address \ and generate the props for the BAR
357 +LOOP \ increase Index by returned len
358 s" assigned-addresses" property drop \ and write it into the device tree
361 \ check if the range is valid and if so encode it into
362 \ child.hi child.mid child.lo parent.hi parent.mid parent.lo size.hi size.lo
363 \ This is needed to translate the childrens addresses
364 \ We implement only 1:1 mapping for all PCI bridges
365 : pci-bridge-gen-range ( paddr plen base limit type -- paddr plen )
366 >r over - \ calc size ( paddr plen base size R:type )
367 dup 0< IF \ IF Size < 0 ( paddr plen base size R:type )
368 2drop r> drop \ | forget values ( paddr plen )
370 1+ swap 2swap \ | adjust stack ( size base paddr plen R:type )
371 r@ encode-int+ \ | Child type ( size base paddr plen R:type )
372 2 pick encode-64+ \ | Child address ( size base paddr plen R:type )
373 r> encode-int+ \ | Parent type ( size base paddr plen )
374 rot encode-64+ \ | Parent address ( size paddr plen )
375 rot encode-64+ \ | Encode size ( paddr plen )
380 \ generate an mmio space to the ranges property
381 : pci-bridge-gen-mmio-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
382 2 pick 20 + rtas-config-l@ \ fetch Value ( addr paddr plen val )
383 dup 0000FFF0 and 10 lshift \ calc base-address ( addr paddr plen val base )
384 swap 000FFFFF or \ calc limit-address ( addr paddr plen base limit )
385 02000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
388 \ generate an mem space to the ranges property
389 : pci-bridge-gen-mem-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
390 2 pick 24 + rtas-config-l@ \ fetch Value ( addr paddr plen val )
391 dup 000FFFFF or \ calc limit Bits 31:0 ( addr paddr plen val limit.31:0 )
392 swap 0000FFF0 and 10 lshift \ calc base Bits 31:0 ( addr paddr plen limit.31:0 base.31:0 )
393 4 pick 28 + rtas-config-l@ \ fetch upper Basebits ( addr paddr plen limit.31:0 base.31:0 base.63:32 )
394 20 lshift or swap \ and calc Base ( addr paddr plen base.63:0 limit.31:0 )
395 4 pick 2C + rtas-config-l@ \ fetch upper Limitbits ( addr paddr plen base.63:0 limit.31:0 limit.63:32 )
396 20 lshift or \ and calc Limit ( addr paddr plen base.63:0 limit.63:0 )
397 42000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
400 \ generate an io space to the ranges property
401 : pci-bridge-gen-io-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
402 2 pick 1C + rtas-config-l@ \ fetch Value ( addr paddr plen val )
403 dup 0000F000 and 00000FFF or \ calc Limit Bits 15:0 ( addr paddr plen val limit.15:0 )
404 swap 000000F0 and 8 lshift \ calc Base Bits 15:0 ( addr paddr plen limit.15:0 base.15:0 )
405 4 pick 30 + rtas-config-l@ \ fetch upper Bits ( addr paddr plen limit.15:0 base.15:0 val )
406 dup FFFF and 10 lshift rot or \ calc Base ( addr paddr plen limit.15:0 val base.31:0 )
407 -rot FFFF0000 and or \ calc Limit ( addr paddr plen base.31:0 limit.31:0 )
408 01000000 pci-bridge-gen-range \ and generate it ( addr paddr plen )
411 \ generate the ranges property for a PCI bridge
412 : pci-bridge-range-props ( addr -- )
413 encode-start \ provide mem for property
414 pci-bridge-gen-mmio-range \ generate the non prefetchable Memory Entry
415 pci-bridge-gen-mem-range \ generate the prefetchable Memory Entry
416 pci-bridge-gen-io-range \ generate the IO Entry
417 dup IF \ IF any space present (propsize>0)
418 s" ranges" property \ | write it into the device tree
420 s" " s" ranges" property
421 2drop \ | forget the properties
423 drop \ forget the address
426 \ create the interrupt map for this bridge
427 : pci-bridge-interrupt-map ( -- )
428 encode-start \ create the property ( paddr plen )
429 get-node child \ find the first child ( paddr plen handle )
430 BEGIN dup WHILE \ Loop as long as the handle is non-zero ( paddr plen handle )
431 dup >r >space \ Get the my-space ( paddr plen addr R: handle )
432 pci-gen-irq-entry \ and Encode the interrupt settings ( paddr plen R: handle)
433 r> peer \ Get neighbour ( paddr plen handle )
434 REPEAT \ process next childe node ( paddr plen handle )
435 drop \ forget the null ( paddr plen )
436 s" interrupt-map" property \ and set it ( -- )
437 1 encode-int s" #interrupt-cells" property \ encode the cell#
438 f800 encode-int 0 encode-int+ 0 encode-int+ \ encode the bit mask for config addr (Dev only)
439 7 encode-int+ s" interrupt-map-mask" property \ encode IRQ#=7 and generate property
442 \ ***************************************************************************************
443 \ Generating the reg property
444 \ ***************************************************************************************
445 \ reg = config-addr 0 0 0 0 [BAR-config-addr 0 0 size.high size.low]
447 \ encode the reg prop for a nonprefetchable 32bit MEM-BAR
448 : encode-mem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
449 dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR )
450 dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
451 >r 02000000 or encode-int+ \ | save size and encode BAR addr
452 0 encode-64+ \ | make mid and lo zero
453 r> encode-64+ \ | encode size
455 2drop \ | don't do anything
457 4 \ BAR-Len = 4 (32Bit)
460 \ encode the reg prop for a prefetchable 32bit MEM-BAR
461 : encode-pmem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
462 dup pci-bar-size-mem32 \ calc BAR-size ( not changing the BAR )
463 dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
464 >r 42000000 or encode-int+ \ | save size and encode BAR addr
465 0 encode-64+ \ | make mid and lo zero
466 r> encode-64+ \ | encode size
468 2drop \ | don't do anything
470 4 \ BAR-Len = 4 (32Bit)
473 \ encode the reg prop for a nonprefetchable 64bit MEM-BAR
474 : encode-mem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
475 dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR )
476 dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
477 >r 03000000 or encode-int+ \ | save size and encode BAR addr
478 0 encode-64+ \ | make mid and lo zero
479 r> encode-64+ \ | encode size
481 2drop \ | don't do anything
483 8 \ BAR-Len = 8 (64Bit)
486 \ encode the reg prop for a prefetchable 64bit MEM-BAR
487 : encode-pmem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
488 dup pci-bar-size-mem64 \ calc BAR-size ( not changing the BAR )
489 dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
490 >r 43000000 or encode-int+ \ | save size and encode BAR addr
491 0 encode-64+ \ | make mid and lo zero
492 r> encode-64+ \ | encode size
494 2drop \ | don't do anything
496 8 \ BAR-Len = 8 (64Bit)
499 \ encode the reg prop for a ROM-BAR
500 : encode-rom-bar ( prop-addr prop-len configaddr -- prop-addr prop-len )
501 dup pci-bar-size-rom \ fetch raw BAR-size
502 dup IF \ IF BAR is used
503 >r 02000000 or encode-int+ \ | save size and encode BAR addr
504 0 encode-64+ \ | make mid and lo zero
505 r> encode-64+ \ | calc and encode the size
507 2drop \ | don't do anything
511 \ encode the reg prop for an IO-BAR
512 : encode-io-bar ( prop-addr prop-len BAR-addr BAR-value -- prop-addr prop-len 4 )
513 dup pci-bar-size-io \ calc BAR-size ( not changing the BAR )
514 dup IF \ IF BAR-size > 0 ( paddr plen baddr bsize )
515 >r 01000000 or encode-int+ \ | save size and encode BAR addr
516 0 encode-64+ \ | make mid and lo zero
517 r> encode-64+ \ | encode size
519 2drop \ | don't do anything
521 4 \ BAR-Len = 4 (32Bit)
524 \ write the representation of this BAR into the reg property
525 : encode-bar ( prop-addr prop-len bar-addr -- prop-addr prop-len bar-len )
526 dup pci-bar-code@ \ calc BAR type
527 CASE \ CASE for the BAR types ( paddr plen baddr val )
528 0 OF drop 4 ENDOF \ - not a valid type so do nothing
529 1 OF encode-io-bar ENDOF \ - IO-BAR
530 2 OF encode-mem32-bar ENDOF \ - MEM32
531 3 OF encode-pmem32-bar ENDOF \ - MEM32 prefetchable
532 4 OF encode-mem64-bar ENDOF \ - MEM64
533 5 OF encode-pmem64-bar ENDOF \ - MEM64 prefetchable
534 ENDCASE \ ESAC ( paddr plen blen )
538 \ first encode the configuration space address
539 : pci-reg-props ( configaddr -- )
540 dup encode-int \ configuration space ( caddr paddr plen )
541 0 encode-64+ \ make the rest 0
542 0 encode-64+ \ encode the size as 0
543 2 pick pci-htype@ \ fetch Header Type ( caddr paddr plen type )
544 1 and IF \ IF Bridge ( caddr paddr plen )
545 18 10 DO \ | loop over all BARs
546 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr )
547 encode-bar \ | encode this BAR ( caddr paddr plen blen )
548 +LOOP \ | increase LoopIndex by the BARlen
549 2 pick 38 + \ | calc ROM-BAR for a bridge ( caddr paddr plen baddr )
550 encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen )
551 ELSE \ ELSE ordinary device ( caddr paddr plen )
552 28 10 DO \ | loop over all BARs
553 2 pick i + \ | calc bar-addr ( caddr paddr plen baddr )
554 encode-bar \ | encode this BAR ( caddr paddr plen blen )
555 +LOOP \ | increase LoopIndex by the BARlen
556 2 pick 30 + \ | calc ROM-BAR for a device ( caddr paddr plen baddr )
557 encode-rom-bar \ | encode the ROM-BAR ( caddr paddr plen )
558 THEN \ FI ( caddr paddr plen )
559 s" reg" property \ and store it into the property
563 \ ***************************************************************************************
564 \ Generating common properties
565 \ ***************************************************************************************
566 \ set up common properties for devices and bridges
567 : pci-common-props ( addr -- )
568 dup pci-class-name device-name
569 dup pci-vendor@ encode-int s" vendor-id" property
570 dup pci-device@ encode-int s" device-id" property
571 dup pci-revision@ encode-int s" revision-id" property
572 dup pci-class@ encode-int s" class-code" property
573 3 encode-int s" #address-cells" property
574 2 encode-int s" #size-cells" property
576 dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN
579 dup 9 rshift 3 and encode-int s" devsel-speed" property
580 dup 7 rshift 1 and IF 0 0 s" fast-back-to-back" property THEN
581 dup 6 rshift 1 and IF 0 0 s" 66mhz-capable" property THEN
582 5 rshift 1 and IF 0 0 s" udf-supported" property THEN
583 dup pci-cache@ ?dup IF encode-int s" cache-line-size" property THEN
584 pci-interrupt@ ?dup IF encode-int s" interrupts" property THEN
587 \ set up device only properties
588 : pci-device-props ( addr -- )
589 \ FIXME no s" compatible" prop
590 \ FIXME no s" alternate-reg" prop
591 \ FIXME no s" fcode-rom-offset" prop
592 \ FIXME no s" power-consumption" prop
594 dup pci-min-grant@ encode-int s" min-grant" property
595 dup pci-max-lat@ encode-int s" max-latency" property
596 dup pci-sub-device@ ?dup IF encode-int s" subsystem-id" property THEN
597 dup pci-sub-vendor@ ?dup IF encode-int s" subsystem-vendor-id" property THEN
598 dup pci-device-assigned-addresses-prop
600 pci-hotplug-enabled IF
601 \ QEMU uses static assignments for my-drc-index:
602 \ 40000000h + $bus << 8 + $slot << 3
603 dup dup pci-addr2bus 8 lshift
604 swap pci-addr2dev 3 lshift or
605 40000000 + encode-int s" ibm,my-drc-index" property
606 \ QEMU uses "Slot $bus*32$slotno" for loc-code
607 dup dup pci-addr2bus 20 *
610 s" Slot " rot $cathex
612 encode-string s" ibm,loc-code" property
616 \ set up bridge only properties
617 : pci-bridge-props ( addr -- )
618 \ FIXME no s" slot-names" prop
619 \ FIXME no s" bus-master-capable" prop
620 \ FIXME no s" clock-frequency" prop
622 encode-int s" primary-bus" property
623 encode-int s" secondary-bus" property
624 encode-int s" subordinate-bus" property
625 dup pci-bus@ drop encode-int rot encode-int+ s" bus-range" property
626 pci-device-slots encode-int s" slot-names" property
627 dup pci-bridge-range-props
628 dup pci-bridge-assigned-addresses-prop
629 \ Only create interrupt-map when it doesn't already exist
630 \ (it can be provided by qemu)
631 s" interrupt-map" get-node get-property IF
632 pci-bridge-interrupt-map
638 \ used to set up all unknown Bridges.
639 \ If a Bridge has no special handling for setup
640 \ the device file (pci-bridge_VENDOR_DEVICE.fs) can call
641 \ this word to setup busses and scan beyond.
642 : pci-bridge-generic-setup ( addr -- )
643 pci-device-slots >r \ save the slot array on return stack
644 dup pci-common-props \ set the common properties before scanning the bus
645 s" pci" device-type \ the type is allways "pci"
646 dup pci-bridge-probe \ find all device connected to it
647 dup assign-all-bridge-bars \ set up all memory access BARs
648 dup pci-set-irq-line \ set the interrupt pin
649 dup pci-set-capabilities \ set up the capabilities
650 pci-bridge-props \ and generate all properties
651 r> TO pci-device-slots \ and reset the slot array
654 DEFER func-pci-device-props
656 \ used for an gerneric device set up
657 \ if a device has no special handling for setup
658 \ the device file (pci-device_VENDOR_DEVICE.fs) can call
659 \ this word to setup the device
660 : pci-device-generic-setup ( config-addr -- )
661 dup assign-all-device-bars \ calc all BARs
662 dup pci-set-irq-line \ set the interrupt pin
663 dup pci-set-capabilities \ set up the capabilities
664 dup func-pci-device-props \ and generate all properties
665 drop \ forget the config-addr
668 ' pci-device-props TO func-pci-device-props