Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: requests.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: @(#)requests.fth 1.13 02/12/19 | |
43 | purpose: | |
44 | copyright: Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved | |
45 | ||
46 | : request-blank ( -- addr ) /request get-chunk ; | |
47 | ||
48 | : descript-form ( len -- addr ) | |
49 | request-blank | |
50 | get-descript-req over request-type w! | |
51 | swap over req-len le-w! | |
52 | ; | |
53 | ||
54 | : get-dev-descript-form ( len -- addr ) | |
55 | descript-form | |
56 | device-descript over req-value 1+ c! | |
57 | ; | |
58 | ||
59 | : get-config-descript-form ( len -- addr ) | |
60 | descript-form | |
61 | config-descript over req-value 1+ c! \ need index as well | |
62 | ; | |
63 | ||
64 | : set-address-form ( usb-addr -- addr ) | |
65 | request-blank | |
66 | set-address-req over request-type w! | |
67 | swap over req-value le-w! | |
68 | ; | |
69 | ||
70 | ||
71 | : add-setup-transfer ( p-adr p-len endp-d -- ) | |
72 | 2 setup-bits rot t>endq | |
73 | ; | |
74 | ||
75 | \ XXX should have a toggle in the stack diagram; see execute-1-interrupt. | |
76 | \ XXX the adding code can be better factored and cleaned up | |
77 | \ dir is 0 for data from target to host, 1 for data from host to target | |
78 | : (add-data-transfer) ( buf-adr buf-len dir endp-d -- ) | |
79 | 3 \ toggle | |
80 | rot if out-bits else in-bits then | |
81 | rot t>endq | |
82 | ; | |
83 | ||
84 | : add-data-transfer ( buf-adr buf-len dir endp-d -- ) | |
85 | rot ?dup if | |
86 | -rot (add-data-transfer) | |
87 | else 2drop drop \ 0 len transfer not needed here | |
88 | then | |
89 | ; | |
90 | ||
91 | \ dir is 0 for out-ack, 1 for in-ack (opposite of add-data-transfer) | |
92 | : add-ack-transfer ( dir endp-d -- ) | |
93 | >r >r | |
94 | 0 0 3 \ status transfer | |
95 | r> if in-bits else out-bits then | |
96 | r> t>endq | |
97 | ; | |
98 | ||
99 | : add-isoc-transfer ( frame# badr blen endp -- ) | |
100 | over if | |
101 | isoct>endq | |
102 | else 2drop 2drop \ 0 len transfer not needed here | |
103 | then | |
104 | ; | |
105 | ||
106 | : enque-control ( endp-d -- ) | |
107 | control-off next-frame | |
108 | control-id e>q | |
109 | control-on control-filled | |
110 | ; | |
111 | ||
112 | \ Need to clear hccontrol bit. on next frame, hccontrolcurrent is adjusted | |
113 | \ so it does not point to the one being removed (ohci 5.2.7.1.2 says use 0). | |
114 | \ adjust pointers in nearby endpoint d's to point around the one being | |
115 | \ removed. then turn on the q in hccontrol again. | |
116 | : deque-control ( endp-d -- ) | |
117 | chip-base hc-control rl@ >r | |
118 | control-off next-frame | |
119 | eq> | |
120 | 0 chip-base hc-control-current rl! \ make sure it's not looking at this 1 | |
121 | control-filled \ make it start over on control q | |
122 | r> chip-base hc-control rl! | |
123 | ; | |
124 | ||
125 | : enque-interrupt ( endp-d q# -- ) | |
126 | periodic-off next-frame | |
127 | e>q | |
128 | periodic-on | |
129 | ; | |
130 | ||
131 | : deque-interrupt ( endp-d -- ) | |
132 | chip-base hc-control rl@ >r | |
133 | periodic-off next-frame | |
134 | eq> | |
135 | r> chip-base hc-control rl! | |
136 | ; | |
137 | ||
138 | : enque-bulk ( endp-d -- ) | |
139 | bulk-off next-frame | |
140 | bulk-id e>q | |
141 | bulk-on bulk-filled | |
142 | ; | |
143 | ||
144 | : deque-bulk ( endp-d -- ) | |
145 | chip-base hc-control rl@ >r | |
146 | bulk-off next-frame | |
147 | eq> | |
148 | r> chip-base hc-control rl! | |
149 | ; | |
150 | ||
151 | : enque-isoc ( endp-d -- ) | |
152 | isoc-off next-frame | |
153 | isoc-id e>q | |
154 | isoc-on periodic-on | |
155 | ; | |
156 | ||
157 | : deque-isoc ( -- ) | |
158 | chip-base hc-control rl@ >r | |
159 | isoc-off next-frame | |
160 | eq> | |
161 | r> chip-base hc-control rl! | |
162 | ; | |
163 | ||
164 | ' take-done-q to bless-done-q \ for polled at probe time; | |
165 | \ could use quit-take-done-q | |
166 | ||
167 | \ ping-pongs once to check both done-q's if needed. Leaves the code pointing | |
168 | \ to the done q with the done transfer waiting that it found, if it found one. | |
169 | \ XXX If other code guarantees this starts on a clean q, ping-pong should be | |
170 | \ first. | |
171 | \ The endpoint starts with the pointer for the distributor set to a clean | |
172 | \ queue, and the regular code looking at a clean queue, so I think the ping- | |
173 | \ pong can be done first. Results in a slightly better response time. | |
174 | \ there's a wrinkle in connection with the interrupt transfers and isoc | |
175 | \ transfers. | |
176 | : done-waiting? ( endpoint -- done-waiting? ) | |
177 | bless-done-q | |
178 | dup code-done-q @ ?dup if | |
179 | nip | |
180 | else | |
181 | dup ping-pong | |
182 | code-done-q @ | |
183 | then | |
184 | ; | |
185 | ||
186 | d# 5000 value time-limit \ 5 sec timeout, usb 7.1.4.3; global ok | |
187 | ||
188 | : more-time? ( limit -- limit-not-hit? ) | |
189 | get-msecs - 0> | |
190 | ; | |
191 | ||
192 | \ 0 if timed-out. | |
193 | : wait-for-reply ( endpoint -- done-q | 0 ) | |
194 | get-msecs time-limit + | |
195 | begin | |
196 | over done-waiting? dup if | |
197 | dup | |
198 | else over more-time? 0= if true then | |
199 | then | |
200 | until | |
201 | nip nip | |
202 | ; | |
203 | ||
204 | : wait-till-stopped ( endpoint -- stopped | 0 ) \ 0 if timed-out | |
205 | get-msecs time-limit + | |
206 | begin | |
207 | over stopped? dup if | |
208 | dup | |
209 | else over more-time? 0= if true then | |
210 | then | |
211 | until | |
212 | nip nip | |
213 | ; | |
214 | ||
215 | \ true if only one more reply outstanding. partly a check that all the | |
216 | \ transfer-d's are accounted for and none left in limbo (endpoint-d shows | |
217 | \ empty, but no reply on the done-q yet). | |
218 | : last-reply? ( endpoint -- last? ) | |
219 | transfer-count @ 1- 0= | |
220 | ; | |
221 | ||
222 | \ Move the transfer-d's from done-q to the stack. | |
223 | : take-transfer-d's ( endpoint -- q-head ) | |
224 | dup code-done-q @ | |
225 | 0 rot code-done-q ! \ this done-q can be reused now. | |
226 | ; | |
227 | ||
228 | \ Assumes that the transfer-d's are put on the q in the same order | |
229 | \ as on the controller done-q. | |
230 | \ code is condition code of last reply or error code of recent reply | |
231 | \ code is present only if bad-or-last? is non-false. | |
232 | : bad-or-last-reply? ( transfer-d endpoint -- [code] bad-or-last? ) | |
233 | 2dup dump-following-transfer-d's | |
234 | swap >r last-reply? if | |
235 | r@ condition-code true | |
236 | else | |
237 | r@ condition-code ?dup | |
238 | then | |
239 | r> dump-transfer | |
240 | ; | |
241 | ||
242 | \ XXX if timeout, need to dump the transfer somehow | |
243 | \ Look for a done transfer. Keep looking until one shows up, or timeout. | |
244 | \ Dump any earlier done transfers. | |
245 | \ Check if it is the last one. If it is, return its condition code. | |
246 | \ If it is not the last one, check it for an error, and return that if | |
247 | \ non-zero. If it isn't the last one, and has no error, keep looking. | |
248 | ||
249 | \ Not used for enable-int-transactions. Should never time out. | |
250 | ||
251 | \ 0 if we got the last reply, there was no timeout, and there was | |
252 | \ no error. Otherwise, there was a timeout, or there was an error. | |
253 | \ The done transfer-d's are dumped. | |
254 | : wait-for-last-reply ( endpoint-d -- reply-code ) | |
255 | begin dup wait-for-reply ?dup if | |
256 | over bad-or-last-reply? | |
257 | else \ timed-out | |
258 | time-out-error true | |
259 | then | |
260 | until | |
261 | nip | |
262 | ; | |
263 | ||
264 | : 1-try-wait ( endpoint-d -- reply-code ) | |
265 | time-limit ( endpoint-d time-limit ) | |
266 | 2 is time-limit | |
267 | swap wait-for-last-reply ( time-limit reply-code ) | |
268 | swap is time-limit ( reply-code ) | |
269 | ; | |
270 | ||
271 | \ Look at the packet status words; report the first error | |
272 | : packet-statuses ( transfer-d -- error-code ) | |
273 | 0 swap \ assume good | |
274 | 8 0 do | |
275 | i over packet-condition-code | |
276 | ?dup if -rot nip leave then | |
277 | loop | |
278 | drop | |
279 | ; | |
280 | ||
281 | : isoc-transfer-bad? ( transfer-d -- error-code ) | |
282 | dup condition-code ?dup if | |
283 | nip | |
284 | else | |
285 | packet-statuses | |
286 | then | |
287 | ; | |
288 | ||
289 | \ Reverse the q of transfer-d's onto the stack. | |
290 | : get-transfer-d's ( q-head -- q-head trans1 ... transn ) | |
291 | begin | |
292 | dup next-transfer le-l@ | |
293 | ?dup 0= | |
294 | until | |
295 | ; | |
296 | ||
297 | \ Look at the transfer-d's on the done-q in reverse order (in order that | |
298 | \ they went on the done-q). Check each one for bad isoc status. Dump | |
299 | \ the transfer-d's. | |
300 | : check-isoc-packets ( done-q-head -- error-code ) | |
301 | 0 >r \ assume good | |
302 | dup >r ( R: 0 done-head ) | |
303 | get-transfer-d's ( done-head trans1 ... transn ) ( R: 0 q-head ) | |
304 | begin | |
305 | dup isoc-transfer-bad? ?dup if | |
306 | r> r> ?dup if | |
307 | >r >r drop | |
308 | else | |
309 | swap >r >r | |
310 | then | |
311 | then | |
312 | dup dump-isoc-transfer | |
313 | r@ = | |
314 | until | |
315 | r> drop | |
316 | r> | |
317 | ; | |
318 | ||
319 | : wait-for-last-isoc-reply ( endp-d -- reply-code ) | |
320 | dup wait-till-stopped if \ endpoint done | |
321 | bless-done-q | |
322 | \ can't be any replies on current done q, so ping-pong: | |
323 | dup ping-pong take-transfer-d's ( done-q-head ) | |
324 | check-isoc-packets \ look for error codes, dump transfer-d's | |
325 | else | |
326 | drop time-out-error | |
327 | then | |
328 | ; | |
329 | ||
330 | : dump-done-q ( endpoint-d -- ) | |
331 | dup code-done-q @ if | |
332 | dup code-done-q @ tuck swap | |
333 | dump-following-transfer-d's dump-transfer | |
334 | else drop | |
335 | then | |
336 | ; | |
337 | ||
338 | ||
339 | \ XXX needs change to return a nak for execute-1-interrupt? | |
340 | 2 constant usb-ack | |
341 | 6 constant usb-nak | |
342 | e constant usb-stall | |
343 | ||
344 | \ hw-err? is anything other than usb ack, nak, or stall | |
345 | : translate-code ( reply-code -- hw-err? | stat 0 ) | |
346 | ?dup if | |
347 | dup stall-error = if drop usb-stall 0 then | |
348 | else usb-ack 0 | |
349 | then | |
350 | ; | |
351 | ||
352 | ||
353 | \ How do we process the transfers in order? Does it matter? | |
354 | \ Right now the done transfers are put on the chip done q in reverse order, | |
355 | \ earlier done ones are pushed towards the tail of the q (it's a "stack"). | |
356 | \ They are moved to the endpoint done q's in the same order (they are | |
357 | \ "stacks"). The distributor code is simpler and faster this way, which | |
358 | \ is a good thing, since it executes on the 10 ms tick timer. | |
359 | ||
360 | \ Could give each transfer descriptor a sequence number, and keep the last | |
361 | \ number in the endpoint. Then could look at each done transfer in order | |
362 | \ of the sequence. | |
363 | ||
364 | \ Doesn't look like we need sequence numbers: | |
365 | \ Can we assume that if transfer 2 shows up on a done q, that transfer 1 | |
366 | \ went through ok? And is on some q already (or already disposed of by the | |
367 | \ code)? At least can assume that 1 is somewhere. Looks like can assume | |
368 | \ that 1 went ok, except for isoc transfers. | |
369 | ||
370 | \ For general transfers, any code other than no-error will cause endpoint to | |
371 | \ halt. isoc transfers will never halt. | |
372 | ||
373 | \ isoc transfers have error codes in the transfer descriptor fields as well | |
374 | \ as the completion code field. The completion code may be no-error, while | |
375 | \ some packet status words may have error codes. | |
376 | ||
377 | \ So, when the code takes a done q, it can reverse the transfer d's to get | |
378 | \ them in sequence of completion, or just dump all but the latest executed. | |
379 | ||
380 | \ So for a non-isoc, non-repeated interrupt, interface method, wait until | |
381 | \ either the last transfer is finished, or some transfer gets an error. | |
382 | \ If last transfer is ok, report good back to caller. Otherwise, report | |
383 | \ error of some sort. |