|
|
1.1 root 1: \ *****************************************************************************
2: \ * Copyright (c) 2004, 2008 IBM Corporation
3: \ * All rights reserved.
4: \ * This program and the accompanying materials
5: \ * are made available under the terms of the BSD License
6: \ * which accompanies this distribution, and is available at
7: \ * http://www.opensource.org/licenses/bsd-license.php
8: \ *
9: \ * Contributors:
10: \ * IBM Corporation - initial implementation
11: \ ****************************************************************************/
12:
13: 0 value NEXT-TD
14:
15: 0 VALUE num-tds
16: 0 VALUE td-retire-count
17: 0 VALUE saved-tail
18: 0 VALUE poll-timer
19: VARIABLE controlxfer-cmd
20:
21: \ Allocate an ED and populate it
22:
23: : (ed-prepare) ( dir addr dlen setup-packet MPS ep-fun --
24: FALSE | dir addr dlen ed-ptr setup-ptr )
25: allocate-ed dup 0= IF ( dir addr dlen setup-packet MPS ep-fun ed-ptr )
26: drop 3drop 2drop FALSE EXIT ( FALSE )
27: THEN
28: TO temp1 ( dir addr dlen setup-packet MPS ep-fun )
29: temp1 zero-out-an-ed-except-link ( dir addr dlen setup-packet MPS ep-fun )
30: temp1 ed>eattr l@-le or temp1 ed>eattr l!-le ( dir addr dlen setup-ptr MPS )
31: dup TO temp2 10 lshift temp1 ed>eattr l@-le or temp1 ed>eattr l!-le
32: ( dir addr dlen setup-packet-address )
33: temp1 swap TRUE ( dir addr dlen ed-ptr setup-ptr TRUE )
34: ;
35:
36:
37: \ Allocate TD list
38:
39:
40: : (td-prepare) ( dir addr dlen ed-ptr setup-ptr --
41: dir FALSE | dir addr dlen ed-ptr setup-ptr td-head td-tail )
42: 2 pick ( dir addr dlen ed-ptr setup-ptr dlen )
43: temp2 ( dir addr dlen ed-ptr setup-ptr dlen MPS )
44: /mod ( dir addr dlen ed-ptr setup-ptr rem quo )
45: swap 0<> IF ( dir addr dlen ed-ptr setup-ptr quo )
46: 1+
47: THEN
48: 2+
49: dup TO num-tds ( dir addr dlen ed-ptr setup-ptr quo+2 )
50: allocate-td-list dup 0= IF ( dir addr dlen ed-ptr setup-ptr quo+2 )
51: 2drop ( dir addr dlen ed-ptr setup-ptr )
52: drop ( dir addr dlen ed-ptr )
53: free-ed ( dir addr dlen )
54: 2drop ( dir )
55: FALSE ( dir FALSE )
56: EXIT
57: THEN TRUE
58: ;
59:
60:
61: \ Fill in the ED structure completely.
62:
63:
64: : (td-ready) ( dir addr dlen ed-ptr setup-ptr td-head td-tail -- )
65: ( dir addr dlen ed-ptr setup-ptr )
66: 3 pick ( dir addr dlen ed-ptr setup-ptr td-head td-tail ed-ptr )
67: tuck ( dir addr dlen ed-ptr setup-ptr td-head ed-ptr td-tail ed-ptr )
68: ed>tdqtp l!-le ( dir addr dlen ed-ptr setup-ptr td-head ed-ptr )
69: ed>tdqhp l!-le ( dir addr dlen ed-ptr setup-ptr )
70: over ed>ned 0 swap l!-le ( dir addr dlen ed-ptr setup-ptr )
71: ;
72:
73:
74: \ Initialize the HEAD and TAIL TDs for SETUP and
75: \ STATUS phase respectively.
76:
77:
78: : (td-setup-status) ( dir addr dlen ed-ptr setup-ptr -- dir addr dlen ed-ptr )
79: over ed>tdqhp l@-le ( dir addr dlen ed-ptr setup-ptr td-head )
80: dup zero-out-a-td-except-link ( dir addr dlen ed-ptr setup-ptr td-head )
81: dup td>tattr DATA0-TOGGLE CC-FRESH-TD or swap l!-le
82: ( dir addr dlen ed-ptr setup-ptr td-head )
83: 2dup td>cbptr l!-le ( dir addr dlen ed-ptr setup-ptr td-head )
84: 2dup td>bfrend swap STD-REQUEST-SETUP-SIZE 1- + swap l!-le
85: ( dir addr dlen ed-ptr setup-ptr td-head )
86: 2drop ( dir addr dlen ed-ptr )
87: ;
88:
89: \ Initialize the TD TAIL pointer.
90:
91:
92: : (td-tailpointer) ( dir addr dlen ed-ptr -- dir addr dlen ed-ptr )
93: dup ed>tdqtp l@-le ( dir addr dlen ed-ptr td-tail )
94: dup zero-out-a-td-except-link ( dir addr dlen ed-ptr td-tail )
95: dup td>tattr dup l@-le DATA1-TOGGLE CC-FRESH-TD or or swap l!-le
96: ( dir addr dlen ed-ptr td-tail )
97: 4 pick 0= ( dir addr dlen ed-ptr td-tail flag )
98: 3 pick 0<> ( dir addr dlen ed-ptr td-tail flag flag )
99: and IF ( dir addr dlen ed-ptr td-tail )
100: dup td>tattr dup l@-le TD-DP-OUT or swap l!-le
101: ( dir addr dlen ed-ptr td-tail )
102: ELSE
103: dup td>tattr dup l@-le TD-DP-IN or swap l!-le
104: ( dir addr dlen ed-ptr td-tail )
105: THEN
106: drop ( dir addr dlen ed-ptr )
107: ;
108:
109: \ Initialize the Data TDs.
110:
111:
112: : (td-data) ( dir addr dlen ed-ptr -- ed-ptr )
113: -rot ( dir ed-ptr addr dlen )
114: dup 0<> IF ( dir ed-ptr addr dlen )
115: >r >r >r TO temp1 r> r> r> temp1 ( ed-ptr addr dlen dir )
116: 3 pick ( ed-ptr addr dlen dir ed-ptr )
117: ed>tdqhp l@-le td>ntd l@-le ( ed-ptr addr dlen dir td-datahead )
118: 4 pick ( ed-ptr addr dlen dir td-datahead ed-ptr )
119: td>tattr l@-le 10 rshift ( ed-ptr addr dlen dir td-head-data MPS )
120: swap ( ed-ptr addr dlen dir MPS td-head-data )
121: >r >r >r >r >r 1 r> r> r> r> r>
122: ( ed-ptr 1 addr dlen dir MPS td-head-data )
123: >r >r 0= IF ( ed-ptr 1 addr dlen dir )
124: OHCI-DP-IN ( ed-ptr 1 addr dlen dir OHCI-DP-IN )
125: ELSE
126: OHCI-DP-OUT ( ed-ptr 1 addr dlen dir OHCI-DP-OUT )
127: THEN
128: r> r> ( ed-ptr 1 addr dlen dir OHCI-DP- MPS td-head-data )
129: fill-TD-list
130: ELSE
131: 2drop nip ( ed-ptr )
132: THEN
133: ;
134:
135:
136: \ Program the HC with the ed-ptr value and wait for status to
137: \ from the HC.
138: \ Free the ED and TDs associated with it.
139: \ PENDING: Above said.
140:
141: 10 CONSTANT max-retire-td
142:
143: : (transfer-wait-for-doneq) ( ed-ptr -- TRUE | FALSE )
144: dup ( ed-ptr ed-ptr )
145: hcctrhead rl!-le ( ed-ptr )
146: HC-enable-control-list-processing ( ed-ptr )
147: 0 TO td-retire-count ( ed-ptr )
148: 0 TO poll-timer ( ed-ptr )
149: BEGIN
150: td-retire-count num-tds <> ( ed-ptr TRUE | FALSE )
151: poll-timer max-retire-td < and ( ed-ptr TRUE | FALSE )
152: WHILE
153: (HC-CHECK-WDH) ( ed-ptr )
154: IF
155: hchccadneq l@-le find-td-list-tail-and-size nip ( ed-ptr n )
156: td-retire-count + TO td-retire-count ( ed-ptr )
157: hchccadneq l@-le dup ( ed-ptr done-td done-td )
158: (td-list-status) ( ed-ptr done-td failed-td CCcode )
159: IF
160: \ keep condition code of TD on return stack
161: dup >r
162: s" (transfer-wait-for-doneq: USB device communication error."
163: usb-debug-print ( ed-ptr done-td failed-td CCcode R: CCcode )
164: dup 4 = swap dup 5 = rot or ( ed-ptr done-td failed-td CCcode R: CCcode )
165: IF
166: max-retire-td TO poll-timer ( ed-ptr done-td failed-td CCcode R: CCcode )
167: THEN
168: ( ed-ptr done-td failed-td CCcode R: CCcode )
169: usb-debug-flag
170: IF
171: s" CC code ->" type . cr
172: s" Failing TD contents:" type cr display-td
173: ELSE
174: 2drop
175: THEN ( ed-ptr done-td R: CCcode )
176: controlxfer-cmd @ GET-MAX-LUN = r> 4 = and
177: IF
178: s" (transfer-wait-for-doneq): GET-MAX-LUN ControlXfer STALLed"
179: usb-debug-print
180: \ Condition Code = 4 means that the device does not support multiple LUNS
181: \ see USB Massbulk 1.0 Standard
182: ELSE
183: drop
184: 5030 error" (USB) Device communication error."
185: ABORT
186: \ FIXME: ABORTing here might leave the HC in an unusable state.
187: \ We should maybe rather ABORT at the end of this Forth
188: \ word, when clean-up has been done (or not ABORT at all)
189: THEN
190: THEN ( ed-ptr done-td )
191: (free-td-list) ( ed-ptr )
192: 0 hchccadneq l!-le ( ed-ptr )
193: (HC-ACK-WDH) \ TDs were written to DOne queue. ACK the HC.
194: THEN
195: poll-timer 1+ TO poll-timer
196: 4 ms \ longer 1 ms
197: REPEAT ( ed-ptr )
198: disable-control-list-processing ( ed-ptr )
199: td-retire-count num-tds <> ( ed-ptr )
200: IF
201: dup display-descriptors ( ed-ptr )
202: s" maximum of retire " usb-debug-print
203: THEN
204: free-ed
205: td-retire-count num-tds <>
206: IF
207: FALSE ( FALSE )
208: ELSE
209: TRUE ( TRUE )
210: THEN
211: ;
212:
213:
214: \ COLON DEFINITION: controlxfer
215: \ INTERFACE FUNCTION
216:
217: \ ARGUMENTS:
218: \ (from the bottom OF stack)
219: \ 1. dir -- This is the direction OF data transfer associated with
220: \ the DATA STAGE OF the control xfer.
221: \ If there is no data transfer (argument dlen is zero)
222: \ THEN this argument DOes not matter, nonethless it has
223: \ to be passed.
224: \ A "0" represents an IN and "1" represents an "OUT".
225: \ 2. addr -- If therez a data stage associated with the transfer,
226: \ THEN, this argument holds the address OF the data buffer
227: \ 3. dlen -- This arg holds the length OF the data buffer discussed
228: \ in previous step (addr)
229: \ 4. setup-packet -- This holds the pointer to the setup packet that
230: \ will be transmitted during the SETUP stage OF
231: \ the control xfer. The function assumes the length
232: \ OF the status packet to be 8 bytes.
233: \ 5. MPS -- This is the MAX PACKET SIZE OF the endpoint.
234: \ 6. ep-fun -- This is the 11-bit value that holds the Endpoint and
235: \ the function address. bit 7 to bit 10 holds the Endpoint
236: \ address. Bits 0 to Bit 6 holds the Function Address.
237: \ The BIT numbering followed : The left most bit is referred
238: \ as bit 0. (not the one followed by PPC)
239: \ Bit 13 must be set for low-speed devices.
240:
241: \ RETURN VALUE:
242: \ Returns TRUE | FALSE depending on the success OF the transaction.
243:
244: \ ASSUMPTIONS:
245: \ 1. Function assumes that the setup packet is 8-bytes in length.
246: \ If in future, IF we need to add a new argument, we need to change
247: \ the function in lot OF places.
248:
249: \ RISKS:
250: \ 1. If for some reason, the USB controller DOes not retire all the TDs
251: \ THEN, the status checking part OF this "word" can spin forever.
252:
253:
254: : controlxfer ( dir addr dlen setup-packet MPS ep-fun -- TRUE | FALSE )
255: 2 pick @ controlxfer-cmd !
256: (ed-prepare) ( FALSE | dir addr dlen ed-ptr setup-ptr )
257: invert IF FALSE EXIT THEN
258: (td-prepare) ( pt ed-type toggle buffer length mps head )
259: invert IF FALSE EXIT THEN
260: (td-ready) ( dir addr dlen ed-ptr setup-ptr )
261: (td-setup-status) ( dir addr dlen ed-ptr )
262: (td-tailpointer) ( dir addr dlen ed-ptr )
263: (td-data) ( ed-ptr )
264:
265:
266: \ FIXME:
267: \ Clear the TAIL pointer in ED. This has got sthg to DO with how
268: \ the HC finds an EMPTY queue condition. Refer spec.
269:
270:
271: dup ed>tdqtp l@-le TO saved-tail ( ed-ptr )
272: dup ed>tdqtp 0 swap l!-le ( ed-ptr )
273: (transfer-wait-for-doneq) ( TRUE | FALSE )
274: ;
275:
276: 0201000000000000 CONSTANT CLEARHALTFEATURE
277: 0 VALUE endpt-num
278: 0 VALUE usb-addr-contr-req
279: : control-std-clear-feature ( endpoint-nr usb-addr -- TRUE|FALSE )
280: TO usb-addr-contr-req \ usb address
281: TO endpt-num \ endpoint number
282: CLEARHALTFEATURE setup-packet !
283: endpt-num setup-packet 4 + c! \ endpoint number
284: 0 0 0 setup-packet DEFAULT-CONTROL-MPS usb-addr-contr-req controlxfer
285: ( TRUE|FALSE )
286: ;
287:
288: \ It resets the usb bulk-device
289: 21FF000000000000 CONSTANT BULK-RESET
290: : control-std-bulk-reset ( usb-addr -- TRUE|FALSE )
291: TO usb-addr-contr-req
292: BULK-RESET setup-packet !
293: 0 0 0 setup-packet DEFAULT-CONTROL-MPS usb-addr-contr-req controlxfer
294: ( TRUE|FALSE )
295: ;
296:
297: : bulk-reset-recovery-procedure ( bulk-out-endp bulk-in-endp usb-addr -- )
298: >r ( bulk-out-endp bulk-in-endp R: usb-addr )
299: \ perform a bulk reset
300: r@ control-std-bulk-reset
301: IF s" bulk reset OK"
302: ELSE s" bulk reset failed"
303: THEN usb-debug-print
304:
305: \ clear bulk-in endpoint ( bulk-out-endp bulk-in-endp R: usb-addr )
306: 80 or r@ control-std-clear-feature
307: IF s" control-std-clear IN endpoint OK"
308: ELSE s" control-std-clear-IN endpoint failed"
309: THEN usb-debug-print
310:
311: \ clear bulk-out endpoint ( bulk-out-endp R: usb-addr )
312: r@ control-std-clear-feature
313: IF s" control-std-clear OUT endpoint OK"
314: ELSE s" control-std-clear-OUT endpoint failed"
315: THEN usb-debug-print
316: r> drop
317: ;
318:
319: 0 VALUE saved-rw-ed
320: 0 VALUE num-rw-tds
321: 0 VALUE num-rw-retired-tds
322: 0 VALUE saved-rw-start-toggle
323: 0 VALUE saved-list-type
324:
325: \ Allocate an ED and populate what you can.
326:
327:
328: : (ed-prepare-rw)
329: ( pt ed-type toggle buffer length mps address ed-ptr --
330: FALSE | pt ed-type toggle buffer length mps )
331: allocate-ed dup 0= IF
332: ( pt ed-type toggle buffer length mps address ed-ptr )
333: drop 2drop 2drop 2drop drop
334: saved-rw-start-toggle FALSE EXIT ( toggle FALSE )
335: THEN
336: TO saved-rw-ed ( pt ed-type toggle buffer length mps address )
337: saved-rw-ed zero-out-an-ed-except-link
338: ( pt ed-type toggle buffer length mps address )
339: saved-rw-ed ed>eattr l!-le ( pt ed-type toggle buffer length mps )
340: dup 10 lshift saved-rw-ed ed>eattr l@-le or
341: ( pt ed-type toggle buffer length mps mps~ )
342: saved-rw-ed ed>eattr l!-le TRUE ( pt ed-type toggle buffer length mps TRUE )
343: ;
344:
345:
346: \ Allocate TD List
347:
348:
349: : (td-prepare-rw)
350: ( pt ed-type toggle buffer length mps --
351: FALSE | pt ed-type toggle buffer length mps head )
352: 2dup ( pt ed-type toggle buffer length mps length mps )
353: /mod ( pt ed-type toggle buffer length mps num-tds rem )
354: swap 0<> IF ( pt ed-type toggle buffer length mps num-tds )
355: 1+ ( pt ed-type toggle buffer length mps num-tds+1 )
356: THEN
357: dup TO num-rw-tds ( pt ed-type toggle buffer length mps num-tds )
358: allocate-td-list ( pt ed-type toggle buffer length mps head tail )
359: dup 0= IF
360: 2drop 2drop 2drop 2drop
361: saved-rw-ed free-ed
362: ." rw-endpoint: TD list allocation failed" cr
363: saved-rw-start-toggle FALSE ( FALSE )
364: EXIT
365: THEN
366: drop TRUE ( pt ed-type toggle buffer length mps head TRUE )
367: ;
368:
369:
370: \ Populate TD list with data buffers and toggle info.
371:
372:
373: : (td-data-rw)
374: ( pt ed-type toggle buffer length mps head -- FALSE | pt et head )
375: 6 pick ( pt ed-type toggle buffer length mps head pt )
376: FALSE TO case-failed CASE
377: 0 OF OHCI-DP-IN ENDOF
378: 1 OF OHCI-DP-OUT ENDOF
379: 2 OF OHCI-DP-SETUP ENDOF
380: dup OF TRUE TO case-failed
381: ." rw-endpoint: Invalid Packet Type!" cr
382: ENDOF
383: ENDCASE ( pt ed-type toggle buffer length mps head dp )
384: case-failed IF
385: saved-rw-ed free-ed ( pt ed-type toggle buffer length mps head dp )
386: drop (free-td-list) ( pt ed-type toggle buffer length mps head )
387: 2drop 2drop 2drop
388: saved-rw-start-toggle FALSE ( FALSE )
389: EXIT ( FALSE )
390: THEN
391: -rot ( pt ed-type toggle buffer length dp mps head )
392: dup >r ( pt ed-type toggle buffer length dp mps head )
393: fill-TD-list r> TRUE ( pt et head TRUE )
394: ;
395:
396:
397: \ Enqueue the ED with the appropriate list
398:
399:
400: : (ed-ready-rw) ( pt et -- - | toggle FALSE )
401: nip ( et )
402: FALSE TO case-failed CASE
403: 0 OF \ Control List. Queue the ED to control list
404: 0 TO saved-list-type
405: saved-rw-ed hcctrhead rl!-le
406: HC-enable-control-list-processing
407: ENDOF
408: 1 OF \ Bulk List. Queue the ED to bulk list
409: 1 TO saved-list-type
410: saved-rw-ed hcbulkhead rl!-le
411: HC-enable-bulk-list-processing
412: ENDOF
413: 2 OF \ Interrupt List.
414: 2 TO saved-list-type
415: saved-rw-ed hchccareg rl@-le rl!-le
416: HC-enable-interrupt-list-processing
417: ENDOF
418: dup OF
419: saved-rw-ed ed>tdqhp l@-le (free-td-list)
420: saved-rw-ed free-ed
421: TRUE TO case-failed
422: ENDOF
423: ENDCASE
424: case-failed IF
425: saved-rw-start-toggle FALSE ( toggle FALSE )
426: EXIT
427: THEN
428: TRUE ( TRUE )
429: ;
430:
431: \ Wait for TDs to return to the Done Q.
432:
433: : (wait-td-retire) ( -- )
434: 0 TO num-rw-retired-tds
435: FALSE TO while-failed
436: BEGIN
437: num-rw-retired-tds num-rw-tds < ( TRUE | FALSE )
438: while-failed FALSE = and ( TRUE | FALSE )
439: WHILE
440: d# 5000 (wait-for-done-q) ( TD-list TRUE|FALSE )
441: IF
442: dup find-td-list-tail-and-size nip ( td-list size )
443: num-rw-retired-tds + TO num-rw-retired-tds ( td-list )
444: dup (td-list-status) ( td-list failed-TD CC )
445: IF
446: dup 4 =
447: IF
448: saved-list-type
449: CASE
450: 0 OF
451: 0 0 control-std-clear-feature
452: s" clear feature " usb-debug-print
453: ENDOF
454: 1 OF \ clean bulk stalled
455: s" clear bulk when stalled " usb-debug-print
456: disable-bulk-list-processing \ disable procesing
457: saved-rw-ed ed>eattr l@-le dup \ extract
458: 780 and 7 rshift 80 or \ endpoint and
459: swap 7f and \ usb addr
460: control-std-clear-feature
461: ENDOF
462: 2 OF
463: 0 saved-rw-ed ed>eattr l@-le
464: control-std-clear-feature
465: ENDOF
466: dup OF
467: s" unknown status " usb-debug-print
468: ENDOF
469: ENDCASE
470: ELSE ( td-list failed-TD CC )
471: ." TD failed " 5b emit .s 5d emit cr
472: 5040 error" (USB) device transaction error (wait-td-retire)."
473: ABORT
474: THEN
475: 2drop drop
476: TRUE TO while-failed \ transaction failed
477: NEXT-TD 0<> \ clean the TD if we
478: IF
479: NEXT-TD (free-td-list) \ had a stalled
480: THEN
481: THEN
482: (free-td-list)
483: ELSE
484: drop \ drop td-list pointer
485: scan-time? IF 2e emit THEN \ show proceeding dots
486: TRUE TO while-failed
487: s" time out wait for done" usb-debug-print
488: 20 ms \ wait for bad device
489: THEN
490: REPEAT
491: ;
492:
493:
494: \ Process retired TDs
495:
496:
497: : (process-retired-td) ( -- TRUE | FALSE )
498: saved-list-type CASE
499: 0 OF disable-control-list-processing ENDOF
500: 1 OF disable-bulk-list-processing ENDOF
501: 2 OF disable-interrupt-list-processing ENDOF
502: ENDCASE
503: saved-rw-ed ed>tdqhp l@-le 2 and 0<> IF
504: 1
505: s" retired 1" usb-debug-print
506: ELSE
507: 0
508: s" retired 0" usb-debug-print
509: THEN
510: \ s" retired " usb-debug-print-val
511: WHILE-failed IF
512: FALSE ( FALSE )
513: ELSE
514: TRUE ( TRUE )
515: THEN
516: saved-rw-ed free-ed
517: ;
518:
519:
520: \ (DO-rw-endpoint): T1 12 80 0 0chis method is an privately visible function
521: \ to be used by the "rw-endpoint" the required
522: \ number OF times based on the actual length
523: \ to be transferred
524:
525: \ Arguments:
526: \ pt: Packet type
527: \ 0 -> IN
528: \ 1 -> OUT
529: \ 2 -> SETUP
530: \ et: Endpoint type
531: \ 0 -> Control
532: \ 1 -> Bulk
533: \ toggle: Starting toggle for this transfer
534: \ buffer length: Data buffer associated with the transfer limited
535: \ accordingly by the "rw-endpoint" method to the
536: \ value OF max packet size
537: \ mps: Max Packet Size.
538: \ address: Address OF endpoint. 11-bit address. The lower 7-bits represent
539: \ the USB addres and the upper 4-bits represent the Endpoint
540: \ number.
541:
542:
543:
544: : (do-rw-endpoint)
545: ( pt ed-type toggle buffer length mps address -- toggle TRUE|toggle FALSE )
546: 4 pick ( pt ed-type toggle buffer length mps address toggle )
547: TO saved-rw-start-toggle ( pt ed-type toggle buffer length mps address )
548: (ed-prepare-rw) ( FALSE | pt ed-type toggle buffer length mps )
549: invert IF FALSE EXIT THEN
550: (td-prepare-rw) ( FALSE | pt ed-type toggle buffer length mps head )
551: invert IF FALSE EXIT THEN
552: (td-data-rw) ( FALSE | pt et head )
553: invert IF FALSE EXIT THEN
554: saved-rw-ed ed>tdqhp l!-le ( pt et )
555: saved-rw-ed ed>tdqhp l@-le td>ntd l@-le TO NEXT-TD \ save for a stalled
556: (ed-ready-rw)
557: invert IF FALSE EXIT THEN
558: (wait-td-retire)
559: (process-retired-td) ( TRUE | FALSE )
560: ;
561:
562:
563: \ rw-endpoint: The method is an externally visible method to be exported
564: \ to the child nodes. It uses the internal method
565: \ "(DO-rw-endpoint)", the required number OF times based on the
566: \ actual length OF transfer, so that the limitataion OF MAX-TDS
567: \ DO not hinder the transfer.
568:
569: \ Arguments:
570: \ pt: Packet type
571: \ 0 -> IN
572: \ 1 -> OUT
573: \ 2 -> SETUP
574: \ et: Endpoint type
575: \ 0 -> Control
576: \ 1 -> Bulk
577: \ toggle: Starting toggle for this transfer
578: \ buffer length: Data buffer associated with the transfer
579: \ mps: Max Packet Size.
580: \ address: Address OF endpoint. 11-bit address. The lower 7-bits represent
581: \ the USB addres and the upper 4-bits represent the Endpoint
582: \ number.
583:
584:
585: 0 VALUE transfer-len
586: 0 VALUE mps-current
587: 0 VALUE addr-current
588: 0 VALUE usb-addr
589: 0 VALUE toggle-current
590: 0 VALUE type-current
591: 0 VALUE pt-current
592: 0 VALUE read-status
593: 0 VALUE counter
594: 0 VALUE residue
595:
596:
597: : rw-endpoint
598: ( pt ed-type toggle buffer length mps address -- )
599: ( toggle TRUE |toggle FALSE )
600:
601: \ a single transfer descriptor can point to a buffer OF
602: \ 8192 bytes a block on the CDROM has 2048 bytes
603: \ but a single transfer is constrained by the MPS
604:
605: 2 pick TO transfer-len ( pt ed-type toggle buffer length mps address )
606: 1 pick TO mps-current ( pt ed-type toggle buffer length mps address )
607: TRUE TO read-status ( pt ed-type toggle buffer length mps address )
608: transfer-len mps-current num-free-tds * <= IF
609: (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
610: TO read-status ( toggle )
611: TO toggle-current
612: ELSE
613: TO usb-addr ( pt ed-type toggle buffer length mps )
614: 2drop ( pt ed-type toggle buffer )
615: TO addr-current ( pt ed-type toggle )
616: TO toggle-current ( pt ed-type )
617: TO type-current ( pt )
618: TO pt-current
619: transfer-len mps-current num-free-tds * /mod ( residue count )
620: ( remainder=residue quotient=count )
621: TO counter ( residue )
622: TO residue
623: mps-current num-free-tds * TO transfer-len BEGIN
624: counter 0 > ( TRUE | FALSE )
625: read-status TRUE = and ( TRUE | FALSE )
626: WHILE
627: pt-current type-current toggle-current ( pt ed-type toggle )
628: addr-current transfer-len ( pt ed-type toggle buffer length )
629: mps-current ( pt ed-type toggle buffer length mps )
630: usb-addr (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
631: TO read-status ( toggle )
632: TO toggle-current
633: addr-current transfer-len + TO addr-current
634: counter 1- TO counter
635: REPEAT
636: residue 0<> ( TRUE |FALSE )
637: read-status TRUE = and IF
638: residue TO transfer-len
639: pt-current type-current toggle-current ( pt ed-type toggle )
640: addr-current transfer-len ( pt ed-type toggle buffer length )
641: mps-current ( pt ed-type toggle buffer length mps )
642: usb-addr (do-rw-endpoint) ( toggle TRUE | toggle FALSE )
643: TO read-status
644: TO toggle-current
645: THEN
646: THEN
647: read-status invert IF
648: THEN
649: toggle-current ( toggle )
650: read-status ( TRUE | FALSE )
651: ;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.