[openfirmware] [commit] r2446 - in dev/usb2: . device hcd hcd/ehci
repository service
svn at openfirmware.info
Tue Aug 9 20:28:36 CEST 2011
Author: lwalter
Date: Tue Aug 9 20:28:35 2011
New Revision: 2446
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2446
Log:
Add isochronous support
Added:
dev/usb2/hcd/ehci/iso.fth
Modified:
dev/usb2/device/common.fth
dev/usb2/hcd/control.fth
dev/usb2/hcd/device.fth
dev/usb2/hcd/ehci/loadpkg.fth
dev/usb2/hcd/ehci/qhtd.fth
dev/usb2/hcd/hcd-call.fth
dev/usb2/pkt-data.fth
Modified: dev/usb2/device/common.fth
==============================================================================
--- dev/usb2/device/common.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/device/common.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -25,6 +25,8 @@
0 value iso-in-pipe
0 value iso-out-pipe
+0 value iso-in-interval
+0 value iso-out-interval
0 value /iso-in-pipe
0 value /iso-out-pipe
Modified: dev/usb2/hcd/control.fth
==============================================================================
--- dev/usb2/hcd/control.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/hcd/control.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -87,7 +87,7 @@
>r 0 0 0 r> DR_DEVICE DR_OUT or SET_CONFIGURATION control-set
;
-: set-interface ( alt intf -- usberr )
+: set-interface ( intf alt -- usberr )
0 0 2swap DR_INTERFACE DR_OUT or SET_INTERFACE control-set
;
@@ -107,6 +107,7 @@
: (unstall-pipe) ( pipe -- ) 0 DR_ENDPOINT clear-feature drop ;
' (unstall-pipe) to unstall-pipe
+external
: get-cfg-desc ( adr idx -- actual )
swap >r ( idx ) ( R: adr )
r@ 9 0 3 pick CONFIGURATION DR_DEVICE get-desc nip 0= if
@@ -115,6 +116,8 @@
r> 2drop 0 ( actual )
then
;
+headers
+
: get-dev-desc ( adr len -- actual )
0 0 DEVICE DR_DEVICE get-desc drop ( actual )
;
Modified: dev/usb2/hcd/device.fth
==============================================================================
--- dev/usb2/hcd/device.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/hcd/device.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -38,17 +38,26 @@
;
: dev-desc@ ( index -- byte ) dev-desc-buf + c@ ;
+: asso-class? ( -- asso? )
+ 4 dev-desc@ h# ef = 5 dev-desc@ 2 = and 6 dev-desc@ 1 = and
+;
: get-class ( -- class subclass protocol )
- 4 dev-desc@ ?dup if ( class )
+ asso-class? if
+ \ Class is in interface association descriptor
+ true to class-in-dev?
+ cfg-desc-buf INTERFACE_ASSO find-desc ( intf-adr )
+ >r r@ 4 + c@ r@ 5 + c@ r> 6 + c@ ( class subclass protocol )
+ else
+ 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 ( )
+ else
\ Class is in interface descriptor
- false to class-in-dev? ( )
+ 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
+ then then
;
: make-class-properties ( -- )
@@ -410,7 +419,8 @@
: make-device-node ( port dev -- )
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 )
+ asso-class? if 1 else cfg-desc-buf 4 + c@ then ( port dev #intf )
+ 0 ?do ( port dev )
dup " refresh-desc-bufs" my-self $call-method ( port dev )
2dup swap i (make-device-node) ( port dev )
loop 2drop ( )
Added: dev/usb2/hcd/ehci/iso.fth
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ dev/usb2/hcd/ehci/iso.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -0,0 +1,358 @@
+purpose: EHCI USB Controller Isochronous Pipes Transaction Processing
+\ See license at end of file
+
+hex
+headers
+
+\ XXX Need to implement isochronous OUT
+\ XXX Need to implement siTD for devices behind a hub
+
+1 constant ISO_LAG \ # of frames to skip when inserting new iTDs
+
+\ ---------------------------------------------------------------------------
+\ Example device driver usage:
+\ init-iso-in \ To allocate and initialize isochronous data structures
+\ begin-iso-in \ To link the framelist and iTDs
+\ get-iso-in \ To read streamed data
+\ end-iso-in \ To deallocate data structures (e.g., during close)
+\ restart-iso-in \ To restart after a long lapse in order to get fresh data
+\ ---------------------------------------------------------------------------
+
+\ ---------------------------------------------------------------------------
+\ Internal isochronus IN variables
+\ ---------------------------------------------------------------------------
+
+0 instance value iso-in-itd
+0 instance value iso-in-itd-phys
+0 instance value iso-in-itd-unaligned
+0 instance value iso-in-#itd
+
+0 instance value iso-in-buf
+0 instance value iso-in-buf-phys
+0 instance value iso-in-buf-unaligned
+0 instance value iso-in-/buf
+
+0 instance value iso-in-pipe
+0 instance value iso-in-/payload
+0 instance value iso-in-mult
+0 instance value iso-in-interval
+
+0 instance value iso-in-cur-itd \ Next IN iTD to process
+0 instance value iso-in-frame \ Last framelist[] used by the IN iTDs
+0 instance value iso-in-#uframe \ Total # of micro-frames in the IN iTDs
+0 instance value iso-in-uframe-cnt \ Micro-frame count in processing iTDs
+
+\ ---------------------------------------------------------------------------
+\ Isochronous Transaction Descriptor (iTD) as defined by the EHCI Spec; 32-byte aligned
+\ ---------------------------------------------------------------------------
+
+0 instance value itd-struct
+
+4 8 * constant /itd-xstat
+4 7 * constant /itd-bptr
+struct
+ \ DMA fields
+ 4 field >itd-link \ Next iTD or QH pointer
+ /itd-xstat field >itd-xstat \ iTD Transaction Status & Control List
+ /itd-bptr field >itd-bptr \ iTD Buffer Page Pointer List
+ /itd-bptr field >itd-xptrs \ 64-bit buffer pointer extensions
+dup constant /itd-sync
+ \ Non-dma fields
+ /n field >itd-phys \ iTD's physical address
+ /n field >itd-buf \ Virtual address of the first >itd-bptr
+ /n field >itd-frame \ Index into framelist where iTD resides
+ /itd-xstat field >itd-xstat-copy \ original >itd-xstat for easy restart
+d# 32 round-up
+constant /itd-struct
+
+: set-itd-struct ( itd# -- ) /itd-struct * iso-in-itd + to itd-struct ;
+
+h# 7000.0000 constant ITD_STATUS
+h# 8000.0000 constant ITD_ACTIVE
+h# 4000.0000 constant ITD_ERR_OVERRUN
+h# 2000.0000 constant ITD_ERR_BABBLE
+h# 1000.0000 constant ITD_ERR_CRC
+h# 0000.0800 constant ITD_IN
+h# 0000.0000 constant ITD_OUT
+
+: alloc-itd ( #itd -- unaligned-virt aligned-virt phys )
+ /itd-struct * dup >r aligned32-alloc-map-in ( unalign virt phys ) ( R: /itd )
+ over r> erase
+;
+: free-itd ( -- )
+ iso-in-itd-unaligned iso-in-itd iso-in-itd-phys
+ iso-in-#itd /itd-struct * aligned32-free-map-out
+;
+
+: copy-itd-xstat ( -- )
+ itd-struct dup >itd-xstat swap >itd-xstat-copy /itd-xstat move
+;
+: restore-itd-xstat ( -- )
+ TERMINATE itd-struct >itd-link le-l!
+ itd-struct dup >itd-xstat-copy swap >itd-xstat /itd-xstat move
+;
+
+0 value pbuf \ Next physical data buffer address
+0 value vbuf \ Next virtual data buffer address
+0 value rlen \ Remaining data len
+0 value tlen \ Transaction length
+
+: init-itd-xstat ( -- )
+ pbuf h# fff and ( offset )
+ 8 0 do ( offset )
+ rlen 0 max tlen min ?dup if ( offset len )
+ d# 16 << ITD_ACTIVE or ( offset xctrl )
+ over or itd-struct >itd-xstat 4 i * + le-l! ( offset )
+ tlen + ( offset )
+ rlen tlen - to rlen
+ then
+ loop drop
+ copy-itd-xstat
+;
+: init-itd ( itd# -- )
+ dup set-itd-struct
+ /itd-struct * iso-in-itd-phys + itd-struct >itd-phys !
+ TERMINATE itd-struct >itd-link le-l!
+ vbuf pbuf h# fff and - itd-struct >itd-buf !
+ init-itd-xstat
+ pbuf dup h# fff and tlen 8 * + d# 12 >> 7 and 1+ 0 do ( pbuf )
+ dup h# ffff.f000 and itd-struct >itd-bptr 4 i * + le-l! ( pbuf )
+ h# 1000 + ( pbuf' )
+ loop drop
+ tlen 8 * dup pbuf + to pbuf
+ vbuf + to vbuf
+ itd-struct >itd-bptr dup le-l@ target or iso-in-pipe 8 << or swap le-l!
+ itd-struct >itd-bptr 4 + dup le-l@ ITD_IN or iso-in-/payload or swap le-l!
+ itd-struct >itd-bptr 8 + dup le-l@ iso-in-mult or swap le-l!
+;
+
+: free-iso ( -- )
+ iso-in-itd 0= if exit then
+ free-itd
+ iso-in-buf iso-in-buf-phys iso-in-/buf dma-map-out
+ iso-in-buf-unaligned iso-in-/buf h# 1000 aligned-free
+ 0 to iso-in-buf
+;
+: (init-iso-in) ( #uframe pipe interval -- )
+ 1 swap 1- << to iso-in-interval ( #uframe pipe )
+ dup to iso-in-pipe ( #uframe pipe )
+ over to iso-in-#uframe ( #uframe pipe )
+ target di-maxpayload@ ( #uframe max )
+ dup d# 11 >> 3 and 1+ dup to iso-in-mult ( #uframe mult max )
+ swap h# 7ff and dup to iso-in-/payload ( #uframe mult xlen )
+ * * dup to iso-in-/buf ( #uframe /buf )
+ dup h# 1000 aligned-alloc ( /buf buf-unalign buf )
+ tuck to iso-in-buf to iso-in-buf-unaligned ( /buf buf )
+ swap true dma-map-in to iso-in-buf-phys ( )
+;
+
+external
+: init-iso-in ( #uframe pipe interval -- )
+ \ Round up #uframe to multiple of 8
+ rot 8 round-up -rot
+
+ \ Initialize the iso in variables and allocate data buffers
+ (init-iso-in)
+
+ \ Setup temporary variables for init-itd
+ iso-in-/payload iso-in-mult * to tlen \ Transaction length
+ iso-in-buf-phys to pbuf \ Data buffer physical addr
+ iso-in-buf to vbuf \ Data buffer virtual addr
+ iso-in-/buf to rlen \ Remaining data buffer len
+
+ \ Allocate and initialize the iTDs
+ iso-in-#uframe 8 / dup to iso-in-#itd ( #itd )
+ dup alloc-itd to iso-in-itd-phys to iso-in-itd to iso-in-itd-unaligned ( #itd )
+ ( #itd ) 0 do i init-itd loop
+;
+headers
+
+: framelist@ ( idx -- n ) 4 * framelist + le-l@ ;
+: framelist@! ( itd-phys idx -- )
+ dup >r framelist@ dup TERMINATE and if \ Nothing in the entry
+ drop ( itd-phys ) ( R: idx )
+ 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 )
+ TYP_ITD or r> framelist! ( )
+;
+
+0 value cur-fidx
+: interval+ ( frame -- frame' ) iso-in-interval + h# 3ff and ;
+: cur-fidx+ ( -- ) cur-fidx interval+ to cur-fidx ;
+: get-cur-fidx ( -- fidx ) frindex@ 2 + ISO_LAG + 3 >> h# 3ff and ;
+
+external
+: begin-iso-in ( -- )
+ \ Find the next frame and start putting into the framelist and link
+ \ to any existing qhs
+ 0 to iso-in-cur-itd
+ get-cur-fidx to cur-fidx
+ iso-in-#itd 0 do
+ i set-itd-struct
+ itd-struct >itd-phys @ cur-fidx framelist@! \ Link into framelist
+ cur-fidx itd-struct >itd-frame ! \ Save itd's framelist index
+ cur-fidx to iso-in-frame \ Update last frame in iTDs
+ cur-fidx+ \ Next framelist index
+ loop
+ #intr #iso or 0= if enable-periodic then
+ #iso++
+;
+
+headers
+: wait-frame-safe ( idx -- )
+ 3 <<
+ begin
+ frindex@ h# ffff.fff8 and over <>
+ until drop
+;
+: restore-framelist ( -- )
+ \ Remove an iTD from the framelist
+ itd-struct >itd-link le-l@ itd-struct >itd-frame @ framelist!
+;
+
+: restart-itd ( -- )
+ \ Restore the link for the framelist[itd.frame]
+ restore-framelist
+
+ \ Init link and restore the transaction fields in the iTD
+ restore-itd-xstat
+
+ \ Put the iTD in framelist[lastframe+interval]
+ iso-in-frame interval+ dup to iso-in-frame dup itd-struct >itd-frame !
+ itd-struct >itd-phys @ swap framelist@!
+;
+
+: .itd-error ( xstat -- )
+ ITD_STATUS and ?dup 0= if exit then
+ dup ITD_ERR_OVERRUN and if " Data Overrun; " USB_ERR_DATAOVERRUN set-usb-error then
+ dup ITD_ERR_BABBLE and if " Babble Detected; " USB_ERR_BABBLE set-usb-error then
+ ITD_ERR_CRC and if " CRC/Timeout/Bad PID; " USB_ERR_CRC set-usb-error then
+;
+
+: cur-in-itd++ ( -- )
+ iso-in-cur-itd 1+ dup iso-in-#itd = if drop 0 then
+ to iso-in-cur-itd
+;
+
+external
+\ Process the iTDs. Returns false when the microframe is not ready.
+\ Otherwise copy data into adr,len and return the actual len and status nibble.
+\
+\ When the last uframe in the iTD is processed, inc cur-itd and restart-itd
+\
+: get-iso-in ( adr len -- false | actual error? true )
+ 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
+ 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
+ dup >r .itd-error ( adr len xstat ) ( R: xstat )
+ r@ h# 7fff and ( adr len buf-offset ) ( R: xstat )
+ itd-struct >itd-buf @ + -rot ( buf adr len ) ( R: xstat )
+
+ r> d# 16 >> h# fff and min dup >r move ( ) ( R: actual )
+ r> usb-error true ( actual error? true )
+ iso-in-uframe-cnt 1+ dup to iso-in-uframe-cnt ( actual error? true uframe# )
+ 7 and 0= if restart-itd cur-in-itd++ then ( actual error? true )
+;
+
+: end-iso-in ( -- )
+ \ Remove itds from the framelist
+ iso-in-#itd 0 do
+ i set-itd-struct
+ itd-struct >itd-frame @ wait-frame-safe
+ restore-framelist
+ loop 1 ms
+
+ #iso--
+ #intr #iso or 0= if disable-periodic then
+;
+
+: restart-iso-in ( -- )
+ end-iso-in
+
+ \ Restore fields in the iTD
+ iso-in-#itd 0 do
+ i set-itd-struct
+ restore-itd-xstat
+ loop
+
+ begin-iso-in
+;
+
+headers
+: (end-extra) ( -- )
+ (end-extra)
+ iso-in-itd 0= if exit then
+ end-iso-in
+ free-iso
+;
+' (end-extra) to end-extra
+
+[ifndef] notdef
+\ Debug aids
+: ldump ( adr len -- ) " ldump" evaluate ;
+: .itd ( -- )
+ iso-in-itd iso-in-#itd /itd-struct * ldump
+;
+: .xstat ( -- )
+ iso-in-#itd 0 do
+ i set-itd-struct
+ itd-struct >itd-xstat /itd-xstat ldump
+ loop
+;
+\ Debug aids for video streaming only (and only if ITD_ACTIVE are all 0s)
+0 value tln
+0 value tframe
+: push-decimal ( -- ) " push-decimal" evaluate ;
+: tlen+ ( len -- ) dup if h# c - then tln + to tln ;
+: tframe++ ( -- ) tframe 1+ to tframe ;
+: 0vid ( -- ) 0 to tln 0 to tframe ;
+: .tlen ( -- ) tframe push-decimal (.) type pop-base ." :" tln u. cr ;
+: .vid ( -- )
+ 0vid
+ iso-in-#itd 0 do
+ i set-itd-struct
+ 8 0 do
+ itd-struct >itd-xstat i la+ le-l@ ( xstat )
+ dup d# 16 >> h# fff and ( xstat len )
+ dup tlen+ tframe++ if ( xstat )
+ h# 7fff and itd-struct >itd-buf @ + ca1+ c@
+ dup u. 2 and if .tlen 0vid then
+ else
+ drop
+ then
+ loop
+ loop
+ .tlen
+;
+[then]
+
+\ LICENSE_BEGIN
+\ Copyright (c) 2011 FirmWorks
+\
+\ Permission is hereby granted, free of charge, to any person obtaining
+\ a copy of this software and associated documentation files (the
+\ "Software"), to deal in the Software without restriction, including
+\ without limitation the rights to use, copy, modify, merge, publish,
+\ distribute, sublicense, and/or sell copies of the Software, and to
+\ permit persons to whom the Software is furnished to do so, subject to
+\ the following conditions:
+\
+\ The above copyright notice and this permission notice shall be
+\ included in all copies or substantial portions of the Software.
+\
+\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+\
+\ LICENSE_END
+
Modified: dev/usb2/hcd/ehci/loadpkg.fth
==============================================================================
--- dev/usb2/hcd/ehci/loadpkg.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/hcd/ehci/loadpkg.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -14,6 +14,7 @@
fload ${BP}/dev/usb2/hcd/ehci/control.fth \ EHCI control pipe operations
fload ${BP}/dev/usb2/hcd/ehci/bulk.fth \ EHCI bulk pipes operations
fload ${BP}/dev/usb2/hcd/ehci/intr.fth \ EHCI interrupt pipes operations
+fload ${BP}/dev/usb2/hcd/ehci/iso.fth \ EHCI isochronous operations
fload ${BP}/dev/usb2/hcd/control.fth \ Common control pipe API
\ EHCI usb bus probing stuff
Modified: dev/usb2/hcd/ehci/qhtd.fth
==============================================================================
--- dev/usb2/hcd/ehci/qhtd.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/hcd/ehci/qhtd.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -456,6 +456,12 @@
\ Empirically, the 4 ms poll interval works optimally with the usb keyboard.
\ ---------------------------------------------------------------------------
+\ Isochronous count
+0 value #iso
+: #iso++ ( -- ) #iso 1+ to #iso ;
+: #iso-- ( -- ) #iso 1- to #iso ;
+
+\ Interrupt count
0 value #intr
d# 32 constant intr-interval \ 4 ms poll interval
@@ -493,7 +499,7 @@
speed-high = if h# 0020 else h# 1c01 then
over >hcqh-endp-cap dup le-l@ rot or swap le-l!
( qh ) #framelist 0 do dup i (insert-intr-qh) intr-interval +loop drop
- #intr 0= if enable-periodic then
+ #intr #iso or 0= if enable-periodic then
#intr++
;
@@ -514,7 +520,7 @@
: remove-intr-qh ( qh -- )
#intr--
( qh ) #framelist 0 do dup i (remove-intr-qh) intr-interval +loop drop
- #intr 0= if disable-periodic then
+ #intr #iso or 0= if disable-periodic then
;
\ ---------------------------------------------------------------------------
Modified: dev/usb2/hcd/hcd-call.fth
==============================================================================
--- dev/usb2/hcd/hcd-call.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/hcd/hcd-call.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -35,6 +35,9 @@
: refresh-desc-bufs ( dev -- )
" refresh-desc-bufs" $call-parent
;
+: get-cfg-desc ( adr idx -- actual )
+ " get-cfg-desc" $call-parent
+;
\ Control pipe operations
: control-get ( adr len idx value rtype req -- actual usberr )
@@ -55,7 +58,7 @@
: set-config ( cfg -- usberr )
" set-config" $call-parent
;
-: set-interface ( alt intf -- usberr )
+: set-interface ( intf alt -- usberr )
" set-interface" $call-parent
;
: clear-feature ( intf/endp feature rtype -- usberr )
@@ -109,7 +112,6 @@
" wait-out" $call-parent
;
-
\ Interrupt pipe operations
: begin-intr-in ( buf len pipe interval -- )
" begin-intr-in" $call-parent
@@ -131,8 +133,6 @@
" reset?" $call-parent
;
-
-
headers
\ LICENSE_BEGIN
Modified: dev/usb2/pkt-data.fth
==============================================================================
--- dev/usb2/pkt-data.fth Tue Aug 9 20:24:45 2011 (r2445)
+++ dev/usb2/pkt-data.fth Tue Aug 9 20:28:35 2011 (r2446)
@@ -60,6 +60,7 @@
03 constant STRING
04 constant INTERFACE
05 constant ENDPOINT
+0b constant INTERFACE_ASSO
29 constant HUB
\ Hub Class Feature Selectors (dr-value)
More information about the openfirmware
mailing list