Module Name: src
Committed By: skrll
Date: Thu May 28 06:15:47 UTC 2015
Modified Files:
src/sys/dev/usb [nick-nhusb]: uhub.c usb.h xhci.c
Log Message:
More changes from Takahiro HAYASHI
+ Add sc_statuspend that stores ports bitmap of pending interrupts
instead of sc_isxhciroothub hack til someone implements suspend pipe.
While sc_explorepending == 1, uhub_intr shall merge sc_status into
sc_statuspend.
+ Eliminate confusing UPS_SUPER_SPEED flag and introduce
UPS_OTHER_SPEED flag that indicates ud_speed of device is
super speed (or more).
uhub shall set this flag if ud_speed is super speed (or more).
+ Add the macro that checks ud_speed is super speed.
The codes shall use this macro to check ud_speed is super speed.
+ Add speed type conversion functions.
+ Include port link status in port_status if port is super speed.
Various other changes to support SS hubs and devices
To generate a diff of this commit:
cvs rdiff -u -r1.126.2.11 -r1.126.2.12 src/sys/dev/usb/uhub.c
cvs rdiff -u -r1.111.2.6 -r1.111.2.7 src/sys/dev/usb/usb.h
cvs rdiff -u -r1.28.2.26 -r1.28.2.27 src/sys/dev/usb/xhci.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/usb/uhub.c
diff -u src/sys/dev/usb/uhub.c:1.126.2.11 src/sys/dev/usb/uhub.c:1.126.2.12
--- src/sys/dev/usb/uhub.c:1.126.2.11 Tue Apr 7 06:23:10 2015
+++ src/sys/dev/usb/uhub.c Thu May 28 06:15:47 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: uhub.c,v 1.126.2.11 2015/04/07 06:23:10 skrll Exp $ */
+/* $NetBSD: uhub.c,v 1.126.2.12 2015/05/28 06:15:47 skrll Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */
/*
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.126.2.11 2015/04/07 06:23:10 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.126.2.12 2015/05/28 06:15:47 skrll Exp $");
#include <sys/param.h>
@@ -104,6 +104,7 @@ struct uhub_softc {
/* XXX second buffer needed because we can't suspend pipes yet */
uint8_t *sc_statusbuf;
+ uint8_t *sc_statuspend;
uint8_t *sc_status;
size_t sc_statuslen;
int sc_explorepending;
@@ -112,7 +113,8 @@ struct uhub_softc {
u_char sc_running;
};
-#define UHUB_IS_HIGH_SPEED(sc) ((sc)->sc_proto != UDPROTO_FSHUB)
+#define UHUB_IS_HIGH_SPEED(sc) \
+ ((sc)->sc_proto == UDPROTO_HSHUBSTT || (sc)->sc_proto == UDPROTO_HSHUBMTT)
#define UHUB_IS_SINGLE_TT(sc) ((sc)->sc_proto == UDPROTO_HSHUBSTT)
#define PORTSTAT_ISSET(sc, port) \
@@ -147,6 +149,76 @@ CFATTACH_DECL2_NEW(uroothub, sizeof(stru
*/
int uhub_ubermatch = 0;
+static usbd_status
+usbd_get_hub_desc(struct usbd_device *dev, usb_hub_descriptor_t *hd, int speed)
+{
+ usb_device_request_t req;
+ usbd_status err;
+ int nports;
+
+ UHUBHIST_FUNC(); UHUBHIST_CALLED();
+
+ /* don't issue UDESC_HUB to SS hub, or it would stall */
+ if (dev->ud_depth != 0 && USB_IS_SS(dev->ud_speed)) {
+ usb_hub_ss_descriptor_t hssd;
+ int rmvlen;
+
+ memset(&hssd, 0, sizeof(hssd));
+ req.bmRequestType = UT_READ_CLASS_DEVICE;
+ req.bRequest = UR_GET_DESCRIPTOR;
+ USETW2(req.wValue, UDESC_SS_HUB, 0);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, USB_HUB_SS_DESCRIPTOR_SIZE);
+ DPRINTFN(1, "getting sshub descriptor", 0, 0, 0, 0);
+ err = usbd_do_request(dev, &req, &hssd);
+ nports = hssd.bNbrPorts;
+ if (dev->ud_depth != 0 && nports > UHD_SS_NPORTS_MAX) {
+ DPRINTF("num of ports %d exceeds maxports %d",
+ nports, UHD_SS_NPORTS_MAX, 0, 0);
+ nports = hd->bNbrPorts = UHD_SS_NPORTS_MAX;
+ }
+ rmvlen = (nports + 7) / 8;
+ hd->bDescLength = USB_HUB_DESCRIPTOR_SIZE +
+ (rmvlen > 1 ? rmvlen : 1) - 1;
+ memcpy(hd->DeviceRemovable, hssd.DeviceRemovable, rmvlen);
+ hd->bDescriptorType = hssd.bDescriptorType;
+ hd->bNbrPorts = hssd.bNbrPorts;
+ hd->wHubCharacteristics[0] = hssd.wHubCharacteristics[0];
+ hd->wHubCharacteristics[1] = hssd.wHubCharacteristics[1];
+ hd->bPwrOn2PwrGood = hssd.bPwrOn2PwrGood;
+ hd->bHubContrCurrent = hssd.bHubContrCurrent;
+ } else {
+ req.bmRequestType = UT_READ_CLASS_DEVICE;
+ req.bRequest = UR_GET_DESCRIPTOR;
+ USETW2(req.wValue, UDESC_HUB, 0);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
+ DPRINTFN(1, "getting hub descriptor", 0, 0, 0, 0);
+ err = usbd_do_request(dev, &req, hd);
+ nports = hd->bNbrPorts;
+ if (!err && nports > 7) {
+ USETW(req.wLength,
+ USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
+ err = usbd_do_request(dev, &req, hd);
+ }
+ }
+
+ return err;
+}
+
+static usbd_status
+usbd_set_hub_depth(struct usbd_device *dev, int depth)
+{
+ usb_device_request_t req;
+
+ req.bmRequestType = UT_WRITE_CLASS_DEVICE;
+ req.bRequest = UR_SET_HUB_DEPTH;
+ USETW(req.wValue, depth);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+ return usbd_do_request(dev, &req, 0);
+}
+
int
uhub_match(device_t parent, cfdata_t match, void *aux)
{
@@ -179,7 +251,6 @@ uhub_attach(device_t parent, device_t se
char *devinfop;
usbd_status err;
struct usbd_hub *hub = NULL;
- usb_device_request_t req;
usb_hub_descriptor_t hubdesc;
int p, port, nports, nremov, pwrdly;
struct usbd_interface *iface;
@@ -219,18 +290,9 @@ uhub_attach(device_t parent, device_t se
}
/* Get hub descriptor. */
- req.bmRequestType = UT_READ_CLASS_DEVICE;
- req.bRequest = UR_GET_DESCRIPTOR;
- USETW2(req.wValue, UDESC_HUB, 0);
- USETW(req.wIndex, 0);
- USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
- DPRINTF("uhub %d getting hub descriptor", device_unit(self), 0, 0, 0);
- err = usbd_do_request(dev, &req, &hubdesc);
+ memset(&hubdesc, 0, sizeof(hubdesc));
+ err = usbd_get_hub_desc(dev, &hubdesc, dev->ud_speed);
nports = hubdesc.bNbrPorts;
- if (!err && nports > 7) {
- USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
- err = usbd_do_request(dev, &req, &hubdesc);
- }
if (err) {
DPRINTF("getting hub descriptor failed, uhub %d error %d",
device_unit(self), err, 0, 0);
@@ -258,6 +320,16 @@ uhub_attach(device_t parent, device_t se
hub->uh_explore = uhub_explore;
hub->uh_hubdesc = hubdesc;
+ if (USB_IS_SS(dev->ud_speed) && dev->ud_depth != 0) {
+ aprint_debug_dev(self, "setting hub depth %u\n",
+ dev->ud_depth-1);
+ err = usbd_set_hub_depth(dev, dev->ud_depth - 1);
+ if (err) {
+ aprint_error_dev(self, "can't set depth\n");
+ goto bad;
+ }
+ }
+
/* Set up interrupt pipe. */
err = usbd_device2interface_handle(dev, 0, &iface);
if (err) {
@@ -285,6 +357,9 @@ uhub_attach(device_t parent, device_t se
sc->sc_statusbuf = kmem_alloc(sc->sc_statuslen, KM_SLEEP);
if (!sc->sc_statusbuf)
goto bad;
+ sc->sc_statuspend = kmem_zalloc(sc->sc_statuslen, KM_SLEEP);
+ if (!sc->sc_statuspend)
+ goto bad;
sc->sc_status = kmem_alloc(sc->sc_statuslen, KM_SLEEP);
if (!sc->sc_status)
goto bad;
@@ -395,6 +470,8 @@ uhub_attach(device_t parent, device_t se
bad:
if (sc->sc_status)
kmem_free(sc->sc_status, sc->sc_statuslen);
+ if (sc->sc_statuspend)
+ kmem_free(sc->sc_statuspend, sc->sc_statuslen);
if (sc->sc_statusbuf)
kmem_free(sc->sc_statusbuf, sc->sc_statuslen);
if (hub)
@@ -469,6 +546,10 @@ uhub_explore(struct usbd_device *dev)
}
status = UGETW(up->up_status.wPortStatus);
change = UGETW(up->up_status.wPortChange);
+ if (USB_IS_SS(dev->ud_speed)) {
+ status |= UPS_OTHER_SPEED;
+ USETW(up->up_status.wPortStatus, status);
+ }
DPRINTF("uhub %d port %d: s/c=%x/%x",
device_unit(sc->sc_dev), port, status, change);
@@ -505,10 +586,26 @@ uhub_explore(struct usbd_device *dev)
port);
}
}
+ int is_wrc = 0;
+ if (change & UPS_C_PORT_RESET)
+ usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
+ if (change & UPS_C_BH_PORT_RESET) {
+ is_wrc = 1;
+ usbd_clear_port_feature(dev, port,
+ UHF_C_BH_PORT_RESET);
+ }
+ if (change & UPS_C_PORT_LINK_STATE)
+ usbd_clear_port_feature(dev, port,
+ UHF_C_PORT_LINK_STATE);
+ if (change & UPS_C_PORT_CONFIG_ERROR)
+ usbd_clear_port_feature(dev, port,
+ UHF_C_PORT_CONFIG_ERROR);
/* XXX handle overcurrent and resume events! */
- if (!reconnect && !(change & UPS_C_CONNECT_STATUS)) {
+ /* xHCI sets WRC instead of CSC when port is reset */
+ if (!reconnect && !(change & UPS_C_CONNECT_STATUS) &&
+ !(is_wrc && (status & UPS_CURRENT_CONNECT_STATUS))) {
/* No status change, just do recursive explore. */
if (up->up_dev != NULL && up->up_dev->ud_hub != NULL)
up->up_dev->ud_hub->uh_explore(up->up_dev);
@@ -537,11 +634,15 @@ uhub_explore(struct usbd_device *dev)
usb_disconnect_port(up, sc->sc_dev, DETACH_FORCE);
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
+ continue;
}
if (!(status & UPS_CURRENT_CONNECT_STATUS)) {
/* Nothing connected, just ignore it. */
DPRINTFN(3, "uhub %d port=%d !CURRENT_CONNECT_STATUS",
device_unit(sc->sc_dev), port, 0, 0);
+ usb_disconnect_port(up, sc->sc_dev, DETACH_FORCE);
+ usbd_clear_port_feature(dev, port,
+ UHF_C_PORT_CONNECTION);
continue;
}
@@ -549,9 +650,22 @@ uhub_explore(struct usbd_device *dev)
DPRINTF("unit %d dev->speed=%u dev->depth=%u",
device_unit(sc->sc_dev), dev->ud_speed, dev->ud_depth, 0);
- if (!(status & UPS_PORT_POWER))
- aprint_normal_dev(sc->sc_dev,
- "strange, connected port %d has no power\n", port);
+ /*
+ * To check whether port has power,
+ * check UPS_PORT_POWER bit if port speed is HS/FS/LS and
+ * check UPS_PORT_POWER_SS bit if port speed is SS.
+ */
+ if (status & UPS_OTHER_SPEED) {
+ if (!(status & UPS_PORT_POWER_SS))
+ aprint_normal_dev(sc->sc_dev,
+ "strange, connected port %d has no power\n",
+ port);
+ } else {
+ if (!(status & UPS_PORT_POWER))
+ aprint_normal_dev(sc->sc_dev,
+ "strange, connected port %d has no power\n",
+ port);
+ }
/* Wait for maximum device power up time. */
usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
@@ -571,6 +685,10 @@ uhub_explore(struct usbd_device *dev)
}
status = UGETW(up->up_status.wPortStatus);
change = UGETW(up->up_status.wPortChange);
+ if (USB_IS_SS(dev->ud_speed)) {
+ status |= UPS_OTHER_SPEED;
+ USETW(up->up_status.wPortStatus, status);
+ }
DPRINTF("hub %d port %d after reset: s/c=%x/%x",
device_unit(sc->sc_dev), port, status, change);
@@ -590,14 +708,15 @@ uhub_explore(struct usbd_device *dev)
#endif
continue;
}
+ /* port reset may cause Warm Reset Change, drop it. */
+ if (change & UPS_C_BH_PORT_RESET)
+ usbd_clear_port_feature(dev, port,
+ UHF_C_BH_PORT_RESET);
/* Figure out device speed */
-#if 0
- if (status & UPS_SUPER_SPEED)
+ if (status & UPS_OTHER_SPEED) {
speed = USB_SPEED_SUPER;
- else
-#endif
- if (status & UPS_HIGH_SPEED)
+ } else if (status & UPS_HIGH_SPEED)
speed = USB_SPEED_HIGH;
else if (status & UPS_LOW_SPEED)
speed = USB_SPEED_LOW;
@@ -637,6 +756,15 @@ uhub_explore(struct usbd_device *dev)
if (!sc->sc_isehciroothub)
memset(sc->sc_status, 0, sc->sc_statuslen);
sc->sc_explorepending = 0;
+ for (int i = 0; i < sc->sc_statuslen; i++) {
+ if (sc->sc_statuspend[i] != 0) {
+ memcpy(sc->sc_status, sc->sc_statuspend,
+ sc->sc_statuslen);
+ memset(sc->sc_statuspend, 0, sc->sc_statuslen);
+ usb_needs_explore(sc->sc_hub);
+ break;
+ }
+ }
return USBD_NORMAL_COMPLETION;
}
@@ -692,6 +820,8 @@ uhub_detach(device_t self, int flags)
sc->sc_hub->ud_hub = NULL;
if (sc->sc_status)
kmem_free(sc->sc_status, sc->sc_statuslen);
+ if (sc->sc_statuspend)
+ kmem_free(sc->sc_statuspend, sc->sc_statuslen);
if (sc->sc_statusbuf)
kmem_free(sc->sc_statusbuf, sc->sc_statuslen);
@@ -771,15 +901,26 @@ uhub_intr(struct usbd_xfer *xfer, void *
if (status == USBD_STALLED)
usbd_clear_endpoint_stall_async(sc->sc_ipipe);
- else if (status == USBD_NORMAL_COMPLETION &&
- !sc->sc_explorepending) {
- /*
- * Make sure the status is not overwritten in between.
- * XXX we should suspend the pipe instead
- */
- memcpy(sc->sc_status, sc->sc_statusbuf, sc->sc_statuslen);
- sc->sc_explorepending = 1;
- usb_needs_explore(sc->sc_hub);
+ else if (status == USBD_NORMAL_COMPLETION) {
+ int i;
+
+ /* merge port bitmap into pending interrupts list */
+ for (i = 0; i < sc->sc_statuslen; i++)
+ sc->sc_statuspend[i] |= sc->sc_statusbuf[i];
+
+ if (!sc->sc_explorepending) {
+ /*
+ * Make sure the status is not overwritten in between.
+ * XXX we should suspend the pipe instead
+ */
+ sc->sc_explorepending = 1;
+ memcpy(sc->sc_status, sc->sc_statuspend,
+ sc->sc_statuslen);
+ memset(sc->sc_statuspend, 0, sc->sc_statuslen);
+ DPRINTFN(5, "uhub%d: exploring ports %02x",
+ device_unit(sc->sc_dev), *sc->sc_status, 0, 0);
+ usb_needs_explore(sc->sc_hub);
+ }
}
/*
* XXX workaround for broken implementation of the interrupt
Index: src/sys/dev/usb/usb.h
diff -u src/sys/dev/usb/usb.h:1.111.2.6 src/sys/dev/usb/usb.h:1.111.2.7
--- src/sys/dev/usb/usb.h:1.111.2.6 Mon Apr 6 15:18:13 2015
+++ src/sys/dev/usb/usb.h Thu May 28 06:15:47 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: usb.h,v 1.111.2.6 2015/04/06 15:18:13 skrll Exp $ */
+/* $NetBSD: usb.h,v 1.111.2.7 2015/05/28 06:15:47 skrll Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb.h,v 1.14 1999/11/17 22:33:46 n_hibma Exp $ */
/*
@@ -561,7 +561,9 @@ typedef struct {
#define UPS_OVERCURRENT_INDICATOR 0x0008
#define UPS_RESET 0x0010
#define UPS_PORT_L1 0x0020
-#define UPS_PORT_LS_GET(x) __SHIFTOUT(x, __BITS(8,5))
+#define UPS_PORT_LS_MASK __BITS(8,5)
+#define UPS_PORT_LS_GET(x) __SHIFTOUT(x, UPS_PORT_LS_MASK)
+#define UPS_PORT_LS_SET(x) __SHIFTIN(x, UPS_PORT_LS_MASK)
#define UPS_PORT_LS_U0 0x00
#define UPS_PORT_LS_U1 0x01
#define UPS_PORT_LS_U2 0x02
@@ -580,9 +582,9 @@ typedef struct {
#define UPS_FULL_SPEED 0x0000 /* for completeness */
#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
+#define UPS_OTHER_SPEED 0x2000 /* currently NetBSD specific */
uWord wPortChange;
#define UPS_C_CONNECT_STATUS 0x0001
#define UPS_C_PORT_ENABLED 0x0002
@@ -852,6 +854,7 @@ struct usb_device_info {
#define USB_SPEED_FULL 2
#define USB_SPEED_HIGH 3
#define USB_SPEED_SUPER 4
+#define USB_IS_SS(X) ((X) == USB_SPEED_SUPER)
int udi_power; /* power consumption in mA, 0 if selfpowered */
int udi_nports;
char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN];
Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.28.2.26 src/sys/dev/usb/xhci.c:1.28.2.27
--- src/sys/dev/usb/xhci.c:1.28.2.26 Wed May 27 07:22:51 2015
+++ src/sys/dev/usb/xhci.c Thu May 28 06:15:47 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: xhci.c,v 1.28.2.26 2015/05/27 07:22:51 skrll Exp $ */
+/* $NetBSD: xhci.c,v 1.28.2.27 2015/05/28 06:15:47 skrll Exp $ */
/*
* Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.26 2015/05/27 07:22:51 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.27 2015/05/28 06:15:47 skrll Exp $");
#include "opt_usb.h"
@@ -1004,31 +1004,52 @@ xhci_intr1(struct xhci_softc * const sc)
* ioctl interface uses these values too.
* port_status speed
* definition: UPS_*_SPEED in usb.h
- * They are used in usb_port_status_t.
- * Some 3.0 values overlap with 2.0 values.
+ * They are used in usb_port_status_t and valid only for USB 2.0.
+ * Speed value is 0 for Super Speed or more.
+ * Note that some 3.0 values overlap with 2.0 values.
* (e.g. 0x200 means UPS_POER_POWER_SS in SS and
* means UPS_LOW_SPEED in HS.)
* port status sent from hub also uses these values.
- * (but I've never seen UPS_SUPER_SPEED in port_status from hub.)
* xspeed:
* definition: Protocol Speed ID (PSI) (xHCI 1.1 7.2.1)
* They are used in only slot context and PORTSC reg of xhci.
- * The difference between usbdi speed and them are that
- * FS and LS values are swapped.
+ * The difference between usbdi speed and xspeed is
+ * that FS and LS values are swapped.
*/
+/* convert usbdi speed to xspeed */
static int
xhci_speed2xspeed(int speed)
{
switch (speed) {
case USB_SPEED_LOW: return 2;
case USB_SPEED_FULL: return 1;
- case USB_SPEED_HIGH: return 3;
- case USB_SPEED_SUPER: return 4;
- default:
- break;
+ default: return speed;
+ }
+}
+
+/* convert xspeed to usbdi speed */
+static int
+xhci_xspeed2speed(int xspeed)
+{
+ switch (xspeed) {
+ case 1: return USB_SPEED_FULL;
+ case 2: return USB_SPEED_LOW;
+ default: return xspeed;
+ }
+}
+
+/* convert xspeed to port status speed */
+static int
+xhci_xspeed2psspeed(int xspeed)
+{
+ switch (xspeed) {
+ case 0: return 0;
+ case 1: return UPS_FULL_SPEED;
+ case 2: return UPS_LOW_SPEED;
+ case 3: return UPS_HIGH_SPEED;
+ default: return UPS_OTHER_SPEED;
}
- return 0;
}
/* construct slot context */
@@ -1179,7 +1200,7 @@ xhci_configure_endpoint(struct usbd_pipe
if (xfertype != UE_ISOCHRONOUS)
cp[1] |= htole32(XHCI_EPCTX_1_CERR_SET(3));
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
usbd_desc_iter_t iter;
const usb_cdc_descriptor_t *cdcd;
const usb_endpoint_ss_comp_descriptor_t * esscd = NULL;
@@ -1233,7 +1254,7 @@ xhci_configure_endpoint(struct usbd_pipe
} else {
ival = ival > 15 ? 15 : ival;
}
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
if (maxb > 0)
mps = 1024;
} else {
@@ -1246,7 +1267,7 @@ xhci_configure_endpoint(struct usbd_pipe
);
break;
case UE_CONTROL:
- if (speed == USB_SPEED_SUPER)
+ if (USB_IS_SS(speed))
mps = 512;
else
mps = mps ? mps : 8;
@@ -1261,7 +1282,7 @@ xhci_configure_endpoint(struct usbd_pipe
} else {
ival = ival > 15 ? 15 : ival;
}
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
mps = 1024;
} else {
mps = mps ? mps : 1024;
@@ -1271,7 +1292,7 @@ xhci_configure_endpoint(struct usbd_pipe
break;
#endif
default:
- if (speed == USB_SPEED_SUPER)
+ if (USB_IS_SS(speed))
mps = 1024;
else
mps = mps ? mps : 512;
@@ -1985,10 +2006,10 @@ xhci_new_device(device_t parent, struct
dev->ud_ep0desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
dev->ud_ep0desc.bmAttributes = UE_CONTROL;
/* 4.3, 4.8.2.1 */
- switch (speed) {
- case USB_SPEED_SUPER:
+ if (USB_IS_SS(speed)) {
USETW(dev->ud_ep0desc.wMaxPacketSize, USB_3_MAX_CTRL_PACKET);
- break;
+ } else
+ switch (speed) {
case USB_SPEED_FULL:
/* XXX using 64 as initial mps of ep0 in FS */
case USB_SPEED_HIGH:
@@ -2119,7 +2140,7 @@ xhci_new_device(device_t parent, struct
if (err)
goto bad;
/* 4.8.2.1 */
- if (speed == USB_SPEED_SUPER) {
+ if (USB_IS_SS(speed)) {
if (dd->bMaxPacketSize != 9) {
printf("%s: invalid mps 2^%u for SS ep0,"
" using 512\n",
@@ -2766,34 +2787,20 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
}
v = xhci_op_read_4(sc, XHCI_PORTSC(index));
DPRINTFN(4, "getrhportsc %d %08x", index, v, 0, 0);
- switch (XHCI_PS_SPEED_GET(v)) {
- case 1:
- i = UPS_FULL_SPEED;
- break;
- case 2:
- i = UPS_LOW_SPEED;
- break;
- case 3:
- i = UPS_HIGH_SPEED;
- break;
- case 4:
- i = UPS_SUPER_SPEED;
- break;
- default:
- i = 0;
- break;
- }
+ i = xhci_xspeed2psspeed(XHCI_PS_SPEED_GET(v));
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_SUSP) i |= UPS_SUSPEND;
if (v & XHCI_PS_PR) i |= UPS_RESET;
if (v & XHCI_PS_PP) {
- if (i & UPS_SUPER_SPEED)
+ if (i & UPS_OTHER_SPEED)
i |= UPS_PORT_POWER_SS;
else
i |= UPS_PORT_POWER;
}
+ if (i & UPS_OTHER_SPEED)
+ i |= UPS_PORT_LS_SET(XHCI_PS_PLS_GET(v));
USETW(ps.wPortStatus, i);
i = 0;
if (v & XHCI_PS_CSC) i |= UPS_C_CONNECT_STATUS;
@@ -2853,7 +2860,7 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
xhci_op_write_4(sc, port, v | XHCI_PS_PRC);
break;
case UHF_PORT_U1_TIMEOUT:
- if (XHCI_PS_SPEED_GET(v) != 4) {
+ if (USB_IS_SS(xhci_xspeed2speed(XHCI_PS_SPEED_GET(v)))){
return -1;
}
port = XHCI_PORTPMSC(index);
@@ -2863,7 +2870,7 @@ xhci_roothub_ctrl(struct usbd_bus *bus,
xhci_op_write_4(sc, port, v);
break;
case UHF_PORT_U2_TIMEOUT:
- if (XHCI_PS_SPEED_GET(v) != 4) {
+ if (USB_IS_SS(xhci_xspeed2speed(XHCI_PS_SPEED_GET(v)))){
return -1;
}
port = XHCI_PORTPMSC(index);