Annotation of qemu/roms/SLOF/slof/fs/usb/usb-ohci.fs, revision 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.