summaryrefslogtreecommitdiff
path: root/sys/dev/usb
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-06-22 10:29:19 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-06-22 10:29:19 +0000
commit4f7aa4c18a69a7a907e70fa9e079a1e397583071 (patch)
tree3c7bffbb4a037464f79aa0cd9f5da9752db01b9c /sys/dev/usb
parent9c3455dee1bcd5e438af37852c4685a933fbcf08 (diff)
Make xhci(4)'s root hub report the same status bits as physical USB3 hubs.
There's not bit to indicate the speed of a USB3.0 device attached to a hub port so do not abuse the PORT_TEST bit. Instead make the xhci(4) root hub report the PORT_POWER_SS bit when appropriate and use it to determin the speed of a new device. While here make the root hub report the link state and config error, from FreeBSD.
Diffstat (limited to 'sys/dev/usb')
-rw-r--r--sys/dev/usb/uhub.c16
-rw-r--r--sys/dev/usb/usb.h5
-rw-r--r--sys/dev/usb/xhci.c20
3 files changed, 24 insertions, 17 deletions
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 340064c1ab5..ce8d0c82d70 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uhub.c,v 1.84 2015/06/15 16:46:21 mpi Exp $ */
+/* $OpenBSD: uhub.c,v 1.85 2015/06/22 10:29:18 mpi Exp $ */
/* $NetBSD: uhub.c,v 1.64 2003/02/08 03:32:51 ichiro Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */
@@ -460,14 +460,14 @@ uhub_explore(struct usbd_device *dev)
continue;
}
/* Get port status again, it might have changed during reset */
- err = usbd_get_port_status(dev, port, &up->status);
- if (err) {
- DPRINTF("%s: get port %d status failed, error=%s\n",
- sc->sc_dev.dv_xname, port, usbd_errstr(err));
+ if (usbd_get_port_status(dev, port, &up->status))
continue;
- }
+
status = UGETW(up->status.wPortStatus);
change = UGETW(up->status.wPortChange);
+ DPRINTF("%s: port %d status=0x%04x change=0x%04x\n",
+ sc->sc_dev.dv_xname, port, status, change);
+
if (!(status & UPS_CURRENT_CONNECT_STATUS)) {
/* Nothing connected, just ignore it. */
DPRINTF("%s: port %d, device disappeared after reset\n",
@@ -482,9 +482,7 @@ uhub_explore(struct usbd_device *dev)
if ((status & UPS_PORT_POWER) == 0)
status &= ~UPS_PORT_POWER_SS;
- if (status & UPS_SUPER_SPEED)
- speed = USB_SPEED_SUPER;
- else if (status & UPS_HIGH_SPEED)
+ if (status & UPS_HIGH_SPEED)
speed = USB_SPEED_HIGH;
else if (status & UPS_LOW_SPEED)
speed = USB_SPEED_LOW;
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 0f549de878a..a68c831776e 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb.h,v 1.50 2015/02/14 06:18:58 uebayasi Exp $ */
+/* $OpenBSD: usb.h,v 1.51 2015/06/22 10:29:18 mpi 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 $ */
@@ -423,13 +423,14 @@ typedef struct {
#define UPS_PORT_LS_HOT_RESET 0x0120
#define UPS_PORT_LS_COMP_MOD 0x0140
#define UPS_PORT_LS_LOOPBACK 0x0160
+#define UPS_PORT_LS_GET(x) (((x) >> 5) & 0xf)
+#define UPS_PORT_LS_SET(x) (((x) & 0xf) << 5)
#define UPS_PORT_POWER 0x0100
#define UPS_PORT_POWER_SS 0x0200 /* USB 3.0 only */
#define UPS_FULL_SPEED 0x0000
#define UPS_LOW_SPEED 0x0200
#define UPS_HIGH_SPEED 0x0400
-#define UPS_SUPER_SPEED 0x0800
#define UPS_PORT_TEST 0x0800
#define UPS_PORT_INDICATOR 0x1000
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 436bf53e34a..1d43f1c7bcd 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.60 2015/05/27 11:13:34 mikeb Exp $ */
+/* $OpenBSD: xhci.c,v 1.61 2015/06/22 10:29:18 mpi Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
@@ -2245,32 +2245,40 @@ xhci_root_ctrl_start(struct usbd_xfer *xfer)
}
v = XOREAD4(sc, XHCI_PORTSC(index));
DPRINTFN(8,("xhci_root_ctrl_start: port status=0x%04x\n", v));
+ i = UPS_PORT_LS_SET(XHCI_PS_GET_PLS(v));
switch (XHCI_PS_SPEED(v)) {
case XHCI_SPEED_FULL:
- i = UPS_FULL_SPEED;
+ i |= UPS_FULL_SPEED;
break;
case XHCI_SPEED_LOW:
- i = UPS_LOW_SPEED;
+ i |= UPS_LOW_SPEED;
break;
case XHCI_SPEED_HIGH:
- i = UPS_HIGH_SPEED;
+ i |= UPS_HIGH_SPEED;
break;
case XHCI_SPEED_SUPER:
default:
- i = UPS_SUPER_SPEED;
break;
}
if (v & XHCI_PS_CCS) i |= UPS_CURRENT_CONNECT_STATUS;
if (v & XHCI_PS_PED) i |= UPS_PORT_ENABLED;
if (v & XHCI_PS_OCA) i |= UPS_OVERCURRENT_INDICATOR;
if (v & XHCI_PS_PR) i |= UPS_RESET;
- if (v & XHCI_PS_PP) i |= UPS_PORT_POWER;
+ if (v & XHCI_PS_PP) {
+ if (XHCI_PS_SPEED(v) >= XHCI_SPEED_FULL &&
+ XHCI_PS_SPEED(v) <= XHCI_SPEED_HIGH)
+ i |= UPS_PORT_POWER;
+ else
+ i |= UPS_PORT_POWER_SS;
+ }
USETW(ps.wPortStatus, i);
i = 0;
if (v & XHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS;
if (v & XHCI_PS_PEC) i |= UPS_C_PORT_ENABLED;
if (v & XHCI_PS_OCC) i |= UPS_C_OVERCURRENT_INDICATOR;
if (v & XHCI_PS_PRC) i |= UPS_C_PORT_RESET;
+ if (v & XHCI_PS_PLC) i |= UPS_C_PORT_LINK_STATE;
+ if (v & XHCI_PS_CEC) i |= UPS_C_PORT_CONFIG_ERROR;
USETW(ps.wPortChange, i);
l = min(len, sizeof ps);
memcpy(buf, &ps, l);