From: mpi Date: Mon, 22 Jun 2015 10:29:18 +0000 (+0000) Subject: Make xhci(4)'s root hub report the same status bits as physical USB3 hubs. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fb72199c69b34c0729b0f87db405f81d4f866411;p=openbsd 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. --- 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);