Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: pcibus.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)pcibus.fth 1.20 06/11/01 08:58:38 | |
43 | purpose: | |
44 | copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | hex | |
48 | ||
49 | h# 40 buffer: function-reg-string | |
50 | 0 value pci-depth | |
51 | ||
52 | headerless | |
53 | 0 value current-bus# | |
54 | false value probe-state? | |
55 | ||
56 | : $config-b@ ( -- str$ ) " config-b@" ; | |
57 | : $config-b! ( -- str$ ) " config-b!" ; | |
58 | : $config-w@ ( -- str$ ) " config-w@" ; | |
59 | : $config-w! ( -- str$ ) " config-w!" ; | |
60 | : $config-l@ ( -- str$ ) " config-l@" ; | |
61 | : $config-l! ( -- str$ ) " config-l!" ; | |
62 | ||
63 | fload ${BP}/dev/pci/make-device.fth | |
64 | fload ${BP}/dev/pci/make-path.fth | |
65 | ||
66 | [ifdef] OBERON? | |
67 | fload ${BP}/dev/oberon/opl/hwd.fth | |
68 | fload ${BP}/dev/oberon/opl/slot-names.fth | |
69 | [then] | |
70 | ||
71 | \ | |
72 | \ bridges need to be able to create some properties after the device | |
73 | \ has completed probing (available for example) this allows well-known | |
74 | \ devices to hook code into the point after any fcode will have completed. | |
75 | \ | |
76 | defer extra-device-function-hook | |
77 | ||
78 | : make-function-node ( arg$ reg$ -- ) | |
79 | new-device set-args ( ) | |
80 | populate-device-node ( ) | |
81 | extra-device-function-hook ( ) | |
82 | ['] noop to extra-device-function-hook ( ) | |
83 | [ifdef] OBERON? | |
84 | " okay" create-status-prop ( ) | |
85 | [then] | |
86 | finish-device ( ) | |
87 | ; | |
88 | ||
89 | \ | |
90 | \ --------------------------------------------------------------------- | |
91 | \ From here down all accesses are in the 'parents' instance, so we | |
92 | \ need to use self-X type words. Ie these routines are executing in | |
93 | \ a host adapter context (pci/pci bridge or host/pci device). | |
94 | ||
95 | : self-b@ ( phys.hi -- b ) $config-b@ $call-self ; | |
96 | : self-b! ( b phys.hi -- ) $config-b! $call-self ; | |
97 | : self-w@ ( phys.hi -- b ) $config-w@ $call-self ; | |
98 | : self-w! ( w phys.hi -- ) $config-w! $call-self ; | |
99 | : self-l@ ( phys.hi -- l ) $config-l@ $call-self ; | |
100 | : self-l! ( l phys.hi -- ) $config-l! $call-self ; | |
101 | ||
102 | : amend-reg$ ( reg$ func# -- reg$' ) | |
103 | push-hex | |
104 | >r ascii , left-parse-string ( rem$ head$ ) | |
105 | 2swap 2drop $hnumber if 0 then r> ( dev# func# ) | |
106 | <# u# drop ascii , hold u#s u#> function-reg-string $save | |
107 | pop-base | |
108 | ; | |
109 | ||
110 | \ Returns true if the card implements a function at the indicated | |
111 | \ configuration address. | |
112 | \ | |
113 | : function-present? ( phys.hi -- flag ) self-w@ h# ffff <> ; | |
114 | ||
115 | headers | |
116 | \ Create a string of the form "D,F" where D is the device number portion | |
117 | \ of the string "reg$" and F is the hexadecimal representation of "func#" | |
118 | \ Probe the card function func# | |
119 | : probe-function ( arg$ reg$ phys.hi fn# -- arg$ reg$ phys.hi ) | |
120 | 2dup fcn#>cfg + function-present? if ( arg$ reg$ phys.hi fn# ) | |
121 | 2>r 2over 2over ( arg$ reg$ arg$ reg$ ) | |
122 | r@ amend-reg$ ( arg$ reg$ arg$ reg$ ) | |
123 | make-function-node ( arg$ reg$ ) | |
124 | 2r> ( arg$ reg$ phys.hi fn# ) | |
125 | then drop ( arg$ reg$ phys.hi ) | |
126 | ; | |
127 | ||
128 | \ Returns 0 if the card isn't present, 8 for a multifunction card, 1 otherwise | |
129 | : max#functions ( phys.hi -- phys.hi n ) | |
130 | dup function-present? if ( phys.hi ) | |
131 | dup h# e + self-b@ ( phys.hi field ) | |
132 | h# 80 and if 8 else 1 then ( phys.hi n ) | |
133 | else ( phys.hi ) | |
134 | 0 ( phys.hi n ) | |
135 | then | |
136 | ; | |
137 | headerless | |
138 | ||
139 | \ Probe the card at the address given by fcode$, setting my-address, | |
140 | \ my-space in the resulting device node to the address given by reg$. | |
141 | \ | |
142 | \ probe-self is meant to handle one PCI device (= 1 physical slot) | |
143 | \ at a time. Up to 8 functions are checked per device. Each can have | |
144 | \ a separate piece of FCode controlling it. | |
145 | ||
146 | : clear-pci-errs ( phys.hi -- ) | |
147 | 6 + dup self-w@ ( stat-reg-addr data ) | |
148 | h# f900 and ( stat-reg-addr clr-err-bits ) | |
149 | swap self-w! ( -- ) | |
150 | ; | |
151 | ||
152 | : .nothing-there diagnostic-mode? if " Nothing there" cmn-append then ; | |
153 | ||
154 | \ This is the entry point into the ASR framework. | |
155 | \ Leave the dev#$ alone and return a flag of true | |
156 | \ if the device is disabled, otherwise false. | |
157 | \ If necessary, in the disabled? case, the dev#$ | |
158 | \ may be modified for printability. | |
159 | defer device-disabled? ( dev#$ -- dev#$' disabled? ) | |
160 | ' false is device-disabled? | |
161 | ||
162 | : .probing-path ( dev#$' flag -- dev#$' flag ) | |
163 | diagnostic-mode? if | |
164 | " Device " cmn-append 3dup drop cmn-append " " cmn-append | |
165 | then | |
166 | ; | |
167 | ||
168 | \ Defer word to be redefined differently at platform level | |
169 | defer pci-function-present? | |
170 | ' function-present? is pci-function-present? | |
171 | ||
172 | \ | |
173 | \ The pci-pci bridge probing code. | |
174 | \ | |
175 | : pci-probe-self ( args$ dev#$ -- ) | |
176 | ['] noop | |
177 | debug-bar-assignment? if drop ['] .dump-assigned-addr then | |
178 | to extra-device-function-hook | |
179 | true to probe-state? | |
180 | ||
181 | device-disabled? ( arg$ dev#$' flag ) | |
182 | .probing-path | |
183 | if 2drop 2drop ( ) | |
184 | diagnostic-mode? if " <Device/Slot Disabled>" cmn-append then | |
185 | exit | |
186 | then ( args$ dev#$ ) | |
187 | ||
188 | 2dup (decode-unit) nip nip ( args$ dev#$ phys.hi.dev ) | |
189 | dup pci-function-present? if ( args$ dev#$ phys.hi.dev ) | |
190 | max#functions ?dup if | |
191 | 0 do i probe-function loop ( args$ dev#$ phys.hi.dev ) | |
192 | else | |
193 | .nothing-there | |
194 | then | |
195 | else ( args$ dev#$ phys.hi.dev ) | |
196 | .nothing-there | |
197 | then ( args$ dev#$ phys.hi.dev ) | |
198 | ||
199 | 3drop 2drop ( ) | |
200 | false to probe-state? | |
201 | ; | |
202 | ||
203 | \ This is the top level prober. | |
204 | \ The maximum depth of 9 is to ensure that we don't overflow the | |
205 | \ return stack as we recurse. Better to not probe devices than | |
206 | \ to crash in some spectacular way. | |
207 | \ | |
208 | ||
209 | [ifdef] OBERON? | |
210 | ||
211 | : pci-prober-pass ( args$ dev#$ -- ) | |
212 | diagnostic-mode? if cmn-msg[ then | |
213 | pci-probe-self | |
214 | diagnostic-mode? if " " ]cmn-end then | |
215 | ; | |
216 | ||
217 | : pci-prober ( probe-list$adr,len -- ) | |
218 | \ Increase pci-depth to support iobox. | |
219 | pci-depth 9 > if | |
220 | ." Maximum PCI probe depth " pci-depth . ." exceeded; " | |
221 | ." No further PCI bridge devices can be probed" cr | |
222 | 2drop exit | |
223 | then | |
224 | oberon-debug? if cr ." pci-prober: pci-depth=" pci-depth .d cr then | |
225 | ||
226 | make-path$ if | |
227 | oberon-debug? if ." devpath=" .path$ then | |
228 | else | |
229 | cmn-warn[ " make-path$ failed" ]cmn-end | |
230 | 2drop exit | |
231 | then ( $adr,len ) | |
232 | ||
233 | pci-path count make-pcipath-id if | |
234 | cmn-warn[ " make-pcipath-id failed" ]cmn-end | |
235 | 2drop exit | |
236 | else | |
237 | oberon-debug? if ." (id=" dup 64.x ." ): " cr then | |
238 | -rot ( id $adr,len ) | |
239 | then | |
240 | oberon-debug? if ." probe-list$=" 2dup type cr then | |
241 | 2 pick create-pci-slot-names-prop ( id $adr,len ) | |
242 | select-hwdtab&get-hwdstat | |
243 | pci-depth dup >r 1+ to pci-depth ( id $adr,len ) ( R: old-pci-dpth ) | |
244 | begin dup while ( id $adr,len ) ( R: old-depth ) | |
245 | ascii , left-parse-string ( id rem$ dev#$ ) ( R: old-depth ) | |
246 | " " 2swap ( id rem$ arg$ dev#$ ) ( R: old-d ) | |
247 | ||
248 | push-hex 2dup $number drop pop-base ( id rem$ arg$ dev#$ dev# ) | |
249 | 7 pick ( id rem$ arg$ dev#$ dev# id ) | |
250 | get-hwd-status if HWDESC-STAT-UNKNOWN then ( id rem$ arg$ dev#$ hwd-stat ) | |
251 | case | |
252 | HWDESC-STAT-PASS of pci-prober-pass endof | |
253 | dup of 2drop 2drop endof | |
254 | endcase ( id rem$ ) | |
255 | repeat ( id null$ ) ( R: old-depth ) | |
256 | 3drop | |
257 | r> to pci-depth | |
258 | oberon-debug? if cr then | |
259 | ; | |
260 | ||
261 | [else] | |
262 | ||
263 | : pci-prober ( probe-list$adr,len -- ) | |
264 | pci-depth 9 > if | |
265 | ." Maximum PCI probe depth " pci-depth . ." exceeded;" | |
266 | ." No further PCI bridge devices can be probed" cr | |
267 | 2drop exit | |
268 | then | |
269 | pci-depth dup >r 1+ to pci-depth ( $adr,len ) ( R: old-pci-dpth ) | |
270 | ||
271 | begin dup while ( $adr,len ) ( R: old-depth ) | |
272 | ascii , left-parse-string ( rem$ dev#$ ) ( R: old-depth ) | |
273 | " " 2swap ( rem$ arg$ dev#$ ) ( R: old-d ) | |
274 | ||
275 | diagnostic-mode? if cmn-msg[ then | |
276 | ||
277 | pci-probe-self | |
278 | ||
279 | diagnostic-mode? if " " ]cmn-end then | |
280 | ||
281 | repeat ( null$ ) ( R: old-depth ) | |
282 | ||
283 | 2drop | |
284 | r> to pci-depth | |
285 | ; | |
286 | ||
287 | [then] | |
288 | ||
289 | : get-my-pci-bus# ( -- n ) " my-pci-bus" $call-self ; | |
290 | ||
291 | : pci-master-probe ( adr,len -- ) | |
292 | 0 to pci-depth | |
293 | ||
294 | \ If previously probed, we need to update current-bus# | |
295 | " bus-range" get-my-property 0= if | |
296 | decode-int nip nip to current-bus# | |
297 | else | |
298 | get-my-pci-bus# to current-bus# | |
299 | then | |
300 | ||
301 | " prober" $call-self | |
302 | get-my-pci-bus# bus#>cfg clear-pci-errs | |
303 | ||
304 | get-my-pci-bus# encode-int | |
305 | current-bus# encode-int encode+ " bus-range" property | |
306 | ; | |
307 | ||
308 | \ This is called twice for each PCI-PCI bridge, | |
309 | \ It is called with n=1 at the beginning of the bridge probing sequence, | |
310 | \ in order to allocate a new bus number and establish base address values. | |
311 | \ It is called with n=0 at the end of the bridge probing sequence, | |
312 | \ in order to determine the "high water marks" of the bus numbers and | |
313 | \ address ranges that were assigned during the (possibly recursive) | |
314 | \ bridge probing process. | |
315 | ||
316 | : trim-node ( node memlist align -- ) | |
317 | >r ( node memlist ) | |
318 | 2dup remove-selected-node drop ( node memlist ) | |
319 | 2dup r@ swap round-node-up ( node memlist ) | |
320 | r> swap round-node-down ( -- ) | |
321 | ; | |
322 | ||
323 | : .no-resource ( -- ) | |
324 | cmn-error[ " No resource available for bridge" ]cmn-end | |
325 | ; | |
326 | ||
327 | : allocate-biggest-resources ( list align -- node ) | |
328 | over get-biggest-node ( list align node ) | |
329 | dup 0= if ( list align node ) | |
330 | 3drop .no-resource abort | |
331 | then | |
332 | dup >r -rot trim-node r> ( node ) | |
333 | ; | |
334 | ||
335 | : allocate-actual-resources ( list align size -- node ) | |
336 | dup >r rot allocate-memrange if | |
337 | r> drop .no-resource abort | |
338 | else | |
339 | r> swap set-node ( node ) | |
340 | then ( node) | |
341 | ; | |
342 | ||
343 | : get-ranges ( mem-n mem64-n io-n -- mem-l mem64-l io-l mem-h mem64-h io-h ) | |
344 | 3dup >r >r >r alloc-bar-struct r> r> r> push-stack | |
345 | ( mem-n mem64-n io-n ) | |
346 | >r >r node-range over + ( mem-l mem-h ) | |
347 | ( R: io-n mem64-n ) | |
348 | r> ?dup if node-range over + else 0 0 then rot swap | |
349 | ( mem-l mem64-l mem-h mem64-h ) | |
350 | ( R: io-n ) | |
351 | r> node-range over + ( mem-l mem64-l mem-h mem64-h io-l io-h ) | |
352 | >r -rot r> ( mem-l mem64-l io-l mem-h mem64-h io-h ) | |
353 | ; | |
354 | ||
355 | \ If size is zero, acquire the largest available piece of the resource. | |
356 | : acquire-bridge-resources ( list align size -- node ) | |
357 | ?dup if | |
358 | allocate-actual-resources | |
359 | else | |
360 | allocate-biggest-resources | |
361 | then | |
362 | ; | |
363 | ||
364 | ||
365 | external | |
366 | ||
367 | \ | |
368 | \ This routine allows allocation of resources from the current IO/MEM lists. | |
369 | \ | |
370 | : resource-alloc ( physhi align size -- addr|0 ) | |
371 | rot cfg>ss# 7 and case | |
372 | 0 of 2drop false exit endof \ cannot claim cfg space | |
373 | 1 of pci-io-list endof | |
374 | 2 of pci-memlist endof | |
375 | 3 of mem64-support? if pci-mem64list else pci-memlist then endof | |
376 | endcase ( list ) | |
377 | allocate-memrange if false then ( addr|0 ) | |
378 | ; | |
379 | ||
380 | \ This routine returns a range to the relevant list. | |
381 | \ Be CAREFUL no checking is done to verify that an allocation from one | |
382 | \ pool is not returned to the other, nor that you are freeing more than | |
383 | \ you alloc'd. | |
384 | : resource-free ( physhi addr len -- ) | |
385 | rot cfg>ss# 7 and case | |
386 | 0 of 2drop exit endof \ cannot claim cfg space | |
387 | 1 of pci-io-list endof | |
388 | 2 of pci-memlist endof | |
389 | 3 of mem64-support? if pci-mem64list else pci-memlist then endof | |
390 | endcase ( list ) | |
391 | free-memrange ( ) | |
392 | ; | |
393 | ||
394 | headerless | |
395 | ||
396 | /n 3 * buffer: pci-alloc-lists | |
397 | : 3@ ( a-addr -- x1 x2 x3 ) dup >r @ r@ /n + @ r> /n 2* + @ ; | |
398 | : 3! ( x1 x2 x3 a-addr -- ) tuck /n 2* + ! tuck /n + ! ! ; | |
399 | ||
400 | : make-bridge-extra-properties ( -- ) | |
401 | \ Called after the bridge has been probed completely. | |
402 | \ The purpose of this routine is to create the 'available' property and | |
403 | \ then free the nodes. | |
404 | get-pointers >r >r >r >r ( ) ( R: io mem64 mem reg ) | |
405 | r@ pci-alloc-lists 3@ set-pointers ( ) ( R: io mem64 mem reg ) | |
406 | make-available-property ( ) ( R: io mem64 mem reg ) | |
407 | pci-alloc-lists 3@ debug-keep-mem-lists? if ( mem mem64 io ) | |
408 | ( R: io mem64 mem reg ) | |
409 | \ Some useful bridge debug properties. | |
410 | " io-list" integer-property ( mem mem64 ) | |
411 | ( R: io mem64 mem reg ) | |
412 | " mem64-list" integer-property ( mem ) ( R: io mem64 mem reg ) | |
413 | " mem-list" integer-property ( ) ( R: io mem64 mem reg ) | |
414 | else ( mem mem64 io ) | |
415 | ( R: io mem64 mem reg ) | |
416 | free-list free-list free-list ( ) ( R: io mem64 mem reg ) | |
417 | then ( ) ( R: io mem64 mem reg ) | |
418 | r> r> r> r> set-pointers ( ) ( R: ) | |
419 | ; | |
420 | ||
421 | : align-resource-list ( align list -- node ) | |
422 | dup get-last-node nip ( align list node ) | |
423 | dup if ( align list node ) | |
424 | tuck over remove-selected-node drop ( align node list ) | |
425 | swap dup >r -rot round-node-up r> ( node ) | |
426 | else ( align list node ) | |
427 | 3drop 0 ( 0 ) | |
428 | then | |
429 | ; | |
430 | ||
431 | \ If either of the node parameters is zero, this function will | |
432 | \ bypass the clause that "hands the resource back to the parent"; | |
433 | \ this behavior may be required for hotplug-capable bridges. | |
434 | : free-resources ( mem-n mem64-n io-n -- mem-l mem64-l io-l mem-h mem64-h io-h ) | |
435 | pop-stack ( mem-n mem64-n io-n reg mem mem64 io ) | |
436 | pci-alloc-lists 3! ( mem-n mem64-n io-n reg ) | |
437 | free-bar-struct ( mem-n mem64-n io-n ) | |
438 | ['] make-bridge-extra-properties ( mem-n mem64-n io-n acf ) | |
439 | to extra-device-function-hook ( mem-n mem64-n io-n ) | |
440 | \ When we get here we have removed the trailing resources | |
441 | \ from the bridge. Now we need to hand the resources back | |
442 | \ to the parent bridge. | |
443 | dup if ( mem-n mem64-n io-n ) | |
444 | dup node-range ( mem-n mem64-n io-n adr len ) | |
445 | 2dup pci-io-list free-memrange ( mem-n mem64-n io-n adr len ) | |
446 | drop swap free-node ( mem-n mem64-n io-h ) | |
447 | then ( mem-n mem64-n io-h ) | |
448 | >r dup if ( mem-n mem64-n ) ( R: io-h ) | |
449 | dup node-range ( mem-n mem64-n adr len ) ( R: io-h ) | |
450 | 2dup pci-mem64list free-memrange ( mem-n mem64-n adr len ) ( R: io-h ) | |
451 | drop swap free-node ( mem-n mem64-h ) ( R: io-h ) | |
452 | then ( mem-n mem64-h ) ( R: io-h ) | |
453 | >r dup if ( mem-n ) ( R: io-h mem64-h ) | |
454 | dup node-range ( mem-n adr len ) ( R: io-h mem64-h ) | |
455 | 2dup pci-memlist free-memrange ( mem-n adr len ) ( R: io-h mem64-h ) | |
456 | drop swap free-node ( mem-h ) ( R: io-h mem64-h ) | |
457 | then ( mem-h ) ( R: io-h mem64-h ) | |
458 | >r 0 0 0 r> r> r> ( mem-l mem64-l io-l mem-h mem64-h io-h ) | |
459 | ; | |
460 | ||
461 | [ifndef] PCIHOTPLUG? | |
462 | \ If the "size" element of the I/O- or Memory- parameter-pair is zero, | |
463 | \ the I/O or Memory resource will be aligned as given and the unused | |
464 | \ resource will be "handed back to the parent". | |
465 | \ | |
466 | \ If "size" is non-zero, then drop the alignment and bypass the call | |
467 | \ to the align-resource-list routine; instead, pass a node-pointer | |
468 | \ of zero to the free-resources routine, so that it will bypass | |
469 | \ the clause that "hands the resource back to the parent", which is | |
470 | \ a behavior that may be required for hotplug-capable bridges. | |
471 | \ | |
472 | \ The "io-n" and "mem-n" notations in the stack-diagrams refer to | |
473 | \ nodes from the pci-io-list or pci-memlist , respectively. | |
474 | \ | |
475 | : release-bridge-resources | |
476 | ( mem-aln mem-sz mem64-aln mem64-sz io-aln io-sz -- mem-l mem64-l io-l mem-h mem64-h io-h ) | |
477 | if ( mem-aln mem-sz mem64-aln mem64-sz io-aln ) | |
478 | drop 0 ( mem-aln mem-sz mem64-aln mem64-sz 0 ) | |
479 | else ( mem-aln mem-sz mem64-aln mem64-sz io-aln ) | |
480 | pci-io-list align-resource-list | |
481 | ( mem-aln mem-sz mem64-aln mem64-sz io-n ) | |
482 | then ( mem-aln mem-sz mem64-aln mem64-sz io-n ) | |
483 | >r ( mem-aln mem-sz mem64-aln mem64-sz ) | |
484 | ( R: io-n ) | |
485 | mem64-support? if ( mem-aln mem-sz mem64-aln mem64-sz ) ( R: io-n ) | |
486 | x0<> if ( mem-aln mem-sz mem64-aln ) ( R: io-n ) | |
487 | drop 0 ( mem-aln mem-sz 0 ) ( R: io-n ) | |
488 | else ( mem-aln mem-sz mem64-aln ) ( R: io-n ) | |
489 | pci-mem64list align-resource-list | |
490 | ( mem-aln mem-sz mem64-n ) ( R: io-n ) | |
491 | then ( mem-aln mem-sz mem64-n ) ( R: io-n ) | |
492 | else ( mem-aln mem-sz mem64-aln mem64-sz ) ( R: io-n ) | |
493 | 2drop 0 ( mem-aln mem-sz 0 ) ( R: io-n ) | |
494 | then | |
495 | >r ( mem-aln mem-sz ) ( R: io-n mem64-n ) | |
496 | if ( mem-aln ) ( R: io-n mem64-n ) | |
497 | drop 0 ( 0 ) ( R: io-n mem64-n ) | |
498 | else ( mem-aln ) ( R: io-n mem64-n ) | |
499 | pci-memlist align-resource-list | |
500 | ( mem-n ) ( R: io-n mem64-n ) | |
501 | then ( mem-n ) ( R: io-n mem64-n ) | |
502 | r> r> free-resources ( mem-l mem64-l io-l mem-hi mem64-hi io-hi ) | |
503 | ; | |
504 | ||
505 | [else] | |
506 | \ Extend bridge upper range. | |
507 | \ upper-limit : bridge upper range | |
508 | \ node : last node in the bridge resource list | |
509 | \ list : bridge resource list | |
510 | : extend-bridge-range ( upper-limit node list -- node ) | |
511 | >r split-node ( prev next ) | |
512 | 2dup <> if ( prev next ) | |
513 | swap node-range r> free-memrange ( next ) | |
514 | else | |
515 | r> 2drop ( prev ) | |
516 | then | |
517 | ; | |
518 | \ This is a hotplug enabled release resource routine. Here | |
519 | \ if the "size" element of the I/O- or Memory- parameter-pair is zero, | |
520 | \ the I/O or Memory resource will be aligned as given and the unused | |
521 | \ resource will be "handed back to the parent". | |
522 | \ | |
523 | \ If "size" is non-zero, then that gives the upper limit | |
524 | \ to which the bridge range needs to be extended to handle | |
525 | \ hotplug resource requirement. For hotplug-capable bridges | |
526 | \ "size" passed is non-zero. In this case, the upper address | |
527 | \ range is extended to what is specified in "size" and the | |
528 | \ rest of what is left is returned to the parent. | |
529 | \ | |
530 | \ The "io-n" and "mem-n" notations in the stack-diagrams refer to | |
531 | \ nodes from the pci-io-list or pci-memlist , respectively. | |
532 | \ | |
533 | : release-bridge-resources | |
534 | ( mem-aln mem-sz mem64-aln mem64-sz io-aln io-sz -- mem-l mem64-l io-l mem-h mem64-h io-h ) | |
535 | ?dup if ( mem-aln mem-sz mem64-aln mem64-sz io-aln io-sz ) | |
536 | swap pci-io-list align-resource-list | |
537 | ( mem-aln mem-sz mem64-aln mem64-sz io-sz io-n ) | |
538 | pci-io-list extend-bridge-range | |
539 | ( mem-aln mem-sz mem64-aln mem64-sz io-n' ) | |
540 | else ( mem-aln mem-sz mem64-aln mem64-sz io-aln ) | |
541 | pci-io-list align-resource-list | |
542 | ( mem-aln mem-sz mem64-aln mem64-sz io-n ) | |
543 | then ( mem-aln mem-sz mem64-aln mem64-sz io-n ) | |
544 | >r ( mem-aln mem-sz mem64-aln mem64-sz ) ( R: io-n ) | |
545 | mem64-support? if \ host-bridge supports mem64 space | |
546 | ?dup x0<> if ( mem-aln mem-sz mem64-aln mem64-sz ) ( R: io-n ) | |
547 | swap pci-mem64list align-resource-list | |
548 | ( mem-aln mem-sz mem64-sz mem64-n ) ( R: io-n ) | |
549 | pci-mem64list extend-bridge-range | |
550 | ( mem-aln mem-sz mem64-n' ) ( R: io-n ) | |
551 | else | |
552 | ( mem-aln mem-sz mem64-aln ) ( R: io-n ) | |
553 | pci-mem64list align-resource-list | |
554 | ( mem-aln mem-sz mem64-n ) ( R: io-n ) | |
555 | then ( mem-aln mem-sz mem64-n ) ( R: io-n ) | |
556 | else \ host-bridge does not support mem64 space | |
557 | 2drop 0 ( mem-aln mem-sz mem64-n ) ( R: io-n ) | |
558 | then | |
559 | >r ( mem-aln mem-sz ) ( R: io-n mem64-n ) | |
560 | ?dup if ( mem-aln mem-sz ) ( R: io-n mem64-n ) | |
561 | swap pci-memlist align-resource-list | |
562 | ( mem-sz mem-n ) ( R: io-n mem64-n ) | |
563 | pci-memlist extend-bridge-range | |
564 | ( mem-n' ) ( R: io-n mem64-n ) | |
565 | else ( mem-aln ) ( R: io-n mem64-n ) | |
566 | pci-memlist align-resource-list | |
567 | ( mem-n ) ( R: io-n mem64-n ) | |
568 | then ( mem-n ) ( R: io-n mem64-n ) | |
569 | r> r> ( mem-n mem64-n io-n ) ( R: ) | |
570 | free-resources ( mem-l mem64-l io-l mem-h mem64-h io-h ) | |
571 | ; | |
572 | [then] | |
573 | ||
574 | : get-dma-range ( -- dma-l dma-h ) | |
575 | " virtual-dma" get-inherited-property 0= if | |
576 | decode-int -rot decode-int nip nip ( dma-l dma-size ) | |
577 | over + ( dma-l dma-h ) | |
578 | else ( ) | |
579 | h# 8000.0000 dup h# 7fff.ffff + ( dma-l dma-h ) | |
580 | then ( dma-l dma-h ) | |
581 | ; | |
582 | ||
583 | [ifndef] PCIHOTPLUG? | |
584 | \ The behavior of this routine changes significantly with variations | |
585 | \ in its parameters: | |
586 | \ | |
587 | \ A non-zero n specifies the acquire-bridge-resources path. | |
588 | \ This means: | |
589 | \ (A) | |
590 | \ A non-zero "size" element of the I/O- or Memory- parameter-pair | |
591 | \ specifies the size of the I/O or Memory resource to acquire; | |
592 | \ a zero "size" specifies acquiring the largest available piece | |
593 | \ of the I/O or Memory resource. | |
594 | \ (B) | |
595 | \ The bus# returned should be one more than current-bus# at | |
596 | \ the time this routine was entered, and current-bus# should | |
597 | \ be incremented by n for the next time 'round. | |
598 | \ | |
599 | \ An n of zero specifies the release-bridge-resources path. | |
600 | \ This means: | |
601 | \ (A) | |
602 | \ The I/O- and Memory- parameter-pairs are passed directly to | |
603 | \ the release-bridge-resources routine (which see). | |
604 | \ (B) | |
605 | \ The bus# returned should be current-bus# , and current-bus# | |
606 | \ should remain unchanged. | |
607 | \ | |
608 | : pci-allocate-bus# ( n m-aln m-sz m64-aln m64-sz io-aln io-sz -- ...... ) | |
609 | ( ..... -- mem-lo mem64-lo io-lo dma-lo mem-hi mem64-hi io-hi dma-hi bus# ) | |
610 | current-bus# >r ( n m-aln m-sz m64-aln m64-sz io-aln io-sz ) | |
611 | ( R: cbus ) | |
612 | 2>r 2>r 2>r ( n ) | |
613 | ( R: cbus io-aln io-sz m64-aln m64-sz m-aln m-sz ) | |
614 | ?dup if ( n ) ( R: cbus io-aln io-sz m64-aln m64-sz m-aln m-sz ) | |
615 | current-bus# + to current-bus# | |
616 | ( ) ( R: cbus io-aln io-sz m64-aln m64-sz m-aln m-sz ) | |
617 | pci-memlist 2r> acquire-bridge-resources | |
618 | ( mem-n ) ( R: cb io-aln io-sz m64-aln m64-sz ) | |
619 | mem64-support? if \ host-bridge supports mem64 space | |
620 | ( mem-n ) ( R: cb io-aln io-sz m64-aln m64-sz ) | |
621 | pci-mem64list 2r> acquire-bridge-resources | |
622 | ( mem-n mem64-n ) ( R: cb io-aln io-sz ) | |
623 | else \ host-bridge does not support mem64 space | |
624 | ( mem-n ) ( R: cb io-aln io-sz m64-aln m64-sz ) | |
625 | 2r> 2drop 0 | |
626 | ( mem-n mem64-n ) ( R: cb io-aln io-sz ) | |
627 | then | |
628 | pci-io-list 2r> acquire-bridge-resources | |
629 | ( mem-node mem64-node io-node ) ( R: cbus ) | |
630 | get-ranges | |
631 | ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) ( R: cbus ) | |
632 | r> 1+ >r ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) ( R: bus# ) | |
633 | else ( ) ( R: bus# io-aln io-sz m64-aln m64-sz m-aln m-sz ) | |
634 | 2r> 2r> 2r> | |
635 | ( m-aln m-sz m64-aln m64-sz io-aln io-sz ) ( R: bus# ) | |
636 | release-bridge-resources | |
637 | ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) ( R: bus# ) | |
638 | then ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) ( R: bus# ) | |
639 | get-dma-range | |
640 | ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi dma-lo dma-hi ) | |
641 | ( R: bus# ) | |
642 | >r swap >r swap >r swap r> r> r> | |
643 | ( mem-lo mem64-lo io-lo dma-lo mem-hi mem64-hi io-hi dma-hi ) | |
644 | ( R: bus# ) | |
645 | r> ( mem-lo mem64-lo io-lo dma-lo mem-hi mem64-hi io-hi dma-hi bus# ) | |
646 | ; | |
647 | ||
648 | [else] | |
649 | \ This is a hotplug enabled allocation routine. | |
650 | \ Here a non-zero n specifies the release-bridge-resource path. | |
651 | \ if n = -1, it implies non hotplug bridge and hence all the resources | |
652 | \ are returned to the parent node. | |
653 | \ if n <> -1, then it implies the request is coming from a hotplug capable | |
654 | \ bridge and "n" represents the minimum upper limit of the bus-range | |
655 | \ for this bridge. Note that in this case mem-hi and io-hi | |
656 | \ represent the upper watermark for memory window and io space | |
657 | \ window for this bridge. | |
658 | \ | |
659 | \ A zero value of n specifies the allocate-bridge-resource path here. | |
660 | \ And there is no change as compared to legacy code here. It still allocates | |
661 | \ a large resource window for the bridge which is needed when pci code | |
662 | \ starts probing the children of the bridge. | |
663 | \ | |
664 | : pci-allocate-bus# ( n m-aln m-sz mem64-aln mem64-sz io-aln io-sz -- ...... ) | |
665 | ( ..... -- mem-lo mem64-lo io-lo dma-lo mem-hi mem64-hi io-hi dma-hi bus# ) | |
666 | current-bus# >r ( n m-aln m-sz io-aln io-sz ) ( R: cbus ) | |
667 | 2>r 2>r 2>r ( n ) | |
668 | ( R: cbus io-aln io-sz mem64-aln mem64-sz m-aln m-sz ) | |
669 | ?dup 0= if ( ) | |
670 | ( R: cbus io-aln io-sz mem64-aln mem64-sz m-aln m-sz ) | |
671 | current-bus# 1+ to current-bus# | |
672 | ( ) | |
673 | ( R: cbus io-aln io-sz mem64-aln mem64-sz m-aln m-sz ) | |
674 | pci-memlist 2r> acquire-bridge-resources | |
675 | ( mem-n ) ( R: cb io-aln io-sz mem64-aln mem64-sz ) | |
676 | mem64-support? if \ host-bridge supports mem64 space | |
677 | ( mem-n ) ( R: cb io-aln io-sz m64-aln m64-sz ) | |
678 | pci-mem64list 2r> acquire-bridge-resources | |
679 | ( mem-n mem64-n ) ( R: cb io-aln io-sz ) | |
680 | else \ host-bridge does not support mem64 space | |
681 | ( mem-n ) ( R: cb io-aln io-sz m64-aln m64-sz ) | |
682 | 2r> 2drop 0 | |
683 | ( mem-n mem64-n ) ( R: cb io-aln io-sz ) | |
684 | then | |
685 | pci-io-list 2r> acquire-bridge-resources | |
686 | ( mem-node mem64-node io-node ) ( R: cbus ) | |
687 | get-ranges ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
688 | ( R: cbus ) | |
689 | r> 1+ >r ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
690 | ( R: bus# ) | |
691 | else ( n ) ( R: bus# io-aln io-sz m-aln m-sz ) | |
692 | 2r> 2r> 2r> ( n m-aln m-sz m64-aln m64-sz io-aln io-sz ) | |
693 | ( R: bus# ) | |
694 | release-bridge-resources | |
695 | ( n mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
696 | ( R: bus# ) | |
697 | 6 roll ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi n ) | |
698 | ( R: bus# ) | |
699 | dup -1 = if ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi n ) | |
700 | ( R: bus# ) | |
701 | drop ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
702 | ( R: bus# ) | |
703 | else ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi n ) | |
704 | ( R: bus# ) | |
705 | \ if <> -1, then n is upper bus number for the hotplug capable bridge | |
706 | r> max dup >r is current-bus# | |
707 | ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
708 | ( R: bus# ) | |
709 | then ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
710 | ( R: bus# ) | |
711 | then ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi ) | |
712 | ( R: bus# ) | |
713 | get-dma-range ( mem-lo mem64-lo io-lo mem-hi mem64-hi io-hi dma-lo dma-hi ) | |
714 | ( r: bus# ) | |
715 | >r swap >r swap >r swap >r ( mem-lo mem64-lo io-lo dma-lo ) | |
716 | ( r: bus# dma-hi io-hi mem64-hi mem-hi ) | |
717 | r> r> r> r> r> ( mem-lo mem64-lo io-lo dma-lo mem-hi mem64-hi io-hi dma-hi bus# ) | |
718 | ( r: ) | |
719 | ; | |
720 | [then] | |
721 | ||
722 | fload ${BP}/dev/pci/map.fth | |
723 | fload ${BP}/dev/pci/unit.fth | |
724 |