Author: wmb Date: Thu Jan 27 00:40:25 2011 New Revision: 2152 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2152
Log: USB - extensive surgery on USB probing code so hot-plug works behind hubs.
Modified: dev/usb2/device/hub/hub.fth dev/usb2/hcd/dev-info.fth dev/usb2/hcd/device.fth dev/usb2/hcd/ehci/control.fth dev/usb2/hcd/ehci/loadpkg.fth dev/usb2/hcd/ehci/probe.fth dev/usb2/hcd/ehci/probehub.fth dev/usb2/hcd/hcd-call.fth dev/usb2/hcd/ohci/probe.fth dev/usb2/hcd/probehub.fth dev/usb2/hcd/uhci/loadpkg.fth dev/usb2/hcd/uhci/probe.fth dev/usb2/hcd/uhci/uhci.fth dev/usb2/pkt-data.fth dev/usb2/pkt-func.fth
Modified: dev/usb2/device/hub/hub.fth ============================================================================== --- dev/usb2/device/hub/hub.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/device/hub/hub.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -33,14 +33,26 @@ then decode-int nip nip ; +: ?make-hub20-dev ( hub-dev -- hub-dev ) + is-hub20? if ( hub-dev ) + " hub20-dev" get-my-property if ( hub-dev ) + dup encode-int " hub20-dev" property ( hub-dev ) + else \ Property already exists ( hub-dev adr len ) + 2drop ( hub-dev ) + then ( hub-dev ) + then ( hub-dev ) +; : probe-hub ( -- ) ['] hub-id catch 0= if - is-hub20? if - dup encode-int " hub20-dev" property - then + ?make-hub20-dev probe-hub-xt execute then ; +: reprobe-hub ( -- ) + ['] hub-id catch 0= if + reprobe-hub-xt execute + then +;
probe-hub
Modified: dev/usb2/hcd/dev-info.fth ============================================================================== --- dev/usb2/hcd/dev-info.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/dev-info.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -62,10 +62,11 @@ : di-in-data-toggle ( pipe idx -- ) 2dup di-in-data@ 1 xor -rot di-in-data! ; : di-out-data-toggle ( pipe idx -- ) 2dup di-out-data@ 1 xor -rot di-out-data! ;
-: ok-to-add-device? ( -- flag ) cur-dev 1+ #max-dev < ; -: new-address ( -- dev ) +: next-device# ( -- true | dev false ) + cur-dev 1+ #max-dev >= if true exit then cur-dev 1+ dup to cur-dev /pipe0 0 cur-dev di-maxpayload! + false ;
: init-di ( -- )
Modified: dev/usb2/hcd/device.fth ============================================================================== --- dev/usb2/hcd/device.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/device.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -10,7 +10,6 @@ \ Buffers for descriptor manipulation 0 value cfg-desc-buf \ Configuration Descriptor 0 value dev-desc-buf \ Device Descriptor -0 value gen-desc-buf \ Any Descriptor 0 value d$-desc-buf \ Device String Descriptor 0 value v$-desc-buf \ Vendor String Descriptor 0 value s$-desc-buf \ Serial Number String Descriptor @@ -25,7 +24,6 @@ cfg-desc-buf 0= if /cfg alloc-mem dup to cfg-desc-buf /cfg erase /cfg alloc-mem dup to dev-desc-buf /cfg erase - /cfg alloc-mem dup to gen-desc-buf /cfg erase /str alloc-mem dup to d$-desc-buf /str erase /str alloc-mem dup to v$-desc-buf /str erase /str alloc-mem dup to s$-desc-buf /str erase @@ -34,14 +32,27 @@ : free-pkt-buf ( -- ) cfg-desc-buf ?dup if /cfg free-mem 0 to cfg-desc-buf then dev-desc-buf ?dup if /cfg free-mem 0 to dev-desc-buf then - gen-desc-buf ?dup if /cfg free-mem 0 to gen-desc-buf then d$-desc-buf ?dup if /str free-mem 0 to d$-desc-buf then v$-desc-buf ?dup if /str free-mem 0 to v$-desc-buf then s$-desc-buf ?dup if /str free-mem 0 to s$-desc-buf then ;
+: dev-desc@ ( index -- byte ) dev-desc-buf + c@ ; +: get-class ( -- class subclass protocol ) + 4 dev-desc@ ?dup if ( class ) + \ Class is in device descriptor + true to class-in-dev? ( class ) + 5 dev-desc@ 6 dev-desc@ ( class subclass protocol ) + else ( ) + \ Class is in interface descriptor + false to class-in-dev? ( ) + cfg-desc-buf my-address find-intf-desc ( intf-adr ) + >r r@ 5 + c@ r@ 6 + c@ r> 7 + c@ ( class subclass protocol ) + then +; + : make-class-properties ( -- ) - dev-desc-buf cfg-desc-buf my-address get-class ( class subclass protocol ) + get-class ( class subclass protocol ) " protocol" int-property " subclass" int-property " class" int-property @@ -83,8 +94,12 @@ device-name ;
+: get-vid ( adr -- vendor product rev ) + dev-desc-buf 8 + le-w@ dev-desc-buf d# 10 + le-w@ dev-desc-buf c + le-w@ +; + : make-vendor-properties ( -- ) - dev-desc-buf get-vid ( vendor product rev ) + get-vid ( vendor product rev ) " release" int-property " device-id" int-property " vendor-id" int-property @@ -256,6 +271,18 @@ >r lbsplit r@ c! r@ 1+ c! r@ 2+ c! r> 3 + c! ;
+: probe-hub-node ( phandle -- ) + >r ( r: phandle ) + " probe-hub" r@ find-method if ( xt r: phandle ) + r@ push-package ( xt r: phandle ) + " " new-instance ( xt r: phandle ) + set-default-unit ( xt r: phandle ) + execute ( r: phandle ) + destroy-instance ( r: phandle ) + pop-package ( r: phandle ) + then ( r: phandle ) + r> drop +; : reuse-node ( dev intf port phandle -- ) >r drop ( dev intf r: phandle )
@@ -269,18 +296,8 @@ drop be-l! ( r: phandle ) then ( r: phandle )
- " probe-hub" r@ find-method if ( xt r: phandle ) - r@ push-package ( xt r: phandle ) - " " new-instance ( xt r: phandle ) - set-default-unit ( xt r: phandle ) - execute ( r: phandle ) - destroy-instance ( r: phandle ) - pop-package ( r: phandle ) - then ( r: phandle ) - - r> drop + r> probe-hub-node ; - : id-match? ( dev intf port phandle -- dev intf port phandle flag? ) " vendor-id" 2 pick get-package-property if false exit then decode-int nip nip >r ( dev intf port phandle r: vid ) @@ -288,7 +305,7 @@ decode-int nip nip >r ( dev intf port phandle r: vid did ) " release" 2 pick get-package-property if r> r> 2drop false exit then decode-int nip nip >r ( dev intf port phandle r: vid did rev ) - dev-desc-buf get-vid ( dev intf port phandle vid1 did1 rev1 r: vid did rev ) + get-vid ( dev intf port phandle vid1 did1 rev1 r: vid did rev ) r> = -rot r> = -rot r> = and and ;
@@ -335,42 +352,126 @@ ;
\ Get all the descriptors we need in making properties now because target is -\ questionable in the child's context. +\ questionable in the child's context. The descriptor buffers are not instance +\ data, so they can be accessed by code that is defined in the root hub node +\ but executing in a subordinate hub node context or a child node context.
h# 409 constant language \ Unicode id +\ Executed in root hub node context : get-string ( lang idx adr -- actual ) over 0= if 3drop 0 exit then \ No string index -rot get-str-desc ; + +\ Executed in root hub node context : get-str-descriptors ( -- ) language ( lang ) dup dev-desc-buf d# 14 + c@ v$-desc-buf get-string to /v$-desc-buf dup dev-desc-buf d# 15 + c@ d$-desc-buf get-string to /d$-desc-buf dev-desc-buf d# 16 + c@ s$-desc-buf get-string to /s$-desc-buf ; -: refresh-desc-bufs ( -- ) + +\ Executed in root hub node context +: refresh-desc-bufs ( dev -- ) + set-target dev-desc-buf 12 get-dev-desc to /dev-desc-buf \ Refresh dev-desc-buf cfg-desc-buf 0 get-cfg-desc to /cfg-desc-buf \ Refresh cfg-desc-buf get-str-descriptors ;
-: set-maxpayload ( dev -- ) - dev-desc-buf /pipe0 get-dev-desc if - dev-desc-buf 7 + c@ 0 rot di-maxpayload! - else - drop - then +\ Executed in root hub node context +: get-initial-descriptors ( dev -- ) + dev-desc-buf /pipe0 get-dev-desc if ( dev ) + dev-desc-buf 7 + c@ 0 rot di-maxpayload! ( ) + else ( dev ) + drop ( ) + then ( ) + cfg-desc-buf 0 get-cfg-desc to /cfg-desc-buf ( ) ;
+\ Executed in hub node context (root hub or subordinate hub) - creates new child nodes via (make-device-node) : make-device-node ( port dev -- ) - dup set-maxpayload ( port dev ) - cfg-desc-buf 0 get-cfg-desc dup to /cfg-desc-buf - 0= if 2drop exit then - cfg-desc-buf 4 + c@ 0 ?do ( port dev ) - dup set-target ( port dev ) \ Refresh target - refresh-desc-bufs ( port dev ) - 2dup swap i (make-device-node) ( port dev ) - loop 2drop ( ) + dup " get-initial-descriptors" my-self $call-method ( port dev ) + /cfg-desc-buf 0= if 2drop exit then ( port dev ) + cfg-desc-buf 4 + c@ 0 ?do ( port dev ) + dup " refresh-desc-bufs" my-self $call-method ( port dev ) + 2dup swap i (make-device-node) ( port dev ) + loop 2drop ( ) +; + +\ See hcd/ehci/probehub.fth for information about hub20-dev and hub20-port + +: get-hub20-dev ( -- hub-dev ) + " hub20-dev" get-inherited-property 0= if ( value$ ) + decode-int nip nip ( hub-dev ) + else ( ) + 1 ( hub-dev ) + then ( hub-dev ) +; + +: get-hub20-port ( port -- port' ) + " hub20-port" get-inherited-property 0= if ( port value$ ) + rot drop ( value$ ) + decode-int nip nip ( port' ) + then ( port ) +; + +\ Executed in the root hub node context +: setup-new-node ( port speed hub-port hub-dev -- true | port dev xt false ) + \ Allocate device number + next-device# if 2drop exit then ( port speed hub-port hub-dev dev ) + + tuck di-hub! ( port speed hub-port dev ) + tuck di-port! ( port speed dev ) + tuck di-speed! ( port dev ) + + 0 set-target ( port dev ) \ Address it as device 0 + dup set-address if ( port dev ) \ Assign it usb addr dev + ." Retrying with a delay" cr + over reset-port d# 5000 ms + dup set-address if ( port dev ) \ Assign it usb addr dev + \ Recycle device number? + 2drop false exit ( -- false ) + then ( port dev ) + then ( port dev ) + + dup set-target ( port dev ) \ Address it as device dev + ['] make-device-node true ( port dev xt ) +; + +\ Begins execution in a (root or subordinate) hub node context, creates an instance record +\ for the subordinate hub node "phandle", switches to that instance context, executes +\ "reprobe-hub" in that context, destroys the instance, and returns to the original context. +: reprobe-hub-node ( phandle -- ) + >r ( r: phandle ) + " reprobe-hub" r@ find-method if ( xt r: phandle ) + r@ push-package ( xt r: phandle ) + " " new-instance ( xt r: phandle ) + set-default-unit ( xt r: phandle ) + execute ( r: phandle ) + destroy-instance ( r: phandle ) + pop-package ( r: phandle ) + then ( r: phandle ) + r> drop +; + +\ Returns true if there is a child hub node associated with port +: port-is-hub? ( port -- false | phandle true ) + my-self ihandle>phandle child ( port phandle ) + begin ?dup while ( port phandle ) + " name" 2 pick get-package-property 0= if ( port phandle adr len ) + 1- " hub" $= if ( port phandle ) + " reg" 2 pick get-package-property 0= if ( port phandle adr len ) + decode-int nip nip ( port phandle port1 ) + 2 pick = if ( port phandle ) + nip true exit ( -- phandle true ) + then ( port phandle ) + then ( port phandle ) + then ( port phandle ) + then ( port phandle ) + peer ( port phandle' ) + repeat ( port ) + drop false ( false ) ;
headers
Modified: dev/usb2/hcd/ehci/control.fth ============================================================================== --- dev/usb2/hcd/ehci/control.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/ehci/control.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -65,7 +65,7 @@ swap case ( qh endp-char pipetype ) pt-ctrl of QH_MULT1 d# 64 endof ( qh endp-char endp-cap /max ) pt-bulk of QH_MULT1 d# 512 endof ( qh endp-char endp-cap /max ) - ( default ) r> QH_MULT1 my-maxpayload r> + ( default ) >r QH_MULT1 my-maxpayload r> ( qh endp-char endp-cap /max ) endcase d# 16 << rot or swap ( qh endp-char endp-cap )
Modified: dev/usb2/hcd/ehci/loadpkg.fth ============================================================================== --- dev/usb2/hcd/ehci/loadpkg.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/ehci/loadpkg.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -21,8 +21,6 @@ fload ${BP}/dev/usb2/device/vendor.fth \ Supported vendor/product tables fload ${BP}/dev/usb2/hcd/fcode.fth \ Load fcode driver for child fload ${BP}/dev/usb2/hcd/device.fth \ Make child node & its properties -fload ${BP}/dev/usb2/hcd/ehci/probe.fth \ Probe root hub fload ${BP}/dev/usb2/hcd/ehci/probehub.fth \ USB 2.0 hub specific stuff -fload ${BP}/dev/usb2/hcd/probehub.fth \ Probe usb hub - - +fload ${BP}/dev/usb2/hcd/ehci/probe.fth \ Probe root hub +fload ${BP}/dev/usb2/hcd/probehub.fth \ Generic hub probing
Modified: dev/usb2/hcd/ehci/probe.fth ============================================================================== --- dev/usb2/hcd/ehci/probe.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/ehci/probe.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -5,29 +5,18 @@ headers
: make-root-hub-node ( port -- ) - ok-to-add-device? 0= if drop exit then \ Can't add another device - - 0 set-target ( port ) \ Address it as device 0 - + \ Some devices (e.g. Lexar USB-to-SD) fail unless you get the cfg desc from device 0 first + 0 set-target \ First address it as device 0 ( port ) speed-high 0 di-speed! \ Use high speed for getting the device descriptor - \ Some devices (e.g. Lexar USB-to-SD) don't work unless you do this first - dev-desc-buf h# 40 get-cfg-desc drop + dev-desc-buf h# 40 get-cfg-desc drop ( port )
- new-address ( port dev ) - speed-high over di-speed! ( port dev ) + speed-high ( port speed )
- 0 set-target ( port dev ) \ Address it as device 0 + \ hub-port and hub-dev route USB 1.1 transactions through USB 2.0 hubs + over get-hub20-port get-hub20-dev ( port speed hub-port hub-dev )
- dup set-address if ( port dev ) \ Assign it usb addr dev - ." Retrying with a delay" cr - over reset-port d# 5000 ms - dup set-address if ( port dev ) \ Assign it usb addr dev - 2drop exit - then - then ( port dev ) - - dup set-target ( port dev ) \ Address it as device dev - make-device-node ( ) + \ Execute setup-new-node in root context and make-device-node in hub node context + setup-new-node if execute then ( ) ;
0 instance value probe-error? \ Back channel to selftest @@ -43,7 +32,7 @@ dup disown-port \ Disown the port else \ A high speed device detected dup ['] make-root-hub-node catch if \ Process high speed device - drop ." Failed to probe root port " dup .d cr + drop ." Failed to make root hub node for port " dup .d cr true to probe-error? then then @@ -105,6 +94,10 @@ i portsc@ 2 and if \ Connection changed \ i rm-obsolete-children \ Remove obsolete device nodes i probe-root-hub-port \ Probe it + else + i port-is-hub? if ( phandle ) \ Already-connected hub? + reprobe-hub-node \ Check for changes on its ports + then then loop
Modified: dev/usb2/hcd/ehci/probehub.fth ============================================================================== --- dev/usb2/hcd/ehci/probehub.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/ehci/probehub.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -31,39 +31,19 @@ \ value and the /usb/hub/mouse hub20-port value are used in the qTD.
: ?set-hub20-port ( speed dev port -- ) - " hub20-dev" my-parent ihandle>phandle get-package-property 0= if - 2drop nip swap speed-high <> if - " hub20-port" int-property - else - drop - then - else - 3drop - then + " hub20-dev" my-parent ihandle>phandle get-package-property 0= if ( speed dev port value$ ) + 2drop ( speed dev port ) + nip swap speed-high <> if ( port ) + encode-int " hub20-port" property ( ) + else ( speed ) + drop ( ) + then ( ) + else ( speed dev port ) + 3drop ( ) + then ( ) ; ' ?set-hub20-port to make-dev-property-hook
-: get-hub20-dev ( -- hub-dev ) - " hub20-dev" get-inherited-property 0= if - decode-int nip nip - else - 1 - then -; - -: get-hub20-port ( port -- port' ) - " hub20-port" get-inherited-property 0= if - rot drop ( $ ) - decode-int nip nip - then -; - -\ Initialize USB 2.0 specific characteristics in di -: set-usb20-char ( port dev -- ) - get-hub20-dev over di-hub! - swap get-hub20-port swap di-port! -; - headers
\ LICENSE_BEGIN
Modified: dev/usb2/hcd/hcd-call.fth ============================================================================== --- dev/usb2/hcd/hcd-call.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/hcd-call.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -10,9 +10,28 @@ : dma-alloc ( size -- virt ) " dma-alloc" $call-parent ; : dma-free ( virt size -- ) " dma-free" $call-parent ;
-: set-target ( device -- ) " set-target" $call-parent ; -: probe-hub-xt ( -- adr ) " probe-hub-xt" $call-parent ; -: set-pipe-maxpayload ( size len -- ) " set-pipe-maxpayload" $call-parent ; +\ Probing support +: set-target ( device -- ) + " set-target" $call-parent + ; +: probe-hub-xt ( -- adr ) + " probe-hub-xt" $call-parent +; +: reprobe-hub-xt ( -- adr ) + " reprobe-hub-xt" $call-parent +; +: set-pipe-maxpayload ( size len -- ) + " set-pipe-maxpayload" $call-parent +; +: setup-new-node ( port speed hub-port hub-dev -- false | port dev xt true ) + " setup-new-node" $call-parent +; +: get-initial-descriptors ( dev -- ) + " get-initial-descriptors" $call-parent +; +: refresh-desc-bufs ( dev -- ) + " refresh-desc-bufs" $call-parent +;
\ Control pipe operations : control-get ( adr len idx value rtype req -- actual usberr )
Modified: dev/usb2/hcd/ohci/probe.fth ============================================================================== --- dev/usb2/hcd/ohci/probe.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/ohci/probe.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -4,7 +4,7 @@ hex headers
-: enable-root-hub-port ( port -- ) +: reset-port ( port -- ) >r h# 1.0002 r@ hc-rh-psta! \ enable port 10 r@ hc-rh-psta! \ reset port @@ -18,17 +18,17 @@ ;
: probe-root-hub-port ( port -- ) - dup hc-rh-psta@ 1 and 0= if drop exit then \ No device connected - ok-to-add-device? 0= if drop exit then \ Can't add another device + dup hc-rh-psta@ 1 and 0= if drop exit then ( port ) \ No device connected
- dup enable-root-hub-port ( port ) - new-address ( port dev ) - over hc-rh-psta@ 200 and if speed-low else speed-full then over di-speed! - - 0 set-target ( port dev ) \ Address it as device 0 - dup set-address if 2drop exit then ( port dev ) \ Assign it usb addr dev - dup set-target ( port dev ) \ Address it as device dev - make-device-node ( ) + \ Reset the port to determine the speed + dup reset-port ( port ) + dup hc-rh-psta@ 200 and if speed-low else speed-full then ( port speed ) + + \ hub-port and hub-speed are irrelevant for OHCI (USB 1.1) + 0 0 ( port speed hub-port hub-dev ) + + \ Execute setup-new-node in root context and make-device-node in hub node context + setup-new-node if execute then ( port dev xt ) ;
false value ports-powered? @@ -99,6 +99,10 @@ drop ." Failed to probe root port " i u. cr then 3.0000 i hc-rh-psta! \ Clear change bits + else + i port-is-hub? if ( phandle ) \ Already-connected hub? + reprobe-hub-node \ Check for changes on its ports + then then loop free-pkt-buf
Modified: dev/usb2/hcd/probehub.fth ============================================================================== --- dev/usb2/hcd/probehub.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/probehub.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -7,63 +7,122 @@ : set-usb20-char ( port dev -- ) 2drop ; [then]
-: power-hub-port ( port -- ) PORT_POWER DR_PORT set-feature drop ; -: reset-hub-port ( dev port -- ) PORT_RESET DR_PORT set-feature drop d# 20 ms ; +8 buffer: hub-buf \ For hub probing + +: power-hub-port ( port -- ) PORT_POWER DR_PORT " set-feature" $call-parent drop ; +: reset-hub-port ( port -- ) PORT_RESET DR_PORT " set-feature" $call-parent drop d# 20 ms ; +: clear-status-change ( port -- ) C_PORT_CONNECTION DR_PORT " clear-feature" $call-parent drop ; +: parent-set-target ( dev -- ) " set-target" $call-parent ; +: get-port-status ( port -- error? ) + hub-buf 4 2 pick DR_PORT " get-status" $call-parent ( port actual usberror ) + nip if ( port ) + ." Failed to get port status for port " u. cr + true ( true ) + else ( port ) + drop false ( false ) + then ( ) +; +: port-status-changed? ( hub-dev port -- false | connected? true ) + swap parent-set-target ( port ) + dup get-port-status if ( port ) + drop false exit ( -- false ) + then ( port ) + + hub-buf 2+ c@ 1 and if ( port ) + \ Status changed + clear-status-change ( ) + hub-buf c@ 1 and 0<> ( connected? ) + true ( connected? true ) + else ( port ) + drop false ( false ) + then +;
: probe-hub-port ( hub-dev port -- ) - swap set-target ( port ) - dup reset-hub-port ( port ) + \ Reset the port to determine the speed + swap parent-set-target ( port ) + dup reset-hub-port ( port ) + + \ get-port-status fills hub-buf with connection status, speed, and other information + dup get-port-status ( port error? ) + over clear-status-change ( port error? ) + if drop exit then ( port )
- gen-desc-buf 4 2 pick DR_PORT get-status nip if - ." Failed to get port status for port " u. cr - exit - then ( port ) + hub-buf c@ 1 and 0= if drop exit then \ No device connected + hub-buf le-w@ h# 600 and 9 >> ( port speed )
- gen-desc-buf c@ 1 and 0= if drop exit then \ No device connected - ok-to-add-device? 0= if drop exit then \ Can't add another device + \ hub-port and hub-dev route USB 1.1 transactions through USB 2.0 hubs + over get-hub20-port get-hub20-dev ( port speed hub-port hub-dev )
- new-address ( port dev ) - gen-desc-buf le-w@ h# 600 and 9 >> over di-speed! - ( port dev ) - 2dup set-usb20-char ( port dev ) - - 0 set-target ( port dev ) \ Address it as device 0 - dup set-address if 2drop exit then ( port dev ) \ Assign it usb addr dev - dup set-target ( port dev ) \ Address it as device dev - make-device-node ( ) + \ Execute setup-new-node in root context and make-device-node in hub node context + " setup-new-node" $call-parent if execute then ( ) ;
-external -: probe-hub ( dev -- ) - dup set-target ( hub-dev ) - gen-desc-buf 8 0 0 HUB DR_HUB get-desc nip if +: hub-#ports ( -- n ) + hub-buf 8 0 0 HUB DR_HUB " get-desc" $call-parent nip if ." Failed to get hub descriptor" cr - exit + 0 exit then + hub-buf 2 + c@ 1+ ( #ports ) +; +: hub-delay ( -- #2ms ) hub-buf 5 + c@ ;
- gen-desc-buf dup 5 + c@ swap ( hub-dev #2ms adr ) - 2 + c@ 1+ ( hub-dev #2ms #ports ) - - " configuration#" get-int-property set-config ( hub-dev #2ms #ports usberr ) - if 2drop ." Failed to set config for hub at " u. cr exit then - - tuck 1 ?do i power-hub-port loop 2* ms - ( hub-dev #ports ) - " usb-delay" ['] evaluate catch if ( hub-dev #ports x x ) - 2drop d# 100 ( hub-dev #ports ms ) - then ( hub-dev #ports ms ) +: power-hub-ports ( #ports -- ) + 1 ?do i power-hub-port loop ( ) + + hub-delay 2* ms ( ) + + " usb-delay" ['] evaluate catch if ( ) + 2drop d# 100 ( ms ) + then ( ms ) ms +;
- ( hub-dev #ports ) 1 ?do - dup i ['] probe-hub-port catch if - 2drop - ." Failed to probe hub port " i u. cr - then - loop drop +: safe-probe-hub-port ( hub-dev port -- ) + tuck ['] probe-hub-port catch if ( port x x ) + 2drop ." Failed to probe hub port " . cr ( ) + else ( port ) + drop ( ) + then ( ) +; +external +: probe-hub ( dev -- ) + dup parent-set-target ( hub-dev ) + hub-#ports ( hub-dev #ports ) + + " configuration#" get-int-property + " set-config" $call-parent ( hub-dev #ports usberr ) + if drop ." Failed to set config for hub at " u. cr exit then ( hub-dev #ports ) + + dup power-hub-ports ( hub-dev #ports ) + + 1 ?do ( hub-dev ) + dup i safe-probe-hub-port ( hub-dev ) + loop ( hub-dev ) + drop ( ) ;
: probe-hub-xt ( -- adr ) ['] probe-hub ;
+: do-reprobe-hub ( dev -- ) + dup parent-set-target ( hub-dev ) + hub-#ports 1 ?do ( hub-dev ) + dup i port-status-changed? if ( hub-dev connected? ) + if ( hub-dev ) + dup i safe-probe-hub-port ( hub-dev ) + \ else Handle disconnect + then ( hub-dev ) + else ( hub-dev ) + i port-is-hub? if ( hub-dev phandle ) + reprobe-hub-node ( hub-dev ) + then ( hub-dev ) + then ( hub-dev ) + loop ( hub-dev ) + drop ( ) +; + +: reprobe-hub-xt ( -- adr ) ['] do-reprobe-hub ; + headers
\ LICENSE_BEGIN
Modified: dev/usb2/hcd/uhci/loadpkg.fth ============================================================================== --- dev/usb2/hcd/uhci/loadpkg.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/uhci/loadpkg.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -21,7 +21,7 @@ fload ${BP}/dev/usb2/device/vendor.fth \ Supported vendor/product tables fload ${BP}/dev/usb2/hcd/fcode.fth \ Load fcode driver for child fload ${BP}/dev/usb2/hcd/device.fth \ Make child node & its properties -fload ${BP}/dev/usb2/hcd/uhci/probe.fth \ Probe root hub fload ${BP}/dev/usb2/hcd/probehub.fth \ Probe usb hub +fload ${BP}/dev/usb2/hcd/uhci/probe.fth \ Probe root hub
Modified: dev/usb2/hcd/uhci/probe.fth ============================================================================== --- dev/usb2/hcd/uhci/probe.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/uhci/probe.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -4,31 +4,18 @@ hex headers
-\ We mustn't wait more than 3 ms between releasing the reset and enabling -\ the port to begin the SOF stream, otherwise some devices (e.g. pl2303) -\ will go into suspend state and then not respond to set-address. -: reset-root-hub-port ( port -- ) - dup >r portsc@ h# 20e invert and ( value r: port ) \ Clear reset, enable, status - dup h# 200 or r@ portsc! ( value r: port ) \ Reset port - d# 30 ms ( value r: port ) \ > 10 ms - reset time - dup r@ portsc! ( value r: port ) \ Release reset - 1 ms ( value r: port ) \ > 5.3 uS - reconnect time - h# e or r> portsc! ( ) \ Enable port and clear status -; - : probe-root-hub-port ( port -- ) - dup reset-root-hub-port - dup portsc@ 1 and 0= if drop exit then \ No device-connected - ok-to-add-device? 0= if drop exit then \ Can't add another device - - new-address ( port dev ) - over portsc@ 100 and if speed-low else speed-full then - over di-speed! ( port dev ) - - 0 set-target ( port dev ) \ Address it as device 0 - dup set-address if 2drop exit then ( port dev ) \ Assign it usb addr dev - dup set-target ( port dev ) \ Address it as device dev - make-device-node ( ) + \ Reset the port to perform connection status and speed detection + dup reset-port ( port ) + dup portsc@ 1 and 0= if drop exit then ( port ) \ No device-connected + + dup portsc@ 100 and if speed-low else speed-full then ( port speed ) + + \ hub-port and hub-speed are irrelevant for UHCI (USB 1.1) + 0 0 ( port speed hub-port hub-dev ) + + \ Execute setup-new-node in root context and make-device-node in hub node context + setup-new-node if execute then ( ) ;
external @@ -46,6 +33,10 @@ drop ." Failed to probe root port " i .d cr then i portsc@ i portsc! \ Clear change bits + else + i port-is-hub? if ( phandle ) \ Already-connected hub? + reprobe-hub-node \ Check for changes on its ports + then then loop free-pkt-buf
Modified: dev/usb2/hcd/uhci/uhci.fth ============================================================================== --- dev/usb2/hcd/uhci/uhci.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/hcd/uhci/uhci.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -38,6 +38,18 @@ : portsc@ ( port -- data ) 2* 10 + uhci-w@ ; : portsc! ( data port -- ) 2* 10 + uhci-w! ;
+\ We mustn't wait more than 3 ms between releasing the reset and enabling +\ the port to begin the SOF stream, otherwise some devices (e.g. pl2303) +\ will go into suspend state and then not respond to set-address. +: reset-port ( port -- ) + dup >r portsc@ h# 20e invert and ( value r: port ) \ Clear reset, enable, status + dup h# 200 or r@ portsc! ( value r: port ) \ Reset port + d# 30 ms ( value r: port ) \ > 10 ms - reset time + dup r@ portsc! ( value r: port ) \ Release reset + 1 ms ( value r: port ) \ > 5.3 uS - reconnect time + h# e or r> portsc! ( ) \ Enable port and clear status +; + : reset-usb ( -- ) uhci-reg dup 0= if map-regs then 4 usbcmd! \ Global reset
Modified: dev/usb2/pkt-data.fth ============================================================================== --- dev/usb2/pkt-data.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/pkt-data.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -80,7 +80,7 @@
\ Use tmp-l to make sure that le-l! and le-w! are atomic writes
-instance variable tmp-l +variable tmp-l : le-w@ ( a -- w ) dup c@ swap ca1+ c@ bwjoin ; : (le-w!) ( w a -- ) >r wbsplit r@ ca1+ c! r> c! ; : le-w! ( w a -- ) swap tmp-l (le-w!) tmp-l w@ swap w! ;
Modified: dev/usb2/pkt-func.fth ============================================================================== --- dev/usb2/pkt-func.fth Wed Jan 26 20:01:33 2011 (r2151) +++ dev/usb2/pkt-func.fth Thu Jan 27 00:40:25 2011 (r2152) @@ -24,22 +24,6 @@ repeat ;
-: get-class ( dev-adr cfg-adr intfidx -- protocol subclass class ) - rot dup 4 + c@ ?dup 0= if ( cfg-adr intfidx dev-adr ) - false to class-in-dev? \ Class is not in device descriptor - drop find-intf-desc ( intf-adr ) - dup 5 + c@ swap dup 6 + c@ swap 7 + c@ - else \ Class is in device-descriptor - true to class-in-dev? ( cfg-adr intfidx dev-adr class ) - 2swap 2drop ( dev-adr class ) - swap dup 5 + c@ swap 6 + c@ - then -; - -: get-vid ( adr -- vendor product rev ) - dup 8 + le-w@ swap dup d# 10 + le-w@ swap c + le-w@ -; - : unicode$>ascii$ ( adr -- actual ) dup c@ 2 - 2/ swap 2 + over 0 ?do ( actual adr' ) dup i 2* 1+ + c@ 0= if \ ASCII
openfirmware@openfirmware.info