summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2006-02-26 02:57:57 +0000
committeriedowse <iedowse@FreeBSD.org>2006-02-26 02:57:57 +0000
commit6ec13e63ee278275582528c6c6b970ede16ac14c (patch)
treefbccb8c0b6ba74482b008a172953ddee086f7842 /sys/dev/usb
parent7c9e42abb8ff3f164843c9c192e95f5d75147f63 (diff)
downloadFreeBSD-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.c4
-rw-r--r--sys/dev/usb/ohci.c6
-rw-r--r--sys/dev/usb/uhci.c3
-rw-r--r--sys/dev/usb/usb_subr.c1
-rw-r--r--sys/dev/usb/usbdivar.h1
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 {
OpenPOWER on IntegriCloud