[openfirmware] [commit] r2591 - in dev/usb2: . hcd hcd/ehci hcd/ohci hcd/uhci

repository service svn at openfirmware.info
Wed Oct 12 00:28:41 CEST 2011


Author: wmb
Date: Wed Oct 12 00:28:40 2011
New Revision: 2591
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2591

Log:
USB - Use interrupt-on-completion for bulk and control transfers, thus eliminating or at least greatly reducing problems related to descriptor polling causing DMA failures.  Also use dma-push and dma-pull instead of dma-sync, for more precise control of coherency.

Modified:
   dev/usb2/align.fth
   dev/usb2/hcd/control.fth
   dev/usb2/hcd/ehci/bulk.fth
   dev/usb2/hcd/ehci/control.fth
   dev/usb2/hcd/ehci/ehci.fth
   dev/usb2/hcd/ehci/intr.fth
   dev/usb2/hcd/ehci/iso.fth
   dev/usb2/hcd/ehci/qhtd.fth
   dev/usb2/hcd/ohci/bulk.fth
   dev/usb2/hcd/ohci/control.fth
   dev/usb2/hcd/ohci/edtd.fth
   dev/usb2/hcd/ohci/intr.fth
   dev/usb2/hcd/uhci/bulk.fth
   dev/usb2/hcd/uhci/control.fth
   dev/usb2/hcd/uhci/intr.fth
   dev/usb2/hcd/uhci/qhtd.fth

