Module Name:    src
Committed By:   skrll
Date:           Sun Sep 13 09:27:54 UTC 2015

Modified Files:
        src/sys/dev/usb [nick-nhusb]: xhci.c xhcireg.h

Log Message:
Various improvements from t-hash (updated by me)

    + Improve xhci_configure_endpoint().
        + Split off maxburst and interval calculation.
            + Start interval calculation with 10, not 11.
            + Put correct maxburst value.
        + Split off constructing endpoint context.
    + Improve xhci_event_transfer()
        + Remove case of unlikely completion codes I added.
    + Clear xr_cookies too when xhci_set_dequeue() clears xr_trb.
    + Return USBD_NO_ADDR if xhci_address_device fails with
      XHCI_TRB_ERROR_NO_SLOTS.
    + Add aprint_debug xhci capability registers.
    + Add & update comments.

I checked HCCPARAMS1 against version 1.1 of the XHCI specification.  Not
sure of previous version formats


To generate a diff of this commit:
cvs rdiff -u -r1.28.2.36 -r1.28.2.37 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.2.2.2 -r1.2.2.3 src/sys/dev/usb/xhcireg.h

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/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.28.2.36 src/sys/dev/usb/xhci.c:1.28.2.37
--- src/sys/dev/usb/xhci.c:1.28.2.36	Sun Sep 13 06:50:09 2015
+++ src/sys/dev/usb/xhci.c	Sun Sep 13 09:27:54 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.28.2.36 2015/09/13 06:50:09 skrll Exp $	*/
+/*	$NetBSD: xhci.c,v 1.28.2.37 2015/09/13 09:27:54 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.36 2015/09/13 06:50:09 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.37 2015/09/13 09:27:54 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -613,12 +613,46 @@ hexdump(const char *msg, const void *bas
 #endif
 }
 
+#define XHCI_HCCPREV1_BITS	\
+	"\177\020"	/* New bitmask */			\
+	"f\020\020XECP\0"					\
+	"f\014\4MAXPSA\0"					\
+	"b\013CFC\0"						\
+	"b\012SEC\0"						\
+	"b\011SBD\0"						\
+	"b\010FSE\0"						\
+	"b\7NSS\0"						\
+	"b\6LTC\0"						\
+	"b\5LHRC\0"						\
+	"b\4PIND\0"						\
+	"b\3PPC\0"						\
+	"b\2CZC\0"						\
+	"b\1BNC\0"						\
+	"b\0AC64\0"						\
+	"\0"
+#define XHCI_HCCV1_x_BITS	\
+	"\177\020"	/* New bitmask */			\
+	"f\020\020XECP\0"					\
+	"f\014\4MAXPSA\0"					\
+	"b\013CFC\0"						\
+	"b\012SEC\0"						\
+	"b\011SPC\0"						\
+	"b\010PAE\0"						\
+	"b\7NSS\0"						\
+	"b\6LTC\0"						\
+	"b\5LHRC\0"						\
+	"b\4PIND\0"						\
+	"b\3PPC\0"						\
+	"b\2CSZ\0"						\
+	"b\1BNC\0"						\
+	"b\0AC64\0"						\
+	"\0"
 
 int
 xhci_init(struct xhci_softc *sc)
 {
 	bus_size_t bsz;
-	uint32_t cap, hcs1, hcs2, hcc, dboff, rtsoff;
+	uint32_t cap, hcs1, hcs2, hcs3, hcc, dboff, rtsoff;
 	uint32_t ecp, ecr;
 	uint32_t usbcmd, usbsts, pagesize, config;
 	int i;
@@ -635,7 +669,8 @@ xhci_init(struct xhci_softc *sc)
 	caplength = XHCI_CAP_CAPLENGTH(cap);
 	hciversion = XHCI_CAP_HCIVERSION(cap);
 
-	if ((hciversion < 0x0096) || (hciversion > 0x0100)) {
+	if (hciversion < XHCI_HCIVERSION_0_96 ||
+	    hciversion > XHCI_HCIVERSION_1_0) {
 		aprint_normal_dev(sc->sc_dev,
 		    "xHCI version %x.%x not known to be supported\n",
 		    (hciversion >> 8) & 0xff, (hciversion >> 0) & 0xff);
@@ -655,15 +690,22 @@ xhci_init(struct xhci_softc *sc)
 	sc->sc_maxintrs = XHCI_HCS1_MAXINTRS(hcs1);
 	sc->sc_maxports = XHCI_HCS1_MAXPORTS(hcs1);
 	hcs2 = xhci_cap_read_4(sc, XHCI_HCSPARAMS2);
-	(void)xhci_cap_read_4(sc, XHCI_HCSPARAMS3);
-	hcc = xhci_cap_read_4(sc, XHCI_HCCPARAMS);
+	hcs3 = xhci_cap_read_4(sc, XHCI_HCSPARAMS3);
+	aprint_debug_dev(sc->sc_dev,
+	    "hcs1=%"PRIx32" hcs2=%"PRIx32" hcs3=%"PRIx32"\n", hcs1, hcs2, hcs3);
 
+	hcc = xhci_cap_read_4(sc, XHCI_HCCPARAMS);
 	sc->sc_ac64 = XHCI_HCC_AC64(hcc);
 	sc->sc_ctxsz = XHCI_HCC_CSZ(hcc) ? 64 : 32;
-	aprint_debug_dev(sc->sc_dev, "ac64 %d ctxsz %d\n", sc->sc_ac64,
-	    sc->sc_ctxsz);
 
+	char sbuf[128];
+	if (hciversion < XHCI_HCIVERSION_1_0)
+		snprintb(sbuf, sizeof(sbuf), XHCI_HCCPREV1_BITS, hcc);
+	else
+		snprintb(sbuf, sizeof sbuf, XHCI_HCCV1_x_BITS, hcc);
+	aprint_debug_dev(sc->sc_dev, "hcc=%s\n", sbuf);
 	aprint_debug_dev(sc->sc_dev, "xECP %x\n", XHCI_HCC_XECP(hcc) * 4);
+
 	ecp = XHCI_HCC_XECP(hcc) * 4;
 	while (ecp != 0) {
 		ecr = xhci_read_4(sc, ecp);
@@ -1072,8 +1114,8 @@ xhci_setup_sctx(struct usbd_device *dev,
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
-	/* 6.2.2 */
 	/*
+	 * 6.2.2, Table 57-60, 6.2.2.1, 6.2.2.2
 	 * tthubslot:
 	 *   This is the slot ID of parent HS hub
 	 *   if LS/FS device is connected && connected through HS hub.
@@ -1093,7 +1135,6 @@ xhci_setup_sctx(struct usbd_device *dev,
 	     dev->ud_myhub->ud_speed == USB_SPEED_HIGH) &&
 	    (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL)) {
 		ttportnum = dev->ud_myhsport->up_portno;
-		/* XXX addr == slot ? */
 		tthubslot = dev->ud_myhsport->up_parent->ud_addr;
 	} else {
 		ttportnum = 0;
@@ -1156,177 +1197,206 @@ xhci_setup_sctx(struct usbd_device *dev,
 	cp[3] |= htole32(0);
 }
 
+static uint32_t
+xhci_get_maxburst(struct usbd_pipe *pipe)
+{
+	usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc;
+	usbd_desc_iter_t iter;
+	const usb_cdc_descriptor_t *cdcd;
+	const usb_endpoint_ss_comp_descriptor_t * esscd = NULL;
+	uint32_t maxb = 0;
+	uint8_t ep;
+
+	cdcd = (const usb_cdc_descriptor_t *)usb_find_desc(
+	    pipe->up_dev, UDESC_INTERFACE, USBD_CDCSUBTYPE_ANY);
+	usb_desc_iter_init(pipe->up_dev, &iter);
+	iter.cur = (const void *)cdcd;
+
+	/* find endpoint_ss_comp desc for ep of this pipe */
+	for (ep = 0;;) {
+		cdcd = (const usb_cdc_descriptor_t *)usb_desc_iter_next(&iter);
+		if (cdcd == NULL)
+			break;
+		if (ep == 0 && cdcd->bDescriptorType == UDESC_ENDPOINT) {
+			ep = ((const usb_endpoint_descriptor_t *)cdcd)->
+			    bEndpointAddress;
+			if (UE_GET_ADDR(ep) ==
+			    UE_GET_ADDR(ed->bEndpointAddress)) {
+				cdcd = (const usb_cdc_descriptor_t *)
+				    usb_desc_iter_next(&iter);
+				break;
+			}
+			ep = 0;
+		}
+	}
+	if (cdcd != NULL && cdcd->bDescriptorType == UDESC_ENDPOINT_SS_COMP) {
+		esscd = (const usb_endpoint_ss_comp_descriptor_t *)cdcd;
+		maxb = esscd->bMaxBurst;
+	}
+
+	return maxb;
+}
+
 /*
- * called
- *  from xhci_open
- *  from usbd_setup_pipe_flags
- *  from usbd_open_pipe_ival
+ * Convert endpoint bInterval value to endpoint context interval value
+ * for Interrupt pipe.
+ * xHCI 6.2.3.6 Table 65, USB 2.0 9.6.6
  */
-static usbd_status
-xhci_configure_endpoint(struct usbd_pipe *pipe)
+static uint32_t
+xhci_bival2ival(uint32_t ival, int speed)
+{
+	if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
+		int i;
+
+		/*
+		 * round ival down to "the nearest base 2 multiple of
+		 * bInterval * 8".
+		 * bInterval is at most 255 as its type is uByte.
+		 * 255(ms) = 2040(x 125us) < 2^11, so start with 10.
+		 */
+		for (i = 10; i > 0; i--) {
+			if ((ival * 8) >= (1 << i))
+				break;
+		}
+		ival = i;
+	} else {
+		/* Interval = bInterval-1 for SS/HS */
+		ival--;
+	}
+
+	return ival;
+}
+
+/*
+ * 4.8.2, 6.2.3.2
+ * construct common endpoint parameters
+ */
+static void
+xhci_setup_endp_ctx(struct usbd_pipe *pipe, uint32_t *cp)
 {
-	struct xhci_softc * const sc = pipe->up_dev->ud_bus->ub_hcpriv;
 	struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv;
-	const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc);
 	usb_endpoint_descriptor_t * const ed = pipe->up_endpoint->ue_edesc;
+	const u_int dci = xhci_ep_get_dci(ed);
 	const uint8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes);
-	struct xhci_trb trb;
-	usbd_status err;
-	uint32_t *cp;
 	uint32_t mps = UGETW(ed->wMaxPacketSize);
 	uint32_t maxb = 0;
 	int speed = pipe->up_dev->ud_speed;
 	uint32_t ival = ed->bInterval;
 
-	XHCIHIST_FUNC(); XHCIHIST_CALLED();
-	DPRINTFN(4, "slot %u dci %u epaddr 0x%02x attr 0x%02x",
-	    xs->xs_idx, dci, ed->bEndpointAddress, ed->bmAttributes);
-
-	/* XXX ensure input context is available? */
-
-	memset(xhci_slot_get_icv(sc, xs, 0), 0, sc->sc_pgsz);
-
-	cp = xhci_slot_get_icv(sc, xs, XHCI_ICI_INPUT_CONTROL);
-	cp[0] = htole32(0);
-	cp[1] = htole32(XHCI_INCTX_1_ADD_MASK(dci));
-
-	/* set up input slot context */
-	cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
-	xhci_setup_sctx(pipe->up_dev, cp);
-	cp[0] |= htole32(XHCI_SCTX_0_CTX_NUM_SET(dci));
-
-	cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(dci));
 	cp[0] = htole32(
 	    XHCI_EPCTX_0_EPSTATE_SET(0) |
+	    XHCI_EPCTX_0_MULT_SET(0) |	/* always 0 except SS iscoh */
 	    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
-	    XHCI_EPCTX_0_LSA_SET(0)
+	    XHCI_EPCTX_0_LSA_SET(0) |
+	    XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_SET(0)
 	    );
 	cp[1] = htole32(
 	    XHCI_EPCTX_1_EPTYPE_SET(xhci_ep_get_type(ed)) |
+	    XHCI_EPCTX_1_HID_SET(0) |
 	    XHCI_EPCTX_1_MAXB_SET(0)
 	    );
 	if (xfertype != UE_ISOCHRONOUS)
 		cp[1] |= htole32(XHCI_EPCTX_1_CERR_SET(3));
 
+	/* 6.2.3.4,  4.8.2.4 */
 	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;
-		uint8_t ep;
-
-		cdcd = (const usb_cdc_descriptor_t *)usb_find_desc(
-		    pipe->up_dev, UDESC_INTERFACE, USBD_CDCSUBTYPE_ANY);
-		usb_desc_iter_init(pipe->up_dev, &iter);
-		iter.cur = (const void *)cdcd;
-
-		/* find endpoint_ss_comp desc for ep of this pipe */
-		for(ep = 0;;) {
-			cdcd = (const usb_cdc_descriptor_t *)
-			    usb_desc_iter_next(&iter);
-			if (cdcd == NULL)
-				break;
-			if (ep == 0 &&
-			    cdcd->bDescriptorType == UDESC_ENDPOINT) {
-				ep = ((const usb_endpoint_descriptor_t *)cdcd)->
-				    bEndpointAddress;
-				if (UE_GET_ADDR(ep) ==
-				    UE_GET_ADDR(ed->bEndpointAddress)) {
-					cdcd = (const usb_cdc_descriptor_t *)
-					    usb_desc_iter_next(&iter);
-					break;
-				}
-				ep = 0;
-			}
-		}
-		if (cdcd != NULL &&
-		    cdcd->bDescriptorType == UDESC_ENDPOINT_SS_COMP) {
-			esscd = (const usb_endpoint_ss_comp_descriptor_t *)cdcd;
-			maxb = esscd->bMaxBurst;
-			cp[1] |= htole32(XHCI_EPCTX_1_MAXB_SET(maxb));
-			DPRINTFN(4, "setting SS MaxBurst %u", maxb, 0, 0, 0);
+		/* UBS 3.1  9.6.6 */
+		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
+		/* UBS 3.1  9.6.7 */
+		maxb = xhci_get_maxburst(pipe);
+		cp[1] |= htole32(XHCI_EPCTX_1_MAXB_SET(maxb));
+	} else {
+		/* UBS 2.0  9.6.6 */
+		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(UE_GET_SIZE(mps)));
+
+		/* 6.2.3.4 */
+		if (speed == USB_SPEED_HIGH &&
+		   (xfertype == UE_ISOCHRONOUS || xfertype == UE_INTERRUPT)) {
+			maxb = UE_GET_TRANS(mps);
+		} else {
+			/* LS/FS or HS CTRL or HS BULK */
+			maxb = 0;
 		}
-	}
-	if (speed == USB_SPEED_HIGH &&
-	    (xfertype == UE_ISOCHRONOUS || xfertype == UE_INTERRUPT)) {
-		maxb = UE_GET_TRANS(UGETW(ed->wMaxPacketSize));
 		cp[1] |= htole32(XHCI_EPCTX_1_MAXB_SET(maxb));
-		DPRINTFN(4, "setting HS MaxBurst %u", maxb, 0, 0, 0);
 	}
 
+	if (xfertype == UE_CONTROL)
+		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(8)); /* 6.2.3 */
+	else if (USB_IS_SS(speed))
+		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(mps));
+	else
+		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(UE_GET_SIZE(mps)));
+
 	switch (xfertype) {
+	case UE_CONTROL:
+		break;
+	case UE_BULK:
+		/* XXX Set MaxPStreams, HID, and LSA if streams enabled */
+		break;
 	case UE_INTERRUPT:
 		if (pipe->up_interval != USBD_DEFAULT_INTERVAL)
 			ival = pipe->up_interval;
 
-		/* xHCI 6.2.3.6 Table 65, USB 2.0 9.6.6 */
-		if (speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) {
-			int i;
-
-			/*
-			 * round ival down to "the nearest base 2 multiple of
-			 * bInterval * 8".
-			 * bInterval is at most 255 as its type is uByte.
-			 * 255(ms) = 2040(x 125us) < 2^11, so start with 11.
-			 */
-			for (i = 11; i > 0; i--) {
-				if ((ival * 8) >= (1 << i))
-					break;
-			}
-			ival = i;
-		} else {
-			/* Interval = bInterval-1 for SS/HS */
-			ival--;
-		}
-		DPRINTFN(4, "ival %u", ival, 0, 0, 0);
-
-		if (USB_IS_SS(speed)) {
-			if (maxb > 0)
-				mps = 1024;
-		} else {
-			mps = mps ? mps : 8;
-		}
+		ival = xhci_bival2ival(ival, speed);
 		cp[0] |= htole32(XHCI_EPCTX_0_IVAL_SET(ival));
-		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
-		cp[4] = htole32(
-		    XHCI_EPCTX_4_AVG_TRB_LEN_SET(8) /* XXX */
-		    );
 		break;
-	case UE_CONTROL:
-		if (USB_IS_SS(speed))
-			mps = 512;
-		else
-			mps = mps ? mps : 8;
-		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
-		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(8)); /* XXX */
-		break;
-#ifdef notyet
 	case UE_ISOCHRONOUS:
