Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / usb / distributor.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: distributor.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: @(#)distributor.fth 1.11 02/03/12
43purpose:
44copyright: Copyright 1997-2000, 2002 Sun Microsystems, Inc. All Rights Reserved
45copyright: Use is subject to license terms.
46
47: end-of-line ( first-transfer -- last-transfer )
48 begin
49 dup next-transfer le-l@
50 while
51 next-transfer le-l@ dev>virt
52 repeat
53;
54
55: add-to-line ( transfer-d last-transfer -- )
56 swap virt>dev swap next-transfer le-l!
57;
58
59\ Put on done q in the same order as they show up on the controller done-q.
60\ Stored on the endpoint done-q's as dev addresses, little endian, because
61\ we reuse next-transfer to tie the q together, just as the other q's.
62\ Could change to use a different field and virt addresses.
63\ Don't need to sync this because the controller never accesses this field.
64: t>end-done ( transfer-d -- )
65 0 over next-transfer l! \ at least for now, this will be the last one
66 \ "should" be le-l!, but the result is the same
67 dup my-endpoint @
68 dup ping-done-q
69 swap for-controller @ + ( transfer-d endp-q-pointer )
70 dup @ if \ go to the end of the line
71 @ end-of-line add-to-line
72 else !
73 then
74;
75
76: distribute-replies ( dev-done-head -- )
77 begin
78 dev>virt dup sync-transfer
79 dup next-transfer le-l@ swap ( dev-next curr-transfer-d )
80 t>end-done ( dev-next )
81 ?dup 0= \ 0 marks end of q
82 until
83;
84
85variable done-mutex \ must be global
86
87\ This mutex code is a little cleverer, it will release the mutex if
88\ the caller is the current owner.
89\ Stolen from the keyboard code.
90\ XXX may not need this cleverness.
91\ XXX heavily dependent on 32 bit execution tokens, as it gets something
92\ from the return stack and saves it in a 32 bit variable.
93
94\ XXX doesn't look like it really works here. mutex-enter is only called by take-done-q,
95\ so the done-owner is always the same (once the open is done). open always unlocks
96\ the mutex, so how does this protect the distributor?
97
98\ variable done-owner \ XXX global?
99
100\ : mutex-enter ( -- locked? )
101\ done-mutex dup @ swap on ( locked? )
102\ r@ done-owner rot if ( req var )
103\ 2dup @ <> if ( req var )
104\ 2drop true exit ( true )
105\ then ( var req )
106\ then ( req var )
107\ ! false ( false )
108\ ;
109
110\ : mutex-exit ( -- ) done-mutex off ;
111
112\ Used by done-waiting?
113: take-done-q ( -- )
114 new-done? if
115 sync-hcca
116 hcca done-head le-l@
117\ toss interrupt-on bit which un-aligns the done-head:
118 1 invert and
119 clear-done-head
120 distribute-replies
121 then
122;
123
124\ Really should take off the alarm list when quit level runs, then put back on alarm
125\ list. Redman says that triggers an alarm list bug, so can't do it now.
126
127: alarm-take-done-q ( -- ) \ use on alarm level with 10 ms tick timer
128 done-mutex @ 0= if \ XXX diff from use in mutex-enter, -exit
129 take-done-q
130 then
131;
132
133: quit-take-done-q ( -- ) \ use on quit loop level
134 true done-mutex ! \ XXX diff from use in mutex-enter, -exit
135 take-done-q
136 0 done-mutex !
137;
138
139\ Replies are distributed by children, but the distributor is protected by
140\ the mutex so that replies go in order.
141
142\ XXX Check this code to make sure it's re-entrant.
143\ XXX Check this code to make sure it has no race conditions with the code
144\ running at the normal level which is editing the q's to install new stuff
145\ or disable-int-transactions.
146
147\ XXX Problem: 10 ms timer ticking for the keyboard and disk being booted
148\ from. each can see the other's transfer descriptors on the done q.
149\ Keep old done-q's until descriptors are all claimed? Or timed out somehow?
150\ **attach a done-q to each endpoint descriptor and distribute them from the
151\ chip's done-q?
152
153\ Still a problem if the keyboard is looking at 10ms timer intervals,
154\ essentially interrupting, while the boot device is looking at the regular
155\ execution intervals. There's a race condition over who looks at the
156\ done q of the chip to distribute the transfer descriptors.
157
158\ In practice there will be 1 set of transactions running off the 10ms timer
159\ for the keyboard and 1 running as usual for a boot device. There may be
160\ more instances of usb devices open, but only these will be running.
161\ Even if there is a usb output device that runs interrupt transfers, that
162\ will probably be run as a normal device, rather than hung off the 10 ms
163\ timer.
164
165\ The normal code looks to see if there are transfers to distribute. There
166\ are. Just then, the interrupt code runs, finds and distributes the
167\ transfers. It finishes, and the normal code thinks there are transfers
168\ to distribute, so it tries to do so -- but they have already been
169\ distributed before the normal code could grab the done q.
170
171\ One possible solution:
172\ Put the done-q transfer distribution code at the 10 ms interrupt as well.
173
174\ Another one:
175\ The normal instance looks again after grabbing the done q to find out if
176\ there are really any transfers to distribute (by looking at the bit in the
177\ register?). If there are it distributes them, because it really has the
178\ done q now, having set the control. If the ones that were there before
179\ have already been distributed, but new ones arrived (so the bit is true),
180\ that's ok. Just go ahead and distribute them.
181
182\ **Better variation:
183\ Grab the done q before finding out whether there are any entries. Then
184\ look at the done q and distribute. Then give up the q, and look at the
185\ endpoint done q.
186
187\ Is there another race condition? The normal code looks at its endpoint
188\ done q, and while fiddling with it, a new transfer is distributed to it
189\ by the 10ms timer instance. What happens? Does grabbing the done q
190\ extend to grabbing all the done q's at once?
191
192\ Note, once the chip done-q is turned over to the software, the chip
193\ essentially stalls until it is returned to the chip. The chip doesn't
194\ re-use the old done-q, but rather starts a new one. So all the transfers
195\ on the done-q must be distributed before the done-q is lost track of. So
196\ can't have the situation where the normal code grabbed its own done q and
197\ locked out the 10 ms timer code from distributing a transfer onto the normal
198\ done q, as the 10 ms timer code has a problem knowing what to do with the
199\ leftover transfers, and can't sit waiting for the normal code to release
200\ its done q.
201
202\ **use two endpoint done q's. one being emptied by the code, one being filled
203\ by the distributor. while the code is emptying one, it does not touch the
204\ other. also, the distributor only puts them on the other and does not touch
205\ the one being emptied. when 1st is empty, code switches to the other.
206\ switch is ok, as if distributor puts some more on just as code is switching,
207\ that's ok.
208
209\ what about a pipe between the distributor and the code? don't see it.
210
211\ could also use a ring of transfer addresses without links. could work,
212\ but it seems more cumbersome than just ping-ponging the q's.
213
214\ must be the kind of thing that the normal code doesn't need to lock, since
215\ the distributor code can't block, since it might be running as part of
216\ the 10ms timer instance.