aboutsummaryrefslogtreecommitdiff
path: root/slof/fs/usb/usb-hub.fs
diff options
context:
space:
mode:
Diffstat (limited to 'slof/fs/usb/usb-hub.fs')
-rw-r--r--slof/fs/usb/usb-hub.fs468
1 files changed, 468 insertions, 0 deletions
diff --git a/slof/fs/usb/usb-hub.fs b/slof/fs/usb/usb-hub.fs
new file mode 100644
index 0000000..ac0ae66
--- /dev/null
+++ b/slof/fs/usb/usb-hub.fs
@@ -0,0 +1,468 @@
+\ *****************************************************************************
+\ * Copyright (c) 2004, 2007 IBM Corporation
+\ * All rights reserved.
+\ * This program and the accompanying materials
+\ * are made available under the terms of the BSD License
+\ * which accompanies this distribution, and is available at
+\ * http://www.opensource.org/licenses/bsd-license.php
+\ *
+\ * Contributors:
+\ * IBM Corporation - initial implementation
+\ ****************************************************************************/
+
+
+\ ----------------------------------------------------------------------------
+\ On detection of a hub after reading the device descriptor this package has to
+\ be called so that the hub enumeration is done to idenitify the down stream
+\ device
+\ --------------------------------------------------------------------------
+\ OF properties
+\ --------------------------------------------------------------------------
+
+
+s" hub" device-name
+s" usb" device-type
+1 encode-int s" #address-cells" property
+0 encode-int s" #size-cells" property
+
+\ converts physical address to text unit string
+
+
+: encode-unit ( port-addr -- unit-str unit-len ) 1 hex-encode-unit ;
+
+
+\ Converts text unit string to phyical address
+
+
+: decode-unit ( addr len -- port-addr ) 1 hex-decode-unit ;
+
+0 VALUE new-device-address
+0 VALUE port-number
+0 VALUE MPS-DCP
+0 VALUE mps
+0 VALUE my-usb-address
+
+00 value device-speed
+
+
+\ Get parameters passed from the parent.
+
+: mps-property-set ( -- )
+ s" HUB Compiling mps-property-set " usb-debug-print
+ s" USB-ADDRESS" get-my-property ( TRUE | prop-addr prop-len FALSE )
+ IF
+ s" notpossible" usb-debug-print
+ ELSE
+ decode-int nip nip to my-usb-address
+ THEN
+ s" MPS-DCP" get-my-property ( TRUE | prop-addr prop-len FALSE )
+ IF
+ s" MPS-DCP property not found Assuming 8 as MAX PACKET SIZE" ( str len )
+ usb-debug-print
+ s" for the default control pipe" usb-debug-print
+ 8 to MPS-DCP
+ ELSE
+ s" MPS-DCP property found!!" usb-debug-print ( prop-addr prop-len FALSE )
+ decode-int nip nip to MPS-DCP
+ THEN
+;
+
+
+\ --------------------------------------------------------------------------
+\ Constant declarations
+\ --------------------------------------------------------------------------
+
+
+2303080000000000 CONSTANT hppwr-set
+2301080000000000 CONSTANT hppwr-clear
+2303040000000000 CONSTANT hprst-set
+A300000000000400 CONSTANT hpsta-get
+2303010000000000 CONSTANT hpena-set
+A006002900000000 CONSTANT hubds-get
+8 CONSTANT DEFAULT-CONTROL-MPS
+12 CONSTANT DEVICE-DESCRIPTOR-LEN
+9 CONSTANT CONFIG-DESCRIPTOR-LEN
+20 CONSTANT BULK-CONFIG-DESCRIPTOR-LEN
+
+
+\ TODO:
+\ CONFIG-DESCRIPTOR-LEN should be only 9. The interface
+\ and endpoint descriptors returned along with config
+\ descriptor are variable and 0x19 is a very wrong VALUE
+\ to specify for this #define.
+
+
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE
+1 CONSTANT DEVICE-DESCRIPTOR-TYPE-OFFSET
+4 CONSTANT DEVICE-DESCRIPTOR-DEVCLASS-OFFSET
+7 CONSTANT DEVICE-DESCRIPTOR-MPS-OFFSET
+9 CONSTANT HUB-DEVICE-CLASS
+0 CONSTANT NO-CLASS
+
+
+\ --------------------------------------------------------------------------
+\ Temporary Variable declarations
+\ --------------------------------------------------------------------------
+
+00 VALUE temp1
+00 VALUE temp2
+00 VALUE temp3
+00 VALUE po2pg \ Power On to Power Good
+
+
+\ --------------------------------------------------------------------------
+\ Buffer allocations
+\ --------------------------------------------------------------------------
+
+
+VARIABLE setup-packet \ 8 bytes for setup packet
+VARIABLE ch-buffer \ 1 byte character buffer
+
+INSTANCE VARIABLE dd-buffer
+INSTANCE VARIABLE cd-buffer
+
+\ TODO:
+\ Should arrive a proper value for the size of the "cd-buffer"
+
+8 chars alloc-mem VALUE status-buffer
+9 chars alloc-mem VALUE hd-buffer
+
+
+: (allocate-mem) ( -- )
+ DEVICE-DESCRIPTOR-LEN chars alloc-mem dd-buffer !
+ BULK-CONFIG-DESCRIPTOR-LEN chars alloc-mem cd-buffer !
+;
+
+
+: (de-allocate-mem) ( -- )
+ dd-buffer @ ?dup IF
+ DEVICE-DESCRIPTOR-LEN free-mem
+ 0 dd-buffer !
+ THEN
+ cd-buffer @ ?dup IF
+ BULK-CONFIG-DESCRIPTOR-LEN free-mem
+ 0 cd-buffer !
+ THEN
+;
+
+
+\ standard open firmware methods
+
+: open ( -- TRUE )
+ (allocate-mem)
+ TRUE
+;
+
+: close ( -- )
+ (de-allocate-mem)
+;
+
+
+\ --------------------------------------------------------------------------
+\ Parent's method
+\ --------------------------------------------------------------------------
+
+
+: controlxfer ( dir addr dlen setup-packet MPS ep-fun -- TRUE|FALSE )
+ s" controlxfer" $call-parent
+;
+
+: control-std-set-address ( speedbit -- usb-address TRUE|FALSE )
+ s" control-std-set-address" $call-parent
+;
+
+: control-std-get-device-descriptor
+ ( data-buffer data-len MPS funcAddr -- TRUE|FALSE )
+ s" control-std-get-device-descriptor" $call-parent
+;
+
+: control-std-get-configuration-descriptor
+ ( data-buffer data-len MPS funcAddr -- TRUE|FALSE )
+ s" control-std-get-configuration-descriptor" $call-parent
+;
+
+: control-std-get-maxlun
+ ( MPS fun-addr dir data-buff data-len -- TRUE|FALSE)
+ s" control-std-get-maxlun" $call-parent
+;
+
+: control-std-set-configuration
+ ( configvalue FuncAddr -- TRUE|FALSE )
+ s" control-std-set-configuration" $call-parent
+;
+
+: control-std-get-string-descriptor
+ ( StringIndex data-buffer data-len MPS FuncAddr -- TRUE|FALSE )
+ s" control-std-get-string-descriptor" $call-parent
+;
+
+: rw-endpoint
+ ( pt ed-type toggle buffer length mps address -- toggle TRUE|toggle FALSE )
+ s" rw-endpoint" $call-parent
+;
+
+: debug-td ( -- )
+ s" debug-td" $call-parent
+;
+
+
+\ --------------------------------------------------------------------------
+\ HUB specific methods
+\ --------------------------------------------------------------------------
+\ To bring on the power on a valid port of a hub with a valid USB address
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-power-set ( port# -- TRUE|FALSE )
+ hppwr-set setup-packet ! ( port#)
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE | FALSE )
+;
+
+
+\ --------------------------------------------------------------------------
+\ To put power off on ports where device detection or enumeration has failed
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-power-clear ( port#-- TRUE|FALSE )
+ hppwr-clear setup-packet ! ( port#)
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To reset a valid port of a hub with a valid USB
+\ address
+\ --------------------------------------------------------------------------
+
+
+: control-hub-port-reset-set ( port# -- TRUE|FALSE )
+ hprst-set setup-packet ! ( port# )
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To enable a particular valid port of a hub with a valid USB address
+\ -------------------------------------------------------------------------
+
+
+: control-hub-port-enable ( port# -- TRUE|FALSE )
+ hpena-set setup-packet ! ( port# )
+ setup-packet 4 + c!
+ 0 0 0 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ -------------------------------------------------------------------------
+\ To get the status of a valid port of a hub with
+\ a valid USB address
+\ -------------------------------------------------------------------------
+
+
+: control-hub-port-status-get ( buffer port# -- TRUE|FALSE )
+ hpsta-get setup-packet ! ( buffer port# )
+ setup-packet 4 + c! ( buffer )
+ 0 swap 4 setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+\ --------------------------------------------------------------------------
+\ To get the hub descriptor to understand how many ports are vailable and the
+\ specs of those ports
+\ ---------------------------------------------------------------------------
+
+
+: control-get-hub-descriptor ( buffer buffer-length -- TRUE|FALSE )
+ hubds-get setup-packet !
+ dup setup-packet 6 + w!-le ( buffer buffer-length )
+ 0 -rot setup-packet MPS-DCP my-usb-address controlxfer ( TRUE|FALSE )
+;
+
+
+s" usb-enumerate.fs" INCLUDED
+
+
+: hub-configure-port ( port# -- )
+
+ \ Step 1: set the Port Power
+ usb-test-flag
+ IF
+ ." Port: " dup . cr
+ 150 ms \ wait for bad devices
+ THEN
+
+ dup control-hub-port-power-set drop ( port# )
+ BEGIN ( port# )
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 102 and 0= ( port# TRUE|FALSE )
+ WHILE ( port# )
+ REPEAT ( port# )
+ po2pg 3 * ms \ wait for bPwrOn2PwrGood*3 ms
+
+ usb-test-flag
+ IF
+ 150 ms
+ THEN
+ \ STEP 2: Reset the port.
+
+ dup control-hub-port-reset-set drop ( port# )
+ BEGIN ( port# )
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 10 and ( port# TRUE|FALSE )
+ usb-test-flag
+ IF
+ s" Port Satus: " status-buffer w@-le usb-debug-print-val
+ THEN
+ WHILE ( port# )
+ REPEAT ( port# )
+
+ \ after reset set port enable -important-
+ dup control-hub-port-enable drop ( port# )
+
+ usb-test-flag
+ IF
+ 10 ms
+ THEN
+
+ \ STEP 3: Check if a device is connected to the
+ \ port.
+
+ status-buffer 4 erase ( port# )
+ status-buffer over control-hub-port-status-get drop ( port# )
+ status-buffer w@-le 103 and 103 <> ( port# TRUE|FALSE )
+ s" Port status bits: " status-buffer w@-le usb-debug-print-val
+ IF ( port# )
+ drop
+ s" Connect status: No device connected " usb-debug-print
+ EXIT
+ THEN
+
+ \ New addition: Sometimes the port status returns connected
+ \ but Set address was failing. Analysis showed that such
+ \ ports do not set this bit to 1.
+
+ status-buffer 2 + w@-le 1 and 1 <> ( port# )
+ IF ( port# )
+ drop
+ s" No device connected to port- set addresss failed" usb-debug-print
+ EXIT
+ THEN
+ s" HUB: New device found!!!" usb-debug-print
+\ s" HUB: Status buffer first word -> " usb-debug-print
+\ s" HUB: Status buffer second word -> " usb-debug-print
+
+ \ STEP 4: Assign an address to this device.
+
+ status-buffer w@-le 200 and 4 lshift \ get speed bit
+ dup to device-speed \ store speed bit
+ ( port# speedbit )
+ control-std-set-address ( port# usb-addr TRUE|FALSE )
+ 50 ms ( port# usb-addr TRUE|FALSE )
+ debug-td ( port# usb-addr TRUE|FALSE )
+ IF ( port# usb-addr )
+ device-speed or ( port# usb-addr+speedbit )
+ to new-device-address ( port# )
+ to port-number
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN erase
+ dd-buffer @ DEFAULT-CONTROL-MPS DEFAULT-CONTROL-MPS new-device-address
+ ( buffer mps mps usb-addr )
+ control-std-get-device-descriptor ( TRUE|FALSE )
+ IF
+ dd-buffer @ DEVICE-DESCRIPTOR-TYPE-OFFSET + c@ ( descriptor-type )
+ DEVICE-DESCRIPTOR-TYPE <> ( TRUE|FALSE )
+ IF
+ s" HUB: ERROR!! Invalid Device Descriptor for the new device"
+ usb-debug-print
+ ELSE
+ dd-buffer @ DEVICE-DESCRIPTOR-MPS-OFFSET + c@ to mps
+
+ \ Re-read the device descriptor again with the known MPS.
+
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN erase
+ dd-buffer @ DEVICE-DESCRIPTOR-LEN mps new-device-address
+ ( buffer descp-len mps usb-addr )
+ \ s" DEVICE DESCRIPTOR: " usb-debug-print
+ control-std-get-device-descriptor drop
+ \ dd-buffer usb-debug-print-val
+ create-usb-device-tree
+ THEN
+ ELSE
+ s" ERROR!! Failed to get device descriptor" usb-debug-print
+ THEN
+ ELSE ( port# )
+ s" USB Set Adddress failed!!" usb-debug-print ( port# )
+ s" Clearing Port Power..." usb-debug-print ( port# )
+ control-hub-port-power-clear ( TRUE|FALSE )
+ IF
+ s" Port power down " usb-debug-print
+ ELSE
+ s" Unable to clear port power!!!" usb-debug-print
+ THEN
+ THEN
+;
+
+
+\ ---------------------------------------------------------------------------
+\ To enumerate all the valid ports of hub
+\ TODO:
+\ 1. Remove hardcoded constants.
+\ 2. Remove Endian Dependencies.
+\ 3. Return values of controlxfer should be checked.
+\ ---------------------------------------------------------------------------
+
+: hub-enumerate ( -- )
+ cd-buffer @ CONFIG-DESCRIPTOR-LEN erase
+
+ \ Get HUB configuration and SET the configuration
+ \ note: remove hard-coded constants.
+
+ cd-buffer @ CONFIG-DESCRIPTOR-LEN MPS-DCP my-usb-address
+ ( buffer descp-len mps usb-address )
+ control-std-get-configuration-descriptor drop
+ cd-buffer @ 1+ c@ 2 <> IF
+ s" Unable to read configuration descriptor" usb-debug-print
+ EXIT
+ THEN
+ cd-buffer @ 4 + c@ 1 <> IF
+ s" Not a valid HUB config descriptor" usb-debug-print
+ EXIT
+ THEN
+
+ \ TODO: Do further checkings on the returned Configuration descriptor
+ \ before proceeding to accept it.
+
+ cd-buffer @ 5 + c@ to temp1 \ Store the configuration in temp1
+ temp1 my-usb-address control-std-set-configuration drop
+ my-usb-address to temp1
+ hd-buffer 9 erase
+ hd-buffer 9 control-get-hub-descriptor drop
+
+ \ PENDING: 1. Check Return value.
+ \ 2. HUB descriptor size is variable. Currently we r hardcoding
+ \ a value of 9.
+
+ hd-buffer 2 + c@ to temp2
+ s" HUB: Found " usb-debug-print \ temp2 .
+ s" number of downstream hub ports! : " temp2 usb-debug-print-val
+ hd-buffer 5 + c@ to po2pg \ get bPwrOn2PwrGood
+ temp2 1+ 1 DO
+ I hub-configure-port
+ LOOP
+;
+
+
+\ --------------------------------------------------------------------------
+\ To initialize hub
+\ --------------------------------------------------------------------------
+
+(allocate-mem)
+mps-property-set
+hub-enumerate
+(de-allocate-mem)
+