[openfirmware] r1651 - in dev/usb2/hcd: . ehci

svn at openfirmware.info svn at openfirmware.info
Fri Jan 8 08:30:03 CET 2010


Author: wmb
Date: 2010-01-08 08:30:03 +0100 (Fri, 08 Jan 2010)
New Revision: 1651

Modified:
   dev/usb2/hcd/dev-info.fth
   dev/usb2/hcd/ehci/bulk.fth
   dev/usb2/hcd/ehci/control.fth
   dev/usb2/hcd/ehci/intr.fth
   dev/usb2/hcd/ehci/probe.fth
   dev/usb2/hcd/ehci/qhtd.fth
Log:
OLPC trac 9969 - make USB work after resume - sort of.  USB 2.0 devices
like mass storage devices and LANs work after resume, so long as you
don't suspend/resume too many times.  Eventually the system dies with
"user area used up", because the device nodes get reloaded every time.
I need to work out how to reuse the device nodes instead of reloading,
but that could get complicated.  I also need to do something about USB 1.1
devices.


Modified: dev/usb2/hcd/dev-info.fth
===================================================================
--- dev/usb2/hcd/dev-info.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/dev-info.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -25,9 +25,9 @@
    1+					\ Padding for word alignment
    /di-ep-struct #max-endpoint * field >di-ep
 					\ Endpoint structure
-dup constant /di-entry
+constant /di-entry
 
-#max-dev * constant /di
+/di-entry #max-dev * constant /di
 0 value di				\ device-info
 
 0 value cur-dev				\ Value of the last assigned usb address
@@ -60,14 +60,17 @@
 ;
 
 : init-di  ( -- )
-   \ allocate and initialize the device descriptors
-   /di alloc-mem to di
-   di /di erase
-   /pipe0 0 0 di-maxpayload!		\ Default max payload
+   di 0=  if
+      \ allocate and initialize the device descriptors
+      /di alloc-mem to di
+      di /di erase
+      /pipe0 0 0 di-maxpayload!		\ Default max payload
+   then
 ;
 
 : init-struct  ( -- )
    init-di
+   0 to cur-dev
 ;
 
 headers

