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-align ( size align var -- al-mem )
95        dup >r @                        \ ( size align cur-mem )
96        swap #aligned                   \ ( size al-mem )
97        tuck +                          \ ( al-mem new-mem )
98        r> !                            \ ( al-mem )
99;
100
101: assign-var-min-align ( size min-align var -- al-mem )
102        >r over umax                    \ ( size align )
103        r> assign-var-align             \ ( al-mem )
104;
105
106\ set bar to current free mem ( in variable ) and set variable to next free mem
107: assign-bar-value32 ( bar size var -- 4 )
108        over IF                         \ IF size > 0
109                >r                      \ | ( bar size )
110                pci-mem-bar-min-align   \ | ( bar size min-align )
111                r> assign-var-min-align \ | ( bar al-mem ) set variable to next mem
112                swap rtas-config-l!     \ | ( -- )         set the bar to al-mem
113        ELSE                            \ ELSE
114                2drop drop              \ | clear stack
115        THEN                            \ FI
116        4                               \ size of the base-address-register
117;
118
119\ set bar to current free mem ( in variable ) and set variable to next free mem
120: assign-io-bar-value32 ( bar size var -- 4 )
121        over IF                         \ IF size > 0
122                >r                      \ | ( bar size )
123                dup                     \ | ( bar size size-align )
124                r> assign-var-align     \ | ( bar al-mem ) set variable to next mem
125                swap rtas-config-l!     \ | ( -- )         set the bar to al-mem
126        ELSE                            \ ELSE
127                2drop drop              \ | clear stack
128        THEN                            \ FI
129        4                               \ size of the base-address-register
130;
131
132\ set bar to current free mem ( in variable ) and set variable to next free mem
133: assign-bar-value64 ( bar size var -- 8 )
134        over IF                         \ IF size > 0
135                >r                      \ | ( bar size )
136                pci-mem-bar-min-align   \ | ( bar size min-align )
137                r> assign-var-min-align \ | ( bar al-mem ) set variable to next mem
138                swap                    \ | ( al-mem addr ) calc config-addr of this bar
139                2dup rtas-config-l!     \ | ( al-mem addr ) set the Lower part of the bar to al-mem
140                4 + swap 20 rshift      \ | ( al-mem>>32 addr ) prepare the upper part of the al-mem
141                swap rtas-config-l!     \ | ( -- ) and set the upper part of the bar
142        ELSE                            \ ELSE
143                2drop drop              \ | clear stack
144        THEN                            \ FI
145        8                               \ size of the base-address-register
146;
147
148\ Setup a prefetchable 64bit BAR and return its size
149: assign-mem64-bar ( bar-addr -- 8 )
150        dup pci-bar-size-mem64         \ fetch size
151        pci-next-mem64 @ 0 = IF          \ Check if we have 64-bit memory range
152	    pci-next-mem
153	ELSE
154	    pci-next-mem64
155	THEN
156        assign-bar-value64              \ and set it all
157;
158
159\ Setup a prefetchable 32bit BAR and return its size
160: assign-mem32-bar ( bar-addr -- 4 )
161        dup pci-bar-size-mem32          \ fetch size
162        \ Do we have a dedicated 32-bit prefetchable area? If not, use MMIO
163        pci-next-mem @ IF
164            pci-next-mem
165        ELSE
166            pci-next-mmio
167        THEN
168        assign-bar-value32              \ and set it all
169;
170
171\ Setup a non-prefetchable 64bit BAR and return its size
172: assign-mmio64-bar ( bar-addr -- 8 )
173        dup pci-bar-size-mem64          \ fetch size
174        pci-next-mmio
175        assign-bar-value64              \ and set it all
176;
177
178\ Setup a non-prefetchable 32bit BAR and return its size
179: assign-mmio32-bar ( bar-addr -- 4 )
180        dup pci-bar-size-mem32          \ fetch size
181        pci-next-mmio                   \ var to change
182        assign-bar-value32              \ and set it all
183;
184
185\ Setup an IO-Bar and return the size of the base-address-register
186: assign-io-bar ( bar-addr -- 4 )
187        dup pci-bar-size-io             \ fetch size
188        pci-next-io                     \ var to change
189        assign-io-bar-value32           \ and set it all
190;
191
192\ Setup an Expansion ROM bar
193: assign-rom-bar ( bar-addr -- )
194        dup pci-bar-size-rom            \ fetch size
195        dup IF                          \ IF size > 0
196                over >r                 \ | save bar addr for enable
197                pci-next-mmio           \ | var to change
198                assign-bar-value32      \ | and set it
199                drop                    \ | forget the BAR length
200                r@ rtas-config-l@       \ | fetch BAR
201                1 or r> rtas-config-l!  \ | and enable the ROM
202        ELSE                            \ ELSE
203                2drop                   \ | clear stack
204        THEN
205;
206
207\ 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
208: assign-bar ( bar-addr -- reg-size )
209        dup pci-bar-code@                       \ calc BAR type
210        dup IF                                  \ IF >0
211                CASE                            \ | CASE Setup the right type
212                1 OF assign-io-bar     ENDOF    \ | - set up an IO-Bar
213                2 OF assign-mmio32-bar ENDOF    \ | - set up an 32bit MMIO-Bar
214                3 OF assign-mem32-bar  ENDOF    \ | - set up an 32bit MEM-Bar (prefetchable)
215                4 OF assign-mmio64-bar ENDOF    \ | - set up an 64bit MMIO-Bar
216                5 OF assign-mem64-bar  ENDOF    \ | - set up an 64bit MEM-Bar (prefetchable)
217                ENDCASE                         \ | ESAC
218        ELSE                                    \ ELSE
219                ABORT                           \ | Throw an exception
220        THEN                                    \ FI
221;
222
223\ Setup all the bars of a pci device
224: assign-all-device-bars ( configaddr -- )
225        28 10 DO                        \ BARs start at 10 and end at 27
226                dup i +                 \ calc config-addr of the BAR
227                assign-bar              \ and set it up
228        +LOOP                           \ add 4 or 8 to the index and loop
229        30 + assign-rom-bar             \ set up the ROM if available
230;
231
232\ Setup all the bars of a pci device
233: assign-all-bridge-bars ( configaddr -- )
234        18 10 DO                        \ BARs start at 10 and end at 17
235                dup i +                 \ calc config-addr of the BAR
236                assign-bar              \ and set it up
237        +LOOP                           \ add 4 or 8 to the index and loop
238        38 + assign-rom-bar             \ set up the ROM if available
239;
240
241\ +---------------------------------------------------------------------------------------+
242\ | Numerical Representaton of a PCI address (PCI Bus Binding 2.2.1.1)                   |
243\ |                                                                                       |
244\ |           31      24       16    11   8        0                                      |
245\ |           +--------+--------+-----+---+--------+                                      |
246\ | phys.hi:  |npt000ss|  bus   | dev |fnc|   reg  |    n - 0 relocatable                 |
247\ |           +--------+--------+-----+---+--------+    p - 1 prefetchable                |
248\ |                                                     t - 1 aliased or <1MB or <64KB    |
249\ |                                                    ss - 00 Configuration Space        |
250\ |                                                         01 I/O Space                  |
251\ |                                                         10 Memory Space 32bits        |
252\ |                                                         11 Memory Space 64bits        |
253\ +---------------------------------------------------------------------------------------+
254
255\ ***************************************************************************************
256\ Generating the assigned-addresses property
257\ ***************************************************************************************
258\ generate assigned-addresses property for non-prefetchable 64Bit MEM-BAR and
259\ return BAR-reg-size. Note: We use "32-bit" as space code here, since these
260\ BARs are allocated from the 32-bit MMIO window (see assign-mmio64-bar)
261: gen-mem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
262        dup pci-bar-size-mem64                  \ fetch BAR Size        ( paddr plen baddr bsize )
263        dup IF                                  \ IF Size > 0
264                >r dup rtas-config-l@           \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
265                over 4 + rtas-config-l@         \ | fetch upper 32 bits               ( paddr plen baddr val.lo val.hi R: size)
266                20 lshift + -10 and >r          \ | calc 64 bit value and save it     ( paddr plen baddr R: size val )
267                82000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
268                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
269                r> encode-64+                   \ | Encode size                       ( paddr plen )
270        ELSE                                    \ ELSE
271                2drop                           \ | don't do anything
272        THEN                                    \ FI
273        8                                       \ sizeof(BAR) = 8 Bytes
274;
275
276\ generate assigned-addresses property for prefetchable 64Bit MEM-BAR and return BAR-reg-size
277: gen-pmem64-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 8 )
278        dup pci-bar-size-mem64                  \ fetch BAR Size        ( paddr plen baddr bsize )
279        dup IF                                  \ IF Size > 0
280                >r dup rtas-config-l@           \ | save size and fetch lower 32 bits ( paddr plen baddr val.lo R: size)
281                over 4 + rtas-config-l@         \ | fetch upper 32 bits               ( paddr plen baddr val.lo val.hi R: size)
282                20 lshift + -10 and >r          \ | calc 64 bit value and save it     ( paddr plen baddr R: size val )
283                C3000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
284                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
285                r> encode-64+                   \ | Encode size                       ( paddr plen )
286        ELSE                                    \ ELSE
287                2drop                           \ | don't do anything
288        THEN                                    \ FI
289        8                                       \ sizeof(BAR) = 8 Bytes
290;
291
292\ generate assigned-addresses property for 32Bit MEM-BAR and return BAR-reg-size
293: gen-mem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
294        dup pci-bar-size-mem32                  \ fetch BAR Size        ( paddr plen baddr bsize )
295        dup IF                                  \ IF Size > 0
296                >r dup rtas-config-l@           \ | save size and fetch value         ( paddr plen baddr val R: size)
297                -10 and >r                      \ | calc 32 bit value and save it     ( paddr plen baddr R: size val )
298                82000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
299                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
300                r> encode-64+                   \ | Encode size                       ( paddr plen )
301        ELSE                                    \ ELSE
302                2drop                           \ | don't do anything
303        THEN                                    \ FI
304        4                                       \ sizeof(BAR) = 4 Bytes
305;
306
307\ generate assigned-addresses property for prefetchable 32Bit MEM-BAR and return BAR-reg-size
308: gen-pmem32-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
309        dup pci-bar-size-mem32                  \ fetch BAR Size        ( paddr plen baddr bsize )
310        dup IF                                  \ IF Size > 0
311                >r dup rtas-config-l@           \ | save size and fetch value         ( paddr plen baddr val R: size)
312                -10 and >r                      \ | calc 32 bit value and save it     ( paddr plen baddr R: size val )
313                C2000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
314                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
315                r> encode-64+                   \ | Encode size                       ( paddr plen )
316        ELSE                                    \ ELSE
317                2drop                           \ | don't do anything
318        THEN                                    \ FI
319        4                                       \ sizeof(BAR) = 4 Bytes
320;
321
322\ generate assigned-addresses property for IO-BAR and return BAR-reg-size
323: gen-io-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len 4 )
324        dup pci-bar-size-io                     \ fetch BAR Size                      ( paddr plen baddr bsize )
325        dup IF                                  \ IF Size > 0
326                >r dup rtas-config-l@           \ | save size and fetch value         ( paddr plen baddr val R: size)
327                -4 and >r                       \ | calc 32 bit value and save it     ( paddr plen baddr R: size val )
328                81000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
329                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
330                r> encode-64+                   \ | Encode size                       ( paddr plen )
331        ELSE                                    \ ELSE
332                2drop                           \ | don't do anything
333        THEN                                    \ FI
334        4                                       \ sizeof(BAR) = 4 Bytes
335;
336
337\ generate assigned-addresses property for ROM-BAR
338: gen-rom-bar-prop ( prop-addr prop-len bar-addr -- prop-addr prop-len )
339        dup pci-bar-size-rom                    \ fetch BAR Size                      ( paddr plen baddr bsize )
340        dup IF                                  \ IF Size > 0
341                >r dup rtas-config-l@           \ | save size and fetch value         ( paddr plen baddr val R: size)
342                FFFFF800 and >r                 \ | calc 32 bit value and save it     ( paddr plen baddr R: size val )
343                82000000 or encode-int+         \ | Encode config addr                ( paddr plen R: size val )
344                r> encode-64+                   \ | Encode assigned addr              ( paddr plen R: size )
345                r> encode-64+                   \ | Encode size                       ( paddr plen )
346        ELSE                                    \ ELSE
347                2drop                           \ | don't do anything
348        THEN                                    \ FI
349;
350
351\ add another BAR to the assigned addresses property and return the size of the encoded register
352: pci-add-assigned-address ( prop-addr prop-len bar-addr -- prop-addr prop-len bsize )
353        dup pci-bar-code@                               \ calc BAR type                         ( paddr plen baddr btype)
354        CASE                                            \ CASE for the BAR types                ( paddr plen baddr )
355                0 OF drop 4              ENDOF          \ - not a valid type so do nothing
356                1 OF gen-io-bar-prop     ENDOF          \ - IO-BAR
357                2 OF gen-mem32-bar-prop  ENDOF          \ - MEM32
358                3 OF gen-pmem32-bar-prop ENDOF          \ - MEM32 prefetchable
359                4 OF gen-mem64-bar-prop  ENDOF          \ - MEM64
360                5 OF gen-pmem64-bar-prop ENDOF          \ - MEM64 prefetchable
361        ENDCASE                                         \ ESAC ( paddr plen bsize )
362;
363
364\ generate the assigned address property for a PCI device
365: pci-device-assigned-addresses-prop ( addr -- )
366        encode-start                                    \ provide mem for property              ( addr paddr plen )
367        2 pick 30 + gen-rom-bar-prop                    \ assign the rom bar
368        28 10 DO                                        \ we have 6 possible BARs
369                2 pick i +                              \ calc BAR address                      ( addr paddr plen bar-addr )
370                pci-add-assigned-address                \ and generate the props for the BAR
371        +LOOP                                           \ increase Index by returned len
372        s" assigned-addresses" property drop            \ and write it into the device tree
373;
374
375\ generate the assigned address property for a PCI bridge
376: pci-bridge-assigned-addresses-prop ( addr -- )
377        encode-start                                    \ provide mem for property
378        2 pick 38 + gen-rom-bar-prop                    \ assign the rom bar
379        18 10 DO                                        \ we have 2 possible BARs
380                2 pick i +                              \ ( addr paddr plen current-addr )
381                pci-add-assigned-address                \ and generate the props for the BAR
382        +LOOP                                           \ increase Index by returned len
383        s" assigned-addresses" property drop            \ and write it into the device tree
384;
385
386\ check if the range is valid and if so encode it into
387\ child.hi child.mid child.lo parent.hi parent.mid parent.lo size.hi size.lo
388\ This is needed to translate the childrens addresses
389\ We implement only 1:1 mapping for all PCI bridges
390: pci-bridge-gen-range ( paddr plen base limit type -- paddr plen )
391        >r over -                       \ calc size             ( paddr plen base size R:type )
392        dup 0< IF                       \ IF Size < 0           ( paddr plen base size R:type )
393                2drop r> drop           \ | forget values       ( paddr plen )
394        ELSE                            \ ELSE
395                1+ swap 2swap           \ | adjust stack        ( size base paddr plen R:type )
396                r@ encode-int+          \ | Child type          ( size base paddr plen R:type )
397                2 pick encode-64+       \ | Child address       ( size base paddr plen R:type )
398                r> encode-int+          \ | Parent type         ( size base paddr plen )
399                rot encode-64+          \ | Parent address      ( size paddr plen )
400                rot encode-64+          \ | Encode size         ( paddr plen )
401        THEN                            \ FI
402;
403
404
405\ generate an mmio space to the ranges property
406: pci-bridge-gen-mmio-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
407        2 pick 20 + rtas-config-l@      \ fetch Value           ( addr paddr plen val )
408        dup 0000FFF0 and 10 lshift      \ calc base-address     ( addr paddr plen val base )
409        swap 000FFFFF or                \ calc limit-address    ( addr paddr plen base limit )
410        02000000 pci-bridge-gen-range   \ and generate it       ( addr paddr plen )
411;
412
413\ generate an mem space to the ranges property
414: pci-bridge-gen-mem-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
415        2 pick 24 + rtas-config-l@      \ fetch Value           ( addr paddr plen val )
416        dup 000FFFFF or                 \ calc limit Bits 31:0  ( addr paddr plen val limit.31:0 )
417        swap 0000FFF0 and 10 lshift     \ calc base Bits 31:0   ( addr paddr plen limit.31:0 base.31:0 )
418        4 pick 28 + rtas-config-l@      \ fetch upper Basebits  ( addr paddr plen limit.31:0 base.31:0 base.63:32 )
419        20 lshift or swap               \ and calc Base         ( addr paddr plen base.63:0 limit.31:0 )
420        4 pick 2C + rtas-config-l@      \ fetch upper Limitbits ( addr paddr plen base.63:0 limit.31:0 limit.63:32 )
421        dup -rot 20 lshift or swap      \ and calc Limit        ( addr paddr plen base.63:0 limit.63:0 limit.63:32 )
422        IF 43000000 ELSE 42000000 THEN  \ 64-bit or 32-bit?     ( addr paddr plen base.63:0 limit.63:0 type )
423        pci-bridge-gen-range            \ and generate it       ( addr paddr plen )
424;
425
426\ generate an io space to the ranges property
427: pci-bridge-gen-io-range ( addr prop-addr prop-len -- addr prop-addr prop-len )
428        2 pick 1C + rtas-config-l@      \ fetch Value           ( addr paddr plen val )
429        dup 0000F000 and 00000FFF or    \ calc Limit Bits 15:0  ( addr paddr plen val limit.15:0 )
430        swap 000000F0 and 8 lshift      \ calc Base Bits 15:0   ( addr paddr plen limit.15:0 base.15:0 )
431        4 pick 30 + rtas-config-l@      \ fetch upper Bits      ( addr paddr plen limit.15:0 base.15:0 val )
432        dup FFFF and 10 lshift rot or   \ calc Base             ( addr paddr plen limit.15:0 val base.31:0 )
433        -rot FFFF0000 and or            \ calc Limit            ( addr paddr plen base.31:0 limit.31:0 )
434        01000000 pci-bridge-gen-range   \ and generate it       ( addr paddr plen )
435;
436
437\ generate the ranges property for a PCI bridge
438: pci-bridge-range-props ( addr -- )
439        encode-start                    \ provide mem for property
440        pci-bridge-gen-mmio-range       \ generate the non prefetchable Memory Entry
441        pci-bridge-gen-mem-range        \ generate the prefetchable Memory Entry
442        pci-bridge-gen-io-range         \ generate the IO Entry
443        dup IF                          \ IF any space present (propsize>0)
444                s" ranges" property     \ | write it into the device tree
445        ELSE                            \ ELSE
446               s" " s" ranges" property
447                2drop                   \ | forget the properties
448        THEN                            \ FI
449        drop                            \ forget the address
450;
451
452\ create the interrupt map for this bridge
453: pci-bridge-interrupt-map ( -- )
454        encode-start                                    \ create the property                           ( paddr plen )
455        get-node child                                  \ find the first child                          ( paddr plen handle )
456        BEGIN dup WHILE                                 \ Loop as long as the handle is non-zero        ( paddr plen handle )
457                dup >r >space                           \ Get the my-space                              ( paddr plen addr R: handle )
458                pci-gen-irq-entry                       \ and Encode the interrupt settings             ( paddr plen R: handle)
459                r> peer                                 \ Get neighbour                                 ( paddr plen handle )
460        REPEAT                                          \ process next childe node                      ( paddr plen handle )
461        drop                                            \ forget the null                               ( paddr plen )
462        s" interrupt-map" property                      \ and set it                                    ( -- )
463        1 encode-int s" #interrupt-cells" property      \ encode the cell#
464        f800 encode-int 0 encode-int+ 0 encode-int+     \ encode the bit mask for config addr (Dev only)
465        7 encode-int+ s" interrupt-map-mask" property   \ encode IRQ#=7 and generate property
466;
467
468\ ***************************************************************************************
469\ Generating the reg property
470\ ***************************************************************************************
471\ reg = config-addr 0 0 0 0 [BAR-config-addr 0 0 size.high size.low]
472
473\ encode the reg prop for a nonprefetchable 32bit MEM-BAR
474: encode-mem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
475        dup pci-bar-size-mem32                  \ calc BAR-size ( not changing the BAR )
476        dup IF                                  \ IF BAR-size > 0       ( paddr plen baddr bsize )
477                >r 02000000 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        4                                       \ BAR-Len = 4 (32Bit)
484;
485
486\ encode the reg prop for a prefetchable 32bit MEM-BAR
487: encode-pmem32-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 4 )
488        dup pci-bar-size-mem32                  \ calc BAR-size ( not changing the BAR )
489        dup IF                                  \ IF BAR-size > 0       ( paddr plen baddr bsize )
490                >r 42000000 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        4                                       \ BAR-Len = 4 (32Bit)
497;
498
499\ encode the reg prop for a nonprefetchable 64bit MEM-BAR
500: encode-mem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
501        dup pci-bar-size-mem64                  \ calc BAR-size ( not changing the BAR )
502        dup IF                                  \ IF BAR-size > 0       ( paddr plen baddr bsize )
503                >r 03000000 or encode-int+      \ | save size and encode BAR addr
504                0 encode-64+                    \ | make mid and lo zero
505                r> encode-64+                   \ | encode size
506        ELSE                                    \ ELSE
507                2drop                           \ | don't do anything
508        THEN                                    \ FI
509        8                                       \ BAR-Len = 8 (64Bit)
510;
511
512\ encode the reg prop for a prefetchable 64bit MEM-BAR
513: encode-pmem64-bar ( prop-addr prop-len BAR-addr -- prop-addr prop-len 8 )
514        dup pci-bar-size-mem64                  \ calc BAR-size ( not changing the BAR )
515        dup IF                                  \ IF BAR-size > 0       ( paddr plen baddr bsize )
516                >r 43000000 or encode-int+      \ | save size and encode BAR addr
517                0 encode-64+                    \ | make mid and lo zero
518                r> encode-64+                   \ | encode size
519        ELSE                                    \ ELSE
520                2drop                           \ | don't do anything
521        THEN                                    \ FI
522        8                                       \ BAR-Len = 8 (64Bit)
523;
524
525\ encode the reg prop for a ROM-BAR
526: encode-rom-bar ( prop-addr prop-len configaddr -- prop-addr prop-len )
527        dup pci-bar-size-rom                            \ fetch raw BAR-size
528        dup IF                                          \ IF BAR is used
529                >r 02000000 or encode-int+              \ | save size and encode BAR addr
530                0 encode-64+                            \ | make mid and lo zero
531                r> encode-64+                           \ | calc and encode the size
532        ELSE                                            \ ELSE
533                2drop                                   \ | don't do anything
534        THEN                                            \ FI
535;
536
537\ encode the reg prop for an IO-BAR
538: encode-io-bar ( prop-addr prop-len BAR-addr BAR-value -- prop-addr prop-len 4 )
539        dup pci-bar-size-io                     \ calc BAR-size ( not changing the BAR )
540        dup IF                                  \ IF BAR-size > 0       ( paddr plen baddr bsize )
541                >r 01000000 or encode-int+      \ | save size and encode BAR addr
542                0 encode-64+                    \ | make mid and lo zero
543                r> encode-64+                   \ | encode size
544        ELSE                                    \ ELSE
545                2drop                           \ | don't do anything
546        THEN                                    \ FI
547        4                                       \ BAR-Len = 4 (32Bit)
548;
549
550\ write the representation of this BAR into the reg property
551: encode-bar ( prop-addr prop-len bar-addr -- prop-addr prop-len bar-len )
552        dup pci-bar-code@                               \ calc BAR type
553        CASE                                            \ CASE for the BAR types ( paddr plen baddr val )
554                0 OF drop 4             ENDOF           \ - not a valid type so do nothing
555                1 OF encode-io-bar      ENDOF           \ - IO-BAR
556                2 OF encode-mem32-bar   ENDOF           \ - MEM32
557                3 OF encode-pmem32-bar  ENDOF           \ - MEM32 prefetchable
558                4 OF encode-mem64-bar   ENDOF           \ - MEM64
559                5 OF encode-pmem64-bar  ENDOF           \ - MEM64 prefetchable
560        ENDCASE                                         \ ESAC ( paddr plen blen )
561;
562
563\ Setup reg property
564\ first encode the configuration space address
565: pci-reg-props ( configaddr -- )
566        dup encode-int                  \ configuration space           ( caddr paddr plen )
567        0 encode-64+                    \ make the rest 0
568        0 encode-64+                    \ encode the size as 0
569        2 pick pci-htype@               \ fetch Header Type             ( caddr paddr plen type )
570        1 and IF                        \ IF Bridge                     ( caddr paddr plen )
571                18 10 DO                \ | loop over all BARs
572                        2 pick i +      \ | calc bar-addr               ( caddr paddr plen baddr )
573                        encode-bar      \ | encode this BAR             ( caddr paddr plen blen )
574                     +LOOP              \ | increase LoopIndex by the BARlen
575                2 pick 38 +             \ | calc ROM-BAR for a bridge   ( caddr paddr plen baddr )
576                encode-rom-bar          \ | encode the ROM-BAR          ( caddr paddr plen )
577        ELSE                            \ ELSE ordinary device          ( caddr paddr plen )
578               28 10 DO                 \ | loop over all BARs
579                        2 pick i +      \ | calc bar-addr               ( caddr paddr plen baddr )
580                        encode-bar      \ | encode this BAR             ( caddr paddr plen blen )
581                     +LOOP              \ | increase LoopIndex by the BARlen
582                2 pick 30 +             \ | calc ROM-BAR for a device   ( caddr paddr plen baddr )
583                encode-rom-bar          \ | encode the ROM-BAR          ( caddr paddr plen )
584        THEN                            \ FI                            ( caddr paddr plen )
585        s" reg" property                \ and store it into the property
586        drop
587;
588
589\ ***************************************************************************************
590\ Generating common properties
591\ ***************************************************************************************
592\ set up common properties for devices and bridges
593: pci-common-props ( addr -- )
594        dup pci-class-name device-name
595        dup pci-vendor@    encode-int s" vendor-id"      property
596        dup pci-device@    encode-int s" device-id"      property
597        dup pci-revision@  encode-int s" revision-id"    property
598        dup pci-class@     encode-int s" class-code"     property
599                         3 encode-int s" #address-cells" property
600                         2 encode-int s" #size-cells"    property
601
602        dup pci-config-ext? IF 1 encode-int s" ibm,pci-config-space-type" property THEN
603
604        dup pci-status@
605                dup 9 rshift 3 and encode-int s" devsel-speed" property
606                dup 7 rshift 1 and IF 0 0 s" fast-back-to-back" property THEN
607                dup 6 rshift 1 and IF 0 0 s" 66mhz-capable" property THEN
608                    5 rshift 1 and IF 0 0 s" udf-supported" property THEN
609        dup pci-cache@     ?dup IF encode-int s" cache-line-size" property THEN
610            pci-interrupt@ ?dup IF encode-int s" interrupts"      property THEN
611;
612
613\ set up device only properties
614: pci-device-props ( addr -- )
615        \ FIXME no s" compatible" prop
616        \ FIXME no s" alternate-reg" prop
617        \ FIXME no s" fcode-rom-offset" prop
618        \ FIXME no s" power-consumption" prop
619        dup pci-common-props
620        dup pci-min-grant@ encode-int s" min-grant"   property
621        dup pci-max-lat@   encode-int s" max-latency" property
622        dup pci-sub-device@ ?dup IF encode-int s" subsystem-id" property THEN
623        dup pci-sub-vendor@ ?dup IF encode-int s" subsystem-vendor-id" property THEN
624        dup pci-device-assigned-addresses-prop
625        pci-reg-props
626        pci-hotplug-enabled IF
627            \ QEMU uses static assignments for my-drc-index:
628            \ 40000000h + $bus << 8 + $slot << 3
629            dup dup pci-addr2bus 8 lshift
630            swap pci-addr2dev 3 lshift or
631            40000000 + encode-int s" ibm,my-drc-index" property
632            \ QEMU uses "Slot $bus*32$slotno" for loc-code
633            dup dup pci-addr2bus 20 *
634            swap pci-addr2dev +
635            a base !
636            s" Slot " rot $cathex
637            hex
638            encode-string s" ibm,loc-code" property
639        THEN
640;
641
642\ set up bridge only properties
643: pci-bridge-props ( addr -- )
644        \ FIXME no s" slot-names" prop
645        \ FIXME no s" bus-master-capable" prop
646        \ FIXME no s" clock-frequency" prop
647        dup pci-bus@
648              encode-int s" primary-bus" property
649              encode-int s" secondary-bus" property
650              encode-int s" subordinate-bus" property
651        dup pci-bus@ drop encode-int rot encode-int+ s" bus-range" property
652            pci-device-slots encode-int s" slot-names" property
653        dup pci-bridge-range-props
654        dup pci-bridge-assigned-addresses-prop
655	\ Only create interrupt-map when it doesn't already exist
656	\ (it can be provided by qemu)
657	s" interrupt-map" get-node get-property IF
658            pci-bridge-interrupt-map
659	ELSE 2drop THEN
660        pci-reg-props
661;
662
663
664\ used to set up all unknown Bridges.
665\ If a Bridge has no special handling for setup
666\ the device file (pci-bridge_VENDOR_DEVICE.fs) can call
667\ this word to setup busses and scan beyond.
668: pci-bridge-generic-setup ( addr -- )
669        pci-device-slots >r             \ save the slot array on return stack
670        dup pci-common-props            \ set the common properties before scanning the bus
671        s" pci" device-type             \ the type is allways "pci"
672        dup func-pci-bridge-probe       \ find all device connected to it
673        dup assign-all-bridge-bars      \ set up all memory access BARs
674        dup pci-set-irq-line            \ set the interrupt pin
675        dup pci-set-capabilities        \ set up the capabilities
676            pci-bridge-props            \ and generate all properties
677        r> TO pci-device-slots          \ and reset the slot array
678;
679
680DEFER func-pci-device-props
681
682\ used for an gerneric device set up
683\ if a device has no special handling for setup
684\ the device file (pci-device_VENDOR_DEVICE.fs) can call
685\ this word to setup the device
686: pci-device-generic-setup ( config-addr -- )
687        dup assign-all-device-bars      \ calc all BARs
688        dup pci-set-irq-line            \ set the interrupt pin
689        dup pci-set-capabilities        \ set up the capabilities
690        dup func-pci-device-props       \ and generate all properties
691        drop                            \ forget the config-addr
692;
693
694' pci-device-props TO func-pci-device-props
695