Annotation of qemu/roms/SLOF/slof/fs/usb/usb-ohci.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: 
                     14: \ We expect to base address of the OHCI controller on the stack:
                     15: 
                     16: CONSTANT baseaddrs
                     17: 
                     18: s" OHCI base address = " baseaddrs usb-debug-print-val
                     19: 
                     20: 
                     21: \ Open Firmware Properties
                     22: 
                     23: 
                     24: s" usb" 2dup device-name device-type
                     25: 1 encode-int s" #address-cells" property
                     26: 0 encode-int s" #size-cells" property
                     27: 
                     28: 
                     29: \ converts physical address to text unit string
                     30: 
                     31: 
                     32: : encode-unit ( port -- unit-str unit-len ) 1 hex-encode-unit ;
                     33: 
                     34: 
                     35: \ Converts text unit string to phyical address
                     36: 
                     37: 
                     38: : decode-unit ( addr len -- port ) 1 hex-decode-unit ;
                     39: 
                     40: 
                     41: \  Data Structure Definitions
                     42: \ OHCI Task Descriptor Structure.
                     43: 
                     44: 
                     45: STRUCT
                     46:    /l field td>tattr
                     47:    /l field td>cbptr
                     48:    /l field td>ntd
                     49:    /l field td>bfrend
                     50: CONSTANT /tdlen
                     51: 
                     52: 
                     53: \ OHCI Endpoint Descriptor Structure.
                     54: 
                     55: 
                     56: STRUCT
                     57:    /l field ed>eattr
                     58:    /l field ed>tdqtp
                     59:    /l field ed>tdqhp
                     60:    /l field ed>ned
                     61: CONSTANT /edlen
                     62: 
                     63: 
                     64: \ HCCA Done queue location packaged as a structure for ease OF use.
                     65: 
                     66: 
                     67: STRUCT
                     68:    /l field hc>hcattr
                     69:    /l field hc>hcdone
                     70: CONSTANT /hclen
                     71: 
                     72: 
                     73: \ OHCI Memory Mapped Registers
                     74: 
                     75: 
                     76: \ : get-base-address ( -- baseaddr )
                     77: \    s" assigned-addresses" get-my-property  IF
                     78: \       s" not possible"  usb-debug-print
                     79: \       -1
                     80: \    ELSE                  ( addr len )
                     81: \       decode-int drop    ( addr len )
                     82: \       decode-int drop    ( addr len )
                     83: \       decode-int nip nip ( n )
                     84: \    THEN
                     85: \    \ TODO: Use translate-address here
                     86: \ ;
                     87: 
                     88: \ get-base-address CONSTANT baseaddrs
                     89: 
                     90: baseaddrs      CONSTANT HcRevision
                     91: baseaddrs 4  + CONSTANT hccontrol
                     92: baseaddrs 8  + CONSTANT hccomstat
                     93: baseaddrs 0c + CONSTANT hcintstat
                     94: baseaddrs 14 + CONSTANT hcintdsbl
                     95: baseaddrs 18 + CONSTANT hchccareg
                     96: baseaddrs 20 + CONSTANT hcctrhead
                     97: baseaddrs 24 + CONSTANT hccurcont
                     98: baseaddrs 28 + CONSTANT hcbulkhead
                     99: baseaddrs 2c + CONSTANT hccurbulk
                    100: baseaddrs 30 + CONSTANT hcdnehead
                    101: baseaddrs 34 + CONSTANT hcintrval
                    102: baseaddrs 40 + CONSTANT HcPeriodicStart
                    103: baseaddrs 48 + CONSTANT hcrhdescA
                    104: baseaddrs 4c + CONSTANT hcrhdescB
                    105: baseaddrs 50 + CONSTANT HcRhStatus
                    106: baseaddrs 54 + CONSTANT hcrhpstat
                    107: baseaddrs 58 + CONSTANT hcrhpstat2
                    108: baseaddrs 5c + CONSTANT hcrhpstat3
                    109: 
                    110: usb-debug-flag IF
                    111:     0 config-l@ ."    - VENDOR: " 8 .r cr
                    112:    40 config-l@ ."    - PMC   : " 8 .r
                    113:    44 config-l@ ."      PMCSR : " 8 .r cr
                    114:    E0 config-l@ ."    - EXT1  : " 8 .r
                    115:    E4 config-l@ ."      EXT2  : " 8 .r cr
                    116: THEN
                    117: 
                    118: \ Constants for INTSTAT register
                    119: 
                    120: 2 CONSTANT WDH
                    121: 
                    122: \ Constants for RH Port Status Register
                    123: 
                    124: 1      CONSTANT RHP-CCS    \ Current Connect Status
                    125: 2      CONSTANT RHP-PES    \ Port Enable Status
                    126: 10     CONSTANT RHP-PRS    \ Port Reset Status
                    127: 100    CONSTANT RHP-PPS    \ Port Power Status
                    128: 10000  CONSTANT RHP-CSC    \ Connect Status Changed
                    129: 100000 CONSTANT RHP-PRSC   \ Port Reset Status Changed
                    130: 
                    131: 
                    132: \ Constants for OHCI
                    133: 
                    134: 0 CONSTANT OHCI-DP-SETUP
                    135: 1 CONSTANT OHCI-DP-OUT
                    136: 2 CONSTANT OHCI-DP-IN
                    137: 3 CONSTANT OHCI-DP-INVALID
                    138: 
                    139: \ 8-byte Standard Device Requests + Hub class specific requests.
                    140: 
                    141: 8006000100001200 CONSTANT get-ddescp
                    142: 8006000200000900 CONSTANT get-cdescp
                    143: 8006000400000900 CONSTANT get-idescp
                    144: 8006000500000700 CONSTANT get-edescp
                    145: A006000000001000 CONSTANT get-hdescp
                    146: 0009010000000000 CONSTANT set-cdescp
                    147: 2303010004000000 CONSTANT hpenable-set
                    148: 2303040001000000 CONSTANT hp1rst-set
                    149: 2303040002000000 CONSTANT hp2rst-set
                    150: 2303040003000000 CONSTANT hp3rst-set
                    151: 2303040004000000 CONSTANT hp4rst-set
                    152: 2303080001000000 CONSTANT hp1pwr-set
                    153: 2303080002000000 CONSTANT hp2pwr-set
                    154: 2303080003000000 CONSTANT hp3pwr-set
                    155: 2303080004000000 CONSTANT hp4pwr-set
                    156: A003000000000400 CONSTANT hstatus-get
                    157: A300000001000400 CONSTANT hp1sta-get
                    158: A300000002000400 CONSTANT hp2sta-get
                    159: A300000003000400 CONSTANT hp3sta-get
                    160: A300000004000400 CONSTANT hp4sta-get
                    161: 8008000000000100 CONSTANT get-config
                    162: 
                    163: A1FE000000000100 CONSTANT GET-MAX-LUN
                    164: 
                    165: 2    18 lshift CONSTANT DATA0-TOGGLE
                    166: 3    18 lshift CONSTANT DATA1-TOGGLE
                    167: 0f   1c lshift CONSTANT CC-FRESH-TD
                    168: 8 CONSTANT STD-REQUEST-SETUP-SIZE
                    169: 0    13 lshift CONSTANT TD-DP-SETUP
                    170: 1    13 lshift CONSTANT TD-DP-OUT
                    171: 2    13 lshift CONSTANT TD-DP-IN
                    172: 
                    173: 400001    CONSTANT ed-cntatr
                    174: 400002    CONSTANT ed-cntatr1
                    175: 80081     CONSTANT ed-hubatr
                    176: 80000     CONSTANT ed-defatr
                    177: 0f0e40000 CONSTANT td-attr
                    178: 00 VALUE ptr
                    179: 
                    180: 
                    181: \ TD Management constants and Data structures.
                    182: 
                    183: 
                    184: 200 CONSTANT MAX-TDS
                    185: 0 VALUE td-freelist-head
                    186: 0 VALUE td-freelist-tail
                    187: 0 VALUE num-free-tds
                    188: 0 VALUE max-rh-ports
                    189: 0 VALUE current-stat
                    190: 
                    191: INSTANCE VARIABLE td-list-region
                    192: 
                    193: \ ED Management constants
                    194: 
                    195: 
                    196: 14 CONSTANT MAX-EDS
                    197: 0 VALUE ed-freelist-head
                    198: 0 VALUE num-free-eds
                    199: INSTANCE VARIABLE ed-list-region
                    200: 0 VALUE usb-address
                    201: 0 VALUE initial-hub-address
                    202: 0 VALUE new-device-address
                    203: 0 VALUE mps
                    204: 0 VALUE DEBUG-TDS
                    205: 0 VALUE case-failed  \ available for general use to see IF a CASE statement
                    206:                      \ failed or not.
                    207: 0 VALUE WHILE-failed \ available for general use to see IF a WHILE LOOP
                    208:                      \ failed in the middle. Used to break from the
                    209:                      \ WHILE LOOP
                    210: 
                    211: 8 CONSTANT DEFAULT-CONTROL-MPS
                    212: 12 CONSTANT DEVICE-DESCRIPTOR-LEN
                    213: 1 CONSTANT DEVICE-DESCRIPTOR-TYPE
                    214: 1 CONSTANT DEVICE-DESCRIPTOR-TYPE-OFFSET
                    215: 4 CONSTANT DEVICE-DESCRIPTOR-DEVCLASS-OFFSET
                    216: 7 CONSTANT DEVICE-DESCRIPTOR-MPS-OFFSET
                    217: 
                    218: 20 CONSTANT BULK-CONFIG-DESCRIPTOR-LEN
                    219: 
                    220: 9 CONSTANT HUB-DEVICE-CLASS
                    221: 0 CONSTANT NO-CLASS
                    222: 
                    223: VARIABLE  setup-packet     \ 8 bytes for setup packet
                    224: VARIABLE  ch-buffer        \ 1 byte character buffer
                    225: 
                    226: INSTANCE VARIABLE dd-buffer
                    227: INSTANCE VARIABLE cd-buffer
                    228: 
                    229: 
                    230: \ Temporary variables for functions. These variables have to be initialized
                    231: \ before usage in functions and their values assume significance only during
                    232: \ the function's execution time. Should be used like local variables.
                    233: \ CAUTION:
                    234: \ If you are calling functions that destroy contents OF these variables, be
                    235: \ smart enuf to save the values before calling them.
                    236: \ It is recommended that these temporary variables are used only amidst normal
                    237: \ FORTH words -- not among the vicinity OF any OF the functions OF this node.
                    238: 
                    239: 
                    240: 0 VALUE temp1
                    241: 0 VALUE temp2
                    242: 0 VALUE temp3
                    243: 0 VALUE extra-bytes
                    244: 0 VALUE num-td
                    245: 0 VALUE current
                    246: 
                    247: 0 VALUE device-speed
                    248: 
                    249: 
                    250: \ Debug functions for displaying ED, TD and their combo list.
                    251: 
                    252: : Show-OHCI-Register
                    253:    ." -> OHCI-Register: " cr
                    254:    ." - HcControl : " hccontrol       rl@-le 8 .r
                    255:    ."   CmdStat   : " hccomstat       rl@-le 8 .r
                    256:    ."   HcInterr. : " hcintstat       rl@-le 8 .r cr
                    257: 
                    258:    ." - HcFmIntval: " hcintrval       rl@-le 8 .r
                    259:    ."   Per. Start: " HcPeriodicStart rl@-le 8 .r cr
                    260: 
                    261:    ." - PortStat-1: " hcrhpstat       rl@-le 8 .r
                    262:    ."   PortStat-2: " hcrhpstat2      rl@-le 8 .r
                    263:    ."   PortStat-3: " hcrhpstat3      rl@-le 8 .r cr
                    264: 
                    265:    ."   Descr-A   : " hcrhdescA       rl@-le 8 .r
                    266:    ."   Descr-B   : " hcrhdescB       rl@-le 8 .r
                    267:    ."   HcRhStat  : " HcRhStatus      rl@-le 8 .r cr
                    268: ;
                    269: 
                    270: : display-ed ( ED-ADDRESS -- )
                    271:    TO temp1
                    272:    usb-debug-flag IF
                    273:       s" Dump OF ED " type temp1 u. cr
                    274:       s" eattr    : " type temp1 ed>eattr l@-le u. cr
                    275:       s" tdqhp    : " type temp1 ed>tdqhp l@-le u. cr
                    276:       s" tdqtp    : " type temp1 ed>tdqtp l@-le u. cr
                    277:       s" ned      : " type temp1 ed>ned   l@-le u. cr
                    278:    THEN
                    279: ;
                    280: 
                    281: 
                    282: \ Displays the transfer descriptors
                    283: 
                    284: : display-td ( TD-ADDRESS -- )
                    285:    TO temp1
                    286:    usb-debug-flag IF
                    287:       s" TD " type temp1 u. s" dump: " type cr
                    288:       s" td>tattr  : " type temp1 td>tattr l@-le u. cr
                    289:       s" td>cbptr  : " type temp1 td>cbptr l@-le u. cr
                    290:       s" td>ntd    : " type temp1 td>ntd l@-le u. cr
                    291:       s" td>bfrend : " type temp1 td>bfrend l@-le u. cr
                    292:    THEN
                    293: ;
                    294: 
                    295: 
                    296: \ display's the descriptors
                    297: 
                    298: 
                    299: : display-descriptors ( ED-ADDRESS -- )
                    300:    10  1- not and             ( ED-ADDRESS~ )
                    301:    dup display-ed ed>tdqhp l@-le  BEGIN ( ED-ADDRESS~ )
                    302:       10  1- not and         ( ED-ADDRESS~ )
                    303:       dup 0<>                ( ED-ADDRESS~ TRUE | FALSE )
                    304:    WHILE
                    305:       dup  display-td td>ntd l@-le ( ED-ADDRESS~ )
                    306:    REPEAT
                    307:    drop
                    308: ;
                    309: 
                    310: 
                    311: \ ---------------------------------------------------------------------------
                    312: \                      TD LIST MANAGEMENT WORDS
                    313: \                       ------------------------
                    314: \        The following are WORDS internal to this node. They are supposed to
                    315: \        be used by other WORDS inside this device node.
                    316: \        The first three WORDS below form the interface. The fourth and fifth
                    317: \        word is a helper function and is not exposed to other portions OF this
                    318: \        device node.
                    319: \        a) initialize-td-free-list
                    320: \        b) allocate-td-list
                    321: \        c) (free-td-list)
                    322: \        d) find-td-list-tail-and-size
                    323: \        e) zero-out-a-td-except-link
                    324: \ ----------------------------------------------------------------------------
                    325: 
                    326: 
                    327: : zero-out-a-td-except-link ( td -- )
                    328: 
                    329: 
                    330:    \ There r definitely smarter ways to DO it especially
                    331:    \ on a 64-bit machine.
                    332: 
                    333:    \ Optimization, Portability:
                    334:    \ --------------------------
                    335:    \ Replace the following code by two "!" OF zeroes. Since
                    336:    \ we know that an "td" is actually 16 bytes and that we
                    337:    \ will be executing on a 64-bit machine, we can finish OFf
                    338:    \ with 2 stores.  But that WONT be portable.
                    339: 
                    340: 
                    341:    dup 0 swap td>tattr  l!-le          ( td )
                    342:    dup 0 swap td>cbptr  l!-le          ( td )
                    343:    dup 0 swap td>bfrend l!-le          ( td )
                    344:    drop
                    345: ;
                    346: 
                    347: 
                    348: \ COLON DEFINITION: initialize-td-free-list - Internal Function
                    349: 
                    350: \ Initialize the TD Free List Region and create a linked list OF successive
                    351: \ TDs. Note that the NEXT pointers are all in little-endian and they
                    352: \ can be directly used for HC purposes.
                    353: 
                    354: 
                    355: : initialize-td-free-list ( -- )
                    356:    MAX-TDS 0= IF EXIT THEN
                    357:    td-list-region @ 0= IF EXIT THEN
                    358:    td-list-region @ TO temp1
                    359:    0 TO temp2  BEGIN
                    360:       temp1 zero-out-a-td-except-link
                    361:       temp1 /tdlen + dup   temp1 td>ntd   l!-le TO temp1
                    362:       temp2 1+ TO temp2
                    363:       temp2 MAX-TDS =          ( TRUE | FALSE )
                    364:    UNTIL
                    365:    temp1 /tdlen - dup 0 swap td>ntd l!-le TO td-freelist-tail
                    366:    td-list-region @ TO td-freelist-head
                    367:    MAX-TDS TO num-free-tds
                    368: ;
                    369: 
                    370: 
                    371: \ COLON DEFINITION: allocate-td-list -- Internal function
                    372: \ Argument:
                    373: \ The function accepts a non-negative number and allocates
                    374: \ a TD-LIST containing that many TDs. A TD-LIST is a list
                    375: \ OF TDs that are linked by the next-td field. The next-td
                    376: \ field is in little-endian mode so that the TD list can
                    377: \ be directly re-used by the HC.
                    378: \ Return value:
                    379: \ The function returns "head" and "tail" OF the allocated
                    380: \ TD-LIST. If for any reason, the function cannot allocate
                    381: \ the TD-LIST, the function returns 2 NULL pointers in the
                    382: \ stack indicating that the allocation failed.
                    383: 
                    384: \ Note that the TD list returned is NULL terminated. i.e
                    385: \ the nextTd field OF the tail is NULL.
                    386: 
                    387: 
                    388: 
                    389: : allocate-td-list ( n -- head tail )
                    390:    dup 0= IF drop 0 0 EXIT THEN                ( 0 0 )
                    391:    dup num-free-tds > IF drop 0 0 EXIT THEN     ( 0 0 )
                    392:    dup num-free-tds = IF                       ( n )
                    393:       drop td-freelist-head td-freelist-tail   ( td-freelist-head td-freelist-tail )
                    394:       0 TO td-freelist-head                    ( td-freelist-head td-freelist-tail )
                    395:       0 TO td-freelist-tail                    ( td-freelist-head td-freelist-tail )
                    396:       0 TO num-free-tds                                ( td-freelist-head td-freelist-tail )
                    397:       EXIT
                    398:    THEN
                    399: 
                    400:    \ If we are here THEN we know that the requested number OF TDs is less
                    401:    \ than what we actually have. We need TO traverse the list and find the
                    402:    \ new Head pointer position and THEN update the head pointer accordingly.
                    403:    \ Update num-free-tds
                    404: 
                    405:    dup num-free-tds swap - TO num-free-tds     ( n )
                    406: 
                    407:    \ Traverse through the Free list to identify the element that exists after
                    408:    \ "n" TDs. Use the info to return the head and tail pointer and update
                    409:    \ the new td-list-head
                    410: 
                    411:    td-freelist-head                            ( n td-list-head )
                    412:    dup TO temp1                                        ( n td-list-head )
                    413:    swap                                        ( td-list-head n )
                    414:    0 DO                                                ( td-list-head   )
                    415:       temp1 TO temp2                           ( td-list-head   )
                    416:       temp1 td>ntd l@-le   TO   temp1          ( td-list-head   )
                    417:    LOOP                                                ( td-list-head   )
                    418:    temp2                                       ( td-list-head td-list-tail )
                    419:    dup td>ntd 0 swap l!-le                     ( td-list-head td-list-tail )
                    420:    temp1 TO td-freelist-head                   ( td-list-head td-list-tail )
                    421: ;
                    422: 
                    423: 
                    424: \ COLON DEFINITION: find-td-list-tail-and-size
                    425: \ This function counts the number OF TD elements
                    426: \ in the given list. It also returns the last tail
                    427: \ TD OF the TD list.
                    428: 
                    429: \ ASSUMPTION:
                    430: \ A NULL terminated TD list is assumed. A not-well formed
                    431: \ list can result in in-determinate behaviour.
                    432: 
                    433: \ ROOM FOR ENHANCEMENT:
                    434: \ We could arrive at a generic function for counting
                    435: \ list elements to which the next-ptr OFfset can also
                    436: \ be passed as an argument (in this case it is >ntd)
                    437: \ This function can THEN be changed to call the
                    438: \ function with "0 >ntd" as an additional argument
                    439: \ (apart from head and tail)
                    440: 
                    441: 
                    442: : find-td-list-tail-and-size  ( head -- tail n )
                    443:    TO temp1
                    444:    0 TO temp2
                    445:    0 TO temp3
                    446:    DEBUG-TDS  IF
                    447:       s" BEGIN find-td-list-tail-and-size: "   usb-debug-print
                    448:    THEN
                    449:    BEGIN
                    450:       temp1 0<>                                        ( TRUE|FALSE )
                    451:    WHILE
                    452:       DEBUG-TDS  IF
                    453:          temp1 u. cr
                    454:       THEN
                    455:       temp1 TO temp3
                    456:       temp1 td>ntd l@-le TO temp1
                    457:       temp2 1+ TO temp2
                    458:    REPEAT
                    459:    temp3 temp2                                 ( tail n )
                    460:    DEBUG-TDS  IF
                    461:       s" END find-td-list-tail-and-size"   usb-debug-print
                    462:    THEN
                    463: ;
                    464: 
                    465: 
                    466: \ COLON DEFINITION: (free-td-list)
                    467: 
                    468: \ Arguments: (head  --)
                    469: \ The "head" pointer OF the TD-LIST to be freed is passed as
                    470: \ an argument to this function. The function merely adds the list to the
                    471: \ already existing TD-LIST
                    472: 
                    473: \ Assumptions:
                    474: \ The function assumes that the TD-LIST passed as argument is a well-formed
                    475: \ list. The function does not DO any check on it.
                    476: \ But since, the "TD-LIST" is generally freed from the DONE-QUEUE which is
                    477: \ a well-formed list, the interface makes much sense.
                    478: 
                    479: \ Return values:
                    480: \ Nothing is returned. The arguments passed are popped OFf.
                    481: 
                    482: 
                    483: : (free-td-list) ( head  -- )
                    484: 
                    485:    \ Enhancement:
                    486:    \ We could zero-out-a-td-except-link for the TD list that is being freed.
                    487:    \ This way, we could prevent some nasty repercussions OF bugs (that r yet
                    488:    \ to be discovered). but we can include this enhancement during the testing
                    489:    \ phase.
                    490: 
                    491:    dup find-td-list-tail-and-size num-free-tds + TO num-free-tds ( head tail )
                    492:    td-freelist-tail 0=  IF                                      ( head tail )
                    493:       dup TO td-freelist-tail                                   ( head tail )
                    494:    THEN                                                                 ( head tail )
                    495:    td>ntd td-freelist-head swap l!-le                           ( head )
                    496:    TO td-freelist-head
                    497: ;
                    498: 
                    499: 
                    500: \          END OF TD LIST MANAGEMENT WORDS
                    501: \         ED Management section BEGINs
                    502: \         ----------------------------
                    503: 
                    504: 
                    505: : zero-out-an-ed-except-link ( ed -- )
                    506: 
                    507:    \ There are definitely smarter ways to do it especially
                    508:    \ on a 64-bit machine.
                    509: 
                    510:    \ Optimization, Portability:
                    511:    \ --------------------------
                    512:    \ Replace by a  "!" and "l!". we know that an "ed" is
                    513:    \ actually 16 bytes and that we will be executing on
                    514:    \ a 64-bit machine, we can finish OFf with 2 stores.
                    515:    \ But that WONT be portable.
                    516: 
                    517:    dup 0 swap ed>eattr  l!-le          ( ed )
                    518:    dup 0 swap ed>tdqtp  l!-le          ( ed )
                    519:    dup 0 swap ed>tdqhp  l!-le          ( ed )
                    520:    drop
                    521: ;
                    522: 
                    523: \ Intialises ed-list afresh
                    524: 
                    525: : initialize-ed-free-list ( -- )
                    526:    MAX-EDS 0= IF EXIT THEN
                    527:    ed-list-region @ 0= IF
                    528:       s" init-ed-list: ed-list-region is not allocated!"   usb-debug-print
                    529:       EXIT
                    530:    THEN
                    531:    ed-list-region @ TO temp1
                    532:    0 TO temp2   BEGIN
                    533:       temp1 zero-out-an-ed-except-link
                    534:       temp1 /edlen + dup   temp1 ed>ned   l!-le TO temp1
                    535:       temp2 1+ TO temp2
                    536:       temp2 MAX-EDS =
                    537:    UNTIL
                    538:    temp1 /edlen - ed>ned 0 swap l!-le
                    539:    ed-list-region @ TO ed-freelist-head
                    540:    MAX-EDS TO num-free-eds
                    541: ;
                    542: 
                    543: 
                    544: \ allocate an ed and return ed address
                    545: 
                    546: 
                    547: : allocate-ed  ( -- ed-ptr )
                    548:    num-free-eds 0= IF 0 EXIT THEN
                    549:    ed-freelist-head                                    ( ed-freelist-head )
                    550:    ed-freelist-head ed>ned l@-le TO ed-freelist-head   ( ed-freelist-head )
                    551:    num-free-eds 1- TO num-free-eds                     ( ed-freelist-head )
                    552:    dup ed>ned 0 swap l!-le \ Terminate the Link.       ( ed-freelist-head )
                    553: ;
                    554: 
                    555: 
                    556: \ free the given ed pointer
                    557: 
                    558: : free-ed ( ed-ptr  -- )
                    559:    dup zero-out-an-ed-except-link                      ( ed-ptr )
                    560:    dup ed>ned ed-freelist-head swap l!-le              ( ed-ptr )
                    561:    TO ed-freelist-head
                    562:    num-free-eds 1+ TO num-free-eds
                    563: ;
                    564: 
                    565: 
                    566: \ Buffer allocations
                    567: \ ------------------
                    568: \ Note:
                    569: \ -----
                    570: \ 1. What should we DO IF alloc-mem fails ?
                    571: \ 2. alloc-mem must return aligned memory addresses.
                    572: \ 3. alloc-mem must return DMAable memory!
                    573: 
                    574: \ Memory for the HCCA - must stay allocated as long as the HC is operational!
                    575: 100 alloc-mem VALUE hchcca
                    576: hchcca ff and IF
                    577:    \ This should never happen - alloc-mem always aligns
                    578:    s" Warning: hchcca not aligned!" usb-debug-print
                    579: THEN
                    580: 
                    581: 84 hchcca + CONSTANT hchccadneq
                    582: 
                    583: 
                    584: : (allocate-mem)  ( -- )
                    585:    /tdlen MAX-TDS * 10 + alloc-mem dup td-list-region !  ( td-list-region-ptr )
                    586:    f and IF
                    587:       s" Warning: td-list-region not aligned!" usb-debug-print
                    588:    THEN
                    589:    initialize-td-free-list
                    590: 
                    591:    /edlen MAX-EDS * 10 + alloc-mem dup ed-list-region !  ( ed-list-region-ptr )
                    592:    f and IF
                    593:       s" Warning: ed-list-region not aligned!" usb-debug-print
                    594:    THEN
                    595:    initialize-ed-free-list
                    596: 
                    597:    DEVICE-DESCRIPTOR-LEN chars alloc-mem dd-buffer !
                    598:    BULK-CONFIG-DESCRIPTOR-LEN chars alloc-mem cd-buffer !
                    599: ;
                    600: 
                    601: 
                    602: \ The method makes sure that when the host node is closed all
                    603: \ associated buffer allocations made for data-structures as
                    604: \ well as data-buffers are freed
                    605: 
                    606: : (de-allocate-mem)  ( -- )
                    607:    td-list-region @ ?dup IF
                    608:       /tdlen MAX-TDS * 10 + free-mem
                    609:       0 td-list-region !
                    610:    THEN
                    611:    ed-list-region @ ?dup IF
                    612:       /edlen MAX-EDS * 10 + free-mem
                    613:       0 ed-list-region !
                    614:    THEN
                    615:    dd-buffer @ ?dup IF
                    616:       DEVICE-DESCRIPTOR-LEN free-mem
                    617:       0 dd-buffer !
                    618:    THEN
                    619:    cd-buffer @ ?dup IF
                    620:       BULK-CONFIG-DESCRIPTOR-LEN free-mem
                    621:       0 cd-buffer !
                    622:    THEN
                    623: ;
                    624: 
                    625: 
                    626: \ Suspend hostcontroller (and the bus).
                    627: \ This method must be called before the operating system starts.
                    628: \ It prevents the HC from doing DMA in the background during boot
                    629: \ (e.g. updating its frame number counter in the HCCA)
                    630: 
                    631: : hc-suspend  ( -- )
                    632:    \ s" USB HC suspend with hccontrol=" type hccontrol . cr
                    633:    00C3 hccontrol rl!-le             \ Suspend USB host controller
                    634: ;
                    635: 
                    636: 
                    637: \ OF methods
                    638: 
                    639: : open  ( -- TRUE|FALSE )
                    640:    (allocate-mem)
                    641:    TRUE
                    642: ;
                    643: 
                    644: : close  ( -- )
                    645:    (de-allocate-mem)
                    646: ;
                    647: 
                    648: 
                    649: \ COLON DEFINITION: HC-enable-control-list-processing
                    650: \ Enables USB HC transactions on control list.
                    651: 
                    652: : HC-enable-control-list-processing ( -- )
                    653:    hccomstat dup rl@-le 02 or swap rl!-le
                    654:    hccontrol dup rl@-le 10 or swap rl!-le
                    655: ;
                    656: 
                    657: 
                    658: \ COLON DEFINTION: HC-enable-bulk-list-processing
                    659: \ PENDING: Remove Hard coded constants.
                    660: 
                    661: : HC-enable-bulk-list-processing ( -- )
                    662:    hccomstat dup rl@-le 04 or swap rl!-le
                    663:    hccontrol dup rl@-le 20 or swap rl!-le
                    664: ;
                    665: 
                    666: 
                    667: : HC-enable-interrupt-list-processing ( -- )
                    668:    hccontrol dup rl@-le 04 or swap rl!-le
                    669: ;
                    670: 
                    671: 
                    672: \ Clearing WDH to allow HC to write into DOne queue again
                    673: 
                    674: : (HC-ACK-WDH) ( -- )   WDH hcintstat rl!-le ;
                    675: 
                    676: \ Checking whether anything has been written into DOne queue
                    677: 
                    678: : (HC-CHECK-WDH) ( -- ) hcintstat rl@-le WDH and 0<> ;
                    679: 
                    680: 
                    681: \ Disable USB transaction and keep it ready
                    682: 
                    683: : disable-control-list-processing ( -- )
                    684:    hccontrol dup rl@-le ffffffef and swap rl!-le
                    685:    hccomstat dup rl@-le fffffffd and swap rl!-le
                    686: ;
                    687: 
                    688: : disable-bulk-list-processing ( -- )
                    689:    hccontrol dup rl@-le ffffffdf and swap rl!-le
                    690:    hccomstat dup rl@-le fffffffb and swap rl!-le
                    691: ;
                    692: 
                    693: 
                    694: : disable-interrupt-list-processing ( -- )
                    695:    hccontrol dup rl@-le fffffffb and swap rl!-le
                    696: ;
                    697: 
                    698: 
                    699: \ COLON DEFINITION: fill-TD-list
                    700: 
                    701: \ This function accepts a TD list and a data-buffer and
                    702: \ distributes this data buffer over the TD list depending
                    703: \ on the Max Packet Size.
                    704: 
                    705: \ Arguments:
                    706: \ ----------
                    707: \ (from bottom OF stack)
                    708: \ 1. addr -- Address OF the data buffer
                    709: \ 2. dlen -- Length OF the data buffer above.
                    710: \ 3. dir  -- Tells whether the TDs r for an IN or
                    711: \            OUT transaction.
                    712: \ 4. MPS  -- Maximum Packet Size associated with the endpoint
                    713: \            that will use this TD list.
                    714: \ 5. TD-List-Head - Head pointer OF the List OF TDs.
                    715: \            This list is NOT expected to be NULL terminated.
                    716: 
                    717: \ Assumptions:
                    718: \ -----------
                    719: \ 1. TD-List for data is well-formed and has sufficient entries
                    720: \    to hold "dlen".
                    721: \ 2. The TDs toggle field is assumed to be taken from the endpoint
                    722: \    descriptor's "toggle carry" field.
                    723: \ 3. Assumes that the caller specifies the correct start-toggle.
                    724: \    If the caller specifies a wrong data toggle OF 1 for a SETUP
                    725: \    PACKET, this method will not find it out.
                    726: 
                    727: \ COLON DEFINTION: (toggle-current-toggle)
                    728: \ Scope: Internal to fill-TD-list
                    729: \ Functionality:
                    730: \        Toggles the "T" field that is passed as argument.
                    731: \        "T" as in the "T" field OF the TD.
                    732: 
                    733: 0 VALUE current-toggle
                    734: : fill-TD-list ( start-toggle addr dlen dp MPS TD-List-Head -- )
                    735:    TO temp1                            ( start-toggle addr dlen dp MPS )
                    736:    TO temp2                            ( start-toggle addr dlen dp )
                    737:    CASE                                        ( start-toggle addr dlen )
                    738:       OHCI-DP-SETUP  OF  TD-DP-SETUP TO temp3 ENDOF ( start-toggle addr dlen )
                    739:       OHCI-DP-IN     OF  TD-DP-IN    TO temp3 ENDOF ( start-toggle addr dlen )
                    740:       OHCI-DP-OUT    OF  TD-DP-OUT   TO temp3 ENDOF ( start-toggle addr dlen )
                    741:       dup            OF  -1          TO temp3       ( start-toggle addr dlen )
                    742:       s" fill-TD-list: Invalid DP specified"   usb-debug-print
                    743:                                                   ENDOF
                    744:    ENDCASE
                    745:    temp3 -1 = IF EXIT THEN                          ( start-toggle addr dlen )
                    746: 
                    747: 
                    748: \ temp1 -- TD-List-Head
                    749: \ temp2 -- Max Packet Size
                    750: \ temp3 -- TD-DP-IN or TD-DP-OUT or TD-DP-SETUP
                    751: 
                    752:    rot                                              ( addr dlen start-toggle )
                    753:    TO current-toggle swap                          ( dlen addr )
                    754:    BEGIN
                    755:       over temp2 >=                                ( dlen addr TRUE|FALSE )
                    756:    WHILE                                           ( dlen addr )
                    757:       dup temp1 td>cbptr l!-le                     ( dlen addr )
                    758:       current-toggle 18 lshift                      ( dlen addr current-toggle~ )
                    759:       DATA0-TOGGLE                        ( dlen  addr current-toggle~ toggle )
                    760:       CC-FRESH-TD temp3 or or or          ( dlen  addr or-result )
                    761:       temp1 td>tattr l!-le                ( dlen addr~  )
                    762:       dup temp2 1- + temp1 td>bfrend l!-le ( dlen addr~  )
                    763:       temp2 +                             ( dlen next-addr )
                    764:       swap temp2 - swap
                    765:       temp1 td>ntd l@-le TO temp1         ( dlen next-addr )
                    766:       current-toggle                      ( dlen next-addr current-toggle )
                    767:       CASE
                    768:          0 OF 1 TO current-toggle ENDOF
                    769:          1 OF 0 TO current-toggle ENDOF
                    770:       ENDCASE
                    771:    REPEAT                                   ( dlen addr )
                    772:    over 0<>  IF
                    773:       dup temp1 td>cbptr l!-le              ( dlen addr )
                    774:       current-toggle 18 lshift              ( dlen addr curent-toggle~ )
                    775:       DATA0-TOGGLE                          ( dlen addr curent-toggle~ toggle )
                    776:       CC-FRESH-TD temp3 or or or            ( dlen addr or-result )
                    777:       temp1 td>tattr l!-le                  ( dlen addr )
                    778:       + 1- temp1 td>bfrend l!-le
                    779:    ELSE
                    780:       2drop
                    781:    THEN
                    782: ;
                    783: 
                    784: 
                    785: \ COLON DEFINITION: (td-list-status )
                    786: \ FUNCTIONALITY:
                    787: \ To traverse the TD list to check for a TD carrying non-zero CC return the
                    788: \ respective TD address and CC ELSE 0
                    789: \ SCOPE:
                    790: \ Internal method
                    791: 
                    792: : (td-list-status) ( PointerToTDlist -- failingTD CCode TRUE | 0 )
                    793:    BEGIN        ( PointerToTDlist )
                    794:       dup 0<>   ( PointerToTDlist TRUE|FALSE )
                    795:    IF           ( PointerToTDlist )
                    796:       dup td>tattr l@-le f0000000 and 1c rshift dup 0= TRUE swap
                    797:        ( PointerToTDlist CCode TRUE TRUE|FALSE )
                    798:    ELSE
                    799:       drop FALSE dup ( FALSE )
                    800:    THEN
                    801:    WHILE
                    802:       drop drop td>ntd l@-le
                    803:    REPEAT
                    804: ;
                    805: 
                    806: 
                    807: \ ==================================================================
                    808: \ COLON DEFINITION: (wait-for-done-q)
                    809: \ FUNCTIONALITY:
                    810: \ To DO a timed polling OF the DOne queue and acknowledge and return
                    811: \ the address OF the last retired Td list
                    812: \ SCOPE:
                    813: \ Internal method
                    814: \ ==================================================================
                    815: 
                    816: : (wait-for-done-q)           ( timeout -- TD-list TRUE | FALSE )
                    817:    BEGIN                      ( timeout )
                    818:       dup 0<>                 ( timeout TRUE|FALSE )
                    819:       (HC-CHECK-WDH) NOT      ( timeout TRUE|FALSE TRUE|FALSE )
                    820:       AND                     \ not timed out AND WDH-bit not set
                    821:       WHILE
                    822:       1 ms                    \ wait
                    823:       1-                      ( timeout )
                    824:       dup ff and 0= IF show-proceed THEN
                    825:    REPEAT                        ( timeout )
                    826:    drop
                    827:    hchccadneq  l@-le          \ read last HcDoneHead (RAM)
                    828:    (HC-CHECK-WDH)             \ HcDoneHead was updated ?
                    829:    IF
                    830:       (HC-ACK-WDH)              \ clear register bit: WDH
                    831:       TRUE                    ( td-list TRUE )
                    832:    ELSE
                    833:       FALSE
                    834:    THEN
                    835: ;
                    836: 
                    837: 
                    838: \ displays free tds
                    839: 
                    840: 
                    841: : debug-td ( -- )
                    842:    s" Num Free TDs = " num-free-tds usb-debug-print-val
                    843: ;
                    844: 
                    845: 
                    846: \ display content of frame counter
                    847: 
                    848: \ : debug-frame-counter ( -- )
                    849: \   40 1 DO
                    850: \      ." Frame ct at HCCA at end OF enumeration = "
                    851: \      hchcca 80 + rl@-le .
                    852: \   LOOP
                    853: \ ;
                    854: 
                    855: \ ============================================================================
                    856: \ COLON DEFINITION: HC-reset
                    857: \ This routine should be the first to be executed.
                    858: \ This routine will reset the HC and will bring it to Operational
                    859: \ state.
                    860: \ PENDING:
                    861: \ Arrive at the right value OF FrameInterval. Currently we are hardcoding
                    862: \ it.
                    863: \ ==========================================================================
                    864: : HC-reset ( -- )
                    865: 
                    866:    hccomstat dup rl@-le 01 or swap rl!-le    \ issue HC reset
                    867:    BEGIN
                    868:       hccomstat rl@-le 01 and 0<>            \ wait for reset end
                    869:       WHILE
                    870:    REPEAT
                    871: 
                    872:    23f02edf hcintrval rl!-le                 \ frame-interval register
                    873:    hchcca   hchccareg rl!-le                 \ HC communication area
                    874:    0000     hcctrhead rl!-le                 \ control transfer head
                    875:    0000     hcbulkhead rl!-le                \ bulk transfer head
                    876:    0ffff    hcintdsbl rl!-le                 \ interrupt disable reg.
                    877: 
                    878: \ all devices are still in reset-state
                    879: \ next command starts sending SOFs
                    880:    83       hccontrol rl!-le                 \ set USBOPERATIONAL
                    881: 
                    882: \ these two repeated register settings are necessary for Bimini
                    883: \ Its OHCI controller (AM8111) behaves different to NEC's one
                    884:    23f02edf hcintrval rl!-le                 \ frame-interval register
                    885:    hchcca   hchccareg rl!-le                 \ HC communication area
                    886:    
                    887:    d# 50 ms
                    888: 
                    889:    hcrhdescA rl@-le ff and     ( total-rh-ports )
                    890:    to max-rh-ports
                    891: 
                    892: \ if no hardware-reset was issued (rescan)
                    893: \ switch off all ports first !
                    894:    hcrhpstat TO current-stat              \ start with first port status reg
                    895:    0                                      \ port status default
                    896:    max-rh-ports 0                         \ checking all ports
                    897:    DO
                    898:       current-stat rl@-le or              \ OR-ing all stats
                    899:       200 current-stat rl!-le             \ Clear Port Power (CPP)
                    900:       current-stat 4 + TO current-stat    \ check next RH-Port
                    901:    LOOP
                    902:    100 and 0<>                            \ any of the ports had power ?
                    903:    IF
                    904:       d# 750 wait-proceed                 \ wait for power discharge
                    905:    THEN
                    906: 
                    907: \ now power on all ports of this root-hub
                    908:    hcrhpstat TO current-stat              \ start with first port status reg
                    909:    max-rh-ports 0
                    910:    DO
                    911:       102 current-stat rl!-le             \ power on and enable
                    912:       hcrhdescA 3 + rb@ 2 * ms            \ startup delay 30 ms (2 * POTPGT)
                    913:       current-stat 4 + TO current-stat    \ check next RH-Port
                    914:    LOOP
                    915:    d# 500 wait-proceed                    \ STEC device needs 300 ms
                    916: ;
                    917: 
                    918: : error-recovery ( -- )
                    919:    initialize-td-free-list
                    920:    initialize-ed-free-list
                    921:    HC-reset
                    922: ;
                    923: 
                    924: \ ================================================================
                    925: : store-initial-usb-hub-address ( -- )
                    926:     usb-address TO initial-hub-address
                    927: ;
                    928: 
                    929: : reset-to-initial-usb-hub-address ( -- )
                    930:     initial-hub-address TO usb-address
                    931: ;
                    932: 
                    933: \ allocate-usb-address:
                    934: \ Function allocates an USB address.
                    935: \ See RISK below.
                    936: 
                    937: 
                    938: : allocate-usb-address ( -- usb-address )
                    939:    usb-address    7f <>                ( TRUE|FALSE )
                    940:    IF
                    941:       usb-address 1+ TO usb-address \ RISK: Check to see IF it overflows 127
                    942:       usb-address              ( usb-address )
                    943:    THEN                                ( usb-address )
                    944: ;
                    945: 
                    946: s" usb-support.fs" INCLUDED
                    947: 
                    948: 
                    949: 
                    950: \ =====================================================================
                    951: \ COLON DEFINTION: control-std-set-address
                    952: \                  INTERFACE FUNCTION
                    953: \ Function allocates an USB addrss and uses it to send SET-ADDRESS packet
                    954: \ to the default USB address.
                    955: \ This is an interface function available to child nodes.
                    956: 
                    957: : control-std-set-address        ( speedbit -- usb-address TRUE | FALSE )
                    958:    >r                                                 ( R: speedbit )
                    959:    0005000000000000 setup-packet !
                    960:    allocate-usb-address dup setup-packet 2 + c!       ( usb-addr  R: speedbit )
                    961:    s" USB set-address: " 2 pick usb-debug-print-val   ( usb-addr  R: speedbit )
                    962:    0 0 0 setup-packet 8 r> controlxfer                ( usb-addr TRUE | FALSE )
                    963:    IF                                                ( TRUE | FALSE )
                    964:       TRUE                                           ( TRUE )
                    965:    ELSE
                    966:       drop FALSE \ PENDING: Return the allocated address back. ( FALSE )
                    967:    THEN                                                      ( TRUE | FALSE )
                    968: ;
                    969: 
                    970: 
                    971: \ Fetches the device decriptor of the usb-device
                    972: 
                    973: 
                    974: : control-std-get-device-descriptor
                    975:                    ( data-buffer data-len MPS fa -- TRUE|FALSE )
                    976: 
                    977:    8006000100000000 setup-packet !
                    978:    2 pick setup-packet 6 + w!-le
                    979:                      ( data-buffer data-len MPS fa )
                    980:    setup-packet -rot ( data-buffer data-len setup-packet MPS fa )
                    981:    >r >r >r >r >r 0 r> r> r> r> r>
                    982:                     ( 0 data-buffer data-len setup-packet MPS fa )
                    983:    controlxfer      ( TRUE | FALSE )
                    984: ;
                    985: 
                    986: 
                    987: \ ==================================================================
                    988: \ To retrieve the configuration descriptor OF a device
                    989: \ with a valid USB address
                    990: 
                    991: 
                    992: : control-std-get-configuration-descriptor
                    993:    ( data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
                    994:    TO temp1 ( data-buffer data-len MPS )
                    995:    TO temp2 ( data-buffer data-len )
                    996:    TO temp3 ( data-buffer )
                    997:    8006000200000000 setup-packet !
                    998:    temp3 setup-packet 6 + w!-le
                    999:    0 swap temp3 setup-packet temp2 temp1 controlxfer
                   1000: ;
                   1001: 
                   1002: \ Fetches num of logical units available for a device
                   1003: : control-std-get-maxlun ( MPS fun-addr dir data-buff data-len -- TRUE | FALSE )
                   1004:    GET-MAX-LUN setup-packet !  ( MPS fun-addr dir data-buff data-len )
                   1005:    setup-packet 5 pick 5 pick
                   1006:    ( MPS fun-addr dir data-buff data-len setup-packet MPS fun-addr )
                   1007:    controlxfer ( MPS fun-addr  TRUE | FALSE )
                   1008:    nip nip    ( TRUE | FALSE )
                   1009: ;
                   1010: 
                   1011: \ Bulk-Only Mass Storage Reset
                   1012: \ fixed to interface #0
                   1013: : control-bulk-reset ( MPS fun-addr dir data-buff data-len -- TRUE | FALSE )
                   1014:    21FF000000000000 setup-packet !  ( MPS fun-addr dir data-buff data-len )
                   1015:    setup-packet 5 pick 5 pick
                   1016:                ( MPS fun-addr dir data-buff data-len setup-packet MPS fun-addr )
                   1017:    controlxfer ( MPS fun-addr  TRUE | FALSE )
                   1018:    nip nip    ( TRUE | FALSE )
                   1019: ;
                   1020: 
                   1021: 
                   1022: 
                   1023: \ get the string descriptor of the usb device
                   1024: 
                   1025: 
                   1026: : control-std-get-string-descriptor
                   1027:    ( StringIndex data-buffer data-len MPS FuncAddr -- TRUE | FALSE )
                   1028:    TO temp1  ( StringIndex data-buffer data-len MPS )
                   1029:    TO temp2  ( StringIndex data-buffer data-len )
                   1030:    TO temp3  ( StringIndex )
                   1031:    8006000300000000 setup-packet !
                   1032:    temp3 setup-packet 6 + w!-le
                   1033:    409 setup-packet 4 + w!-le \ US English Language code.
                   1034:    swap      ( data buffer StringIndex )
                   1035:    setup-packet 2 + c! ( data-buffer )
                   1036:    0 swap temp3 setup-packet temp2 temp1 controlxfer ( TRUE | FALSE )
                   1037: ;
                   1038: 
                   1039: \ sets a valid usb configaration for a device
                   1040: 
                   1041: : control-std-set-configuration ( configvalue FuncAddr -- TRUE|FALSE )
                   1042:    TO temp1                     ( configvalue )
                   1043:    TO temp2
                   1044:    0009000000000000 setup-packet ! \ RISK: Endian and 64-bit assumptions
                   1045:    temp2 setup-packet 2 + w!-le
                   1046:    0 0 0 setup-packet DEFAULT-CONTROL-MPS temp1 controlxfer
                   1047: 
                   1048:    \ NOTE: We could use DEFAULT-CONTROL-MPS because there is no data phase
                   1049:    \ associated with this control xfer. Its a dont care.
                   1050: ;
                   1051: 
                   1052: 
                   1053: \ To set the device address retrive the device descriptor and build the
                   1054: \ usb device tree by passing device class
                   1055: 
                   1056: 
                   1057: 0 VALUE port-number
                   1058: 
                   1059: s" usb-enumerate.fs" INCLUDED
                   1060: 
                   1061: : rhport-enumerate ( port-num -- )
                   1062:    TO port-number
                   1063:    device-speed control-std-set-address        ( usb-addr TRUE | FALSE )
                   1064:    IF
                   1065:       device-speed or                          ( usb-addr+speedbit )
                   1066:       TO new-device-address
                   1067:       dd-buffer @ 8 erase
                   1068: 
                   1069:       \ Read Device Descriptor - First 8 bytes.
                   1070: 
                   1071:       dd-buffer @ DEFAULT-CONTROL-MPS DEFAULT-CONTROL-MPS      ( buffer mps mps )
                   1072:       new-device-address control-std-get-device-descriptor   ( TRUE | FALSE )
                   1073:       IF
                   1074:       ELSE
                   1075:          s" USB: Read Dev Descriptor failed"   usb-debug-print EXIT
                   1076: 
                   1077:          \ NOTE: Tomorrow, IF there is a LOOP here,we may need to UNLOOP before
                   1078:          \ "EXIT"ing. Beware. Much depends on what LOOPing construct is used.
                   1079: 
                   1080:       THEN
                   1081: 
                   1082:       \ Read the Descriptor Type and check IF we have read correctly.
                   1083: 
                   1084:       dd-buffer @ DEVICE-DESCRIPTOR-TYPE-OFFSET + c@  ( Descriptor-type )
                   1085:       DEVICE-DESCRIPTOR-TYPE <> IF
                   1086:          s" USB: Error Reading Device Descriptor"   usb-debug-print
                   1087:          s" Read descriptor is not OF the right type"  usb-debug-print
                   1088:          s" Aborting enumeration"  usb-debug-print
                   1089:          EXIT
                   1090:          \ NOTE: Tomorrow, IF u have a LOOP here THEN we may need to
                   1091:          \ UNLOOP before EXITing. Depends on what type OF LOOPing construct
                   1092:          \ is used. Beware.
                   1093: 
                   1094:       THEN
                   1095: 
                   1096:       \ Read the MPS and store it.
                   1097: 
                   1098:       dd-buffer @ DEVICE-DESCRIPTOR-MPS-OFFSET + c@ TO mps
                   1099: 
                   1100:       \ NOTE: Probably, we could check MPS for only 8/16/32/64
                   1101:       \       hmm.. not now...
                   1102: 
                   1103:       \ Read the device class to see what type OF device it is and create an
                   1104:       \ appropriate child node here.
                   1105:       create-usb-device-tree
                   1106:    ELSE
                   1107:       s" Set address failed on port " port-number usb-debug-print-val
                   1108:       s" Aborting Enumeration."   usb-debug-print
                   1109:       EXIT
                   1110: 
                   1111:       \ NOTE: Tomorrow , IF u have a LOOP here THEN we may need to
                   1112:       \ UNLOOP before EXITing. Depends on what type OF LOOPing construct
                   1113:       \ is used. Beware.
                   1114: 
                   1115:    THEN
                   1116: ;
                   1117: 
                   1118: 
                   1119: \ =========================================================================
                   1120: \ PROTOTYPE FUNCTION: "rhport-initialize"
                   1121: \ Detect Device, reset and enable the respective port.
                   1122: \ COLON Definition rhport-initialize accepts the total number OF root hub
                   1123: \ ports as an argument and probes every available root hub port and initiates
                   1124: \ the build OF the USB devie sub-tree so is effectively the mother OF all
                   1125: \ USB device nodes that are to be detected and instantiated.
                   1126: \ ==========================================================================
                   1127: : rhport-initialize ( -- )
                   1128: 
                   1129:    hcrhpstat TO current-stat              \ start with first port status reg
                   1130:    max-rh-ports 1+ 1
                   1131:    DO
                   1132:       \ any Device connected to that port ?
                   1133:       current-stat rl@-le RHP-CCS and 0<>      ( TRUE|FALSE )
                   1134:       IF
                   1135:          current-stat hcrhpstat3 =        \ third port of NEC ?
                   1136:          IF
                   1137:             81 to uDOC-present            \ uDOC is present and now processed
                   1138:          THEN
                   1139: 
                   1140:          s" Device connected to this port!" usb-debug-print
                   1141:          RHP-PRS current-stat rl!-le      \ issue a port reset
                   1142:          BEGIN
                   1143:             current-stat rl@-le RHP-PRS AND    \ wait for reset end
                   1144:             WHILE
                   1145:          REPEAT
                   1146:          hcrhdescA 3 + rb@ 2 * ms         \ startup delay 30 ms (POTPGT)
                   1147:          d# 100 ms
                   1148: 
                   1149:          current-stat rl@-le 200 and 4 lshift
                   1150:          to device-speed                  \ store speed bit
                   1151: 
                   1152:          RHP-CSC RHP-PRSC or current-stat rl!-le
                   1153: 
                   1154:          I ['] rhport-enumerate CATCH IF  \ Scan port
                   1155:             s" USB scan failed on root hub port: " rot usb-debug-print-val
                   1156:             reset-to-initial-usb-hub-address
                   1157:          THEN
                   1158: 
                   1159:       ELSE
                   1160:          s" No device detected at this port." usb-debug-print
                   1161:          current-stat hcrhpstat3 =        \ third port of NEC ? (=ModFD)
                   1162:          IF                               \ here a ModFD should be on ELBA
                   1163:             current-stat rl@-le 80000 and 0<>  \ is over-current detected ?
                   1164:             IF
                   1165:                uDOC-present 08 or to uDOC-present  \ set flag for uDOC-check
                   1166:             THEN
                   1167:          THEN
                   1168:       THEN
                   1169:       current-stat 4 + TO current-stat    \ check next RH-Port
                   1170:       uDOC-present 0f and to uDOC-present \ remove processing flag
                   1171:    LOOP
                   1172: ;
                   1173: 
                   1174: 
                   1175: \ ===================================================
                   1176: \ Enumeration at Host level
                   1177: \ ===================================================
                   1178: 
                   1179: : enumerate ( -- )
                   1180:    HC-reset
                   1181:    ['] hc-suspend add-quiesce-xt     \ Assert that HC will be supsended
                   1182:    store-initial-usb-hub-address
                   1183:    rhport-initialize                 \ Probe all available RH ports
                   1184:    reset-to-initial-usb-hub-address
                   1185: ;
                   1186: 
                   1187: 
                   1188: \ Create an alias for this controller:
                   1189: set-ohci-alias
                   1190: 

unix.superglobalmegacorp.com

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