kernel/usb4bsd: Update xhci to r278477
authorMarkus Pfeiffer <markus.pfeiffer@morphism.de>
Sat, 21 Feb 2015 23:43:47 +0000 (23:43 +0000)
committerMarkus Pfeiffer <markus.pfeiffer@morphism.de>
Sat, 21 Feb 2015 23:43:47 +0000 (23:43 +0000)
sys/bus/u4b/controller/xhci.c
sys/bus/u4b/controller/xhci.h
sys/bus/u4b/usb_core.h

index d5df2ee..a750cc0 100644 (file)
@@ -1,3 +1,4 @@
+/* $FreeBSD: head/sys/dev/usb/controller/xhci.c 278477 2015-02-09 21:47:12Z hselasky $ */
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
  *
@@ -345,34 +346,11 @@ xhci_start_controller(struct xhci_softc *sc)
 
        DPRINTF("\n");
 
-       sc->sc_capa_off = 0;
-       sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
-       sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
-       sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
-
-       DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
-       DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
-       DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
-
        sc->sc_event_ccs = 1;
        sc->sc_event_idx = 0;
        sc->sc_command_ccs = 1;
        sc->sc_command_idx = 0;
 
-       DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
-
-       temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
-
-       DPRINTF("HCS0 = 0x%08x\n", temp);
-
-       if (XHCI_HCS0_CSZ(temp)) {
-               sc->sc_ctx_is_64_byte = 1;
-               device_printf(sc->sc_bus.parent, "64 byte context size.\n");
-       } else {
-               sc->sc_ctx_is_64_byte = 0;
-               device_printf(sc->sc_bus.parent, "32 byte context size.\n");
-       }
-
        /* Reset controller */
        XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
 
@@ -487,8 +465,12 @@ xhci_start_controller(struct xhci_softc *sc)
 
        XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(temp));
 
+       /* Check if we should use the default IMOD value */
+       if (sc->sc_imod_default == 0)
+               sc->sc_imod_default = XHCI_IMOD_DEFAULT;
+
        /* Setup interrupt rate */
-       XWRITE4(sc, runt, XHCI_IMOD(0), XHCI_IMOD_DEFAULT);
+       XWRITE4(sc, runt, XHCI_IMOD(0), sc->sc_imod_default);
 
        usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
 
@@ -507,7 +489,7 @@ xhci_start_controller(struct xhci_softc *sc)
        XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr);
        XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
 
-       addr = (uint64_t)buf_res.physaddr;
+       addr = buf_res.physaddr;
 
        DPRINTF("ERSTBA(0)=0x%016llx\n", (unsigned long long)addr);
 
@@ -593,6 +575,10 @@ xhci_halt_controller(struct xhci_softc *sc)
 usb_error_t
 xhci_init(struct xhci_softc *sc, device_t self)
 {
+       uint32_t temp;
+
+       DPRINTF("\n");
+
        /* initialise some bus fields */
        sc->sc_bus.parent = self;
 
@@ -606,9 +592,38 @@ xhci_init(struct xhci_softc *sc, device_t self)
        sc->sc_bus.devices = sc->sc_devices;
        sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
 
-       /* setup command queue mutex and condition varible */
-       cv_init(&sc->sc_cmd_cv, "CMDQ");
-       lockinit(&sc->sc_cmd_lock, "CMDQ lock", 0, 0);
+       /* set default cycle state in case of early interrupts */
+       sc->sc_event_ccs = 1;
+       sc->sc_command_ccs = 1;
+
+       /* set up bus space offsets */
+       sc->sc_capa_off = 0;
+       sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
+       sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
+       sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
+
+       DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
+       DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
+       DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
+
+       DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+
+       temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+
+       DPRINTF("HCS0 = 0x%08x\n", temp);
+
+       /* set up context size */
+       if (XHCI_HCS0_CSZ(temp)) {
+               sc->sc_ctx_is_64_byte = 1;
+       } else {
+               sc->sc_ctx_is_64_byte = 0;
+       }
+
+       /* get DMA bits */
+       sc->sc_bus.dma_bits = XHCI_HCS0_AC64(temp) ? 64 : 32;
+
+       device_printf(self, "%d bytes context size, %d-bit DMA\n",
+           sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits);
 
        /* get all DMA memory */
        if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -616,10 +631,14 @@ xhci_init(struct xhci_softc *sc, device_t self)
                return (ENOMEM);
        }
 
