Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: endpointmap.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: @(#)endpointmap.fth 1.9 98/03/17 | |
43 | purpose: | |
44 | copyright: Copyright 1997 Sun Microsystems, Inc. All Rights Reserved | |
45 | ||
46 | \ XXX need to re-do this, as the fields may not line up correctly for | |
47 | \ @ and ! especially for-controller, ping- and pong- | |
48 | struct | |
49 | 4 field endpoint-control | |
50 | 4 field td-tail | |
51 | 4 field td-head | |
52 | 4 field next-endpoint | |
53 | /n field prev-endpoint \ used by software only, virt | |
54 | \ 0 means first on q | |
55 | /n field q-id \ this endpoint is on the q q-id | |
56 | 4 field dummy? \ false if this is a real endpoint | |
57 | \ These next 3 fields are dependent on being in this order and together: | |
58 | /n field for-controller \ 0 if reply distributor puts | |
59 | \ transfer descriptors on ping-q, | |
60 | \ /n if distributor puts onto pong-q. | |
61 | /n field ping-done-q \ 0 if no transfer-d's here, virt | |
62 | /n field pong-done-q \ ditto | |
63 | \ /n field caller-buf | |
64 | /n field caller-len | |
65 | /n field interrupt-buf \ used for interrupt transfers, virt | |
66 | /n field transfer-count \ number of real transfer d's outstanding | |
67 | h# 10 over h# 10 mod - \ pad to next 16 byte boundary | |
68 | field endpad | |
69 | ||
70 | ( endpoint descrip. size ) constant /endpoint | |
71 | ||
72 | \ XXX The above allocation wastes a dictionary entry for endpad and 16 bytes | |
73 | \ of space if the other fields add up to 0 mod 16. Can save the dict. space | |
74 | \ by pushing calculation into the size of transfer-count | |
75 | ||
76 | \ q-id above is needed so that if a transfer descriptor on the done q shows | |
77 | \ an error which requires flushing other descriptors for its endpoint, and | |
78 | \ the endpoint has no transfer descriptors left after flushing, and hence | |
79 | \ the endpoint should be pulled off the q, the software can figure out | |
80 | \ which code should be used to pull the endpoint off the q. | |
81 | ||
82 | \ dummy? above is needed to help figuring out the ends of the interrupt q's | |
83 | \ more easily, instead of checking whether a particular address of an | |
84 | \ endpoint is actually the start of the next q. | |
85 | ||
86 | \ ping-done-q and pong-done-q, with for-controller, are used as done q's for | |
87 | \ this endpoint. The reply distributor code moves transfer descriptors from | |
88 | \ the done q of the controller to (only) one of these endpoint done q's. | |
89 | \ The endpoint reply processing code takes transfer descriptors from the | |
90 | \ other ping-pong done q. This avoids a race condition between the distributor | |
91 | \ code and the processing code. | |
92 | \ ping- and pong-done-q hold virtual addresses. The transfer descriptors | |
93 | \ themselves are linked via the next-transfer field, which holds dev addresses, | |
94 | \ little endian. | |
95 | ||
96 | \ transfer-count does not include the dummy transfer-d. | |
97 | ||
98 | \ 0-3e (0-62) are interrupt q id's. | |
99 | d# 63 constant isoc-id | |
100 | d# 64 constant control-id | |
101 | d# 65 constant bulk-id | |
102 | ||
103 | d# 66 constant #dummy-qs | |
104 | ||
105 | : isoc-endpoint? ( e-addr -- isoc? ) | |
106 | endpoint-control le-l@ h# 8000 and | |
107 | ; | |
108 | ||
109 | : dummy-endpoint? ( e-addr -- dummy? ) dummy? l@ ; | |
110 | ||
111 | : halted? ( e-addr -- halted? ) td-head le-l@ 1 and ; | |
112 | ||
113 | : end-toggle ( e-addr -- toggle ) td-head le-l@ 2 and 1 rshift ; | |
114 | ||
115 | : skip-endp ( e-addr -- ) | |
116 | endpoint-control dup le-l@ | |
117 | h# 4000 or | |
118 | swap le-l! | |
119 | ; | |
120 | ||
121 | : unskip-endp ( e-addr -- ) | |
122 | endpoint-control dup le-l@ | |
123 | h# 4000 invert and | |
124 | swap le-l! | |
125 | ; | |
126 | ||
127 | \ Need to leave some td-tail bits alone: | |
128 | : td-tail@ ( e-addr -- td-tail ) td-tail le-l@ h# f invert and ; | |
129 | ||
130 | : td-tail! ( n e-addr -- ) | |
131 | td-tail tuck le-l@ h# f and or | |
132 | swap le-l! | |
133 | ; | |
134 | ||
135 | \ Need to leave some td-head bits alone: | |
136 | : td-head@ ( e-addr -- n ) td-head le-l@ h# f invert and ; | |
137 | ||
138 | : td-head! ( n e-addr -- ) | |
139 | td-head tuck le-l@ h# f and or | |
140 | swap le-l! | |
141 | ; | |
142 | ||
143 | \ Need to leave some next-endpoint bits alone: | |
144 | : next-endpoint@ ( e-addr -- n ) next-endpoint le-l@ h# f invert and ; | |
145 | ||
146 | : next-endpoint! ( n e-addr -- ) | |
147 | next-endpoint tuck le-l@ h# f and or | |
148 | swap le-l! | |
149 | ; | |
150 | ||
151 | : empty-endp? ( e-addr -- empty? ) | |
152 | dup td-tail@ swap td-head@ = | |
153 | ; | |
154 | ||
155 | : stopped? ( e-addr -- empty?-or-halted? ) | |
156 | dup empty-endp? | |
157 | swap halted? or | |
158 | ; | |
159 | ||
160 | : code-done-q ( endpoint -- q-head ) | |
161 | dup ping-done-q swap for-controller @ /n - abs + | |
162 | ; | |
163 | ||
164 | : ping-pong ( endpoint -- ) | |
165 | dup for-controller @ | |
166 | /n - abs | |
167 | swap for-controller ! | |
168 | ; | |
169 | ||
170 | \ XXX the endpoints/transfers can't have a device address of 0, or the | |
171 | \ chip won't function correctly when traversing the q's. The code to detect | |
172 | \ q ends won't work either. | |
173 | ||
174 | \ XXX the various queued descriptors have alignment restrictions | |
175 | ||
176 | \ 63 dummy interrupt endpoint descriptors are arranged so that the | |
177 | \ next-endpoint fields hook them together in a tree. See ohci 3.3.2, | |
178 | \ figure 3-4. These are marked SKIP. There are no transfer descriptors, | |
179 | \ since they will never be activated. When a real interrupt endpoint is | |
180 | \ desired, it is hooked into the interrupt tree after the dummy endpoint at | |
181 | \ a spot for its interrupt interval. The dummies remain on the tree. They | |
182 | \ use q-ids 0 through 62. They are each considered to be head of q, so | |
183 | \ prev-endpoint is 0 for each of them. | |
184 | ||
185 | \ Level 1 of the tree is directly connected to the interrupt slots in hcca, | |
186 | \ dummies 0 thru 31. Level 2 of the tree (dummies 32 thru 47) is connected | |
187 | \ to level 1 dummies. Level 3 (dummies 48 thru 55) is connected to level 2. | |
188 | \ Level 4 (dummies 56 thru 59) is connected to level 3. Level 5 (dummies 60 | |
189 | \ thru 61) is connected to level 4, and level 6 (dummy 62) is connected to | |
190 | \ level 5. The dummies are connected so as to space the times for each | |
191 | \ entry of each level evenly through the 32 millisecond round robin cycle | |
192 | \ of periodic frame processing. | |
193 | ||
194 | \ Interrupt endpoints on level 1 are processed once per 32 msec. Level 2 | |
195 | \ endpoints are processed once per 16 msec. Level 3 endpoints are processed | |
196 | \ once per 8 msec. Level 4 endpoints go once per 4 msec. Level 5 endpoints | |
197 | \ run once per 2 msec, and level 6 endpoints run every msec. | |
198 | ||
199 | \ Connection algorithm: | |
200 | \ Start with level 1 -- dummies 0 thru 31. Each is connected to the same | |
201 | \ number slot in the interrupt table as its q-id. | |
202 | \ Each is connected to a dummy in level 2 whose q-id is determined thus: | |
203 | \ 1. change bit 4 of its q-id to 0. | |
204 | \ 2. change bit 5 of its q-id to 1. | |
205 | \ Each level 2 dummy is connected to a level 3 dummy whose q-id is determined: | |
206 | \ 1. change bit 3 of its q-id to 0. | |
207 | \ 2. change bit 4 of its q-id to 1. | |
208 | \ Connect all level 3 dummies to level 4 dummies: | |
209 | \ 1. change bit 2 of the q-id to 0. | |
210 | \ 2. change bit 3 of the q-id to 1. | |
211 | \ Level 4 dummies connect to level 5 dummies: | |
212 | \ 1. change bit 1 of the q-id to 0. | |
213 | \ 2. change bit 2 of the q-id to 1. | |
214 | \ Connect both level 5 dummies to level 6: | |
215 | \ 1. change bit 0 of the q-id to 0. | |
216 | \ 2. change bit 1 of the q-id to 1. | |
217 | ||
218 | \ 0\ | |
219 | \ 32\ | |
220 | \ 16/ \ | |
221 | \ 48\ | |
222 | \ 8\ / \ | |
223 | \ 40/ \ | |
224 | \ 24/ \ | |
225 | \ 56\ | |
226 | \ 4\ / \ | |
227 | \ 36\ / \ | |
228 | \ 20/ \ / | | |
229 | \ 52/ | | |
230 | \ 12\ / | | |
231 | \ 44/ | | |
232 | \ 28/ | | |
233 | \ 60\ | |
234 | \ 2\ | \ | |
235 | \ 34\ | \ | |
236 | \ 18/ \ | | | |
237 | \ 50\ | | | |
238 | \ 10\ / \ | | | |
239 | \ 42/ \ / | | |
240 | \ 26/ \ / | | |
241 | \ 58/ | | |
242 | \ 6\ / | | |
243 | \ 38\ / | | |
244 | \ 22/ \ / | | |
245 | \ 54/ | | |
246 | \ 14\ / | | |
247 | \ 46/ | | |
248 | \ 30/ | | |
249 | \ 62 | |
250 | \ 1\ | | |
251 | \ 33\ | | |
252 | \ 17/ \ | | |
253 | \ 49\ | | |
254 | \ 9\ / \ | | |
255 | \ 41/ \ | | |
256 | \ 25/ \ | | |
257 | \ 57\ | | |
258 | \ 5\ / \ | | |
259 | \ 37\ / \ | | |
260 | \ 21/ \ / | | | |
261 | \ 53/ | | | |
262 | \ 13\ / | | | |
263 | \ 45/ | / | |
264 | \ 29/ | / | |
265 | \ 61/ | |
266 | \ 3\ | | |
267 | \ 35\ | | |
268 | \ 19/ \ | | |
269 | \ 51\ | | |
270 | \ 11\ / \ | | |
271 | \ 43/ \ / | |
272 | \ 27/ \ / | |
273 | \ 59/ | |
274 | \ 7\ / | |
275 | \ 39\ / | |
276 | \ 23/ \ / | |
277 | \ 55/ | |
278 | \ 15\ / | |
279 | \ 47/ | |
280 | \ 31/ | |
281 | ||
282 | \ XXX code to balance the tree is desired. | |
283 | ||
284 | \ The control, bulk, and isochronous q's each have one dummy start endpoint | |
285 | \ descriptor that has no transfer descriptors. Each dummy is marked with | |
286 | \ SKIP. Each is considered to be head of q, so prev-endpoint is 0. | |
287 | ||
288 | \ The isoc q dummy hooks onto the end of interrupt q 62. It is marked as | |
289 | \ isochronous endpoint format. | |
290 | ||
291 | \ XXX Bandwidth problems or chip problems may require going back to the | |
292 | \ earlier q style, with no dummy q heads. | |
293 | ||
294 | 0 value dummy-endpoints | |
295 | 0 value dev-dummy-endpoints | |
296 | /endpoint #dummy-qs * constant /dummies | |
297 | ||
298 | : sync-dummies ( -- ) sync-mem ; | |
299 | ||
300 | \ The interrupt dummies come first: | |
301 | : interrupt-dummy ( q-id -- addr ) /endpoint * dummy-endpoints + ; | |
302 | ||
303 | : dev-interrupt-dummy ( q-id -- devaddr ) | |
304 | /endpoint * dev-dummy-endpoints + | |
305 | ; | |
306 | ||
307 | ||
308 | : isoc-dummy ( -- addr ) isoc-id interrupt-dummy ; | |
309 | ||
310 | : dev-isoc-dummy ( -- devaddr ) isoc-id dev-interrupt-dummy ; | |
311 | ||
312 | : control-dummy ( -- addr ) control-id interrupt-dummy ; | |
313 | ||
314 | : dev-control-dummy ( -- devaddr ) control-id dev-interrupt-dummy ; | |
315 | ||
316 | : bulk-dummy ( -- addr ) bulk-id interrupt-dummy ; | |
317 | ||
318 | : dev-bulk-dummy ( -- devaddr ) bulk-id dev-interrupt-dummy ; | |
319 | ||
320 | ||
321 | : plugdummy ( devaddr q-id -- ) | |
322 | interrupt-dummy next-endpoint le-l! | |
323 | ; | |
324 | ||
325 | \ XXX could use two nested loops, passing in the level to a common routine: | |
326 | : getnext1 ( q-id -- devaddr ) \ devaddr of next for level 1 of int dummies | |
327 | h# 10 invert and h# 20 or dev-interrupt-dummy | |
328 | ; | |
329 | ||
330 | : getnext2 ( q-id -- devaddr ) | |
331 | 8 invert and h# 10 or dev-interrupt-dummy | |
332 | ; | |
333 | ||
334 | : getnext3 ( q-id -- devaddr ) | |
335 | 4 invert and 8 or dev-interrupt-dummy | |
336 | ; | |
337 | ||
338 | : getnext4 ( q-id -- devaddr ) | |
339 | 2 invert and 4 or dev-interrupt-dummy | |
340 | ; | |
341 | ||
342 | : getnext5 ( q-id -- devaddr ) | |
343 | 1 invert and 2 or dev-interrupt-dummy | |
344 | ; | |
345 | ||
346 | : connect-dummies ( -- ) \ connect the interrupt dummies into a tree | |
347 | d# 32 0 do \ connect 1st to 2nd level | |
348 | i getnext1 i plugdummy | |
349 | loop | |
350 | d# 48 d# 32 do \ connect 2nd to 3rd level | |
351 | i getnext2 i plugdummy | |
352 | loop | |
353 | d# 56 d# 48 do \ connect 3rd to 4th level | |
354 | i getnext3 i plugdummy | |
355 | loop | |
356 | d# 60 d# 56 do \ connect 4th to 5th level | |
357 | i getnext4 i plugdummy | |
358 | loop | |
359 | d# 62 d# 60 do \ connect 5th to 6th level | |
360 | i getnext5 i plugdummy | |
361 | loop | |
362 | dev-isoc-dummy d# 62 plugdummy \ connect isoc dummy to int 62 | |
363 | ; | |
364 | ||
365 | : skip-dummies ( -- ) \ mark dummies to be skipped | |
366 | dummy-endpoints dummy? \ mark as dummies | |
367 | #dummy-qs 0 do | |
368 | true over l! /endpoint + | |
369 | loop drop | |
370 | dummy-endpoints endpoint-control \ mark to be skipped | |
371 | #dummy-qs 0 do | |
372 | h# 4000 over le-l! /endpoint + | |
373 | loop drop | |
374 | h# c000 isoc-dummy endpoint-control le-l! \ mark isoc q head format | |
375 | ; | |
376 | ||
377 | : name-dummies ( -- ) \ set q-ids | |
378 | dummy-endpoints q-id | |
379 | #dummy-qs 0 do | |
380 | i over ! /endpoint + | |
381 | loop drop | |
382 | ; | |
383 | ||
384 | : make-dummies ( -- ) | |
385 | /dummies get-chunk to dummy-endpoints | |
386 | dummy-endpoints virt>dev to dev-dummy-endpoints | |
387 | skip-dummies | |
388 | connect-dummies | |
389 | name-dummies | |
390 | sync-dummies | |
391 | ; | |
392 | ||
393 | : dump-dummies ( -- ) | |
394 | -1 to dev-dummy-endpoints | |
395 | dummy-endpoints /dummies give-chunk | |
396 | -1 to dummy-endpoints | |
397 | ; | |
398 | ||
399 | ||
400 | \ : dev-dummy? ( dev-addr -- dev-dummy? ) \ true if a dummy dev addr. | |
401 | \ dev-dummy-endpoints /dummies bounds swap between | |
402 | \ ; | |
403 | ||
404 | : dummydev>virt ( dev-addr -- virt ) \ for dummies | |
405 | dev>virt | |
406 | ; |