diff options
author | iedowse <iedowse@FreeBSD.org> | 2006-02-26 02:57:57 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2006-02-26 02:57:57 +0000 |
commit | 6ec13e63ee278275582528c6c6b970ede16ac14c (patch) | |
tree | fbccb8c0b6ba74482b008a172953ddee086f7842 /sys/dev/usb | |
parent | 7c9e42abb8ff3f164843c9c192e95f5d75147f63 (diff) | |
download | FreeBSD-src-6ec13e63ee278275582528c6c6b970ede16ac14c.zip FreeBSD-src-6ec13e63ee278275582528c6c6b970ede16ac14c.tar.gz |
Save and restore the data toggle value when a pipe to an endpoint
is closed and then reopened. This appears to be necessary now that
we no longer clear endpoint stalls every time a pipe is opened.
Previously we could assume an initial toggle value of zero because
the clear-stall operation resets the device's toggle state.
Reported by: Holger Kipp
MFC after: 3 days
Diffstat (limited to 'sys/dev/usb')
-rw-r--r-- | sys/dev/usb/ehci.c | 4 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/uhci.c | 3 | ||||
-rw-r--r-- | sys/dev/usb/usb_subr.c | 1 | ||||
-rw-r--r-- | sys/dev/usb/usbdivar.h | 1 |
5 files changed, 12 insertions, 3 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index a66ac97..3a39ba5 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1390,7 +1390,7 @@ ehci_open(usbd_pipe_handle pipe) if (sc->sc_dying) return (USBD_IOERROR); - epipe->nexttoggle = 0; + epipe->nexttoggle = pipe->endpoint->savedtoggle; if (addr == sc->sc_addr) { switch (ed->bEndpointAddress) { @@ -2479,6 +2479,8 @@ ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) ehci_rem_qh(sc, sqh, head); splx(s); ehci_free_sqh(sc, epipe->sqh); + + pipe->endpoint->savedtoggle = epipe->nexttoggle; } /* diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 6c87a8c..b3ccfdd 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -2161,7 +2161,9 @@ ohci_open(usbd_pipe_handle pipe) (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) | fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize))); - sed->ed.ed_headp = sed->ed.ed_tailp = htole32(tdphys); + sed->ed.ed_headp = htole32(tdphys | + (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0)); + sed->ed.ed_tailp = htole32(tdphys); switch (xfertype) { case UE_CONTROL: @@ -2247,6 +2249,8 @@ ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) /* Make sure the host controller is not touching this ED */ usb_delay_ms(&sc->sc_bus, 1); splx(s); + pipe->endpoint->savedtoggle = + (le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; ohci_free_sed(sc, opipe->sed); } diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 3382d5b..e47d2b4 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -2033,6 +2033,7 @@ uhci_device_bulk_close(usbd_pipe_handle pipe) uhci_softc_t *sc = (uhci_softc_t *)dev->bus; uhci_free_sqh(sc, upipe->u.bulk.sqh); + pipe->endpoint->savedtoggle = upipe->nexttoggle; } usbd_status @@ -2917,7 +2918,7 @@ uhci_open(usbd_pipe_handle pipe) ed->bEndpointAddress, sc->sc_addr)); upipe->aborting = 0; - upipe->nexttoggle = 0; + upipe->nexttoggle = pipe->endpoint->savedtoggle; if (pipe->device->address == sc->sc_addr) { switch (ed->bEndpointAddress) { diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c index 2ec453e..9813fb7 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -515,6 +515,7 @@ usbd_fill_iface_data(usbd_device_handle dev, int ifaceidx, int altidx) } } ifc->endpoints[endpt].refcnt = 0; + ifc->endpoints[endpt].savedtoggle = 0; p += ed->bLength; } #undef ed diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 69f2366..42537da 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -51,6 +51,7 @@ struct usbd_pipe; struct usbd_endpoint { usb_endpoint_descriptor_t *edesc; int refcnt; + int savedtoggle; }; struct usbd_bus_methods { |