tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
patch: verbose debug code for xhci
Hello,
This patch does NOT improve xhci.c at all but may (or not) help
people who try to read debugging hexdump even though they are not
familiar with it.
This patch is imcomplete, buggy, and does not support all requests.
For example, you can read TRB values in human-readable form like this:
Before:
xhci0: xhci_do_command: input: 0x000000000355e000 0x00000000 0x01002c00
xhci0: xhci_do_command: output: 0x00000000033aa010 0x01000000 0x01008401
After:
xhci0: xhci_do_command: input: 0x000000000355e000 0x00000000 0x01002c00
TYPE_ADDRESS_DEVICE(11) slot 1 bsr 0 ictx 000000000355e000 c 0
xhci0: xhci_do_command: output: 0x00000000033aa010 0x01000000 0x01008401
EVENT_CMD_COMPLETE(33) SUCCESS(1) slot 1 vf 0 c 1 param 0 cmd 00000000033aa010
by inserting xhci_dump_trb() to appropriate positions.
--- xhci.c.orig 2014-08-12 23:29:37.000000000 +0900
+++ xhci.c 2014-09-19 08:04:11.000000000 +0900
@@ -1734,6 +2451,7 @@ xhci_do_command(struct xhci_softc * cons
device_printf(sc->sc_dev, "%s input: "
"0x%016"PRIx64" 0x%08"PRIx32" 0x%08"PRIx32"\n", __func__,
trb->trb_0, trb->trb_2, trb->trb_3);
+ xhci_dump_trb(-1, trb);
mutex_enter(&sc->sc_lock);
@@ -1759,6 +2477,7 @@ xhci_do_command(struct xhci_softc * cons
device_printf(sc->sc_dev, "%s output: "
"0x%016"PRIx64" 0x%08"PRIx32" 0x%08"PRIx32"\n", __func__,
trb->trb_0, trb->trb_2, trb->trb_3);
+ xhci_dump_trb(-1, trb);
switch (XHCI_TRB_2_ERROR_GET(trb->trb_2)) {
case XHCI_TRB_ERROR_SUCCESS:
For example, you can see device request and reply in human-readable form
like this:
Before:
req: 80 06 0200 0000 0009
req: 80 06 0200 0000 001f
After:
req: GET_DESCRIPTOR(6) IN,STAND,DEV CONFIG(0x0200) idx 0000 len 9
getdesc: len 9: CONFIG(2) len 9<len 31 noiface 1 confval 1 iconf 0 attr e0 pwr
0>
req: GET_DESCRIPTOR(6) IN,STAND,DEV CONFIG(0x0200) idx 0000 len 31
getdesc: len 31: CONFIG(2) len 9<len 31 noiface 1 confval 1 iconf 0 attr e0 pwr 0>, INTERFACE(4)
len 9<>, ENDPOINT(5) len 7<notyet>, SSEP_COMPANION(48) len 6<maxburst 0 attr 00 b/i 2>
by adding xhci_dump_{req,reply}().
--- xhci.c.orig 2014-08-12 23:29:37.000000000 +0900
+++ xhci.c 2014-09-19 08:04:11.000000000 +0900
@@ -1235,6 +1801,10 @@ xhci_handle_event(struct xhci_softc * co
}
xfer->status = err;
+ if (err == USBD_NORMAL_COMPLETION && (trb_0 & 0x3) == 0x3) {
+ xhci_dump_reply(0, xfer);
+ }
+
//mutex_enter(&sc->sc_lock); /* XXX ??? */
if ((trb_3 & XHCI_TRB_3_ED_BIT) != 0) {
if ((trb_0 & 0x3) == 0x0) {
@@ -2541,10 +3491,8 @@ xhci_device_ctrl_start(usbd_xfer_handle
uint32_t control;
u_int i;
- DPRINTF(("%s\n", __func__));
- DPRINTF(("req: %02x %02x %04x %04x %04x\n", req->bmRequestType,
- req->bRequest, UGETW(req->wValue), UGETW(req->wIndex),
- UGETW(req->wLength)));
+ DPRINTF(("req: ));
+ xhci_dump_req(0, req);
/* XXX */
if (tr->is_halted) {
Thanks,
--
t-hash
--- xhci.c.orig 2014-08-12 23:29:37.000000000 +0900
+++ xhci.c 2014-09-19 08:04:11.000000000 +0900
@@ -147,6 +234,29 @@ static void xhci_device_bulk_done(usbd_x
static void xhci_timeout(void *);
static void xhci_timeout_task(void *);
+#ifdef XHCI_DEBUG
+static const char *str_trberr(int);
+static void xhci_dump_ictlctx(int, uint32_t *);
+static void xhci_dump_sctx(int, uint32_t *);
+static void xhci_dump_epctx(int, uint32_t *);
+static void xhci_dump_trbn(int, uint64_t, uint32_t, uint32_t);
+static void xhci_dump_trb(int, const struct xhci_trb * const);
+static void xhci_dump_portsc(int, uint32_t);
+static void xhci_dump_desc(int, void *);
+static void xhci_dump_reply(int, usbd_xfer_handle);
+static void xhci_dump_req(int, void *);
+#else /* XHCI_DEBUG */
+#define xhci_dump_ictlctx(n, x) ((void)0)
+#define xhci_dump_sctx(n, x) ((void)0)
+#define xhci_dump_epctx(n,x) ((void)0)
+#define xhci_dump_trbn(n, t0, t2, t3) ((void)0)
+#define xhci_dump_trb(n, x) ((void)0)
+#define xhci_dump_portsc(n, x) ((void)0)
+#define xhci_dump_desc(n, x) ((void)0)
+#define xhci_dump_reply(n, x) ((void)0)
+#define xhci_dump_req(n, x) ((void)0)
+#endif /* XHCI_DEBUG */
+
static const struct usbd_bus_methods xhci_bus_methods = {
.open_pipe = xhci_open,
.soft_intr = xhci_softintr,
@@ -2934,3 +4100,753 @@ xhci_timeout_task(void *addr)
#endif
mutex_exit(&sc->sc_lock);
}
+
+
+#ifdef XHCI_DEBUG
+/* verbose debug dump */
+
+struct tbl_t {
+ int idx;
+ const char *str;
+};
+
+#define TBLELEM(elem) { .idx = (elem), .str = #elem }
+
+static struct tbl_t trbtypetbl[] = {
+ TBLELEM(XHCI_TRB_TYPE_RESERVED),
+ TBLELEM(XHCI_TRB_TYPE_NORMAL),
+ TBLELEM(XHCI_TRB_TYPE_SETUP_STAGE),
+ TBLELEM(XHCI_TRB_TYPE_DATA_STAGE),
+ TBLELEM(XHCI_TRB_TYPE_STATUS_STAGE),
+ TBLELEM(XHCI_TRB_TYPE_ISOCH),
+ TBLELEM(XHCI_TRB_TYPE_LINK),
+ TBLELEM(XHCI_TRB_TYPE_EVENT_DATA),
+ TBLELEM(XHCI_TRB_TYPE_NOOP),
+ TBLELEM(XHCI_TRB_TYPE_ENABLE_SLOT),
+ TBLELEM(XHCI_TRB_TYPE_DISABLE_SLOT),
+ TBLELEM(XHCI_TRB_TYPE_ADDRESS_DEVICE),
+ TBLELEM(XHCI_TRB_TYPE_CONFIGURE_EP),
+ TBLELEM(XHCI_TRB_TYPE_EVALUATE_CTX),
+ TBLELEM(XHCI_TRB_TYPE_RESET_EP),
+ TBLELEM(XHCI_TRB_TYPE_STOP_EP),
+ TBLELEM(XHCI_TRB_TYPE_SET_TR_DEQUEUE),
+ TBLELEM(XHCI_TRB_TYPE_RESET_DEVICE),
+ TBLELEM(XHCI_TRB_TYPE_FORCE_EVENT),
+ TBLELEM(XHCI_TRB_TYPE_NEGOTIATE_BW),
+ TBLELEM(XHCI_TRB_TYPE_SET_LATENCY_TOL),
+ TBLELEM(XHCI_TRB_TYPE_GET_PORT_BW),
+ TBLELEM(XHCI_TRB_TYPE_FORCE_HEADER),
+ TBLELEM(XHCI_TRB_TYPE_NOOP_CMD),
+ TBLELEM(XHCI_TRB_EVENT_TRANSFER),
+ TBLELEM(XHCI_TRB_EVENT_CMD_COMPLETE),
+ TBLELEM(XHCI_TRB_EVENT_PORT_STS_CHANGE),
+ TBLELEM(XHCI_TRB_EVENT_BW_REQUEST),
+ TBLELEM(XHCI_TRB_EVENT_DOORBELL),
+ TBLELEM(XHCI_TRB_EVENT_HOST_CTRL),
+ TBLELEM(XHCI_TRB_EVENT_DEVICE_NOTIFY),
+ TBLELEM(XHCI_TRB_EVENT_MFINDEX_WRAP),
+};
+
+static struct tbl_t trberrtbl[] = {
+ TBLELEM(XHCI_TRB_ERROR_INVALID),
+ TBLELEM(XHCI_TRB_ERROR_SUCCESS),
+ TBLELEM(XHCI_TRB_ERROR_DATA_BUF),
+ TBLELEM(XHCI_TRB_ERROR_BABBLE),
+ TBLELEM(XHCI_TRB_ERROR_XACT),
+ TBLELEM(XHCI_TRB_ERROR_TRB),
+ TBLELEM(XHCI_TRB_ERROR_STALL),
+ TBLELEM(XHCI_TRB_ERROR_RESOURCE),
+ TBLELEM(XHCI_TRB_ERROR_BANDWIDTH),
+ TBLELEM(XHCI_TRB_ERROR_NO_SLOTS),
+ TBLELEM(XHCI_TRB_ERROR_STREAM_TYPE),
+ TBLELEM(XHCI_TRB_ERROR_SLOT_NOT_ON),
+ TBLELEM(XHCI_TRB_ERROR_ENDP_NOT_ON),
+ TBLELEM(XHCI_TRB_ERROR_SHORT_PKT),
+ TBLELEM(XHCI_TRB_ERROR_RING_UNDERRUN),
+ TBLELEM(XHCI_TRB_ERROR_RING_OVERRUN),
+ TBLELEM(XHCI_TRB_ERROR_VF_RING_FULL),
+ TBLELEM(XHCI_TRB_ERROR_PARAMETER),
+ TBLELEM(XHCI_TRB_ERROR_BW_OVERRUN),
+ TBLELEM(XHCI_TRB_ERROR_CONTEXT_STATE),
+ TBLELEM(XHCI_TRB_ERROR_NO_PING_RESP),
+ TBLELEM(XHCI_TRB_ERROR_EV_RING_FULL),
+ TBLELEM(XHCI_TRB_ERROR_INCOMPAT_DEV),
+ TBLELEM(XHCI_TRB_ERROR_MISSED_SERVICE),
+ TBLELEM(XHCI_TRB_ERROR_CMD_RING_STOP),
+ TBLELEM(XHCI_TRB_ERROR_CMD_ABORTED),
+ TBLELEM(XHCI_TRB_ERROR_STOPPED),
+ TBLELEM(XHCI_TRB_ERROR_LENGTH),
+ TBLELEM(XHCI_TRB_ERROR_BAD_MELAT),
+ TBLELEM(XHCI_TRB_ERROR_ISOC_OVERRUN),
+ TBLELEM(XHCI_TRB_ERROR_EVENT_LOST),
+ TBLELEM(XHCI_TRB_ERROR_UNDEFINED),
+ TBLELEM(XHCI_TRB_ERROR_INVALID_SID),
+ TBLELEM(XHCI_TRB_ERROR_SEC_BW),
+ TBLELEM(XHCI_TRB_ERROR_SPLIT_XACT),
+};
+
+#define TBLLOOKUP(tbl,skip) do { \
+ int i; \
+ for (i = 0; i < __arraycount(tbl) ; i++) \
+ if (tbl[i].idx == key) \
+ return &tbl[i].str[skip]; \
+ return "unknown"; \
+ } while (0/*CONSTCOND*/)
+
+static const char *
+str_trbtype(int key)
+{
+ TBLLOOKUP(trbtypetbl, 9);
+}
+
+static const char *
+str_trberr(int key)
+{
+ TBLLOOKUP(trberrtbl, 15);
+}
+
+static void __used
+xhci_dump_ictlctx(int dbglvl, uint32_t *cp)
+{
+ int i, n;
+
+ if (xhcidebug <= dbglvl)
+ return;
+
+ printf("ctlctx Drop: ");
+ for (i = 0, n = 0; i < 32; i++)
+ if ((cp[0] >> i) & 1) {
+ printf("%d ", i);
+ n++;
+ }
+ if (n == 0)
+ printf("(none)");
+ printf("\nctlctx Add: ");
+ for (i = 0, n = 0; i < 32; i++)
+ if ((cp[1] >> i) & 1) {
+ printf("%d ", i);
+ n++;
+ }
+ if (n == 0)
+ printf("(none)");
+ printf("\n");
+}
+
+static void __used
+xhci_dump_sctx(int dbglvl, uint32_t *cp)
+{
+ if (xhcidebug <= dbglvl)
+ return;
+
+ printf("cp0: ctxentry %u hub %u mtt %u speed %u rtstr %05x\n",
+ XHCI_SCTX_0_CTX_NUM_GET(cp[0]),
+ XHCI_SCTX_0_HUB_GET(cp[0]),
+ XHCI_SCTX_0_MTT_GET(cp[0]),
+ XHCI_SCTX_0_SPEED_GET(cp[0]),
+ XHCI_SCTX_0_ROUTE_GET(cp[0]));
+ printf("cp1: nports %u rhport %u maxel %u\n",
+ XHCI_SCTX_1_NUM_PORTS_GET(cp[1]),
+ XHCI_SCTX_1_RH_PORT_GET(cp[1]),
+ XHCI_SCTX_1_MAX_EL_GET(cp[1]));
+ printf("cp2: intrtarg %u ttt %u ttportnum %u tthubsid %u\n",
+ XHCI_SCTX_2_IRQ_TARGET_GET(cp[2]),
+ XHCI_SCTX_2_TT_THINK_TIME_GET(cp[2]),
+ XHCI_SCTX_2_TT_PORT_NUM_GET(cp[2]),
+ XHCI_SCTX_2_TT_HUB_SID_GET(cp[2]));
+ printf("cp3: slotstate %u addr %u\n",
+ XHCI_SCTX_3_SLOT_STATE_GET(cp[3]),
+ XHCI_SCTX_3_DEV_ADDR_GET(cp[3]));
+}
+
+#ifdef notyet
+static void
+xhci_dump_stctx(int dbglvl, uint32_t *cp)
+{
+}
+#endif
+
+static void __used
+xhci_dump_epctx(int dbglvl, uint32_t *cp)
+{
+ if (xhcidebug <= dbglvl)
+ return;
+
+ char sbuf[126];
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "f\030\010MESIT\0f\020\010IVAL\0b\017LSA\0"
+ "f\012\010MAXPS\0f\010\2MULT\0f\0\3EPSTATE\0\0", cp[0]);
+ printf("cp0: %s\n", sbuf);
+
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "f\020\020MPS\0f\010\010MBURST\0b\7HID\0"
+ "f\3\3EPTYPE\0f\1\2CERR\0\0", cp[1]);
+ printf("cp1: %s\n", sbuf);
+
+ printf("cp2: TR dqptr %016"PRIx64"\n",
+ (uint64_t)cp[3] << 32 | cp[2]);
+
+ printf("cp4: mesit %016x avgTRBlen %u\n",
+ XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_GET(cp[4]),
+ XHCI_EPCTX_4_AVG_TRB_LEN_GET(cp[4]));
+}
+
+#ifdef notyet
+static void
+xhci_dump_devctx(int dbglvl, uint32_t *cp)
+{
+}
+
+static void
+xhci_dump_pbwctx(int dbglvl, uint32_t *cp)
+{
+}
+#endif
+
+#define _B(x) ((x) ? 1 : 0)
+
+static void __used
+xhci_dump_trbn(int dbglvl, uint64_t trb_0, uint32_t trb_2, uint32_t trb_3)
+{
+ uint32_t trbtype;
+ char sbuf[128];
+
+ if (xhcidebug <= dbglvl)
+ return;
+
+ trb_0 = le64toh(trb_0);
+ trb_2 = le32toh(trb_2);
+ trb_3 = le32toh(trb_3);
+
+ trbtype = XHCI_TRB_3_TYPE_GET(trb_3);
+ printf("%s(%u) ", str_trbtype(trbtype), trbtype);
+
+ switch(trbtype) {
+ case XHCI_TRB_TYPE_SETUP_STAGE:
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "f\020\020wValue\0f\010\010bRequest\0"
+ "f\0\010bmReqType\0", (trb_0 & 0xffffffffU));
+ printf("%s ", sbuf);
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "f\020\020wLength\0f\0\020wIndex\0\0", (trb_0 >> 32));
+ printf("%s ", sbuf);
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "b\020TRT\0b\6IDT\0b\5IOC\0b\0C\0\0",
+ trb_3);
+ printf("irq %u tdsz %u len %u %s\n",
+ XHCI_TRB_2_IRQ_GET(trb_2),
+ XHCI_TRB_2_TDSZ_GET(trb_2),
+ XHCI_TRB_2_BYTES_GET(trb_2),
+ sbuf);
+ break;
+ case XHCI_TRB_TYPE_ISOCH:
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "b\037SIA\0f\024\013FRAMEID\0f\020\4TLBPC\0"
+ "b\011BEI\0f\7\2TBC\0"
+ "b\6IDT\0"
+ "b\5IOC\0b\4CH\0"
+ "b\3NS\0b\2ISP\0"
+ "b\1ENT\0b\0C\0\0",
+ trb_3);
+ printf("irq %u tdsz %u len %u %s buf %016"PRIx64"\n",
+ XHCI_TRB_2_IRQ_GET(trb_2),
+ XHCI_TRB_2_TDSZ_GET(trb_2),
+ XHCI_TRB_2_BYTES_GET(trb_2),
+ sbuf,
+ trb_0);
+ break;
+ case XHCI_TRB_TYPE_LINK:
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "b\5IOC\0b\4CH\0b\1TC\0b\0C\0\0",
+ trb_3);
+ printf("irq %u %s ringseg %016"PRIx64"\n",
+ XHCI_TRB_2_IRQ_GET(trb_2),
+ sbuf,
+ trb_0);
+ break;
+ case XHCI_TRB_TYPE_NORMAL:
+ case XHCI_TRB_TYPE_DATA_STAGE:
+ case XHCI_TRB_TYPE_STATUS_STAGE:
+ case XHCI_TRB_TYPE_EVENT_DATA:
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "b\020DIR\0"
+ "b\6IDT\0"
+ "b\5IOC\0b\4CH\0"
+ "b\3NS\0b\2ISP\0"
+ "b\1ENT\0b\0C\0\0",
+ trb_3);
+ printf("irq %u tdsz %u len %u %s buf %016"PRIx64"\n",
+ XHCI_TRB_2_IRQ_GET(trb_2),
+ XHCI_TRB_2_TDSZ_GET(trb_2),
+ XHCI_TRB_2_BYTES_GET(trb_2),
+ sbuf,
+ trb_0);
+ break;
+ case XHCI_TRB_TYPE_RESERVED:
+ case XHCI_TRB_TYPE_NOOP:
+ case XHCI_TRB_TYPE_ENABLE_SLOT:
+ printf("\n");
+ break;
+ case XHCI_TRB_TYPE_DISABLE_SLOT:
+ case XHCI_TRB_TYPE_RESET_DEVICE:
+ printf("slot %u c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_ADDRESS_DEVICE:
+ printf("slot %u bsr %u ictx %016"PRIx64" c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ _B(XHCI_TRB_3_BSR_BIT & trb_3),
+ trb_0,
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_CONFIGURE_EP:
+ printf("slot %u dc %u ictx %016"PRIx64" c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ _B(XHCI_TRB_3_DCEP_BIT & trb_3),
+ trb_0,
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_EVALUATE_CTX:
+ printf("slot %u ictx %016"PRIx64" c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ trb_0,
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_RESET_EP:
+ printf("slot %u ep %u prsv %u c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ XHCI_TRB_3_EP_GET(trb_3),
+ _B(XHCI_TRB_3_PRSV_BIT & trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_STOP_EP:
+ printf("slot %u ep %u sp %u c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ XHCI_TRB_3_EP_GET(trb_3),
+ _B(XHCI_TRB_3_SUSP_EP_BIT & trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_TYPE_SET_TR_DEQUEUE:
+ printf("slot %u ep %u stream %u c %u ptr %016"PRIx64"\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ XHCI_TRB_3_EP_GET(trb_3),
+ XHCI_TRB_2_STREAM_GET(trb_2),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3),
+ trb_0);
+ break;
+ case XHCI_TRB_TYPE_FORCE_EVENT:
+ case XHCI_TRB_TYPE_NEGOTIATE_BW:
+ case XHCI_TRB_TYPE_SET_LATENCY_TOL:
+ case XHCI_TRB_TYPE_GET_PORT_BW:
+ case XHCI_TRB_TYPE_FORCE_HEADER:
+ case XHCI_TRB_TYPE_NOOP_CMD:
+ printf("slot %u c %u\n",
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+
+ case XHCI_TRB_EVENT_TRANSFER:
+ printf("%s(%u) slot %u ep %u ed %u c %u remlen %u ptr %016"
+ PRIx64"\n",
+ str_trberr(XHCI_TRB_2_ERROR_GET(trb_2)),
+ XHCI_TRB_2_ERROR_GET(trb_2),
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ XHCI_TRB_3_EP_GET(trb_3),
+ _B(XHCI_TRB_3_ED_BIT & trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3),
+ XHCI_TRB_2_REM_GET(trb_2),
+ trb_0);
+ break;
+ case XHCI_TRB_EVENT_CMD_COMPLETE:
+ printf("%s(%u) slot %u vf %u c %u param %u cmd %016"
+ PRIx64"\n",
+ str_trberr(XHCI_TRB_2_ERROR_GET(trb_2)),
+ XHCI_TRB_2_ERROR_GET(trb_2),
+ XHCI_TRB_3_SLOT_GET(trb_3),
+ XHCI_TRB_3_VFID_GET(trb_3),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3),
+ XHCI_TRB_2_REM_GET(trb_2),
+ trb_0);
+ break;
+ case XHCI_TRB_EVENT_PORT_STS_CHANGE:
+ printf("%s(%u) port %u c %u\n",
+ str_trberr(XHCI_TRB_2_ERROR_GET(trb_2)),
+ XHCI_TRB_2_ERROR_GET(trb_2),
+ (uint32_t)((trb_0 >> 24) & 0xff),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ case XHCI_TRB_EVENT_HOST_CTRL:
+ case XHCI_TRB_EVENT_BW_REQUEST:
+ case XHCI_TRB_EVENT_DOORBELL:
+ case XHCI_TRB_EVENT_DEVICE_NOTIFY:
+ case XHCI_TRB_EVENT_MFINDEX_WRAP:
+ printf("%s(%u) c %u\n",
+ str_trberr(XHCI_TRB_2_ERROR_GET(trb_2)),
+ XHCI_TRB_2_ERROR_GET(trb_2),
+ _B(XHCI_TRB_3_CYCLE_BIT & trb_3));
+ break;
+ default:
+ printf("\n");
+ break;
+ };
+}
+
+static void __used
+xhci_dump_trb(int dbglvl, const struct xhci_trb * const trb)
+{
+ xhci_dump_trbn(dbglvl, trb->trb_0, trb->trb_2, trb->trb_3);
+}
+
+/* from umassvar.h */
+#define UR_BBB_GET_MAX_LUN 0xfe
+#define UR_BBB_RESET 0xff /* Bulk-Only reset */
+
+static struct tbl_t reqtbl[] = {
+ TBLELEM(UR_GET_STATUS),
+ TBLELEM(UR_CLEAR_FEATURE),
+ TBLELEM(UR_SET_FEATURE),
+ TBLELEM(UR_SET_ADDRESS),
+ TBLELEM(UR_GET_DESCRIPTOR),
+ TBLELEM(UR_SET_DESCRIPTOR),
+ TBLELEM(UR_GET_CONFIG),
+ TBLELEM(UR_SET_CONFIG),
+ TBLELEM(UR_GET_INTERFACE),
+ TBLELEM(UR_SET_INTERFACE),
+ TBLELEM(UR_SYNCH_FRAME),
+ TBLELEM(UR_SET_ENCRYPTION),
+ TBLELEM(UR_GET_ENCRYPTION),
+ TBLELEM(UR_SET_HANDSHAKE),
+ TBLELEM(UR_GET_HANDSHAKE),
+ TBLELEM(UR_SET_CONNECTION),
+ TBLELEM(UR_SET_SECURITY_DATA),
+ TBLELEM(UR_GET_SECURITY_DATA),
+ TBLELEM(UR_SET_WUSB_DATA),
+ TBLELEM(UR_LOOPBACK_DATA_WRITE),
+ TBLELEM(UR_LOOPBACK_DATA_READ),
+ TBLELEM(UR_SET_INTERFACE_DS),
+ TBLELEM(UR_SET_SEL),
+ TBLELEM(UR_SET_ISOCH_DELAY),
+ TBLELEM(UR_BBB_GET_MAX_LUN),
+ TBLELEM(UR_BBB_RESET)
+};
+
+static struct tbl_t desctbl[] = {
+ TBLELEM(UDESC_DEVICE),
+ TBLELEM(UDESC_CONFIG),
+ TBLELEM(UDESC_STRING),
+ TBLELEM(UDESC_INTERFACE),
+ TBLELEM(UDESC_ENDPOINT),
+ TBLELEM(UDESC_DEVICE_QUALIFIER),
+ TBLELEM(UDESC_OTHER_SPEED_CONFIGURATION),
+ TBLELEM(UDESC_INTERFACE_POWER),
+ TBLELEM(UDESC_OTG),
+ TBLELEM(UDESC_DEBUG),
+ TBLELEM(UDESC_INTERFACE_ASSOC),
+ TBLELEM(UDESC_BOS),
+ TBLELEM(UDESC_DEVICE_CAPABILITY),
+ TBLELEM(UDESC_CS_DEVICE),
+ TBLELEM(UDESC_CS_CONFIG),
+ TBLELEM(UDESC_CS_STRING),
+ TBLELEM(UDESC_CS_INTERFACE),
+ TBLELEM(UDESC_CS_ENDPOINT),
+ TBLELEM(UDESC_HUB),
+ TBLELEM(UDESC_SSHUB),
+ TBLELEM(UDESC_SSEP_COMPANION),
+ TBLELEM(UDESC_SSP_ISOCHEP_COMPANION)
+};
+
+static struct tbl_t uftbl[] = {
+ TBLELEM(UF_ENDPOINT_HALT),
+ TBLELEM(UF_INTERFACE_FUNCTION_SUSPEND),
+ TBLELEM(UF_DEVICE_REMOTE_WAKEUP),
+ TBLELEM(UF_TEST_MODE),
+ TBLELEM(UF_DEVICE_B_HNP_ENABLE),
+ TBLELEM(UF_DEVICE_A_HNP_SUPPORT),
+ TBLELEM(UF_DEVICE_A_ALT_HNP_SUPPORT),
+ TBLELEM(UF_DEVICE_WUSB_DEVICE),
+ TBLELEM(UF_DEVICE_U1_ENABLE),
+ TBLELEM(UF_DEVICE_U2_ENABLE),
+ TBLELEM(UF_DEVICE_LTM_ENABLE),
+ TBLELEM(UF_DEVICE_B3_NTF_HOST_SEL),
+ TBLELEM(UF_DEVICE_B3_RESP_ENABLE),
+ TBLELEM(UF_DEVICE_LDM_ENABLE)
+};
+
+static struct tbl_t uhrtbl[] = {
+ TBLELEM(UR_GET_BUS_STATE),
+ TBLELEM(UR_CLEAR_TT_BUFFER),
+ TBLELEM(UR_RESET_TT),
+ TBLELEM(UR_GET_TT_STATE),
+ TBLELEM(UR_STOP_TT)
+};
+
+static struct tbl_t uhftbl[] = {
+// TBLELEM(UHF_C_HUB_LOCAL_POWER),
+// TBLELEM(UHF_C_HUB_OVER_CURRENT),
+ TBLELEM(UHF_PORT_CONNECTION),
+ TBLELEM(UHF_PORT_ENABLE),
+ TBLELEM(UHF_PORT_SUSPEND),
+ TBLELEM(UHF_PORT_OVER_CURRENT),
+ TBLELEM(UHF_PORT_RESET),
+ TBLELEM(UHF_PORT_POWER),
+ TBLELEM(UHF_PORT_LOW_SPEED),
+ TBLELEM(UHF_PORT_L1),
+ TBLELEM(UHF_C_PORT_CONNECTION),
+ TBLELEM(UHF_C_PORT_ENABLE),
+ TBLELEM(UHF_C_PORT_SUSPEND),
+ TBLELEM(UHF_C_PORT_OVER_CURRENT),
+ TBLELEM(UHF_C_PORT_RESET),
+ TBLELEM(UHF_PORT_TEST),
+ TBLELEM(UHF_PORT_INDICATOR),
+ TBLELEM(UHF_C_PORT_L1)
+};
+
+static const char *
+str_reqtype(int key)
+{
+ TBLLOOKUP(reqtbl, 3);
+}
+
+static const char *
+str_desctype(int key)
+{
+ TBLLOOKUP(desctbl, 6);
+}
+
+static const char *
+str_uftype(int key)
+{
+ TBLLOOKUP(uftbl, 3);
+}
+
+static const char * __used
+str_uhrtype(int key)
+{
+ TBLLOOKUP(uhrtbl, 3);
+}
+
+static const char *
+str_uhftype(int key)
+{
+ TBLLOOKUP(uhftbl, 4);
+}
+
+static void __used
+xhci_dump_desc(int dbglvl, void *p)
+{
+ usb_device_descriptor_t *ud = p;
+
+ switch (ud->bDescriptorType) {
+ case UDESC_DEVICE:
+ printf("%04x class %u subc %u proto %u mps %u noconf %u",
+ UGETW(ud->bcdUSB),
+ ud->bDeviceClass,
+ ud->bDeviceSubClass,
+ ud->bDeviceProtocol,
+ ud->bMaxPacketSize,
+ ud->bNumConfigurations);
+ break;
+ case UDESC_CONFIG: {
+ usb_config_descriptor_t *ucd = p;
+ printf("len %u noiface %u confval %u iconf %u attr %02x pwr %u",
+ UGETW(ucd->wTotalLength),
+ ucd->bNumInterface,
+ ucd->bConfigurationValue,
+ ucd->iConfiguration,
+ ucd->bmAttributes,
+ ucd->bMaxPower);
+ break;
+ }
+ case UDESC_STRING:
+ case UDESC_ENDPOINT:
+ case UDESC_BOS:
+ printf("notyet");
+ break;
+ case UDESC_HUB: {
+ usb_hub_descriptor_t *uhd = p;
+ printf("nports %u hubchar %04x pwrdelay %u cur %u",
+ uhd->bNbrPorts,
+ UGETW(uhd->wHubCharacteristics),
+ uhd->bPwrOn2PwrGood,
+ uhd->bHubContrCurrent);
+ break;
+ }
+ case UDESC_SSHUB:
+ printf("notyet");
+ break;
+ case UDESC_SSEP_COMPANION: {
+ usb_ssep_companion_descriptor_t *ussepd = p;
+ printf("maxburst %u attr %02x b/i %u",
+ ussepd->bMaxBurst,
+ ussepd->bmAttributes,
+ UGETW(ussepd->wBytesPerInterval));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void __used
+xhci_dump_reply(int dbglvl, usbd_xfer_handle xfer)
+{
+ usb_device_request_t *udr;
+
+ if (xhcidebug <= dbglvl)
+ return;
+
+ if (xfer == NULL)
+ return;
+
+ udr = &xfer->request;
+ if (udr->bRequest != UR_GET_DESCRIPTOR)
+ return;
+ switch (UGETW(udr->wValue) >> 8) {
+ case UDESC_CONFIG: /* conf, ifassoc, if, ep, ssep companion */
+ case UDESC_DEVICE:
+ case UDESC_BOS: /* bos, usb2 ext, ss dev cap, container id */
+ //case UDESC_STRING:
+ case UDESC_HUB:
+ case UDESC_SSHUB:
+ break;
+ default:
+ return;
+ }
+
+ int remlen = UGETW(udr->wLength);
+ uint8_t *ud = KERNADDR(&xfer->dmabuf, 0);
+ int comma = 0;
+ usb_device_descriptor_t *udd;
+ printf("getdesc: len %u: ", remlen);
+ while (remlen > 0) {
+ udd = (usb_device_descriptor_t *)ud;
+ if (udd->bLength == 0)
+ break;
+ printf("%s%s(%u) len %u<",
+ comma ? ">, " : "",
+ str_desctype(udd->bDescriptorType),
+ udd->bDescriptorType,
+ udd->bLength);
+ xhci_dump_desc(dbglvl, ud);
+ comma = 1;
+ remlen -= udd->bLength;
+ ud += udd->bLength;
+ }
+ printf("%s\n", comma ? ">" : "");
+}
+
+static void __used
+xhci_dump_req(int dbglvl, void *p)
+{
+ usb_device_request_t *udr = p;
+ const char *type, *rcpt;
+
+ if (udr == NULL)
+ return;
+
+ if (xhcidebug <= dbglvl)
+ return;
+
+ switch (UT_GET_TYPE(udr->bmRequestType)) {
+ case UT_STANDARD: type = "STAND"; break;
+ case UT_CLASS: type = "CLASS"; break;
+ case UT_VENDOR: type = "VENDOR"; break;
+ default: type = "unknown"; break;
+ }
+ switch (UT_GET_RECIPIENT(udr->bmRequestType)) {
+ case UT_DEVICE: rcpt = "DEV"; break;
+ case UT_INTERFACE: rcpt = "IFACE"; break;
+ case UT_ENDPOINT: rcpt = "ENDP"; break;
+ case UT_OTHER: rcpt = "OTHER"; break;
+ default: rcpt = "unknown"; break;
+ }
+ if (UT_GET_TYPE(udr->bmRequestType) != UT_STANDARD &&
+ UT_GET_TYPE(udr->bmRequestType) != UT_CLASS) {
+ /* vendor specific request, no analysis any more */
+ printf("%02x %s,%s,%s val %04x idx %04x len %04x\n",
+ udr->bRequest,
+ UT_GET_DIR(udr->bmRequestType) == UT_WRITE ?
+ "OUT" : "IN",
+ type, rcpt,
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ return;
+ }
+ printf("%s(%u) %s,%s,%s",
+ str_reqtype(udr->bRequest), udr->bRequest,
+ UT_GET_DIR(udr->bmRequestType) == UT_WRITE ? "OUT" : "IN",
+ type, rcpt);
+
+ switch (udr->bRequest) {
+ case UR_GET_DESCRIPTOR:
+ printf(" %s(0x%04x) idx %04x len %u\n",
+ str_desctype(UGETW(udr->wValue) >> 8),
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ break;
+ case UR_CLEAR_FEATURE:
+ if (UT_GET_RECIPIENT(udr->bmRequestType) == UT_OTHER) {
+ printf(" %s(%u) idx %u len %u\n",
+ str_uhftype(UGETW(udr->wValue) & 0xff),
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ } else {
+ printf(" %s(%u) idx %04x len %u\n",
+ str_uftype(UGETW(udr->wValue) & 0xff),
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ }
+ break;
+ case UR_SET_FEATURE:
+ if (UT_GET_RECIPIENT(udr->bmRequestType) == UT_OTHER) {
+ printf(" %s(%u) idx %u len %u\n",
+ str_uhftype(UGETW(udr->wValue) & 0xff),
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ } else {
+ printf(" %s(%u) idx %04x len %u\n",
+ str_uftype(UGETW(udr->wValue) & 0xff),
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ }
+ break;
+ case UR_SET_ADDRESS:
+ default:
+ printf(" val %04x idx %04x len %04x\n",
+ UGETW(udr->wValue),
+ UGETW(udr->wIndex),
+ UGETW(udr->wLength));
+ break;
+ }
+}
+
+
+static void __used
+xhci_dump_portsc(int dbglvl, uint32_t v)
+{
+ char sbuf[128];
+
+ if (xhcidebug <= dbglvl)
+ return;
+
+ snprintb(sbuf, sizeof sbuf, "\177\020"
+ "b\037WPR\0b\036DR\0b\033WOE\0b\032WDE\0b\031WCE\0"
+ "b\030CAS\0b\027CEC\0b\026PLC\0b\025PRC\0"
+ "b\024OCC\0b\023WRC\0b\022PEC\0b\021CSC\0b\020LWS\0"
+ "f\016\2PIC\0f\012\4SPEED\0b\011PP\0f\5\4PLS\0"
+ "b\4PR\0b\3OCA\0b\1PED\0b\0CCS\0\0",
+ v);
+ printf("%s\n", sbuf);
+}
+
+#undef TBLELEM
+#undef TBLLOOKUP
+#undef _B
+
+#endif /* XHCI_DEBUG */
--- xhcireg.h.orig 2014-09-09 11:24:29.000000000 +0900
+++ xhcireg.h 2014-09-16 11:02:28.000000000 +0900
@@ -266,6 +274,8 @@
#define XHCI_TRB_3_FRID_SET(x) (((x) & 0x7FF) << 20)
#define XHCI_TRB_3_ISO_SIA_BIT (1U << 31)
#define XHCI_TRB_3_SUSP_EP_BIT (1U << 23)
+#define XHCI_TRB_3_VFID_GET(x) (((x) >> 16) & 0xFF)
+#define XHCI_TRB_3_VFID_SET(x) (((x) & 0xFF) << 16)
#define XHCI_TRB_3_SLOT_GET(x) (((x) >> 24) & 0xFF)
#define XHCI_TRB_3_SLOT_SET(x) (((x) & 0xFF) << 24)
--- usb.h.orig 2014-09-09 11:25:20.000000000 +0900
+++ usb.h 2014-09-18 19:05:17.000000000 +0900
@@ -241,6 +165,8 @@
#define UDESC_OTG 0x09
#define UDESC_DEBUG 0x0a
#define UDESC_INTERFACE_ASSOC 0x0b
+#define UDESC_BOS 0x0f
+#define UDESC_DEVICE_CAPABILITY 0x10
#define UDESC_CS_DEVICE 0x21 /* class specific */
#define UDESC_CS_CONFIG 0x22
#define UDESC_CS_STRING 0x23
@@ -248,23 +174,47 @@
#define UDESC_CS_ENDPOINT 0x25
#define UDESC_HUB 0x29
#define UDESC_SSHUB 0x2a
+#define UDESC_SSEP_COMPANION 0x30 /* SUPERSPEED_USB_ENDPOINT_COMPANION */
+#define UDESC_SSP_ISOCHEP_COMPANION 0x31
+ /* SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION */
#define UR_SET_DESCRIPTOR 0x07
#define UR_GET_CONFIG 0x08
#define UR_SET_CONFIG 0x09
#define UR_GET_INTERFACE 0x0a
#define UR_SET_INTERFACE 0x0b
#define UR_SYNCH_FRAME 0x0c
+#define UR_SET_ENCRYPTION 0x0d
+#define UR_GET_ENCRYPTION 0x0e
+#define UR_SET_HANDSHAKE 0x0f
+#define UR_GET_HANDSHAKE 0x10
+#define UR_SET_CONNECTION 0x11
+#define UR_SET_SECURITY_DATA 0x12
+#define UR_GET_SECURITY_DATA 0x13
+#define UR_SET_WUSB_DATA 0x14
+#define UR_LOOPBACK_DATA_WRITE 0x15
+#define UR_LOOPBACK_DATA_READ 0x16
+#define UR_SET_INTERFACE_DS 0x17
+#define UR_SET_SEL 0x30
+#define UR_SET_ISOCH_DELAY 0x31
/*
* Feature selectors. USB 2.0 spec, table 9-6 and OTG and EH suppliment,
* table 6-2
*/
#define UF_ENDPOINT_HALT 0
+#define UF_INTERFACE_FUNCTION_SUSPEND 0
#define UF_DEVICE_REMOTE_WAKEUP 1
#define UF_TEST_MODE 2
#define UF_DEVICE_B_HNP_ENABLE 3
#define UF_DEVICE_A_HNP_SUPPORT 4
#define UF_DEVICE_A_ALT_HNP_SUPPORT 5
+#define UF_DEVICE_WUSB_DEVICE 6
+#define UF_DEVICE_U1_ENABLE 48
+#define UF_DEVICE_U2_ENABLE 49
+#define UF_DEVICE_LTM_ENABLE 50
+#define UF_DEVICE_B3_NTF_HOST_SEL 51
+#define UF_DEVICE_B3_RESP_ENABLE 52
+#define UF_DEVICE_LDM_ENABLE 53
#define USB_MAX_IPACKET 8 /* maximum size of the initial packet
*/
@@ -371,6 +321,15 @@
typedef struct {
uByte bLength;
+ uByte bDescriptorType; /* 0x30 */
+ uByte bMaxBurst;
+ uByte bmAttributes;
+ uWord wBytesPerInterval;
+} UPACKED usb_ssep_companion_descriptor_t;
+#define USB_SSEP_COMPANION_DESCRIPTOR_SIZE 6
+
+typedef struct {
+ uByte bLength;
uByte bDescriptorType;
uWord bString[126];
} UPACKED usb_string_descriptor_t;
Home |
Main Index |
Thread Index |
Old Index