|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.