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)