+		if (pipe->up_interval != USBD_DEFAULT_INTERVAL)
+			ival = pipe->up_interval;
+
+		/* xHCI 6.2.3.6 Table 65, USB 2.0 9.6.6 */
 		if (speed == USB_SPEED_FULL)
 			ival += 3; /* 1ms -> 125us */
 		ival--;
-		DPRINTFN(4, "ival %u", ival, 0, 0, 0);
+		cp[0] |= htole32(XHCI_EPCTX_0_IVAL_SET(ival));
 
 		if (USB_IS_SS(speed)) {
-			mps = 1024;
-		} else {
-			mps = mps ? mps : 1024;
+			/* XXX if LEC = 1, set ESIT instead */
+			cp[0] |= htole32(XHCI_EPCTX_0_MULT_SET(0));
 		}
-		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
-		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(1024)); /* XXX */
 		break;
-#endif
 	default:
-		if (USB_IS_SS(speed))
-			mps = 1024;
-		else
-			mps = mps ? mps : 512;
-		cp[1] |= htole32(XHCI_EPCTX_1_MAXP_SIZE_SET(mps));
-		cp[4] = htole32(XHCI_EPCTX_4_AVG_TRB_LEN_SET(1024)); /* XXX */
 		break;
 	}
 	*(uint64_t *)(&cp[2]) = htole64(
 	    xhci_ring_trbp(&xs->xs_ep[dci].xe_tr, 0) |
 	    XHCI_EPCTX_2_DCS_SET(1));