Modified: dev/usb2/hcd/ehci/bulk.fth
===================================================================
--- dev/usb2/hcd/ehci/bulk.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/ehci/bulk.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -76,9 +76,9 @@
    then                                           ( #qtds )
    bulk-qh reuse-qhqtds
 ;
-: free-bulk-qhqtds  ( -- )
+: free-bulk-qh  ( -- )
    bulk-qh ?dup  if                     ( qh )
-      free-qhqtds			( )
+      free-qh				( )
       0 to bulk-qh
    then
 ;
@@ -512,7 +512,7 @@
 
 headers
 
-: (end-extra)  ( -- )  end-bulk-in free-bulk-qhqtds ;
+: (end-extra)  ( -- )  end-bulk-in free-bulk-qh  ;
 
 
 \ LICENSE_BEGIN

Modified: dev/usb2/hcd/ehci/control.fth
===================================================================
--- dev/usb2/hcd/ehci/control.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/ehci/control.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -149,7 +149,7 @@
       then
    then
 
-   my-qh dup remove-qh  free-qhqtds		( actual )
+   my-qh dup remove-qh  free-qh			( actual )
    usb-error					( actual usberr )
 ;
 
@@ -161,7 +161,7 @@
    \ Process results
    my-qh done? 0=  if  my-qh error? drop  then
 
-   my-qh dup remove-qh  free-qhqtds
+   my-qh dup remove-qh  free-qh
    usb-error
 ;
 

Modified: dev/usb2/hcd/ehci/intr.fth
===================================================================
--- dev/usb2/hcd/ehci/intr.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/ehci/intr.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -112,7 +112,7 @@
    intr-in-qh 0=  if  exit  then
    intr-in-qh dup fixup-intr-in-data
    intr-in-qtd map-out-bptrs
-   dup remove-intr-qh  free-qhqtds
+   dup remove-intr-qh  free-qh
    0 to intr-in-qh  0 to intr-in-qtd
 ;
 

Modified: dev/usb2/hcd/ehci/probe.fth
===================================================================
--- dev/usb2/hcd/ehci/probe.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/ehci/probe.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -134,6 +134,17 @@
    probe-teardown
 ;
 
+: do-resume  ( -- )
+   init-ehci-regs
+   start-usb
+   claim-ownership
+   init-struct
+   init-extra
+;
+
+\ This is a sneaky way to determine if the hardware has been turned off without the software's knowledge
+: suspended?  ( -- flag )  asynclist@ 0=  qh-ptr 0<>  and  ;
+
 : open  ( -- flag )
    parse-my-args
    open-count 0=  if
@@ -148,25 +159,15 @@
          then
          0 ehci-reg@  h# ff and to op-reg-offset
          reset-usb
-         init-ehci-regs
-         start-usb
-         claim-ownership
-         init-struct
-         init-extra
+         do-resume
       then
+      suspended?  if  do-resume  then
       probe-root-hub
    then
    open-count 1+ to open-count
    true
 ;
 
-: do-resume  ( -- )
-   init-ehci-regs
-   start-usb
-   claim-ownership
-   framelist-phys periodic!
-;
-
 : close  ( -- )
    open-count 1- to open-count
    end-extra

Modified: dev/usb2/hcd/ehci/qhtd.fth
===================================================================
--- dev/usb2/hcd/ehci/qhtd.fth	2010-01-08 07:23:30 UTC (rev 1650)
+++ dev/usb2/hcd/ehci/qhtd.fth	2010-01-08 07:30:03 UTC (rev 1651)
@@ -47,14 +47,16 @@
 : framelist!  ( n idx -- )  4 * framelist + le-l!  ;
 
 : init-framelist  ( -- )
-   \ Allocate framelist
-   /framelist /align4kb aligned-alloc	( unaligned virt )
-   swap to framelist-unaligned		( virt )
-   dup to framelist			( virt )
-   /framelist true dma-map-in to framelist-phys	( )
+   framelist 0=  if
+      \ Allocate framelist
+      /framelist /align4kb aligned-alloc	    ( unaligned virt )
+      swap to framelist-unaligned		    ( virt )
+      dup to framelist			            ( virt )
+      /framelist true dma-map-in to framelist-phys  ( )
 
-   \ Initialize framelist
-   #framelist 0  do  TERMINATE i framelist!  loop
+      \ Initialize framelist
+      #framelist 0  do  TERMINATE i framelist!  loop
+   then
    framelist-phys periodic!
 ;
 
@@ -77,8 +79,10 @@
 : intr-tail!  ( adr idx -- )  'intr >intr-tail l!  ;
 
 : init-intr  ( -- )
-   /intr alloc-mem dup to intr		\ Allocate intr
-   /intr erase				\ Initialize intr
+   intr 0=  if
+      /intr alloc-mem dup to intr		\ Allocate intr
+      /intr erase				\ Initialize intr
+   then
 ;
 
 \ ---------------------------------------------------------------------------
@@ -283,17 +287,8 @@
    r> 4 pick link-qhqtds		( qh qtd )
 ;
 
-: free-qh  ( qh -- )
-   >r					( R: qh )
-   r@ >qh-unaligned l@			( qh.u )  ( R: qh )
-   r@ dup >qh-phys l@			( qh.u,v,p )  ( R: qh )
-   r> >qh-size l@			( qh.u,v,p size )
-   aligned32-free-map-out		( )
-;
+\ Qtds will be freed automatically when the qh is freed
 
-\ Same as free-qh because the size field tells all
-: free-qhqtds  ( qh -- )  free-qh  ;
-
 : reuse-qhqtds  ( #qtds qh -- qh qtd )
    swap dup >r  /qtd * /qh + >r		( qh )  ( R: #qtds len )
    dup >qh-unaligned l@ swap		( qh.u,v )  ( R: #qtds len )
@@ -367,36 +362,41 @@
       usbcmd@ h# 20 and  5 >>  usbsts@ h# 8000 and d# 15 >> 
    = until
 ;
-: enable-async  ( phys -- )
-   asynclist!                async-wait
+: enable-async  ( qh -- )
+   >qh-phys l@  asynclist!   async-wait
    usbcmd@ h# 20 or usbcmd!  async-wait
 ;
 : disable-async  ( -- )
    async-wait  usbcmd@ h# 20 invert and usbcmd!  async-wait
+   0 to qh-ptr
 ;
 
+: link-to-qh-ptr  ( qh -- )
+   dup  qh-ptr >qh-next  l!                               ( qh )
+   dup  >qh-phys l@  TYP_QH or  qh-ptr >hcqh-next  le-l!  ( qh )
+   sync-qhqtds                                            ( )
+;
 : insert-qh  ( qh -- )
-   >r
-   qh-ptr  if
-      \ If there is another qh in the system, link the new qh to the existing
-      \ qh head.
-      qh-ptr r@ >qh-prev l!
-      qh-ptr >qh-next l@ r@ >qh-next l!
-      qh-ptr >hcqh-next le-l@ r@ >hcqh-next le-l!
-      r@ qh-ptr >qh-next l!
-      r@ >qh-phys l@ TYP_QH or qh-ptr >hcqh-next le-l!
+   qh-ptr  if                                                 ( qh )
+      \ If there is another qh, link the new qh to the existing qh head.
+      qh-ptr                    over >qh-prev      l!         ( qh )
+      qh-ptr >qh-next      l@   over >qh-next      l!         ( qh )
+      qh-ptr >hcqh-next le-l@   over >hcqh-next le-l!         ( qh )
 
-      r> sync-qhqtds
-      qh-ptr sync-qh
-   else
-      \ If there is no qh in the system, link it to itself and mark it the
-      \ head.
-      r@ to qh-ptr
-      r@ >hcqh-endp-char dup le-l@ QH_HEAD or swap le-l!
-      r@ dup >qh-next l!
-      r@ >qh-phys l@ dup TYP_QH or r@ >hcqh-next le-l!
-      r> sync-qhqtds
-      enable-async
+      link-to-qh-ptr                                          ( )
+
+      qh-ptr sync-qh                                          ( )
+   else                                                       ( )
+      \ If there is no other qh, make it the head, link it to itself, 
+      \ and start the asynch schedule.
+
+      to qh-ptr                                                  ( )
+
+      qh-ptr >hcqh-endp-char  dup le-l@  QH_HEAD or  swap le-l!  ( )
+
+      qh-ptr link-to-qh-ptr                                      ( )
+
+      qh-ptr enable-async                                        ( )
    then
 ;
 : fix-wraparound-qh  ( qh -- )
@@ -423,7 +423,6 @@
    dup >qh-next l@ over =  if
       \ If qh is the only qh in the system, disable-async and exit
       drop disable-async
-      0 to qh-ptr
    else
       \ Otherwise, qh.prev points to qh.next, fix up reclamation bits.
       \ Ring doorbell, wait for answer.
@@ -625,17 +624,20 @@
       drop to dummy-qh
       TERMINATE dummy-qh >hcqh-overlay >hcqtd-next le-l!
    then
+   0 to qh-ptr
    dummy-qh insert-qh
 ;
 
 : free-dummy-qh  ( -- )
-   dummy-qh ?dup  if  free-qhqtds  0 to dummy-qh  then
+   dummy-qh ?dup  if  free-qh  0 to dummy-qh  then
 ;
 
 : ?alloc-dummy-qh  ( -- )
    0 my-w@ h# 1106 ( VIA ) =  if  alloc-dummy-qh  then
 ;
 
+\ The words this calls are written so they can be called again
+\ on resume from S3 state without causing redundant memory allocation.
 : (init-extra)  ( -- )
    ?alloc-dummy-qh
    init-intr




More information about the openfirmware mailing list