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