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