diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2006-05-31 06:18:10 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2006-05-31 06:18:10 +0000 |
commit | be8822770de6bb641c77d3f517bbf21f1367b51e (patch) | |
tree | 268c3490529fc55fcbbb9ca2f3484d673d4cd896 | |
parent | da51c4853286e94d057b950343040e002f1f24e4 (diff) |
Save and restore the data toggle value when a pipe to an endpoint
is closed and then reopened. This may 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
a clear-stall operation resets the device's toggle state.
Derived from work in FreeBSD.
This is most likely to affect devices like printers, which open
pipes for short periods of time and close them again.
ok dlg@
-rw-r--r-- | sys/dev/usb/ehci.c | 7 | ||||
-rw-r--r-- | sys/dev/usb/ohci.c | 8 | ||||
-rw-r--r-- | sys/dev/usb/uhci.c | 5 | ||||
-rw-r--r-- | sys/dev/usb/usb_subr.c | 3 | ||||
-rw-r--r-- | sys/dev/usb/usbdivar.h | 3 |
5 files changed, 18 insertions, 8 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 8289d3ade57..9cc6e99af02 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci.c,v 1.57 2006/05/30 19:21:07 pascoe Exp $ */ +/* $OpenBSD: ehci.c,v 1.58 2006/05/31 06:18:09 pascoe Exp $ */ /* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */ /* @@ -1403,7 +1403,8 @@ ehci_open(usbd_pipe_handle pipe) /* Fill the overlay qTD */ sqh->qh.qh_qtd.qtd_next = EHCI_NULL; sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; - sqh->qh.qh_qtd.qtd_status = htole32(0); + sqh->qh.qh_qtd.qtd_status = + htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle)); epipe->sqh = sqh; @@ -2393,6 +2394,8 @@ ehci_close_pipe(usbd_pipe_handle pipe, ehci_soft_qh_t *head) s = splusb(); ehci_rem_qh(sc, sqh, head); splx(s); + pipe->endpoint->savedtoggle = + EHCI_QTD_GET_TOGGLE(le32toh(sqh->qh.qh_qtd.qtd_status)); ehci_free_sqh(sc, epipe->sqh); } diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 6af9669043f..fbcc074bf6a 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ohci.c,v 1.71 2006/05/29 03:49:22 pascoe Exp $ */ +/* $OpenBSD: ohci.c,v 1.72 2006/05/31 06:18:09 pascoe Exp $ */ /* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ @@ -2047,7 +2047,9 @@ ohci_open(usbd_pipe_handle pipe) OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) | (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: @@ -2133,6 +2135,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 983cf6c4a09..8ded2cc3deb 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhci.c,v 1.46 2006/05/29 04:15:49 pascoe Exp $ */ +/* $OpenBSD: uhci.c,v 1.47 2006/05/31 06:18:09 pascoe Exp $ */ /* $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ @@ -1985,6 +1985,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 @@ -2858,7 +2859,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 004c1c49134..7e4da9b9017 100644 --- a/sys/dev/usb/usb_subr.c +++ b/sys/dev/usb/usb_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: usb_subr.c,v 1.42 2006/05/01 01:34:10 krw Exp $ */ +/* $OpenBSD: usb_subr.c,v 1.43 2006/05/31 06:18:09 pascoe Exp $ */ /* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */ @@ -571,6 +571,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 78136b3462d..a284581b6ab 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: usbdivar.h,v 1.23 2005/03/13 02:54:04 pascoe Exp $ */ +/* $OpenBSD: usbdivar.h,v 1.24 2006/05/31 06:18:09 pascoe Exp $ */ /* $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ @@ -52,6 +52,7 @@ struct usbd_pipe; struct usbd_endpoint { usb_endpoint_descriptor_t *edesc; int refcnt; + int savedtoggle; }; struct usbd_bus_methods { |