Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / slof / fs / pci-properties.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 #include "pci-class-code-names.fs"
14
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 ;
19
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
26 ;
27
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
33 ;
34
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
40 ;
41
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
48 ;
49
50 \ calc IO BAR 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
55 ;
56
57
58 \ decode the Bar Type
59 \ +----------------------------------------------------------------------------------------+
60 \ |                                         3 2 1 0                                        |
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                                                        |
68 \ |          1 - IO - Bar                                                                  |
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
76         1 and IF                          \ IO BAR ?
77                 2 and IF 0 ELSE 1 THEN    \ only '01' is valid
78         ELSE                              \ Memory BAR ?
79                 F and CASE
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
85                 ENDCASE
86         THEN
87 ;
88
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
99 ;
100
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
106         ELSE                            \ ELSE
107                 2drop drop              \ | clear stack
108         THEN                            \ FI
109         4                               \ size of the base-address-register
110 ;
111
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
120         ELSE                            \ ELSE
121                 2drop drop              \ | clear stack
122         THEN                            \ FI
123         8                               \ size of the base-address-register
124 ;
125
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
130             pci-next-mem
131         ELSE
132             pci-next-mem64
133         THEN
134         assign-bar-value64              \ and set it all
135 ;
136
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
142 ;
143
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
148             pci-next-mmio
149         ELSE
150             pci-next-mem64              \ for board-qemu we will use same range
151         THEN
152         assign-bar-value64              \ and set it all
153 ;
154
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
160 ;
161
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
167 ;
168
169 \ Setup an Expansion ROM bar
170 : assign-rom-bar ( bar-addr -- )
171         dup pci-bar-size-rom            \ fetch size
172         dup IF                          \ IF size > 0
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
179         ELSE                            \ ELSE
180                 2drop                   \ | clear stack
181         THEN
182 ;
183
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
187         dup IF                                  \ IF >0
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)
194                 ENDCASE                         \ | ESAC
195         ELSE                                    \ ELSE
196                 ABORT                           \ | Throw an exception
197         THEN                                    \ FI
198 ;
199
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
207 ;
208
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
216 ;
217
218 \ +---------------------------------------------------------------------------------------+
219 \ | Numerical Representaton of a PCI address (PCI Bus Binding 2.2.1.1)                   |
220 \ |                                                                                       |
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        |
227 \ |                                                         01 I/O Space                  |
228 \ |                                                         10 Memory Space 32bits        |
229 \ |                                                         11 Memory Space 64bits        |
230 \ +---------------------------------------------------------------------------------------+
231
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 )
238         dup IF                                  \ IF Size > 0
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 )
245         ELSE                                    \ ELSE
246                 2drop                           \ | don't do anything
247         THEN                                    \ FI
248         8                                       \ sizeof(BAR) = 8 Bytes
249 ;
250
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 )
254         dup IF                                  \ IF Size > 0
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 )
261         ELSE                                    \ ELSE
262                 2drop                           \ | don't do anything
263         THEN                                    \ FI
264         8                                       \ sizeof(BAR) = 8 Bytes
265 ;
266
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 )
270         dup IF                                  \ IF Size > 0
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 )
276         ELSE                                    \ ELSE
277                 2drop                           \ | don't do anything
278         THEN                                    \ FI
279         4                                       \ sizeof(BAR) = 4 Bytes
280 ;
281
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 )
285         dup IF                                  \ IF Size > 0
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 )
291         ELSE                                    \ ELSE
292                 2drop                           \ | don't do anything
293         THEN                                    \ FI
294         4                                       \ sizeof(BAR) = 4 Bytes
295 ;
296
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 )
300         dup IF                                  \ IF Size > 0
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 )
306         ELSE                                    \ ELSE
307                 2drop                           \ | don't do anything
308         THEN                                    \ FI
309         4                                       \ sizeof(BAR) = 4 Bytes
310 ;
311
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 )
315         dup IF                                  \ IF Size > 0
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 )
321         ELSE                                    \ ELSE
322                 2drop                           \ | don't do anything
323         THEN                                    \ FI
324 ;
325
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 )
337 ;
338
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
348 ;
349
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
359 ;
360
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 )
369         ELSE                            \ ELSE
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 )
376         THEN                            \ FI
377 ;
378
379
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 )
386 ;
387
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 )
398 ;
399
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 )
409 ;
410
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
419         ELSE                            \ ELSE
420                s" " s" ranges" property
421                 2drop                   \ | forget the properties
422         THEN                            \ FI
423         drop                            \ forget the address
424 ;
425
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
440 ;
441
442 \ ***************************************************************************************
443 \ Generating the reg property
444 \ ***************************************************************************************
445 \ reg = config-addr 0 0 0 0 [BAR-config-addr 0 0 size.high size.low]
446
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
454         ELSE                                    \ ELSE
455                 2drop                           \ | don't do anything
456         THEN                                    \ FI
457         4                                       \ BAR-Len = 4 (32Bit)
458 ;
459
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
467         ELSE                                    \ ELSE
468                 2drop                           \ | don't do anything
469         THEN                                    \ FI
470         4                                       \ BAR-Len = 4 (32Bit)
471 ;
472
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
480         ELSE                                    \ ELSE
481                 2drop                           \ | don't do anything
482         THEN                                    \ FI
483         8                                       \ BAR-Len = 8 (64Bit)
484 ;
485
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
493         ELSE                                    \ ELSE
494                 2drop                           \ | don't do anything
495         THEN                                    \ FI
496         8                                       \ BAR-Len = 8 (64Bit)
497 ;
498
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
506         ELSE                                            \ ELSE
507                 2drop                                   \ | don't do anything
508         THEN                                            \ FI
509 ;
510
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
518         ELSE                                    \ ELSE
519                 2drop                           \ | don't do anything
520         THEN                                    \ FI
521         4                                       \ BAR-Len = 4 (32Bit)
522 ;
523
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 )
535 ;
536
537 \ Setup reg property
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
560         drop
561 ;
562
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
575
576         dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN
577
578         dup pci-status@
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
585 ;
586
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
593         dup pci-common-props
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
599         pci-reg-props
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 *
608             swap pci-addr2dev +
609             a base !
610             s" Slot " rot $cathex
611             hex
612             encode-string s" ibm,loc-code" property
613         THEN
614 ;
615
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
621         dup pci-bus@
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
633         ELSE 2drop THEN
634         pci-reg-props
635 ;
636
637
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
652 ;
653
654 DEFER func-pci-device-props
655
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
666 ;
667
668 ' pci-device-props TO func-pci-device-props