+}
+
+/*
+ * Construct input contexts and issue TRB
+ */
+static usbd_status
+xhci_configure_endpoint(struct usbd_pipe *pipe)
+{
+	struct xhci_softc * const sc = pipe->up_dev->ud_bus->ub_hcpriv;
+	struct xhci_slot * const xs = pipe->up_dev->ud_hcpriv;
+	const u_int dci = xhci_ep_get_dci(pipe->up_endpoint->ue_edesc);
+	struct xhci_trb trb;
+	usbd_status err;
+	uint32_t *cp;
+
+	XHCIHIST_FUNC(); XHCIHIST_CALLED();
+	DPRINTFN(4, "slot %u dci %u epaddr 0x%02x attr 0x%02x",
+	    xs->xs_idx, dci, pipe->up_endpoint->ue_edesc->bEndpointAddress,
+	    pipe->up_endpoint->ue_edesc->bmAttributes);
+
+	/* XXX ensure input context is available? */
+
+	memset(xhci_slot_get_icv(sc, xs, 0), 0, sc->sc_pgsz);
+
+	cp = xhci_slot_get_icv(sc, xs, XHCI_ICI_INPUT_CONTROL);
+	cp[0] = htole32(0);
+	cp[1] = htole32(XHCI_INCTX_1_ADD_MASK(dci));
+
+	/* set up input slot context */
+	cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
+	xhci_setup_sctx(pipe->up_dev, cp);
+	cp[0] |= htole32(XHCI_SCTX_0_CTX_NUM_SET(dci));
+
+	/* set up input endpoint context */
+	cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(dci));
+	xhci_setup_endp_ctx(pipe, cp);
 
 	/* sync input contexts before they are read from memory */
 	usb_syncmem(&xs->xs_ic_dma, 0, sc->sc_pgsz, BUS_DMASYNC_PREWRITE);
@@ -1442,6 +1512,7 @@ xhci_set_dequeue(struct usbd_pipe *pipe)
 	memset(xr->xr_trb, 0, xr->xr_ntrb * XHCI_TRB_SIZE);
 	usb_syncmem(&xr->xr_dma, 0, xr->xr_ntrb * XHCI_TRB_SIZE,
 	    BUS_DMASYNC_PREWRITE);
+	memset(xr->xr_cookies, 0, xr->xr_ntrb * sizeof(*xr->xr_cookies));
 
 	xr->xr_ep = 0;
 	xr->xr_cs = 1;
@@ -1546,7 +1617,7 @@ xhci_close_pipe(struct usbd_pipe *pipe)
 		/* xs is uninitialized before xhci_init_slot */
 		return;
 
-	DPRINTFN(4, "slot %u dci %u", xs->xs_idx, dci, 0, 0);
+	DPRINTFN(4, "pipe %p slot %u dci %u", pipe, xs->xs_idx, dci, 0);
 
 	KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), "called from intr ctx");
 	KASSERT(mutex_owned(&sc->sc_lock));
@@ -1620,11 +1691,11 @@ xhci_abort_xfer(struct usbd_xfer *xfer, 
 	xfer->ux_status = status;
 	callout_stop(&xfer->ux_callout);
 	usb_transfer_complete(xfer);
+	DPRINTFN(14, "end", 0, 0, 0, 0);
 
 	KASSERT(mutex_owned(&sc->sc_lock));
 }
 
-#if 1 /* XXX experimental */
 /*
  * Recover STALLed endpoint.
  * xHCI 1.1 sect 4.10.2.1
@@ -1675,8 +1746,6 @@ xhci_clear_endpoint_stall_async(struct u
 	return USBD_NORMAL_COMPLETION;
 }
 
-#endif /* XXX experimental */
-
 /* Process roothub port status/change events and notify to uhub_intr. */
 static void
 xhci_rhpsc(struct xhci_softc * const sc, u_int port)