-        sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
-        sc->sc_config_msg[0].bus = &sc->sc_bus;
-        sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
-        sc->sc_config_msg[1].bus = &sc->sc_bus;
+       /* setup command queue mutex and condition varible */
+       cv_init(&sc->sc_cmd_cv, "CMDQ");
+       lockinit(&sc->sc_cmd_lock, "CMDQ lock", 0, LK_CANRECURSE);
+
+       sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
+       sc->sc_config_msg[0].bus = &sc->sc_bus;
+       sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
+       sc->sc_config_msg[1].bus = &sc->sc_bus;
 
        return (0);
 }
@@ -1092,7 +1111,7 @@ xhci_interrupt_poll(struct xhci_softc *sc)
         * register.
         */
 
-       addr = (uint32_t)buf_res.physaddr;
+       addr = buf_res.physaddr;
        addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[i];
 
        /* try to clear busy bit */
@@ -1210,8 +1229,20 @@ retry:
                 */
                if (timeout == 0 &&
                    xhci_reset_command_queue_locked(sc) == 0) {
-                       timeout = 1;
-                       goto retry;
+                       temp = le32toh(trb->dwTrb3);
+
+                       /*
+                        * Avoid infinite XHCI reset loops if the set
+                        * address command fails to respond due to a
+                        * non-enumerating device:
+                        */
+                       if (XHCI_TRB_3_TYPE_GET(temp) == XHCI_TRB_TYPE_ADDRESS_DEVICE &&
+                           (temp & XHCI_TRB_3_BSR_BIT) == 0) {
+                               DPRINTF("Set address timeout\n");
+                       } else {
+                               timeout = 1;
+                               goto retry;
+                       }
                } else {
                        DPRINTF("Controller reset!\n");
                        usb_bus_reset_async_locked(&sc->sc_bus);
@@ -1570,24 +1601,26 @@ void
 xhci_interrupt(struct xhci_softc *sc)
 {
        uint32_t status;
+       uint32_t temp;
 
        USB_BUS_LOCK(&sc->sc_bus);
 
        status = XREAD4(sc, oper, XHCI_USBSTS);
-       if (status == 0) {
-               goto done;
+
+       /* acknowledge interrupts, if any */
+       if (status != 0) {
+               XWRITE4(sc, oper, XHCI_USBSTS, status);
+               DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
        }
-       
-       /* acknowledge interrupts */
 
-       XWRITE4(sc, oper, XHCI_USBSTS, status);
+       temp = XREAD4(sc, runt, XHCI_IMAN(0));
 
-       DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+       /* force clearing of pending interrupts */
+       if (temp & XHCI_IMAN_INTR_PEND)
+               XWRITE4(sc, runt, XHCI_IMAN(0), temp);
  
-       if (status & XHCI_STS_EINT) {
-               /* check for event(s) */
-               xhci_interrupt_poll(sc);
-       }
+       /* check for event(s) */
+       xhci_interrupt_poll(sc);
 
        if (status & (XHCI_STS_PCD | XHCI_STS_HCH |
            XHCI_STS_HSE | XHCI_STS_HCE)) {
@@ -1611,7 +1644,6 @@ xhci_interrupt(struct xhci_softc *sc)
                           __func__);
                }
        }
-done:
        USB_BUS_UNLOCK(&sc->sc_bus);
 }
 
