summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/ehci.c8
-rw-r--r--sys/dev/usb/ohci.c5
-rw-r--r--sys/dev/usb/uhci.c6
-rw-r--r--sys/dev/usb/usb.h3
-rw-r--r--sys/dev/usb/usb_quirks.c4
-rw-r--r--sys/dev/usb/usb_quirks.h4
-rw-r--r--sys/dev/usb/usb_subr.c52
-rw-r--r--sys/dev/usb/usbdivar.h4
8 files changed, 77 insertions, 9 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 360797439b0..da641102b1d 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ehci.c,v 1.83 2008/06/26 05:42:18 ray Exp $ */
+/* $OpenBSD: ehci.c,v 1.84 2008/06/29 10:04:15 yuo Exp $ */
/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
/*
@@ -1897,6 +1897,12 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer)
case UHF_PORT_SUSPEND:
EOWRITE4(sc, port, v | EHCI_PS_SUSP);
break;
+ case UHF_PORT_DISOWN_TO_1_1:
+ /* enter to Port Reset State */
+ v &= ~EHCI_PS_PE;
+ EOWRITE4(sc, port, v | EHCI_PS_PR);
+ ehci_disown(sc, index, 0);
+ break;
case UHF_PORT_RESET:
DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n",
index));
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 41b93638092..6f99c172624 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.86 2008/06/26 05:42:18 ray Exp $ */
+/* $OpenBSD: ohci.c,v 1.87 2008/06/29 10:04:15 yuo 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 $ */
@@ -2659,6 +2659,9 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer)
"%d\n", index));
OWRITE4(sc, port, UPS_PORT_POWER);
break;
+ case UHF_PORT_DISOWN_TO_1_1:
+ /* accept, but do nothing */
+ break;
default:
err = USBD_IOERROR;
goto ret;
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 0565ef0059b..586eedbc6f5 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhci.c,v 1.67 2008/06/26 05:42:18 ray Exp $ */
+/* $OpenBSD: uhci.c,v 1.68 2008/06/29 10:04:15 yuo 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 $ */
@@ -3379,6 +3379,10 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer)
/* Pretend we turned on power */
err = USBD_NORMAL_COMPLETION;
goto ret;
+ case UHF_PORT_DISOWN_TO_1_1:
+ /* accept, but do nothing */
+ err = USBD_NORMAL_COMPLETION;
+ goto ret;
case UHF_C_PORT_CONNECTION:
case UHF_C_PORT_ENABLE:
case UHF_C_PORT_OVER_CURRENT:
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 8f7d01b3972..04a04173686 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.h,v 1.31 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb.h,v 1.32 2008/06/29 10:04:15 yuo Exp $ */
/* $NetBSD: usb.h,v 1.69 2002/09/22 23:20:50 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */
@@ -285,6 +285,7 @@ typedef struct {
#define UHF_C_PORT_RESET 20
#define UHF_PORT_TEST 21
#define UHF_PORT_INDICATOR 22
+#define UHF_PORT_DISOWN_TO_1_1 30
typedef struct {
uByte bDescLength;
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index 866c86ecf88..f2c4a248cae 100644
--- a/sys/dev/usb/usb_quirks.c
+++ b/sys/dev/usb/usb_quirks.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_quirks.c,v 1.42 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb_quirks.c,v 1.43 2008/06/29 10:04:15 yuo Exp $ */
/* $NetBSD: usb_quirks.c,v 1.45 2003/05/10 17:47:14 hamajima Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $ */
@@ -158,7 +158,7 @@ const struct usbd_dev_quirk_entry {
u_int8_t bDeviceProtocol;
struct usbd_quirks quirks;
} usb_dev_quirks[] = {
- /* currently this table is empty */
+ { UDCLASS_VIDEO, bANY, bANY, { UQ_EHCI_NEEDTO_DISOWN }},
{ 0, 0, 0, { 0 } }
};
diff --git a/sys/dev/usb/usb_quirks.h b/sys/dev/usb/usb_quirks.h
index 93dbfab9005..ef398007e04 100644
--- a/sys/dev/usb/usb_quirks.h
+++ b/sys/dev/usb/usb_quirks.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_quirks.h,v 1.12 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb_quirks.h,v 1.13 2008/06/29 10:04:15 yuo Exp $ */
/* $NetBSD: usb_quirks.h,v 1.20 2001/04/15 09:38:01 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.9 1999/11/12 23:31:03 n_hibma Exp $ */
@@ -68,6 +68,8 @@ struct usbd_quirks {
#define UQ_MS_BAD_CLASS 0x00008000
/* mouse sends an unknown leading byte. */
#define UQ_MS_LEADING_BYTE 0x00010000
+ /* need to attach as 1.1 device if it is 2.0 */
+#define UQ_EHCI_NEEDTO_DISOWN 0x00020000
};
extern const struct usbd_quirks usbd_no_quirk;
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 2d6ac2d77fd..0b682d87a09 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.68 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.69 2008/06/29 10:04:15 yuo 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 $ */
@@ -352,6 +352,42 @@ usbd_delay_ms(usbd_device_handle dev, u_int ms)
}
usbd_status
+usbd_port_disown_to_1_1(usbd_device_handle dev, int port, usb_port_status_t *ps)
+{
+ usb_device_request_t req;
+ usbd_status err;
+ int n;
+
+ req.bmRequestType = UT_WRITE_CLASS_OTHER;
+ req.bRequest = UR_SET_FEATURE;
+ USETW(req.wValue, UHF_PORT_DISOWN_TO_1_1);
+ USETW(req.wIndex, port);
+ USETW(req.wLength, 0);
+ err = usbd_do_request(dev, &req, 0);
+ DPRINTF(("usbd_disown_to_1_1: port %d disown request done, error=%s\n",
+ port, usbd_errstr(err)));
+ if (err)
+ return (err);
+ n = 10;
+ do {
+ /* Wait for device to recover from reset. */
+ usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
+ err = usbd_get_port_status(dev, port, ps);
+ if (err) {
+ DPRINTF(("%s: get status failed %d\n", __func__, err));
+ return (err);
+ }
+ /* If the device disappeared, just give up. */
+ if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
+ return (USBD_NORMAL_COMPLETION);
+ } while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
+ if (n == 0)
+ return (USBD_TIMEOUT);
+
+ return (err);
+}
+
+usbd_status
usbd_reset_port(usbd_device_handle dev, int port, usb_port_status_t *ps)
{
usb_device_request_t req;
@@ -1127,6 +1163,20 @@ usbd_new_device(struct device *parent, usbd_bus_handle bus, int depth,
return (err);
}
+ /* send disown request to handover 2.0 to 1.1. */
+ if (dev->quirks->uq_flags & UQ_EHCI_NEEDTO_DISOWN) {
+
+ /* only effective when the target device is on ehci */
+ if (dev->bus->usbrev == USBREV_2_0) {
+ DPRINTF(("%s: disown request issues to dev:%p on usb2.0 bus\n",
+ __func__, dev));
+ (void) usbd_port_disown_to_1_1(dev->myhub, port, &ps);
+ /* reset_port required to finish disown request */
+ (void) usbd_reset_port(dev->myhub, port, &ps);
+ return (USBD_NORMAL_COMPLETION);
+ }
+ }
+
/* Assume 100mA bus powered for now. Changed when configured. */
dev->power = USB_MIN_POWER;
dev->self_powered = 0;
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index 721b7592480..feed6655134 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usbdivar.h,v 1.33 2008/06/26 05:42:19 ray Exp $ */
+/* $OpenBSD: usbdivar.h,v 1.34 2008/06/29 10:04:15 yuo 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 $ */
@@ -231,6 +231,8 @@ void usbd_dump_pipe(usbd_pipe_handle pipe);
/* Routines from usb_subr.c */
int usbctlprint(void *, const char *);
void usb_delay_ms(usbd_bus_handle, u_int);
+usbd_status usbd_port_disown_to_1_1(usbd_device_handle dev,
+ int port, usb_port_status_t *ps);
usbd_status usbd_reset_port(usbd_device_handle dev,
int port, usb_port_status_t *ps);
usbd_status usbd_setup_pipe(usbd_device_handle dev,