Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / usb / endpointmap.fth
CommitLineData
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 ============================================
42id: @(#)endpointmap.fth 1.9 98/03/17
43purpose:
44copyright: 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-
48struct
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.
99d# 63 constant isoc-id
100d# 64 constant control-id
101d# 65 constant bulk-id
102
103d# 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
2940 value dummy-endpoints
2950 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;