@@ -1750,7 +1782,8 @@ restart:
                        /* check wLength */
                        if (td->td_trb[0].qwTrb0 &
                           htole64(XHCI_TRB_0_WLENGTH_MASK)) {
-                               if (td->td_trb[0].qwTrb0 & htole64(1))
+                               if (td->td_trb[0].qwTrb0 &
+                                   htole64(XHCI_TRB_0_DIR_IN_MASK))
                                        dword |= XHCI_TRB_3_TRT_IN;
                                else
                                        dword |= XHCI_TRB_3_TRT_OUT;
@@ -1823,31 +1856,34 @@ restart:
                                            XHCI_TRB_3_ISO_SIA_BIT;
                                }
                                if (temp->direction == UE_DIR_IN)
-                                       dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+                                       dword |= XHCI_TRB_3_ISP_BIT;
                                break;
                        case XHCI_TRB_TYPE_DATA_STAGE:
                                dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE) |
-                                   XHCI_TRB_3_TBC_SET(temp->tbc) |
-                                   XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE);
                                if (temp->direction == UE_DIR_IN)
                                        dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+                               /*
+                                * Section 3.2.9 in the XHCI
+                                * specification about control
+                                * transfers says that we should use a
+                                * normal-TRB if there are more TRBs
+                                * extending the data-stage
+                                * TRB. Update the "trb_type".
+                                */
+                               temp->trb_type = XHCI_TRB_TYPE_NORMAL;
                                break;
                        case XHCI_TRB_TYPE_STATUS_STAGE:
                                dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE) |
-                                   XHCI_TRB_3_TBC_SET(temp->tbc) |
-                                   XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE);
                                if (temp->direction == UE_DIR_IN)
                                        dword |= XHCI_TRB_3_DIR_IN;
                                break;
                        default:        /* XHCI_TRB_TYPE_NORMAL */
                                dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL) |
-                                   XHCI_TRB_3_TBC_SET(temp->tbc) |
-                                   XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+                                   XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL);
                                if (temp->direction == UE_DIR_IN)
-                                       dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+                                       dword |= XHCI_TRB_3_ISP_BIT;
                                break;
                        }
                        td->td_trb[x].dwTrb3 = htole32(dword);
@@ -2076,7 +2112,8 @@ xhci_setup_generic_chain(struct usb_xfer *xfer)
                mult = 1;
                temp.isoc_delta = 0;
                temp.isoc_frame = 0;
-               temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE;
+               temp.trb_type = xfer->flags_int.control_did_data ?
+                   XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE;
        } else {
                x = 0;
                mult = 1;
@@ -2232,7 +2269,14 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
                xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
                xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
        } else {
-               xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
+               /*
+                * Some hardware requires that we drop the endpoint
+                * context before adding it again:
+                */
+               xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0,
+                   mask & XHCI_INCTX_NON_CTRL_MASK);
+
+               /* Add new endpoint context */
                xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
 
                /* find most significant set bit */
@@ -2244,15 +2288,19 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
                /* adjust */
                x--;
 
-               /* figure out maximum */
-               if (x > sc->sc_hw.devs[index].context_num) {
+               /* figure out the maximum number of contexts */
+               if (x > sc->sc_hw.devs[index].context_num)
                        sc->sc_hw.devs[index].context_num = x;
-                       temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
-                       temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
-                       temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
-                       xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
-               }
+               else
+                       x = sc->sc_hw.devs[index].context_num;
+
+               /* update number of contexts */
+               temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
+               temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
+               temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
+               xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
        }
+       usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc);
        return (0);
 }
 