Modified: dev/usb2/align.fth
==============================================================================
--- dev/usb2/align.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/align.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -11,7 +11,8 @@
 : round-up  ( n align -- n' )  1- tuck + swap invert and  ;
 
 external
-: dma-sync     ( virt phys size -- )         " dma-sync" $call-parent     ;
+: dma-push     ( virt phys size -- )         " dma-push" $call-parent     ;
+: dma-pull     ( virt phys size -- )         " dma-pull" $call-parent     ;
 : dma-alloc    ( size -- virt )              " dma-alloc" $call-parent    ;
 : dma-free     ( virt size -- )              " dma-free" $call-parent     ;
 : dma-map-in   ( virt size cache? -- phys )  " dma-map-in" $call-parent   ;

Modified: dev/usb2/hcd/control.fth
==============================================================================
--- dev/usb2/hcd/control.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/control.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -14,7 +14,7 @@
    tuck >dr-value le-w!				( len idx vpcbp )
    tuck >dr-index le-w!				( len vpcbp )
    >dr-len le-w!				( )
-   setup-buf setup-buf-phys /dr dma-sync	( )
+   setup-buf setup-buf-phys /dr dma-push	( )
 ;
 
 external

Modified: dev/usb2/hcd/ehci/bulk.fth
==============================================================================
--- dev/usb2/hcd/ehci/bulk.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/bulk.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -225,6 +225,7 @@
    dup le-l@                                    ( in? token-adr token-val r: qtd qh )
    rot  if  bulk-in-data@  else  bulk-out-data@  then   ( token-adr token-val toggle r: qtd qh )
    or                                           ( token-adr token-val' r: qtd qh )
+   TD_IOC or                                    ( token-adr token-val' r: qtd qh )
    swap le-l!                                   ( r: qtd qh )
 
    r> r>					( qh qtd )
@@ -257,7 +258,7 @@
    over >hcqtd-token		( qtd len token-adr )
    tuck 2+ le-w!		( qtd token-adr )
    TD_C_ERR3  TD_PID_OUT or  TD_STAT_PING or  TD_STAT_ACTIVE or   swap le-w!  ( qtd )
-   sync-qtd
+   push-qtd
 ;
 
 : wait-out  ( qtd -- error? )
@@ -310,12 +311,12 @@
 : bulk-in-ready?  ( -- false | error true |  buf actual 0 true )
    clear-usb-error
    bulk-in-qtd >r
-   r@ sync-qtd
+   r@ pull-qtd
    r@ qtd-done?  if				( )
       r@  bulk-in-qh qtd-error? ?dup  0=  if	( )
          r@ >qtd-buf l@				( buf actual )
          r@ qtd-get-actual			( buf actual )
-         2dup  r@ >qtd-pbuf l@  swap  dma-sync	( buf actual )
+         2dup  r@ >qtd-pbuf l@  swap  dma-pull	( buf actual )
          0					( buf actual 0 )
       then					( error | buf actual 0 )
       true					( ... )
@@ -352,7 +353,7 @@
 
    \ Recycle the first qtd last so the transaction is atomic WRT the HC
    drop dup recycle-one-qtd	( qtd0 )
-   sync-qtds
+   push-qtds
 ;
 
 \ Fixup the host-controller-writable fields in the chain of qTDs -
@@ -451,6 +452,12 @@
 
 : recycle-buffer restart-bulk-in ;
 
+: start-bulk-transaction  ( pid -- )
+   my-bulk-qtd fill-bulk-io-qtds	( )
+   my-bulk-qh pt-bulk fill-qh		( )
+   my-bulk-qh interrupt-on-last-td      ( )
+   my-bulk-qh insert-qh			( )
+;
 : bulk-in  ( buf len pipe -- actual usberr )
    debug?  if  ." bulk-in" cr  then
    dup to bulk-in-pipe
@@ -459,22 +466,14 @@
    bulk-in-timeout my-bulk-qh >qh-timeout l!
 
    \ IN qTDs
-   TD_PID_IN my-bulk-qtd fill-bulk-io-qtds
-
-   \ Start bulk in transaction
-   my-bulk-qh pt-bulk fill-qh
-   my-bulk-qh insert-qh
+   TD_PID_IN start-bulk-transaction		( )
 
    \ Process results
-   my-bulk-qh done?  if				( )
-      0						( actual )	\ System error, timeout
+   my-bulk-qh done-error?  if			( )		\ System error, timeout, or USB error
+      0						( actual )	
    else						( )
-      my-bulk-qh error?  if			( )
-         0					( actual )	\ USB error
-      else					( )
-         my-bulk-qtd dup my-#qtds get-actual	( qtd actual )
-         over >qtd-buf l@ rot >qtd-pbuf l@ 2 pick dma-sync	( actual )
-      then					( actual )
+      my-bulk-qtd dup my-#qtds get-actual	( qtd actual )
+      over >qtd-buf l@ rot >qtd-pbuf l@ 2 pick dma-pull	( actual )
    then						( actual )
 
    usb-error					( actual usberr )
@@ -486,9 +485,7 @@
 0 instance value bulk-out-busy?
 : done-bulk-out  ( -- error? )
    \ Process results
-   my-bulk-qh done? 0=  if  my-bulk-qh error? drop  then
-
-   usb-error				( usberr )
+   my-bulk-qh done-error?		( usberr )
    my-bulk-qtd map-out-bptrs		( usberr )
    my-bulk-qh fixup-bulk-out-data	( usberr )
    my-bulk-qh remove-qh			( usberr )
@@ -507,11 +504,7 @@
    my-bulk-qh >hcqh-overlay >hcqtd-token dup le-l@ TD_STAT_PING or swap le-l!
 
    \ OUT qTDs
-   TD_PID_OUT my-bulk-qtd fill-bulk-io-qtds		( )
-
-   \ Start bulk out transaction
-   my-bulk-qh pt-bulk fill-qh		( )
-   my-bulk-qh insert-qh			( )
+   TD_PID_OUT start-bulk-transaction	( )
    true to bulk-out-busy?		( )
    0					( usberr )
 ;

Modified: dev/usb2/hcd/ehci/control.fth
==============================================================================
--- dev/usb2/hcd/ehci/control.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/control.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -135,19 +135,16 @@
 
    \ Start control transaction
    my-qh pt-ctrl fill-qh
+   my-qh interrupt-on-last-td
    my-qh insert-qh
 
    \ Process results
-   my-qh done?  if
-      0						( actual )	\ System error, timeout
-   else
-      my-qh error?  if
-         0					( actual )	\ USB error
-      else
-         my-qtd >qtd-next l@ dup my-#qtds get-actual		( qtd actual )
-         over >qtd-buf l@ rot >qtd-pbuf l@ 2 pick dma-sync	( actual )
-      then
-   then
+   my-qh done-error?  if			( )
+      0						( actual )	\ System error, timeout, or USB error
+   else						( )
+      my-qtd >qtd-next l@ dup my-#qtds get-actual	( qtd actual )
+      over >qtd-buf l@ rot >qtd-pbuf l@ 2 pick dma-pull	( actual )
+   then						( actual )
 
    my-qh dup remove-qh  free-qh			( actual )
    usb-error					( actual usberr )
@@ -156,13 +153,12 @@
 : run-control  ( -- usberr )
    \ Start control transaction
    my-qh pt-ctrl fill-qh
+   my-qh interrupt-on-last-td
    my-qh insert-qh
 
    \ Process results
-   my-qh done? 0=  if  my-qh error? drop  then
-
-   my-qh dup remove-qh  free-qh
-   usb-error
+   my-qh done-error?                ( usberr )
+   my-qh dup remove-qh  free-qh     ( usberr )
 ;
 
 : (control-set)  ( sbuf sphy slen buf phy len -- usberr )

Modified: dev/usb2/hcd/ehci/ehci.fth
==============================================================================
--- dev/usb2/hcd/ehci/ehci.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/ehci.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -69,6 +69,16 @@
    usbsts@ dup usbsts!		\ Clear interrupts and errors
    h# 10  and  if  " Host system error" USB_ERR_HCHALTED set-usb-error  then
 ;
+: hc-interrupt?  ( -- interrupt? )
+   usbsts@ h# 13 and  dup  if   ( status )
+      dup usbsts!               ( status )  \ Clear interrupts, frame rollover, errors
+      dup h# 10  and  if        ( status )
+         " USB host controller halted" USB_ERR_HCHALTED set-usb-error
+      then                      ( status )
+   then                         ( status )
+   0<>                          ( interrupt? )
+;
+
 : get-hc-status  ( -- status )
    usbsts@ dup usbsts!		\ Clear interrupts and errors
    dup h# 10  and  if  " Host system error" USB_ERR_HCHALTED set-usb-error  then

Modified: dev/usb2/hcd/ehci/intr.fth
==============================================================================
--- dev/usb2/hcd/ehci/intr.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/intr.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -36,6 +36,8 @@
       2 pick over d# 16 << or			( dir qtd /bptr token )
       TD_C_ERR3 or TD_STAT_ACTIVE or		( dir qtd /bptr token' )
       intr-in-data@  toggle-intr-in-data  or	( dir qtd /bptr token' )
+\ See the comment about Interrupt-On-Completion elsewhere in this file
+\     i my-#qtds 1- =  if  TD_IOC or  then      ( dir qtd /bptr token' )
       2 pick >hcqtd-token le-l!			( dir qtd /bptr )
       my-buf++					( dir qtd )
       dup fixup-last-qtd			( dir qtd )
@@ -66,18 +68,28 @@
 : intr-in?  ( -- actual usberr )
    intr-in-qh 0=  if  0 USB_ERR_INV_OP exit  then  ( )
    clear-usb-error                   ( )
-   intr-in-qh qh-done?  if           ( )
-      intr-in-qh error?  if          ( )
-         0                           ( actual )
+   \ Ironically, we can't use Interrupt-On-Completion for interrupt pipes,
+   \ because when a bulk or control transaction is performed with IOC, the
+   \ call to hc-interrupt? from that transaction can prevent this routine
+   \ from seeing its IOC completion status.  The "right" solution might be to
+   \ scan all queue heads on an IOC "interrupt", then set a flag in the private
+   \ area of the queue head.  It's unclear that that is better for interrupt
+   \ pipes than just polling, since the polling typically happens on a timer
+   \ and thus is relatively infrequent.
+   \ If we were to use Interrupt-On-Completion for interrupt pipes, we would
+   \ use "intr-qh-done?" instead of "qh-done?" here.
+   intr-in-qh qh-done?  0=  if       ( )
+      0 usb-error                    ( actual usberr )	\ Timeout or system error
+   else				     ( )
+      intr-in-qh qh-error?  if       ( )
+	 0                           ( actual )  \ USB error
       else                           ( )
-         intr-in-qh sync-qhqtds      ( )
+         intr-in-qh pull-qhqtds      ( )
          intr-in-qtd  intr-in-qh >qh-#qtds l@  get-actual  ( actual )
-         intr-in-qtd >qtd-buf  intr-in-qtd >qtd-pbuf l@  2 pick  dma-sync  ( actual )
+         intr-in-qtd >qtd-buf  intr-in-qtd >qtd-pbuf l@  2 pick  dma-pull  ( actual )
       then                           ( actual )
       usb-error                      ( actual usberr )
       intr-in-qh fixup-intr-in-data  ( actual usberr )
-   else                              ( )
-      0 usb-error                    ( actual usberr )
    then                              ( actual usberr )
 ;
 
@@ -87,6 +99,8 @@
       dup >hcqtd-bptr0 dup le-l@ h# ffff.f000 and swap le-l!
       dup >qtd-/buf l@ d# 16 <<
       TD_STAT_ACTIVE or TD_C_ERR3 or TD_PID_IN or
+\ See the comment about Interrupt-On-Completion elsewhere in this file
+\     TD_IOC or
       intr-in-data@ or 
       over >hcqtd-token le-l!
       >qtd-next l@
@@ -104,7 +118,7 @@
    intr-in-timeout intr-in-qh >qh-timeout l!
    intr-in-qh >hcqh-endp-char dup le-l@ QH_TD_TOGGLE invert and swap le-l!
    intr-in-qtd >qtd-phys l@ intr-in-qh >hcqh-overlay >hcqtd-next le-l!
-   intr-in-qh sync-qhqtds
+   intr-in-qh push-qhqtds
 ;
 
 : end-intr-in  ( -- )

Modified: dev/usb2/hcd/ehci/iso.fth
==============================================================================
--- dev/usb2/hcd/ehci/iso.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/iso.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -174,7 +174,7 @@
    else					    \ Link and replace the entry
       itd-struct >itd-link le-l!	    ( itd-phys )  ( R: idx )
    then
-   itd-struct over /itd-sync dma-sync       ( itd-phys )  ( R: idx )
+   itd-struct over /itd-sync dma-push       ( itd-phys )  ( R: idx )
    TYP_ITD or r> framelist!                 ( )
 ;
 
@@ -246,7 +246,7 @@
    clear-usb-error
    iso-in-cur-itd set-itd-struct              ( adr len )
    itd-struct >itd-frame @  wait-frame-safe   ( adr len )
-   itd-struct dup >itd-phys @ /itd-sync dma-sync
+   itd-struct dup >itd-phys @ /itd-sync dma-pull
    iso-in-uframe-cnt 7 and                    ( adr len uframe# )
    4 * itd-struct >itd-xstat + le-l@          ( adr len xstat )
    dup ITD_ACTIVE and  if  3drop false exit  then    \ Not done yet
@@ -295,14 +295,14 @@
 
 [ifndef] notdef
 \ Debug aids
-: ldump  ( adr len -- )  " ldump" evaluate  ;
+: sys-ldump  ( adr len -- )  " ldump" evaluate  ;
 : .itd  ( -- )
-   iso-in-itd  iso-in-#itd /itd-struct *  ldump
+   iso-in-itd  iso-in-#itd /itd-struct *  sys-ldump
 ;
 : .xstat  ( -- )
    iso-in-#itd 0  do
       i set-itd-struct
-      itd-struct >itd-xstat /itd-xstat ldump
+      itd-struct >itd-xstat /itd-xstat sys-ldump
    loop
 ;
 \ Debug aids for video streaming only (and only if ITD_ACTIVE are all 0s)

Modified: dev/usb2/hcd/ehci/qhtd.fth
==============================================================================
--- dev/usb2/hcd/ehci/qhtd.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ehci/qhtd.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -189,10 +189,14 @@
 \ QH and its list of TDs are allocated as needed.
 \ ---------------------------------------------------------------------------
 
-: sync-qh      ( qh  -- )  dup >qh-phys  l@ /hcqh  dma-sync  ;
-: sync-qtd     ( qtd -- )  dup >qtd-phys l@ /hcqtd dma-sync  ;
-: sync-qtds    ( qtd -- )  dup >qtd-phys l@ over >qtd-size l@  dma-sync  ;
-: sync-qhqtds  ( qh  -- )  dup >qh-phys  l@ over >qh-size  l@  dma-sync  ;
+: push-qh      ( qh  -- )  dup >qh-phys  l@ /hcqh  dma-push  ;
+: pull-qh      ( qh  -- )  dup >qh-phys  l@ /hcqh  dma-pull  ;
+: push-qtd     ( qtd -- )  dup >qtd-phys l@ /hcqtd dma-push  ;
+: pull-qtd     ( qtd -- )  dup >qtd-phys l@ /hcqtd dma-pull  ;
+: push-qtds    ( qtd -- )  dup >qtd-phys l@ over >qtd-size l@  dma-push  ;
+: pull-qtds    ( qtd -- )  dup >qtd-phys l@ over >qtd-size l@  dma-pull  ;
+: push-qhqtds  ( qh  -- )  dup >qh-phys  l@ over >qh-size  l@  dma-push  ;
+: pull-qhqtds  ( qh  -- )  dup >qh-phys  l@ over >qh-size  l@  dma-pull  ;
 
 : map-out-bptrs  ( qtd -- )
    dup >qtd-buf l@ over >qtd-pbuf l@ rot >qtd-/buf-all l@ hcd-map-out
@@ -214,27 +218,6 @@
    TERMINATE swap >hcqtd-next-alt le-l!		( )
 ;
 
-: alloc-qtds  ( #qtds -- qtd )
-   dup >r  /qtd * dup >r		( len )  ( R: #qtds len )
-   aligned32-alloc-map-in		( u v p )  ( R: #qtds len )
-   swap					( u p v )  ( R: #qtds len )
-   dup r@ erase				( u p v )  ( R: #qtds len )
-
-   \ Record QTD size for later freeing
-   rot over >qtd-unaligned l!		( p v )  ( R: #qtds len )
-   r> over >qtd-size l!			( p v )  ( R: #qtds )
-
-   dup rot r> link-qtds			( qtd.v )
-;
-
-: free-qtds  ( qtd -- )
-   >r					( R: qtd )
-   r@ >qtd-unaligned l@			( u )  ( R: qtd )
-   r@ dup >qtd-phys l@			( u v p )  ( R: qtd )
-   r> >qtd-size l@			( u v p size )
-   aligned32-free-map-out		( )
-;
-
 : link-qhqtd  ( qtd.p qh -- )
    >hcqh-overlay tuck			( qh.overlay qtd.p qh.overlay )
    >hcqtd-next le-l!			( qh.overlay )
@@ -261,14 +244,6 @@
    >qh-unaligned l!			( )
 ;
 
-: alloc-qh  ( -- qh )
-   /qh aligned32-alloc-map-in		( u v p )
-   over /qh erase			( u v p )
-   over >r				( u v p r: v )
-   /qh 0 init-qh			( r: v )
-   TERMINATE r@ link-qhqtd		( r: v )
-   r>					( qh.v )
-;
 : free-qh  ( qh -- )
    >r					( R: qh )
    r@ >qh-unaligned l@			( qh.u )  ( R: qh )
@@ -375,9 +350,22 @@
 : 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                                            ( )
+   push-qhqtds                                            ( )
 ;
+: interrupt-on-last-td  ( qh -- )
+   /qh +                                   ( qtd )
+   begin                                   ( qtd )
+      dup >hcqtd-next le-l@ TERMINATE <>   ( qtd flag )
+   while                                   ( qtd )
+      >qtd-next l@                         ( qtd' )
+   repeat                                  ( qtd )
+   >hcqtd-token                            ( 'token )
+   dup le-l@  TD_IOC or  swap le-l!        ( )
+;
+
 : insert-qh  ( qh -- )
+   hc-interrupt? drop      \ Clear any pending transfer-complete interrupts
+   0 >hcqh-cur-pqtd off
    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 )
@@ -386,7 +374,7 @@
 
       link-to-qh-ptr                                          ( )
 
-      qh-ptr sync-qh                                          ( )
+      qh-ptr push-qh                                          ( )
    else                                                       ( )
       \ If there is no other qh, make it the head, link it to itself, 
       \ and start the asynch schedule.
@@ -431,7 +419,7 @@
       dup >qh-prev l@ ?dup if		( qh prev.qh )
          over >hcqh-next le-l@ over >hcqh-next le-l!
          over >qh-next l@ swap >qh-next l!
-         dup sync-qh
+         dup push-qh
          dup >qh-next l@ qh-ptr <>  if
             dup >qh-prev l@ swap >qh-next l@ >qh-prev l!
          else
@@ -442,7 +430,7 @@
          qh-ptr >hcqh-endp-char dup le-l@ QH_HEAD or swap le-l!  ( qh )
          fix-wraparound-qh          ( )
          0 qh-ptr >qh-prev l!       ( )
-	 qh-ptr sync-qh
+	 qh-ptr push-qh
       then
       ring-doorbell
    then
@@ -540,40 +528,61 @@
 ;
 
 : qtd-done?  ( qtd -- done? )
-   >hcqtd-token le-l@		( token )
-
-   dup TD_STAT_HALTED and  if	( token )
-      drop true exit
-   then				( token )
-   TD_STAT_ACTIVE and 0=	( done? )
+   >hcqtd-token le-l@  TD_STAT_ACTIVE and  0=
 ;
 
+[ifdef] notdef
+\ This version looks for the ending condition in the transfer overlay
 : qh-done?  ( qh -- done? )
-   process-hc-status          ( qh )
-   dup sync-qh                ( qh )
-   >hcqh-cur-pqtd le-l@  dup  if  qtd-done?  then  ( done? )
-;
-
-true value delay?
-: poll-delay  ( -- )  d# 300 " us" evaluate  ;
-: done?  ( qh -- usberr )
-   delay?  if  poll-delay  then
-   begin  dup qh-done?  0=  while   ( qh )
-      1 ms
-      dup >qh-timeout	( qh timeout-adr )
-      dup l@ 1-		( qh timeout-adr timeout' )
-      dup rot l!	( qh timeout' )
-      0=  if            ( qh )
-delay? 0=  if  cr  7 emit  7 emit  ." TIMEOUT" cr  debug-me  then
-         " Timeout" USB_ERR_TIMEOUT set-usb-error ( qh )
-         drop           ( )
-         usb-error      ( usberr )
-         exit
-      then
-   repeat               ( qh )
-   drop                 ( )
+   hc-interrupt? 0=  if  drop false exit  then   ( qh )
+   dup pull-qh                    ( qh )
+   dup >hcqh-cur-pqtd l@  0=  if  ( qh )
+      drop false exit             ( -- done? )
+   then                           ( qh )
+   >hcqh-overlay               ( qtd )
+   dup >hcqtd-token le-l@      ( qtd token )
+   dup TD_STAT_ACTIVE and  if  ( qtd token )
+      2drop false              ( done? )
+   else                        ( qtd token )
+      TD_STAT_HALTED and  if   ( qtd )
+         drop true             ( done? )
+      else                     ( qtd )
+         >hcqtd-next le-l@     ( next )
+	 TERMINATE =           ( done? )
+      then                     ( done? )
+   then                        ( done? )
+;
+[then]
 
-   usb-error		( usberr )
+\ This version traverses the list of QTDs, looking for an ending condition
+: qh-done?  ( qh -- done? )
+   dup pull-qh      ( qh )
+\   d# 30 us         ( qh )
+   /qh +                                      ( qtd )
+   begin                                      ( qtd )
+      dup >hcqtd-token le-l@                  ( qtd token )
+      dup TD_STAT_ACTIVE and  0=              ( qtd token qtd-complete? )
+   while                                      ( qtd token )
+      \ This QTD is complete - it is the end of the list if either
+      \ the next field is TERMINATE or if the HALTED bit is set
+      TD_STAT_HALTED and  if                  ( qtd )
+         drop true exit                       ( -- done? )
+      then                                    ( qtd )
+      dup >hcqtd-next le-l@ TERMINATE =  if   ( qtd )
+         drop true exit                       ( -- done? )
+      then                                    ( qtd )
+      /qtd +                                  ( qtd' )
+   repeat                                     ( qtd token )
+   \ If we get here, we hit a QTD that is still active
+   2drop false                                ( done? )
+;
+
+: intr-qh-done?  ( qh -- done? )
+   hc-interrupt?  if   ( qh )
+      qh-done?         ( done? )
+   else                ( qh )
+      drop false       ( done? )
+   then                ( done? )
 ;
 
 : qtd-error?  ( qtd qh -- usberr )
@@ -583,11 +592,27 @@
    usb-error
 ;
 
-: error?  ( qh -- usberr )  dup >hcqh-overlay  swap  qtd-error?   ;
+: qh-error?  ( qh -- usberr )  dup >hcqh-overlay  swap  qtd-error?   ;
+
+: done-error?  ( qh -- usberr )
+   dup >qh-timeout l@  get-msecs +   ( qh timeout )
+   begin  over intr-qh-done?  0=  while   ( qh timeout )
+      usb-error ?dup if  ." USB ERROR " . cr  then
+      dup get-msecs - 0<  if         ( qh timeout )
+         " Timeout" USB_ERR_TIMEOUT set-usb-error ( qh timeout )
+         2drop                       ( )
+         usb-error                   ( usberr )
+         exit
+      then                           ( qh timeout )
+   repeat                            ( qh timeout )
+   drop                              ( qh )
+
+   qh-error?	                     ( usberr )
+;
 
 : get-actual  ( qtd #qtd -- actual )
    0 -rot 0  ?do			( actual qtd )
-      dup sync-qtd			( actual qtd )
+      dup pull-qtd			( actual qtd )
       dup >hcqtd-token le-l@ dup TD_STAT_ACTIVE and 0=  if
          over >qtd-/buf l@		( actual qtd token len )
          swap d# 16 >> h# 7fff and -	( actual qtd len' )
@@ -601,7 +626,7 @@
 
 : qtd-get-actual  ( qtd -- actual )
    0 swap  begin			( actual qtd )
-      dup sync-qtd			( actual qtd )
+      dup pull-qtd			( actual qtd )
       dup >hcqtd-token le-l@ dup TD_STAT_ACTIVE and 0=  if
          over >qtd-/buf l@		( actual qtd token len )
          swap d# 16 >> h# 7fff and -	( actual qtd len' )

Modified: dev/usb2/hcd/ohci/bulk.fth
==============================================================================
--- dev/usb2/hcd/ohci/bulk.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ohci/bulk.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -79,7 +79,7 @@
    ( ed ) dup >hced-tdhead le-l@		( dir ed head )
    rot ED_DIR_IN =  if  bulk-in-data@  else  bulk-out-data@  then  or
    over >hced-tdhead le-l!			( ed )
-   ( ed ) sync-edtds
+   ( ed ) push-edtds
 ;
 : insert-my-bulk     ( ed dir -- )  over fill-bulk-ed  insert-bulk  ;
 : insert-my-bulk-in  ( ed -- )  ED_DIR_IN  insert-my-bulk  ;
@@ -108,12 +108,12 @@
 : bulk-in-ready?  ( -- false | error true |  buf actual 0 true )
    clear-usb-error				( )
    process-hc-status				( )
-   bulk-in-ed dup sync-edtds			( ed )
+   bulk-in-ed dup pull-edtds			( ed )
    ed-done?  if					( )
       bulk-in-td error? ?dup 0=  if		( )
          bulk-in-td >td-cbp l@			( buf )
          bulk-in-td get-actual			( buf actual )
-         2dup bulk-in-td >td-pcbp l@ swap dma-sync	( buf actual )
+         2dup bulk-in-td >td-pcbp l@ swap dma-pull	( buf actual )
          0					( buf actual 0 )
       then					( error | buf actual 0 )
       bulk-in-ed fixup-bulk-in-data		( error | buf actual 0 )
@@ -126,13 +126,13 @@
    bulk-in-ed 0=  if  0 USB_ERR_INV_OP exit  then
    clear-usb-error				( )
    process-hc-status				( )
-   bulk-in-ed dup sync-edtds			( ed )
+   bulk-in-ed dup pull-edtds			( ed )
    ed-done?  if					( )
       bulk-in-td error?  if
          0					( actual )
       else
          bulk-in-td dup get-actual		( td actual )
-         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-sync	( actual )
+         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-pull	( actual )
       then
       usb-error					( actual usberr )
       bulk-in-ed fixup-bulk-in-data		( actual usberr )
@@ -165,7 +165,7 @@
 
    \ Setup ED again
    bulk-in-td >td-phys l@ bulk-in-data@ or bulk-in-ed >hced-tdhead le-l!
-   bulk-in-ed dup sync-edtds
+   bulk-in-ed dup push-edtds
    ed-unset-skip
    enable-bulk
 ;
@@ -198,7 +198,7 @@
          0					( actual )	\ USB error
       else
          my-td dup get-actual			( td actual )
-         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-sync	( actual )
+         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-pull	( actual )
       then
    then
 

Modified: dev/usb2/hcd/ohci/control.fth
==============================================================================
--- dev/usb2/hcd/ohci/control.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ohci/control.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -105,7 +105,7 @@
 
 : insert-my-control  ( -- )
    my-ed dup fill-control-ed
-   dup sync-edtds
+   dup push-edtds
    insert-control
 ;
 
@@ -146,7 +146,7 @@
 	 0					( actual )	\ USB error
       else
          my-td >td-next l@ dup get-actual	( td actual )
-         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-sync	( actual )
+         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-pull	( actual )
       then
    then
 

Modified: dev/usb2/hcd/ohci/edtd.fth
==============================================================================
--- dev/usb2/hcd/ohci/edtd.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ohci/edtd.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -45,7 +45,7 @@
 
    \ Initialize hcca
    hcca /hcca erase
-   hcca hcca-phys /hcca dma-sync
+   hcca hcca-phys /hcca dma-push
 ;
 
 \ ---------------------------------------------------------------------------
@@ -138,7 +138,7 @@
    dup >hced-control dup le-l@
    ED_SKIP_MASK invert and r> or
    swap le-l!
-   dup >ed-phys l@ /hced dma-sync
+   dup >ed-phys l@ /hced dma-push
 ;
 : ed-set-skip    ( ed -- )  ED_SKIP_ON  (set-skip)  ;
 : ed-unset-skip  ( ed -- )  ED_SKIP_OFF (set-skip)  ;
@@ -269,10 +269,15 @@
    r> >ed-size l@			( ed.u,v,p size )
    aligned32-free-map-out		( )
 ;
-: sync-edtds  ( ed -- )
+: push-edtds  ( ed -- )
    dup >ed-phys l@			( ed.v,p )
    over >ed-size l@			( ed.v,p len )
-   dma-sync				( )
+   dma-push				( )
+;
+: pull-edtds  ( ed -- )
+   dup >ed-phys l@			( ed.v,p )
+   over >ed-size l@			( ed.v,p len )
+   dma-pull				( )
 ;
 : map-out-cbp  ( td -- )
    dup >td-cbp l@ over >td-pcbp l@ rot >td-/cbp-all l@ hcd-map-out
@@ -429,7 +434,7 @@
 : done?  ( ed -- error? )
    begin
       process-hc-status
-      dup sync-edtds
+      dup pull-edtds
       dup ed-done? ?dup 0=  if
          1 ms
 	 timeout 1- dup to timeout 0=

Modified: dev/usb2/hcd/ohci/intr.fth
==============================================================================
--- dev/usb2/hcd/ohci/intr.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/ohci/intr.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -52,7 +52,7 @@
    ( ed ) dup >hced-tdhead le-l@		( ed head )
    intr-in-data@  or				( ed head' )
    over >hced-tdhead le-l!			( ed )
-   ( ed ) sync-edtds				( )
+   ( ed ) push-edtds				( )
 ;
 : remove-my-intr  ( ed -- )  dup remove-intr  free-edtds  ;
 
@@ -80,13 +80,13 @@
    intr-in-ed 0=  if  0 USB_ERR_INV_OP exit  then
    clear-usb-error				( )
    process-hc-status				( )
-   intr-in-ed dup sync-edtds			( ed )
+   intr-in-ed dup pull-edtds			( ed )
    ed-done?  if					( )
       intr-in-td error?  if
          0					( actual )
       else					( )
 	 intr-in-td dup get-actual		( td actual )
-         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-sync	( actual )
+         over >td-cbp l@ rot >td-pcbp l@ 2 pick dma-pull	( actual )
       then
       usb-error					( actual usberr )
       intr-in-ed fixup-intr-in-data		( actual usberr )
@@ -118,7 +118,7 @@
 
    \ Setup ED again
    intr-in-td >td-phys l@ intr-in-data@ or intr-in-ed >hced-tdhead le-l!
-   intr-in-ed dup sync-edtds
+   intr-in-ed dup push-edtds
    ed-unset-skip
 ;
 

Modified: dev/usb2/hcd/uhci/bulk.fth
==============================================================================
--- dev/usb2/hcd/uhci/bulk.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/uhci/bulk.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -113,12 +113,12 @@
    bulk-in-qh 0=  if  0 USB_ERR_INV_OP exit  then
    clear-usb-error
    process-hc-status
-   bulk-in-qh dup sync-qhtds                            ( bulk-in-qh )
+   bulk-in-qh dup pull-qhtds                            ( bulk-in-qh )
    qh-done?  if                                         ( )
       bulk-in-actual                                    ( actual usberr )
    else                                                 ( )
       bulk-in-qh dup >hcqh-elem le-l@			( qh elem )
-      1 ms  over sync-qhtds				( qh elem )
+      1 ms  over pull-qhtds				( qh elem )
       swap >hcqh-elem le-l@ =  if			\ No movement in the past ms
          bulk-in-actual                                 ( actual usberr )
          bulk-in-td bulk-in-qh >qh-#tds l@ fixup-bulk-in-data
@@ -127,7 +127,7 @@
       then
    then
    over  if
-      bulk-in-td dup >td-buf l@ swap >td-pbuf l@ 2 pick dma-sync
+      bulk-in-td dup >td-buf l@ swap >td-pbuf l@ 2 pick dma-pull
    then
 ;
 
@@ -155,7 +155,7 @@
 
    \ Setup QH again
    bulk-in-td >td-phys l@ bulk-in-qh >hcqh-elem le-l!
-   bulk-in-qh sync-qhtds
+   bulk-in-qh push-qhtds
 ;
 
 : end-bulk-in  ( -- )
@@ -188,7 +188,7 @@
          0					( actual )	\ USB error
       else
          my-td dup my-#tds get-actual		( td actual )
-	 over >td-buf l@ rot >td-pbuf l@ 2 pick dma-sync	( actual )
+	 over >td-buf l@ rot >td-pbuf l@ 2 pick dma-pull	( actual )
       then
    then
 

Modified: dev/usb2/hcd/uhci/control.fth
==============================================================================
--- dev/usb2/hcd/uhci/control.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/uhci/control.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -125,7 +125,7 @@
          0					( actual )	\ USB error
       else
          my-td >td-next l@ dup my-#tds get-actual		( td actual )
-         over >td-buf l@ rot >td-pbuf l@ 2 pick dma-sync	( actual )
+         over >td-buf l@ rot >td-pbuf l@ 2 pick dma-pull	( actual )
       then
    then
 

Modified: dev/usb2/hcd/uhci/intr.fth
==============================================================================
--- dev/usb2/hcd/uhci/intr.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/uhci/intr.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -76,11 +76,11 @@
    intr-in-qh 0=  if  0 USB_ERR_INV_OP exit  then
    clear-usb-error
    process-hc-status
-   intr-in-qh dup sync-qhtds
+   intr-in-qh dup pull-qhtds
    qh-done?  if
       intr-in-td intr-in-qh >qh-#tds l@ get-actual	( actual )
       usb-error						( actual usberr )
-      intr-in-td dup >td-buf l@ swap >td-pbuf l@ 2 pick dma-sync
+      intr-in-td dup >td-buf l@ swap >td-pbuf l@ 2 pick dma-pull
       intr-in-td intr-in-qh >qh-#tds l@ fixup-intr-in-data
    else
       0 usb-error					( actual usberr )
@@ -109,7 +109,7 @@
 
    \ Setup QH again
    intr-in-td >td-phys l@ intr-in-qh >hcqh-elem le-l!
-   intr-in-qh sync-qhtds
+   intr-in-qh push-qhtds
 ;
 
 : end-intr-in  ( -- )

Modified: dev/usb2/hcd/uhci/qhtd.fth
==============================================================================
--- dev/usb2/hcd/uhci/qhtd.fth	Tue Oct 11 23:59:39 2011	(r2590)
+++ dev/usb2/hcd/uhci/qhtd.fth	Wed Oct 12 00:28:40 2011	(r2591)
@@ -230,8 +230,12 @@
    aligned16-free-map-out
 ;
 
-: sync-qhtds  ( qh -- )
-   dup >qh-phys l@ over >qh-size l@  dma-sync
+: push-qhtds  ( qh -- )
+   dup >qh-phys l@ over >qh-size l@  dma-push
+;
+
+: pull-qhtds  ( qh -- )
+   dup >qh-phys l@ over >qh-size l@  dma-pull
 ;
 
 : map-out-buf  ( td -- )
@@ -299,7 +303,7 @@
       process-hc-status  usb-error  if
          true
       else
-         dup sync-qhtds
+         dup pull-qhtds
          dup qh-done? ?dup 0=   if
             1 ms
 	    timeout 1- dup to timeout 0=
@@ -310,7 +314,7 @@
    ( qh ) dup qh-done? 0=  if
       " Timeout" USB_ERR_TIMEOUT set-usb-error
       TERMINATE over >hcqh-elem le-l!		\ Terminate QH
-      sync-qhtds
+      push-qhtds
       1 ms
    else
       drop



More information about the openfirmware mailing list