@@ -1729,12 +1798,14 @@ xhci_event_transfer(struct xhci_softc * 
 	xr = &xs->xs_ep[dci].xe_tr;
 
 	/* sanity check */
-	if (xs->xs_idx == 0 || xs->xs_idx >= sc->sc_maxslots) {
-		DPRINTFN(1, "invalid slot %u", xs->xs_idx, 0, 0, 0);
-		return;
-	}
+	KASSERTMSG(xs->xs_idx != 0 && xs->xs_idx < sc->sc_maxslots,
+	    "invalid xs_idx %u slot %u", xs->xs_idx, slot);
 
 	if ((trb_3 & XHCI_TRB_3_ED_BIT) == 0) {
+		/*
+		 * When ED == 0, trb_0 is physical address of the TRB
+		 * that caused this event. (6.4.2.1)
+		 */
 		bus_addr_t trbp = xhci_ring_trbp(xr, 0);
 
 		/* trb_0 range sanity check */
@@ -1748,7 +1819,20 @@ xhci_event_transfer(struct xhci_softc * 
 		}
 		int idx = (trb_0 - trbp) / sizeof(struct xhci_trb);
 		xx = xr->xr_cookies[idx];
+
+		/*
+		 * If endpoint is stopped between TDs, TRB pointer points at
+		 * next TRB, however, it is not put yet or is a garbage TRB.
+		 * That's why xr_cookies may be NULL or look like broken.
+		 * Note: this ev happens only when hciversion >= 1.0 or
+		 * hciversion == 0.96 and FSE of hcc1 is set.
+		 */
+		if (xx == NULL || trbcode == XHCI_TRB_ERROR_LENGTH) {
+			DPRINTFN(1, "xx NULL: #%u: cookie %p: code %u trb_0 %"
+			    PRIx64, idx, xx, trbcode, trb_0);
+		}
 	} else {
+		/* When ED != 0, trb_0 is kaddr of struct xhci_xfer. */
 		xx = (void *)(uintptr_t)(trb_0 & ~0x3);
 	}
 	/* XXX this may not happen */
@@ -1759,24 +1843,24 @@ xhci_event_transfer(struct xhci_softc * 
 	xfer = &xx->xx_xfer;
 	/* XXX this may happen when detaching */
 	if (xfer == NULL) {
-		DPRINTFN(1, "xfer done: xfer is NULL", 0, 0, 0, 0);
+		DPRINTFN(1, "xx(%p)->xx_xfer is NULL trb_0 %#"PRIx64,
+		    xx, trb_0, 0, 0);
 		return;
 	}
 	DPRINTFN(14, "xfer %p", xfer, 0, 0, 0);
 	/* XXX I dunno why this happens */
-	KASSERT(xfer->ux_pipe != NULL);
+	KASSERTMSG(xfer->ux_pipe != NULL, "xfer(%p)->ux_pipe is NULL", xfer);
 
 	if (!xfer->ux_pipe->up_repeat &&
 	    SIMPLEQ_EMPTY(&xfer->ux_pipe->up_queue)) {
-		DPRINTFN(1, "xfer done: xfer not started", 0, 0, 0, 0);
+		DPRINTFN(1, "xfer(%p)->pipe not queued", xfer, 0, 0, 0);
 		return;
 	}
 
+	/* 4.11.5.2 Event Data TRB */
 	if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
-		DPRINTFN(14, "transfer event data: "
-		    "0x%016"PRIx64" 0x%08"PRIx32" %02x",
-		    trb_0, XHCI_TRB_2_REM_GET(trb_2),
-		    XHCI_TRB_2_ERROR_GET(trb_2), 0);
+		DPRINTFN(14, "transfer Event Data: 0x%016"PRIx64" 0x%08"PRIx32
+		    " %02x", trb_0, XHCI_TRB_2_REM_GET(trb_2), trbcode, 0);
 		if ((trb_0 & 0x3) == 0x3) {
 			xfer->ux_actlen = XHCI_TRB_2_REM_GET(trb_2);
 		}
@@ -1791,15 +1875,13 @@ xhci_event_transfer(struct xhci_softc * 
 		break;
 	case XHCI_TRB_ERROR_STALL:
 	case XHCI_TRB_ERROR_BABBLE:
-		DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
-		    trbcode, slot, dci, 0);
+		DPRINTFN(1, "ERR %u slot %u dci %u", trbcode, slot, dci, 0);
 		xr->is_halted = true;
 		err = USBD_STALLED;
-#if 1 /* XXX experimental */
 		/*
 		 * Stalled endpoints can be recoverd by issuing
 		 * command TRB TYPE_RESET_EP on xHCI instead of
-		 * issuing request CLEAR_PORT_FEATURE UF_ENDPOINT_HALT
+		 * issuing request CLEAR_FEATURE UF_ENDPOINT_HALT
 		 * on the endpoint. However, this function may be
 		 * called from softint context (e.g. from umass),
 		 * in that case driver gets KASSERT in cv_timedwait
@@ -1812,25 +1894,13 @@ xhci_event_transfer(struct xhci_softc * 
 		xfer->ux_status = err;
 		xhci_clear_endpoint_stall_async(xfer);
 		return;
-#else
-		break;
-#endif
-	case XHCI_TRB_ERROR_CMD_ABORTED:
-	case XHCI_TRB_ERROR_STOPPED:
-		err = USBD_CANCELLED;
-		break;
-	case XHCI_TRB_ERROR_NO_SLOTS:
-		err = USBD_NO_ADDR;
-		break;
 	default:
-		DPRINTFN(1, "evh: xfer done: ERR %u slot %u dci %u",
-		    trbcode, slot, dci, 0);
+		DPRINTFN(1, "ERR %u slot %u dci %u", trbcode, slot, dci, 0);
 		err = USBD_IOERROR;
 		break;
 	}
 	xfer->ux_status = err;
 
-	//mutex_enter(&sc->sc_lock); /* XXX ??? */
 	if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
 		if ((trb_0 & 0x3) == 0x0) {
 			usb_transfer_complete(xfer);
@@ -1838,7 +1908,6 @@ xhci_event_transfer(struct xhci_softc * 
 	} else {
 		usb_transfer_complete(xfer);
 	}
-	//mutex_exit(&sc->sc_lock); /* XXX ??? */
 }
 
 /* Process Command complete events */
@@ -2313,6 +2382,7 @@ xhci_ring_put(struct xhci_softc * const 
 
 	XHCIHIST_FUNC(); XHCIHIST_CALLED();
 
+	KASSERT(ntrbs <= XHCI_XFER_NTRB);
 	for (i = 0; i < ntrbs; i++) {
 		DPRINTFN(12, "xr %p trbs %p num %zu", xr, trbs, i, 0);
 		DPRINTFN(12, " %016"PRIx64" %08"PRIx32" %08"PRIx32,
@@ -2562,6 +2632,10 @@ xhci_address_device(struct xhci_softc * 
 	    (bsr ? XHCI_TRB_3_BSR_BIT : 0);
 
 	err = xhci_do_command(sc, &trb, USBD_DEFAULT_TIMEOUT);
+
+	if (XHCI_TRB_2_ERROR_GET(trb.trb_2) == XHCI_TRB_ERROR_NO_SLOTS)
+		err = USBD_NO_ADDR;
+
 	return err;
 }
 
@@ -3098,6 +3172,7 @@ xhci_device_ctrl_start(struct usbd_xfer 
 	    req->bmRequestType | (req->bRequest << 8), UGETW(req->wValue),
 	    UGETW(req->wIndex), UGETW(req->wLength));
 
+#if 0 /* event handler does this */
 	/* XXX */
 	if (tr->is_halted) {
 		DPRINTFN(1, "ctrl xfer %p halted: slot %u dci %u",
@@ -3106,6 +3181,7 @@ xhci_device_ctrl_start(struct usbd_xfer 
 		tr->is_halted = false;
 		xhci_set_dequeue(xfer->ux_pipe);
 	}
+#endif
 
 	/* we rely on the bottom bits for extra info */
 	KASSERT(((uintptr_t)xfer & 0x3) == 0x0);

Index: src/sys/dev/usb/xhcireg.h
diff -u src/sys/dev/usb/xhcireg.h:1.2.2.2 src/sys/dev/usb/xhcireg.h:1.2.2.3
--- src/sys/dev/usb/xhcireg.h:1.2.2.2	Sat Jun  6 16:38:07 2015
+++ src/sys/dev/usb/xhcireg.h	Sun Sep 13 09:27:54 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: xhcireg.h,v 1.2.2.2 2015/06/06 16:38:07 skrll Exp $ */
+/* $NetBSD: xhcireg.h,v 1.2.2.3 2015/09/13 09:27:54 skrll Exp $ */
 /* $FreeBSD$ */
 
 /*-
@@ -36,6 +36,7 @@
 #define	PCI_USBREV		0x60	/* RO USB protocol revision */
 #define	 PCI_USBREV_MASK	0xFF
 #define	 PCI_USBREV_3_0		0x30	/* USB 3.0 */
+
 #define	PCI_XHCI_FLADJ		0x61	/* RW frame length adjust */
 
 #define	PCI_XHCI_INTEL_XUSB2PR	0xD0    /* Intel USB2 Port Routing */
@@ -44,72 +45,87 @@
 #define	PCI_XHCI_INTEL_USB3PRM	0xDC    /* Intel USB3 Port Routing Mask */
 
 /* XHCI capability registers */
-#define XHCI_CAPLENGTH		0x00	/* RO capability */
-#define	XHCI_CAP_CAPLENGTH(x)	((x) & 0xFF)
-#define	XHCI_CAP_HCIVERSION(x)	(((x) >> 16) & 0xFFFF)	/* RO Interface version number */
-#define	XHCI_HCIVERSION_0_9	0x0090	/* xHCI version 0.9 */
-#define	XHCI_HCIVERSION_1_0	0x0100	/* xHCI version 1.0 */
+#define	XHCI_CAPLENGTH		0x00	/* RO capability */
+#define	 XHCI_CAP_CAPLENGTH(x)	((x) & 0xFF)
+#define	 XHCI_CAP_HCIVERSION(x)	(((x) >> 16) & 0xFFFF)	/* RO Interface version number */
+#define	 XHCI_HCIVERSION_0_9	0x0090	/* xHCI version 0.9 */
+#define	 XHCI_HCIVERSION_0_96	0x0096	/* xHCI version 0.96 */
+#define	 XHCI_HCIVERSION_1_0	0x0100	/* xHCI version 1.0 */
+
 #define	XHCI_HCSPARAMS1		0x04	/* RO structual parameters 1 */
-#define	XHCI_HCS1_MAXSLOTS(x)	((x) & 0xFF)
-#define	XHCI_HCS1_MAXINTRS(x)	(((x) >> 8) & 0x7FF)
-#define	XHCI_HCS1_MAXPORTS(x)	(((x) >> 24) & 0xFF)
+#define	 XHCI_HCS1_MAXSLOTS(x)	((x) & 0xFF)
+#define	 XHCI_HCS1_MAXINTRS(x)	(((x) >> 8) & 0x7FF)
+#define	 XHCI_HCS1_MAXPORTS(x)	(((x) >> 24) & 0xFF)
+
 #define	XHCI_HCSPARAMS2		0x08	/* RO structual parameters 2 */
-#define	XHCI_HCS2_IST(x)	((x) & 0xF)
-#define	XHCI_HCS2_ERST_MAX(x)	(((x) >> 4) & 0xF)
-#define	XHCI_HCS2_SPR(x)	(((x) >> 24) & 0x1)
-#define	XHCI_HCS2_MAXSPBUF(x)	(((x) >> 27) & 0x7F)
+#define	 XHCI_HCS2_IST(x)	((x) & 0xF)
+#define	 XHCI_HCS2_ERST_MAX(x)	(((x) >> 4) & 0xF)
+#define	 XHCI_HCS2_SPR(x)	(((x) >> 24) & 0x1)
+#define	 XHCI_HCS2_MAXSPBUF(x)	(((x) >> 27) & 0x7F)
+
 #define	XHCI_HCSPARAMS3		0x0C	/* RO structual parameters 3 */
-#define	XHCI_HCS3_U1_DEL(x)	((x) & 0xFF)
-#define	XHCI_HCS3_U2_DEL(x)	(((x) >> 16) & 0xFFFF)
+#define	 XHCI_HCS3_U1_DEL(x)	((x) & 0xFF)
+#define	 XHCI_HCS3_U2_DEL(x)	(((x) >> 16) & 0xFFFF)
+
 #define	XHCI_HCCPARAMS		0x10	/* RO capability parameters */
-#define	XHCI_HCC_AC64(x)	((x) & 0x1)		/* 64-bit capable */
-#define	XHCI_HCC_BNC(x)	(((x) >> 1) & 0x1)	/* BW negotiation */
-#define	XHCI_HCC_CSZ(x)	(((x) >> 2) & 0x1)	/* context size */
-#define	XHCI_HCC_PPC(x)	(((x) >> 3) & 0x1)	/* port power control */
-#define	XHCI_HCC_PIND(x)	(((x) >> 4) & 0x1)	/* port indicators */
-#define	XHCI_HCC_LHRC(x)	(((x) >> 5) & 0x1)	/* light HC reset */
-#define	XHCI_HCC_LTC(x)	(((x) >> 6) & 0x1)	/* latency tolerance msg */
-#define	XHCI_HCC_NSS(x)	(((x) >> 7) & 0x1)	/* no secondary sid */
-#define	XHCI_HCC_MAXPSASIZE(x)	(((x) >> 12) & 0xF)	/* max pri. stream array size */
-#define	XHCI_HCC_XECP(x)	(((x) >> 16) & 0xFFFF)	/* extended capabilities pointer */
-#define	XHCI_DBOFF		0x14	/* RO doorbell offset */
-#define	XHCI_RTSOFF		0x18	/* RO runtime register space offset */
+#define	 XHCI_HCC_AC64(x)	(((x) >> 0) & 0x1)	/* 64-bit capable */
+#define	 XHCI_HCC_BNC(x)	(((x) >> 1) & 0x1)	/* BW negotiation */
+#define	 XHCI_HCC_CSZ(x)	(((x) >> 2) & 0x1)	/* context size */
+#define	 XHCI_HCC_PPC(x)	(((x) >> 3) & 0x1)	/* port power control */
+#define	 XHCI_HCC_PIND(x)	(((x) >> 4) & 0x1)	/* port indicators */
+#define	 XHCI_HCC_LHRC(x)	(((x) >> 5) & 0x1)	/* light HC reset */
+#define	 XHCI_HCC_LTC(x)	(((x) >> 6) & 0x1)	/* latency tolerance msg */
+#define	 XHCI_HCC_NSS(x)	(((x) >> 7) & 0x1)	/* no secondary sid */
+#define	 XHCI_HCC_PAE(x)	(((x) >> 8) & 0x1)	/* Pase All Event Data */
+#define	 XHCI_HCC_SPC(x)	(((x) >> 9) & 0x1)	/* Short packet */
+#define	 XHCI_HCC_SEC(x)	(((x) >> 10) & 0x1)	/* Stopped EDTLA */
+#define	 XHCI_HCC_CFC(x)	(((x) >> 11) & 0x1)	/* Configuous Frame ID */
+#define	 XHCI_HCC_MAXPSASIZE(x)	(((x) >> 12) & 0xF)	/* max pri. stream array size */
+#define	 XHCI_HCC_XECP(x)	(((x) >> 16) & 0xFFFF)	/* extended capabilities pointer */
+
+#define	 XHCI_DBOFF		0x14	/* RO doorbell offset */
+#define	 XHCI_RTSOFF		0x18	/* RO runtime register space offset */
 
 /* XHCI operational registers.  Offset given by XHCI_CAPLENGTH register */
 #define	XHCI_USBCMD		0x00	/* XHCI command */
-#define	XHCI_CMD_RS		0x00000001	/* RW Run/Stop */
-#define	XHCI_CMD_HCRST		0x00000002	/* RW Host Controller Reset */
-#define	XHCI_CMD_INTE		0x00000004	/* RW Interrupter Enable */
-#define	XHCI_CMD_HSEE		0x00000008	/* RW Host System Error Enable */
-#define	XHCI_CMD_LHCRST		0x00000080	/* RO/RW Light Host Controller Reset */
-#define	XHCI_CMD_CSS		0x00000100	/* RW Controller Save State */
-#define	XHCI_CMD_CRS		0x00000200	/* RW Controller Restore State */
-#define	XHCI_CMD_EWE		0x00000400	/* RW Enable Wrap Event */
-#define	XHCI_CMD_EU3S		0x00000800	/* RW Enable U3 MFINDEX Stop */
+#define	 XHCI_CMD_RS		0x00000001	/* RW Run/Stop */
+#define	 XHCI_CMD_HCRST		0x00000002	/* RW Host Controller Reset */
+#define	 XHCI_CMD_INTE		0x00000004	/* RW Interrupter Enable */
+#define	 XHCI_CMD_HSEE		0x00000008	/* RW Host System Error Enable */
+#define	 XHCI_CMD_LHCRST		0x00000080	/* RO/RW Light Host Controller Reset */
+#define	 XHCI_CMD_CSS		0x00000100	/* RW Controller Save State */
+#define	 XHCI_CMD_CRS		0x00000200	/* RW Controller Restore State */
+#define	 XHCI_CMD_EWE		0x00000400	/* RW Enable Wrap Event */
+#define	 XHCI_CMD_EU3S		0x00000800	/* RW Enable U3 MFINDEX Stop */
+
 #define	XHCI_USBSTS		0x04	/* XHCI status */
-#define	XHCI_STS_HCH		0x00000001	/* RO - Host Controller Halted */
-#define	XHCI_STS_HSE		0x00000004	/* RW - Host System Error */
-#define	XHCI_STS_EINT		0x00000008	/* RW - Event Interrupt */
-#define	XHCI_STS_PCD		0x00000010	/* RW - Port Change Detect */
-#define	XHCI_STS_SSS		0x00000100	/* RO - Save State Status */
-#define	XHCI_STS_RSS		0x00000200	/* RO - Restore State Status */
-#define	XHCI_STS_SRE		0x00000400	/* RW - Save/Restore Error */
-#define	XHCI_STS_CNR		0x00000800	/* RO - Controller Not Ready */
-#define	XHCI_STS_HCE		0x00001000	/* RO - Host Controller Error */
+#define	 XHCI_STS_HCH		0x00000001	/* RO - Host Controller Halted */
+#define	 XHCI_STS_HSE		0x00000004	/* RW - Host System Error */
+#define	 XHCI_STS_EINT		0x00000008	/* RW - Event Interrupt */
+#define	 XHCI_STS_PCD		0x00000010	/* RW - Port Change Detect */
+#define	 XHCI_STS_SSS		0x00000100	/* RO - Save State Status */
+#define	 XHCI_STS_RSS		0x00000200	/* RO - Restore State Status */
+#define	 XHCI_STS_SRE		0x00000400	/* RW - Save/Restore Error */
+#define	 XHCI_STS_CNR		0x00000800	/* RO - Controller Not Ready */
+#define	 XHCI_STS_HCE		0x00001000	/* RO - Host Controller Error */
+
 #define	XHCI_PAGESIZE		0x08	/* XHCI page size mask */
-#define	XHCI_PAGESIZE_4K	0x00000001	/* 4K Page Size */
-#define	XHCI_PAGESIZE_8K	0x00000002	/* 8K Page Size */
-#define	XHCI_PAGESIZE_16K	0x00000004	/* 16K Page Size */
-#define	XHCI_PAGESIZE_32K	0x00000008	/* 32K Page Size */
-#define	XHCI_PAGESIZE_64K	0x00000010	/* 64K Page Size */
-#define	XHCI_DNCTRL		0x14	/* XHCI device notification control */
+#define	 XHCI_PAGESIZE_4K	0x00000001	/* 4K Page Size */
+#define	 XHCI_PAGESIZE_8K	0x00000002	/* 8K Page Size */
+#define	 XHCI_PAGESIZE_16K	0x00000004	/* 16K Page Size */
+#define	 XHCI_PAGESIZE_32K	0x00000008	/* 32K Page Size */
+#define	 XHCI_PAGESIZE_64K	0x00000010	/* 64K Page Size */
+
+#define	 XHCI_DNCTRL		0x14	/* XHCI device notification control */
 #define	XHCI_DNCTRL_MASK(n)	(1U << (n))
+
 #define	XHCI_CRCR		0x18	/* XHCI command ring control */
-#define	XHCI_CRCR_LO_RCS	0x00000001	/* RW - consumer cycle state */
-#define	XHCI_CRCR_LO_CS		0x00000002	/* RW - command stop */
-#define	XHCI_CRCR_LO_CA		0x00000004	/* RW - command abort */
-#define	XHCI_CRCR_LO_CRR	0x00000008	/* RW - command ring running */
-#define	XHCI_CRCR_LO_MASK	0x0000000F
+#define	 XHCI_CRCR_LO_RCS	0x00000001	/* RW - consumer cycle state */
+#define	 XHCI_CRCR_LO_CS	0x00000002	/* RW - command stop */
+#define	 XHCI_CRCR_LO_CA	0x00000004	/* RW - command abort */
+#define	 XHCI_CRCR_LO_CRR	0x00000008	/* RW - command ring running */
+#define	 XHCI_CRCR_LO_MASK	0x0000000F
+
 #define	XHCI_CRCR_HI		0x1C	/* XHCI command ring control */
 #define	XHCI_DCBAAP		0x30	/* XHCI dev context BA pointer */
 #define	XHCI_DCBAAP_HI		0x34	/* XHCI dev context BA pointer */
@@ -118,78 +134,85 @@
 
 /* XHCI port status registers */
 #define	XHCI_PORTSC(n)		(0x3F0 + (0x10 * (n)))	/* XHCI port status */
-#define	XHCI_PS_CCS		0x00000001	/* RO - current connect status */
-#define	XHCI_PS_PED		0x00000002	/* RW - port enabled / disabled */
-#define	XHCI_PS_OCA		0x00000008	/* RO - over current active */
-#define	XHCI_PS_PR		0x00000010	/* RW - port reset */
-#define	XHCI_PS_PLS_GET(x)	(((x) >> 5) & 0xF)	/* RW - port link state */
-#define	XHCI_PS_PLS_SET(x)	(((x) & 0xF) << 5)	/* RW - port link state */
-#define	XHCI_PS_PP		0x00000200	/* RW - port power */
-#define	XHCI_PS_SPEED_GET(x)	(((x) >> 10) & 0xF)	/* RO - port speed */
-#define	XHCI_PS_PIC_GET(x)	(((x) >> 14) & 0x3)	/* RW - port indicator */
-#define	XHCI_PS_PIC_SET(x)	(((x) & 0x3) << 14)	/* RW - port indicator */
-#define	XHCI_PS_LWS		0x00010000	/* RW - port link state write strobe */
-#define	XHCI_PS_CSC		0x00020000	/* RW - connect status change */
-#define	XHCI_PS_PEC		0x00040000	/* RW - port enable/disable change */
-#define	XHCI_PS_WRC		0x00080000	/* RW - warm port reset change */
-#define	XHCI_PS_OCC		0x00100000	/* RW - over-current change */
-#define	XHCI_PS_PRC		0x00200000	/* RW - port reset change */
-#define	XHCI_PS_PLC		0x00400000	/* RW - port link state change */
-#define	XHCI_PS_CEC		0x00800000	/* RW - config error change */
-#define	XHCI_PS_CAS		0x01000000	/* RO - cold attach status */
-#define	XHCI_PS_WCE		0x02000000	/* RW - wake on connect enable */
-#define	XHCI_PS_WDE		0x04000000	/* RW - wake on disconnect enable */
-#define	XHCI_PS_WOE		0x08000000	/* RW - wake on over-current enable */
-#define	XHCI_PS_DR		0x40000000	/* RO - device removable */
-#define	XHCI_PS_WPR		0x80000000U	/* RW - warm port reset */
-#define	XHCI_PS_CLEAR		0x80FF01FFU	/* command bits */
+#define	 XHCI_PS_CCS		0x00000001	/* RO - current connect status */
+#define	 XHCI_PS_PED		0x00000002	/* RW - port enabled / disabled */
+#define	 XHCI_PS_OCA		0x00000008	/* RO - over current active */
+#define	 XHCI_PS_PR		0x00000010	/* RW - port reset */
+#define	 XHCI_PS_PLS_GET(x)	(((x) >> 5) & 0xF)	/* RW - port link state */
+#define	 XHCI_PS_PLS_SET(x)	(((x) & 0xF) << 5)	/* RW - port link state */
+#define	 XHCI_PS_PP		0x00000200	/* RW - port power */
+#define	 XHCI_PS_SPEED_GET(x)	(((x) >> 10) & 0xF)	/* RO - port speed */
+#define	 XHCI_PS_PIC_GET(x)	(((x) >> 14) & 0x3)	/* RW - port indicator */
+#define	 XHCI_PS_PIC_SET(x)	(((x) & 0x3) << 14)	/* RW - port indicator */
+#define	 XHCI_PS_LWS		0x00010000	/* RW - port link state write strobe */
+#define	 XHCI_PS_CSC		0x00020000	/* RW - connect status change */
+#define	 XHCI_PS_PEC		0x00040000	/* RW - port enable/disable change */
+#define	 XHCI_PS_WRC		0x00080000	/* RW - warm port reset change */
+#define	 XHCI_PS_OCC		0x00100000	/* RW - over-current change */
+#define	 XHCI_PS_PRC		0x00200000	/* RW - port reset change */
+#define	 XHCI_PS_PLC		0x00400000	/* RW - port link state change */
+#define	 XHCI_PS_CEC		0x00800000	/* RW - config error change */
+#define	 XHCI_PS_CAS		0x01000000	/* RO - cold attach status */
+#define	 XHCI_PS_WCE		0x02000000	/* RW - wake on connect enable */
+#define	 XHCI_PS_WDE		0x04000000	/* RW - wake on disconnect enable */
+#define	 XHCI_PS_WOE		0x08000000	/* RW - wake on over-current enable */
+#define	 XHCI_PS_DR		0x40000000	/* RO - device removable */
+#define	 XHCI_PS_WPR		0x80000000U	/* RW - warm port reset */
+#define	 XHCI_PS_CLEAR		0x80FF01FFU	/* command bits */
 
 #define	XHCI_PORTPMSC(n)	(0x3F4 + (0x10 * (n)))	/* XHCI status and control */
-#define	XHCI_PM3_U1TO_GET(x)	(((x) >> 0) & 0xFF)	/* RW - U1 timeout */
-#define	XHCI_PM3_U1TO_SET(x)	(((x) & 0xFF) << 0)	/* RW - U1 timeout */
-#define	XHCI_PM3_U2TO_GET(x)	(((x) >> 8) & 0xFF)	/* RW - U2 timeout */
-#define	XHCI_PM3_U2TO_SET(x)	(((x) & 0xFF) << 8)	/* RW - U2 timeout */
-#define	XHCI_PM3_FLA		0x00010000	/* RW - Force Link PM Accept */
-#define	XHCI_PM2_L1S_GET(x)	(((x) >> 0) & 0x7)	/* RO - L1 status */
-#define	XHCI_PM2_RWE		0x00000008		/* RW - remote wakup enable */
-#define	XHCI_PM2_HIRD_GET(x)	(((x) >> 4) & 0xF)	/* RW - host initiated resume duration */
-#define	XHCI_PM2_HIRD_SET(x)	(((x) & 0xF) << 4)	/* RW - host initiated resume duration */
-#define	XHCI_PM2_L1SLOT_GET(x)	(((x) >> 8) & 0xFF)	/* RW - L1 device slot */
-#define	XHCI_PM2_L1SLOT_SET(x)	(((x) & 0xFF) << 8)	/* RW - L1 device slot */
-#define	XHCI_PM2_HLE		0x00010000		/* RW - hardware LPM enable */
+#define	 XHCI_PM3_U1TO_GET(x)	(((x) >> 0) & 0xFF)	/* RW - U1 timeout */
+#define	 XHCI_PM3_U1TO_SET(x)	(((x) & 0xFF) << 0)	/* RW - U1 timeout */
+#define	 XHCI_PM3_U2TO_GET(x)	(((x) >> 8) & 0xFF)	/* RW - U2 timeout */
+#define	 XHCI_PM3_U2TO_SET(x)	(((x) & 0xFF) << 8)	/* RW - U2 timeout */
+#define	 XHCI_PM3_FLA		0x00010000	/* RW - Force Link PM Accept */
+#define	 XHCI_PM2_L1S_GET(x)	(((x) >> 0) & 0x7)	/* RO - L1 status */
+#define	 XHCI_PM2_RWE		0x00000008		/* RW - remote wakup enable */
+#define	 XHCI_PM2_HIRD_GET(x)	(((x) >> 4) & 0xF)	/* RW - host initiated resume duration */
+#define	 XHCI_PM2_HIRD_SET(x)	(((x) & 0xF) << 4)	/* RW - host initiated resume duration */
+#define	 XHCI_PM2_L1SLOT_GET(x)	(((x) >> 8) & 0xFF)	/* RW - L1 device slot */
+#define	 XHCI_PM2_L1SLOT_SET(x)	(((x) & 0xFF) << 8)	/* RW - L1 device slot */
+#define	 XHCI_PM2_HLE		0x00010000		/* RW - hardware LPM enable */
+
 #define	XHCI_PORTLI(n)		(0x3F8 + (0x10 * (n)))	/* XHCI port link info */
-#define	XHCI_PLI3_ERR_GET(x)	(((x) >> 0) & 0xFFFF)	/* RO - port link errors */
+#define	 XHCI_PLI3_ERR_GET(x)	(((x) >> 0) & 0xFFFF)	/* RO - port link errors */
+
 #define	XHCI_PORTRSV(n)		(0x3FC + (0x10 * (n)))	/* XHCI port reserved */
 
 /* XHCI runtime registers.  Offset given by XHCI_CAPLENGTH + XHCI_RTSOFF registers */
 #define	XHCI_MFINDEX		0x0000		/* RO - microframe index */
 #define	XHCI_MFINDEX_GET(x)	((x) & 0x3FFF)
+
 #define	XHCI_IMAN(n)		(0x0020 + (0x20 * (n)))	/* XHCI interrupt management */
-#define	XHCI_IMAN_INTR_PEND	0x00000001	/* RW - interrupt pending */
-#define	XHCI_IMAN_INTR_ENA	0x00000002	/* RW - interrupt enable */
+#define	 XHCI_IMAN_INTR_PEND	0x00000001	/* RW - interrupt pending */
+#define	 XHCI_IMAN_INTR_ENA	0x00000002	/* RW - interrupt enable */
+
 #define	XHCI_IMOD(n)		(0x0024 + (0x20 * (n)))	/* XHCI interrupt moderation */
-#define	XHCI_IMOD_IVAL_GET(x)	(((x) >> 0) & 0xFFFF)	/* 250ns unit */
-#define	XHCI_IMOD_IVAL_SET(x)	(((x) & 0xFFFF) << 0)	/* 250ns unit */
-#define	XHCI_IMOD_ICNT_GET(x)	(((x) >> 16) & 0xFFFF)	/* 250ns unit */
-#define	XHCI_IMOD_ICNT_SET(x)	(((x) & 0xFFFF) << 16)	/* 250ns unit */
-#define	XHCI_IMOD_DEFAULT	0x000001F4U	/* 8000 IRQ/second */
-#define	XHCI_IMOD_DEFAULT_LP	0x000003E8U	/* 4000 IRQ/sec for LynxPoint */
+#define	 XHCI_IMOD_IVAL_GET(x)	(((x) >> 0) & 0xFFFF)	/* 250ns unit */
+#define	 XHCI_IMOD_IVAL_SET(x)	(((x) & 0xFFFF) << 0)	/* 250ns unit */
+#define	 XHCI_IMOD_ICNT_GET(x)	(((x) >> 16) & 0xFFFF)	/* 250ns unit */
+#define	 XHCI_IMOD_ICNT_SET(x)	(((x) & 0xFFFF) << 16)	/* 250ns unit */
+#define	 XHCI_IMOD_DEFAULT	0x000001F4U	/* 8000 IRQ/second */
+#define	 XHCI_IMOD_DEFAULT_LP	0x000003E8U	/* 4000 IRQ/sec for LynxPoint */
+
 #define	XHCI_ERSTSZ(n)		(0x0028 + (0x20 * (n)))	/* XHCI event ring segment table size */
-#define	XHCI_ERSTS_GET(x)	((x) & 0xFFFF)
-#define	XHCI_ERSTS_SET(x)	((x) & 0xFFFF)
-#define	XHCI_ERSTBA(n)	(0x0030 + (0x20 * (n)))	/* XHCI event ring segment table BA */
+#define	 XHCI_ERSTS_GET(x)	((x) & 0xFFFF)
+#define	 XHCI_ERSTS_SET(x)	((x) & 0xFFFF)
+
+#define	XHCI_ERSTBA(n)		(0x0030 + (0x20 * (n)))	/* XHCI event ring segment table BA */
 #define	XHCI_ERSTBA_HI(n)	(0x0034 + (0x20 * (n)))	/* XHCI event ring segment table BA */
-#define	XHCI_ERDP(n)	(0x0038 + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
-#define	XHCI_ERDP_LO_SINDEX(x)	((x) & 0x7)	/* RO - dequeue segment index */
-#define	XHCI_ERDP_LO_BUSY	0x00000008	/* RW - event handler busy */
-#define	XHCI_ERDP_HI(n)	(0x003C + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
+
+#define	XHCI_ERDP(n)		(0x0038 + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
+#define	XHCI_ERDP_HI(n)		(0x003C + (0x20 * (n)))	/* XHCI event ring dequeue pointer */
+#define	 XHCI_ERDP_LO_SINDEX(x)	((x) & 0x7)	/* RO - dequeue segment index */
+#define	 XHCI_ERDP_LO_BUSY	0x00000008	/* RW - event handler busy */
 
 /* XHCI doorbell registers. Offset given by XHCI_CAPLENGTH + XHCI_DBOFF registers */
 #define	XHCI_DOORBELL(n)	(0x0000 + (4 * (n)))
-#define	XHCI_DB_TARGET_GET(x)	((x) & 0xFF)		/* RW - doorbell target */
-#define	XHCI_DB_TARGET_SET(x)	((x) & 0xFF)		/* RW - doorbell target */
-#define	XHCI_DB_SID_GET(x)	(((x) >> 16) & 0xFFFF)	/* RW - doorbell stream ID */
-#define	XHCI_DB_SID_SET(x)	(((x) & 0xFFFF) << 16)	/* RW - doorbell stream ID */
+#define	 XHCI_DB_TARGET_GET(x)	((x) & 0xFF)		/* RW - doorbell target */
+#define	 XHCI_DB_TARGET_SET(x)	((x) & 0xFF)		/* RW - doorbell target */
+#define	 XHCI_DB_SID_GET(x)	(((x) >> 16) & 0xFFFF)	/* RW - doorbell stream ID */
+#define	 XHCI_DB_SID_SET(x)	(((x) & 0xFFFF) << 16)	/* RW - doorbell stream ID */
 
 /* XHCI legacy support */
 #define	XHCI_XECP_ID(x)		((x) & 0xFF)
@@ -344,6 +367,7 @@ struct xhci_trb {
 #define XHCI_TRB_ERROR_CMD_ABORTED      0x19
 #define XHCI_TRB_ERROR_STOPPED          0x1A
 #define XHCI_TRB_ERROR_LENGTH           0x1B
+#define XHCI_TRB_ERROR_STOPPED_SHORT    0x1C
 #define XHCI_TRB_ERROR_BAD_MELAT        0x1D
 #define XHCI_TRB_ERROR_ISOC_OVERRUN     0x1F
 #define XHCI_TRB_ERROR_EVENT_LOST       0x20
@@ -407,6 +431,9 @@ struct xhci_trb {
 #define XHCI_EPCTX_0_LSA_GET(x)                 (((x) >> 15) & 0x1)
 #define XHCI_EPCTX_0_IVAL_SET(x)                (((x) & 0xFF) << 16)
 #define XHCI_EPCTX_0_IVAL_GET(x)                (((x) >> 16) & 0xFF)
+#define XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_MASK	__BITS(31,24)
+#define XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_SET(x) __SHIFTIN((x), XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_MASK)
+#define XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_GET(x) __SHIFTOUT((x), XHCI_EPCTX_0_MAX_ESIT_PAYLOAD_HI_MASK)
 
 #define XHCI_EPCTX_1_CERR_SET(x)                (((x) & 0x3) << 1)
 #define XHCI_EPCTX_1_CERR_GET(x)                (((x) >> 1) & 0x3)

Reply via email to