@@ -2357,10 +2405,14 @@ xhci_configure_endpoint(struct usb_device *udev,
            XHCI_EPCTX_1_MAXB_SET(max_packet_count) |
            XHCI_EPCTX_1_MAXP_SIZE_SET(max_packet_size);
 
-       if ((udev->parent_hs_hub != NULL) || (udev->address != 0)) {
-               if (type != UE_ISOCHRONOUS)
-                       temp |= XHCI_EPCTX_1_CERR_SET(3);
-       }
+       /*
+        * Always enable the "three strikes and you are gone" feature
+        * except for ISOCHRONOUS endpoints. This is suggested by
+        * section 4.3.3 in the XHCI specification about device slot
+        * initialisation.
+        */
+       if (type != UE_ISOCHRONOUS)
+               temp |= XHCI_EPCTX_1_CERR_SET(3);
 
        switch (type) {
        case UE_CONTROL:
@@ -2663,24 +2715,23 @@ xhci_alloc_device_ext(struct usb_device *udev)
                goto error;
        }
 
-       pc = &sc->sc_hw.devs[index].endpoint_pc;
-       pg = &sc->sc_hw.devs[index].endpoint_pg;
+       /* initialize all endpoint LINK TRBs */
 
-       /* need to initialize the page cache */
-       pc->tag_parent = sc->sc_bus.dma_parent_tag;
+       for (i = 0; i != XHCI_MAX_ENDPOINTS; i++) {
 
-       if (usb_pc_alloc_mem(pc, pg,
-           sizeof(struct xhci_dev_endpoint_trbs), XHCI_PAGE_SIZE)) {
-               goto error;
-       }
+               pc = &sc->sc_hw.devs[index].endpoint_pc[i];
+               pg = &sc->sc_hw.devs[index].endpoint_pg[i];
 
-       /* initialise all endpoint LINK TRBs */
+               /* need to initialize the page cache */
+               pc->tag_parent = sc->sc_bus.dma_parent_tag;
 
-       for (i = 0; i != XHCI_MAX_ENDPOINTS; i++) {
+               if (usb_pc_alloc_mem(pc, pg,
+                   sizeof(struct xhci_dev_endpoint_trbs), XHCI_TRB_ALIGN)) {
+                       goto error;
+               }
 
                /* lookup endpoint TRB ring */
-               usbd_get_page(pc, (uintptr_t)&
-                   ((struct xhci_dev_endpoint_trbs *)0)->trb[i][0], &buf_ep);
+               usbd_get_page(pc, 0, &buf_ep);
 
                /* get TRB pointer */
                trb = buf_ep.buffer;
@@ -2694,9 +2745,9 @@ xhci_alloc_device_ext(struct usb_device *udev)
                trb->dwTrb2 = htole32(XHCI_TRB_2_IRQ_SET(0));
                trb->dwTrb3 = htole32(XHCI_TRB_3_CYCLE_BIT |
                    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK));
-       }
 
-       usb_pc_cpu_flush(pc);
+               usb_pc_cpu_flush(pc);
+       }
 
        xhci_set_slot_pointer(sc, index, buf_dev.physaddr);
 
@@ -2713,13 +2764,15 @@ xhci_free_device_ext(struct usb_device *udev)
 {
        struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
        uint8_t index;
+       uint8_t i;
 
        index = udev->controller_slot_id;
        xhci_set_slot_pointer(sc, index, 0);
 
        usb_pc_free_mem(&sc->sc_hw.devs[index].device_pc);
        usb_pc_free_mem(&sc->sc_hw.devs[index].input_pc);
-       usb_pc_free_mem(&sc->sc_hw.devs[index].endpoint_pc);
+       for (i = 0; i != XHCI_MAX_ENDPOINTS; i++)
+               usb_pc_free_mem(&sc->sc_hw.devs[index].endpoint_pc[i]);
 }
 
 static struct xhci_endpoint_ext *
@@ -2740,10 +2793,9 @@ xhci_get_endpoint_ext(struct usb_device *udev, struct usb_endpoint_descriptor *e
 
        index = udev->controller_slot_id;
 
-       pc = &sc->sc_hw.devs[index].endpoint_pc;
+       pc = &sc->sc_hw.devs[index].endpoint_pc[epno];
 
-       usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->
-           trb[epno][0], &buf_ep);
+       usbd_get_page(pc, 0, &buf_ep);
 
        pepext = &sc->sc_hw.devs[index].endp[epno];
        pepext->page_cache = pc;
