Annotation of qemu/roms/SLOF/slof/fs/usb/usb-support.fs, revision 1.1.1.1

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: ;

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.