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

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

unix.superglobalmegacorp.com

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