index 074e568..aeb760f 100644 (file)
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/dev/usb/controller/xhci.h 276799 2015-01-08 00:12:54Z hselasky $ */
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -192,6 +192,7 @@ struct xhci_stream_ctx {
 
 struct xhci_trb {
        volatile uint64_t       qwTrb0;
+#define        XHCI_TRB_0_DIR_IN_MASK          (0x80ULL << 0)
 #define        XHCI_TRB_0_WLENGTH_MASK         (0xFFFFULL << 48)
        volatile uint32_t       dwTrb2;
 #define        XHCI_TRB_2_ERROR_GET(x)         (((x) >> 24) & 0xFF)
@@ -315,15 +316,27 @@ struct xhci_trb {
 } __aligned(4);
 
 struct xhci_dev_endpoint_trbs {
-       struct xhci_trb         trb[XHCI_MAX_ENDPOINTS]
-           [(XHCI_MAX_STREAMS * XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS];
+       struct xhci_trb         trb[(XHCI_MAX_STREAMS *
+           XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS];
 };
 
-#define        XHCI_TD_PAGE_NBUF       17      /* units, room enough for 64Kbytes */
-#define        XHCI_TD_PAGE_SIZE       4096    /* bytes */
-#define        XHCI_TD_PAYLOAD_MAX     (XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1))
+#if (USB_PAGE_SIZE < 4096)
+#error "The XHCI driver needs a pagesize above or equal to 4K"
+#endif
+
+/* Define the maximum payload which we will handle in a single TRB */
+#define        XHCI_TD_PAYLOAD_MAX     65536   /* bytes */
+
+/* Define the maximum payload of a single scatter-gather list element */
+#define        XHCI_TD_PAGE_SIZE \
+  ((USB_PAGE_SIZE < XHCI_TD_PAYLOAD_MAX) ? USB_PAGE_SIZE : XHCI_TD_PAYLOAD_MAX)
+
+/* Define the maximum length of the scatter-gather list */
+#define        XHCI_TD_PAGE_NBUF \
+  (((XHCI_TD_PAYLOAD_MAX + XHCI_TD_PAGE_SIZE - 1) / XHCI_TD_PAGE_SIZE) + 1)
 
 struct xhci_td {
+       /* one LINK TRB has been added to the TRB array */
        struct xhci_trb         td_trb[XHCI_TD_PAGE_NBUF + 1];
 
 /*
@@ -384,11 +397,11 @@ enum {
 struct xhci_hw_dev {
        struct usb_page_cache   device_pc;
        struct usb_page_cache   input_pc;
-       struct usb_page_cache   endpoint_pc;
+       struct usb_page_cache   endpoint_pc[XHCI_MAX_ENDPOINTS];
 
        struct usb_page         device_pg;
        struct usb_page         input_pg;
-       struct usb_page         endpoint_pg;
+       struct usb_page         endpoint_pg[XHCI_MAX_ENDPOINTS];
 
        struct xhci_endpoint_ext endp[XHCI_MAX_ENDPOINTS];
 
@@ -480,6 +493,7 @@ struct xhci_softc {
        uint16_t                sc_erst_max;
        uint16_t                sc_event_idx;
        uint16_t                sc_command_idx;
+       uint16_t                sc_imod_default;
 
        uint8_t                 sc_event_ccs;
        uint8_t                 sc_command_ccs;
@@ -491,7 +505,8 @@ struct xhci_softc {
        uint8_t                 sc_noscratch;
        /* root HUB device configuration */
        uint8_t                 sc_conf;
-       uint8_t                 sc_hub_idata[2];
+       /* root HUB port event bitmap, max 256 ports */
+       uint8_t                 sc_hub_idata[32];
 
        /* size of context */
        uint8_t                 sc_ctx_is_64_byte;
index 5fef4fc..81f250f 100644 (file)
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_core.h 266394 2014-05-18 09:13:29Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_core.h 278071 2015-02-02 11:06:41Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -100,6 +100,7 @@ struct usb_xfer_flags_int {
                                         * sent */
        uint8_t control_act:1;          /* set if control transfer is active */
        uint8_t control_stall:1;        /* set if control transfer should be stalled */
+       uint8_t control_did_data:1;     /* set if control DATA has been transferred */
 
        uint8_t short_frames_ok:1;      /* filtered version */
        uint8_t short_xfer_ok:1;        /* filtered version */