Date: Mon, 2 Aug 2010 18:22:10 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 181738 for review Message-ID: <201008021822.o72IMAVd029633@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181738?ac=10 Change 181738 by hselasky@hselasky_laptop001 on 2010/08/02 18:21:20 USB controller (XHCI): - add code to configure device and endpoint - refactor some structures Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#9 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#11 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#9 (text+ko) ==== @@ -113,6 +113,7 @@ static void xhci_device_done(struct usb_xfer *, usb_error_t); static void xhci_root_intr(struct xhci_softc *); static void xhci_free_device_ext(struct usb_device *udev); +static struct xhci_endpoint_ext *xhci_get_endpoint_ext(struct usb_xfer *xfer); extern struct usb_bus_methods xhci_bus_methods; @@ -1162,7 +1163,6 @@ xfer->td_transfer_cache = td; if (xfer->flags_int.isochronous_xfr) { - uint8_t shift; x = XREAD4(temp.sc, runt, XHCI_MFINDEX); @@ -1171,17 +1171,19 @@ case USB_SPEED_FULL: shift = 3; temp.isoc_delta = 8; /* 1ms */ + x += temp.isoc_delta - 1; + x &= ~(temp.isoc_delta - 1); break; default: shift = usbd_xfer_get_fps_shift(xfer); temp.isoc_delta = 1U << shift; + x += temp.isoc_delta - 1; + x &= ~(temp.isoc_delta - 1); + /* simple frame load balancing */ + x += xfer->endpoint->usb_uframe; break; } - x += temp.isoc_delta - 1; - x &= ~(temp.isoc_delta - 1); - x += xfer->endpoint->usb_uframe; - y = XHCI_MFINDEX_GET(x - xfer->endpoint->isoc_next); if ((xfer->endpoint->is_synced == 0) || @@ -1198,6 +1200,14 @@ DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next); } + /* compute isochronous completion time */ + + y = XHCI_MFINDEX_GET(xfer->endpoint->isoc_next - (x & ~7)); + + xfer->isoc_time_complete = + usb_isoc_time_expand(&temp.sc->sc_bus, x / 8) + + (y / 8) + (((xfer->nframes << shift) + 7) / 8); + x = 0; temp.isoc_frame = xfer->endpoint->isoc_next; temp.trb_type = XHCI_TRB_TYPE_ISOCH; @@ -1344,232 +1354,338 @@ usb_pc_cpu_flush(&sc->sc_hw.ctx_pc); } +static uint8_t +xhci_log2(uint32_t x) +{ + uint8_t retval; + + retval = 0; + while (1) { + if (x == 1) + break; + x >>= 2; + if (x == 0) + break; + retval++; + } + return (retval); +} + static usb_error_t -xhci_alloc_device_ext(struct usb_device *udev) +xhci_configure_endpoint(struct usb_xfer *xfer) { - struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); - struct usb_page_search buf_scp; - struct usb_page_search buf_dev; - struct usb_page_cache *pcd; - struct usb_page *pgd; - struct usb_page_cache *pcs; - struct usb_page *pgs; - struct xhci_dev_ctx *pdctx; - struct usb_device *hubdev; + struct usb_page_search buf_inp; + struct usb_page_search buf_ep; + struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus); + struct xhci_input_dev_ctx *pinp; + struct usb_endpoint_descriptor *edesc; + struct xhci_endpoint_ext *pepext; + struct usb_device *udev; uint64_t addr; uint32_t temp; uint8_t index; - uint8_t failure; - uint8_t i; - uint8_t rh_port; + uint8_t epno; + uint8_t k; + + usbd_get_page(&sc->sc_hw.devs[index].input_pc, 0, &buf_inp); + usbd_get_page(&sc->sc_hw.devs[index].endpoint_pc, 0, &buf_ep); + + pepext = xhci_get_endpoint_ext(xfer); + + udev = xfer->xroot->udev; index = udev->device_index; - failure = 0; + + edesc = xfer->endpoint->edesc; + + epno = edesc->bEndpointAddress; + + if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) + epno |= UE_DIR_IN; + + epno = XHCI_EPNO2EPID(epno); + + if (epno == 0) + return (USB_ERR_INVAL); /* invalid */ + + pinp = buf_inp.buffer; + + XXX; + pinp->ctx_input.dwInCtx0 |= htole32(0xFFFFFFFC); + pinp->ctx_input.dwInCtx1 &= htole32(0x1); - pcd = &sc->sc_hw.devs[index].device_pc; - pgd = &sc->sc_hw.devs[index].device_pg; + temp = XHCI_EPCTX_0_EPSTATE_SET(0) | + XHCI_EPCTX_0_MAXP_STREAMS_SET(0) | + XHCI_EPCTX_0_LSA_SET(0); - /* need to initialize the page cache */ - pcd->tag_parent = sc->sc_bus.dma_parent_tag; + switch (edesc->bmAttributes & UE_XFERTYPE) { + case UE_INTERRUPT: + k = xhci_log2(xfer->interval) + 3; + temp |= XHCI_EPCTX_0_IVAL_SET(k); + break; + case UE_ISOCHRONOUS: + if (udev->speed == USB_SPEED_SUPER) + temp |= XHCI_EPCTX_0_MULT_SET(xfer->max_packet_count); + break; + default: + break; + } - if (usb_pc_alloc_mem(pcd, pgd, sizeof(*pdctx), XHCI_PAGE_SIZE)) - failure = 1; + pinp->ctx_ep[epno - 1].dwEpCtx0 = htole32(temp); - if (failure == 0) { + temp = + XHCI_EPCTX_1_HID_SET(0) | + XHCI_EPCTX_1_MAXB_SET(xfer->max_packet_count) | + XHCI_EPCTX_1_MAXP_SIZE_SET(xfer->max_packet_size); - usbd_get_page(pcd, 0, &buf_dev); + if ((udev->parent_hs_hub != NULL) || (udev->address != 0)) + temp |= XHCI_EPCTX_1_CERR_SET(3); - pdctx = buf_dev.buffer; - addr = buf_dev.physaddr; + switch (edesc->bmAttributes & UE_XFERTYPE) { + case UE_CONTROL: + temp |= XHCI_EPCTX_1_EPTYPE_SET(4); + break; + case UE_ISOCHRONOUS: + temp |= XHCI_EPCTX_1_EPTYPE_SET(1); + break; + case UE_BULK: + temp |= XHCI_EPCTX_1_EPTYPE_SET(2); + break; + default: + temp |= XHCI_EPCTX_1_EPTYPE_SET(3); + break; + } - hubdev = udev; - temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1); + if (edesc->bmAttributes & UE_DIR_IN) + temp |= XHCI_EPCTX_1_EPTYPE_SET(4); - while (hubdev->parent_hub != NULL) { - temp |= (hubdev->port_no & 0xF) << ((hubdev->depth - 1) * 4); - hubdev = hubdev->parent_hub; - } + pinp->ctx_ep[epno - 1].dwEpCtx1 = htole32(temp); - rh_port = hubdev->port_no; + pepext->trb_ccs = 1; + pepext->trb_index = 0; + pepext->trb_halted = 0; - switch (udev->speed) { - case USB_SPEED_LOW: - temp |= XHCI_SCTX_0_SPEED_SET(2); - break; - case USB_SPEED_HIGH: - temp |= XHCI_SCTX_0_SPEED_SET(3); - break; - case USB_SPEED_FULL: - temp |= XHCI_SCTX_0_SPEED_SET(1); - break; - default: - temp |= XHCI_SCTX_0_SPEED_SET(4); - break; - } + for (k = 0; k != XHCI_MAX_TRANSFERS; k++) + pepext->trb[k].dwTrb3 = 0; - if (udev->hub != NULL) - temp |= XHCI_SCTX_0_HUB_SET(1); + usb_pc_cpu_flush(pepext->page_cache); - pdctx->ctx_slot.dwSctx0 = htole32(temp); + addr = XHCI_EPCTX_2_DCS_SET(1) | + (buf_ep.physaddr + (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0]); - temp = XHCI_SCTX_1_RH_PORT_SET(rh_port); + pinp->ctx_ep[epno - 1].qwEpCtx2 = htole64(addr); - if (udev->hub != NULL) - temp |= XHCI_SCTX_1_NUM_PORTS_SET(udev->hub->nports); + temp = XHCI_EPCTX_4_AVG_TRB_LEN_SET() | + XHCI_EPCTX_4_MAX_ESIT_PAYLOAD_SET(); - switch (udev->speed) { - case USB_SPEED_LOW: - case USB_SPEED_HIGH: - case USB_SPEED_FULL: - default: - temp |= XHCI_SCTX_1_MAX_EL_SET(sc->sc_exit_lat_max); - break; - } + pinp->ctx_ep[epno - 1].dwEpCtx4 = htole32(temp); - pdctx->ctx_slot.dwSctx1 = htole32(temp); + usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc); +} - temp = XHCI_SCTX_2_IRQ_TARGET_SET(0); +static usb_error_t +xhci_configure_device(struct usb_device *udev) +{ + struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); + struct usb_page_search buf_scp; + struct usb_page_search buf_dev; + struct usb_page_search buf_inp; + struct usb_page_cache *pcdev; + struct usb_page_cache *pcinp; + struct usb_page_cache *pc; + struct xhci_input_dev_ctx *pinp; + struct usb_device *hubdev; + uint32_t temp; + uint8_t index; + uint8_t rh_port; + uint8_t i; - if ((udev->hub != NULL) && - (udev->speed == USB_SPEED_HIGH)) - temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(3); + pcdev = &sc->sc_hw.devs[index].device_pc; + pcinp = &sc->sc_hw.devs[index].input_pc; - hubdev = udev->parent_hs_hub; + usbd_get_page(pcdev, 0, &buf_dev); + usbd_get_page(pcinp, 0, &buf_inp); - if (hubdev != NULL) { - temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->device_index); - temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no); - } + pinp = buf_inp.buffer; - pdctx->ctx_slot.dwSctx2 = htole32(temp); + hubdev = udev; + temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1); - temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) | - XHCI_SCTX_3_SLOT_STATE_SET(3); + while (hubdev->parent_hub != NULL) { + temp |= ((uint32_t)(hubdev->port_no & 0xF)) << ((hubdev->depth - 1) * 4); + hubdev = hubdev->parent_hub; + } - pdctx->ctx_slot.dwSctx3 = htole32(temp); + rh_port = hubdev->port_no; - } else { - pdctx = NULL; + switch (udev->speed) { + case USB_SPEED_LOW: + temp |= XHCI_SCTX_0_SPEED_SET(2); + break; + case USB_SPEED_HIGH: + temp |= XHCI_SCTX_0_SPEED_SET(3); + break; + case USB_SPEED_FULL: + temp |= XHCI_SCTX_0_SPEED_SET(1); + break; + default: + temp |= XHCI_SCTX_0_SPEED_SET(4); + break; } - for (i = 0; i != sc->sc_noscratch; i++) { + if (udev->hub != NULL) + temp |= XHCI_SCTX_0_HUB_SET(1); - pcs = &sc->sc_hw.devs[index].scratch_pc[i]; - pgs = &sc->sc_hw.devs[index].scratch_pg[i]; + pinp->ctx_slot.dwSctx0 = htole32(temp); - /* need to initialize the page cache */ - pcs->tag_parent = sc->sc_bus.dma_parent_tag; + temp = XHCI_SCTX_1_RH_PORT_SET(rh_port); - if (usb_pc_alloc_mem(pcs, pgs, XHCI_PAGE_SIZE, XHCI_PAGE_SIZE)) - failure = 1; + if (udev->hub != NULL) + temp |= XHCI_SCTX_1_NUM_PORTS_SET(udev->hub->nports); - if (failure == 0) { - usbd_get_page(pcs, 0, &buf_scp); - pdctx->ctx_sp_buf_ptr[i] = htole64((uint64_t)buf_scp.physaddr); - } + switch (udev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + default: + temp |= XHCI_SCTX_1_MAX_EL_SET(sc->sc_exit_lat_max); + break; } - if (failure) - goto error; + + pinp->ctx_slot.dwSctx1 = htole32(temp); - usb_pc_cpu_flush(pcd); + temp = XHCI_SCTX_2_IRQ_TARGET_SET(0); - xhci_set_slot_scratch(sc, udev->device_index, addr, - addr + (uintptr_t)&((struct xhci_dev_ctx *)0)->ctx_sp_buf_ptr[0]); + if ((udev->hub != NULL) && + (udev->speed == USB_SPEED_HIGH)) + temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(3); - return (0); + hubdev = udev->parent_hs_hub; -error: - xhci_free_device_ext(udev); + if (hubdev != NULL) { + temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->device_index); + temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no); + } - return (USB_ERR_NOMEM); -} + pinp->ctx_slot.dwSctx2 = htole32(temp); -static void -xhci_free_device_ext(struct usb_device *udev) -{ - struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); - struct usb_page_cache *pcd; - struct usb_page_cache *pcs; - uint8_t index; - uint8_t i; + temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) | + XHCI_SCTX_3_SLOT_STATE_SET(3); - index = udev->device_index; + pinp->ctx_slot.dwSctx3 = htole32(temp); - pcd = &sc->sc_hw.devs[index].device_pc; + for (i = 0; i != sc->sc_noscratch; i++) { - usb_pc_free_mem(pcd); + pc = &sc->sc_hw.devs[index].scratch_pc[i]; - for (i = 0; i != sc->sc_noscratch; i++) { - pcs = &sc->sc_hw.devs[index].scratch_pc[i]; + usbd_get_page(pc, 0, &buf_scp); - usb_pc_free_mem(pcs); + pinp->ctx_sp_buf_ptr[i] = htole64((uint64_t)buf_scp.physaddr); } - xhci_set_slot_scratch(sc, udev->device_index, 0, 0); + usb_pc_cpu_flush(pcinp); + + xhci_set_slot_scratch(sc, udev->device_index, buf_dev.physaddr, + buf_inp.physaddr + (uintptr_t)&((struct xhci_input_dev_ctx *)0)->ctx_sp_buf_ptr[0]); + + XXX_cmd_config(); } static usb_error_t -xhci_alloc_endpoint_ext(struct xhci_softc *sc, uint8_t index, - struct usb_endpoint_descriptor *edesc) +xhci_alloc_device_ext(struct usb_device *udev) { - struct usb_page_search buf_res; - struct xhci_endpoint_ext *pepext; + struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); struct usb_page_cache *pc; struct usb_page *pg; - uint8_t epno; + uint8_t i; + uint8_t index; + + index = udev->device_index; + + pc = &sc->sc_hw.devs[index].device_pc; + pg = &sc->sc_hw.devs[index].device_pg; - epno = edesc->bEndpointAddress; + /* need to initialize the page cache */ + pc->tag_parent = sc->sc_bus.dma_parent_tag; - if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) - epno |= UE_DIR_IN; + if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_ctx), XHCI_PAGE_SIZE)) + goto error; - epno = XHCI_EPNO2EPID(epno); - pc = &sc->sc_hw.devs[index].endpoint_pc[epno]; - pg = &sc->sc_hw.devs[index].endpoint_pg[epno]; + pc = &sc->sc_hw.devs[index].input_pc; + pg = &sc->sc_hw.devs[index].input_pg; /* need to initialize the page cache */ pc->tag_parent = sc->sc_bus.dma_parent_tag; - if (usb_pc_alloc_mem(pc, pg, sizeof(*pepext), XHCI_TRB_ALIGN)) { - return (USB_ERR_NOMEM); /* failure */ - } + if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_input_dev_ctx), XHCI_PAGE_SIZE)) + goto error; + + pc = &sc->sc_hw.devs[index].endpoint_pc; + pg = &sc->sc_hw.devs[index].endpoint_pg; - /* the allocated memory is zeroed */ + /* need to initialize the page cache */ + pc->tag_parent = sc->sc_bus.dma_parent_tag; - usbd_get_page(pc, 0, &buf_res); + if (usb_pc_alloc_mem(pc, pg, sizeof(struct xhci_dev_endpoint_trbs), XHCI_PAGE_SIZE)) + goto error; - pepext = buf_res.buffer; + for (i = 0; i != sc->sc_noscratch; i++) { - pepext->page_cache = pc; - pepext->trb_ccs = 1; + pc = &sc->sc_hw.devs[index].scratch_pc[i]; + pg = &sc->sc_hw.devs[index].scratch_pg[i]; - usb_pc_cpu_flush(pepext->page_cache); + /* need to initialize the page cache */ + pc->tag_parent = sc->sc_bus.dma_parent_tag; + if (usb_pc_alloc_mem(pc, pg, XHCI_PAGE_SIZE, XHCI_PAGE_SIZE)) + goto error; + } return (0); + +error: + xhci_free_device_ext(udev); + + return (USB_ERR_NOMEM); } static void -xhci_free_endpoint_ext(struct xhci_softc *sc, uint8_t index, - struct usb_endpoint_descriptor *edesc) +xhci_free_device_ext(struct usb_device *udev) { + struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); struct usb_page_cache *pc; - uint8_t epno; + uint8_t index; + uint8_t i; + + index = udev->device_index; + + xhci_set_slot_scratch(sc, index, 0, 0); + + pc = &sc->sc_hw.devs[index].device_pc; + + usb_pc_free_mem(pc); - epno = edesc->bEndpointAddress; + pc = &sc->sc_hw.devs[index].input_pc; - if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) - epno |= UE_DIR_IN; + usb_pc_free_mem(pc); - epno = XHCI_EPNO2EPID(epno); - pc = &sc->sc_hw.devs[index].endpoint_pc[epno]; + pc = &sc->sc_hw.devs[index].endpoint_pc; usb_pc_free_mem(pc); + + for (i = 0; i != sc->sc_noscratch; i++) { + pc = &sc->sc_hw.devs[index].scratch_pc[i]; + + usb_pc_free_mem(pc); + } } -static void -xhci_get_endpoint_ext(struct usb_xfer *xfer, struct usb_page_search *buf) +static struct xhci_endpoint_ext * +xhci_get_endpoint_ext(struct usb_xfer *xfer) { struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus); + struct xhci_endpoint_ext *pepext; + struct usb_page_cache *pc; + struct usb_page_search buf_res; uint8_t epno; uint8_t index; @@ -1580,7 +1696,16 @@ epno = XHCI_EPNO2EPID(epno); index = xfer->xroot->udev->device_index; - usbd_get_page(&sc->sc_hw.devs[index].endpoint_pc[epno], 0, buf); + pc = &sc->sc_hw.devs[index].endpoint_pc; + + usbd_get_page(pc, (XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) * epno, &buf_res); + + pepext = &sc->sc_hw.devs[index].endp[epno]; + pepext->page_cache = pc; + pepext->trb = buf_res.buffer; + pepext->physaddr = buf_res.physaddr; + + return (pepext); } static void @@ -1603,20 +1728,15 @@ static void xhci_transfer_remove(struct usb_xfer *xfer, usb_error_t error) { - struct usb_page_search buf_res; struct xhci_endpoint_ext *pepext; if (xfer->flags_int.bandwidth_reclaimed) { xfer->flags_int.bandwidth_reclaimed = 0; - xhci_get_endpoint_ext(xfer, &buf_res); - - pepext = buf_res.buffer; + pepext = xhci_get_endpoint_ext(xfer); pepext->trb_used--; - usb_pc_cpu_flush(pepext->page_cache); - if (error) xhci_transfer_stop_endpoint(xfer); } @@ -1625,7 +1745,6 @@ static usb_error_t xhci_transfer_insert(struct usb_xfer *xfer) { - struct usb_page_search buf_res; struct xhci_td *td_first; struct xhci_td *td_last; struct xhci_endpoint_ext *pepext; @@ -1638,12 +1757,11 @@ if (xfer->flags_int.bandwidth_reclaimed) return (0); - xhci_get_endpoint_ext(xfer, &buf_res); + pepext = xhci_get_endpoint_ext(xfer); td_first = xfer->td_transfer_first; td_last = xfer->td_transfer_last; - pepext = buf_res.buffer; - addr = buf_res.physaddr; + addr = pepext->physaddr; if (pepext->trb_used >= (XHCI_MAX_TRANSFERS - 1)) return (USB_ERR_NOMEM); @@ -1694,7 +1812,7 @@ if (i == (XHCI_MAX_TRANSFERS - 1)) { - addr = buf_res.physaddr; + addr = pepext->physaddr; /* update next pointer of link TRB */ ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#11 (text+ko) ==== @@ -147,13 +147,22 @@ volatile uint32_t dwInCtx7; }; +struct xhci_input_dev_ctx { + struct xhci_input_ctx ctx_input; + struct xhci_slot_ctx ctx_slot; + struct xhci_endp_ctx ctx_ep[XHCI_MAX_ENDPOINTS - 1]; + volatile uint64_t ctx_sp_buf_ptr[XHCI_MAX_SCRATCHPADS]; +}; + struct xhci_dev_ctx { struct xhci_slot_ctx ctx_slot; - struct xhci_endp_ctx ctx_ep0; - struct xhci_endp_ctx ctx_epN[XHCI_MAX_ENDPOINTS - 2]; - volatile uint64_t ctx_sp_buf_ptr[XHCI_MAX_SCRATCHPADS]; + struct xhci_endp_ctx ctx_epN[XHCI_MAX_ENDPOINTS - 1]; } __aligned(XHCI_DEV_CTX_ALIGN); +struct xhci_dev_endpoint_trbs { + struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS]; +}; + struct xhci_stream_ctx { volatile uint64_t qwSctx0; #define XHCI_SCTX_0_DCS_GET(x) ((x) & 0x1) @@ -333,28 +342,29 @@ }; struct xhci_endpoint_ext { - - struct xhci_trb trb[XHCI_MAX_TRANSFERS]; - struct xhci_command ep_stop_cmd; - + struct xhci_command ep_config_cmd; + struct xhci_trb *trb; struct usb_page_cache *page_cache; - + uint64_t physaddr; uint8_t trb_used; uint8_t trb_ccs; uint8_t trb_index; + uint8_t trb_halted; }; struct xhci_hw_dev { struct usb_page_cache device_pc; - struct usb_page_cache endpoint_pc[XHCI_MAX_ENDPOINTS]; struct usb_page_cache input_pc; + struct usb_page_cache endpoint_pc; struct usb_page_cache scratch_pc[XHCI_MAX_SCRATCHPADS]; struct usb_page device_pg; - struct usb_page endpoint_pg[XHCI_MAX_ENDPOINTS]; struct usb_page input_pg; + struct usb_page endpoint_pg; struct usb_page scratch_pg[XHCI_MAX_SCRATCHPADS]; + + struct xhci_endpoint_ext endp[XHCI_MAX_ENDPOINTS]; }; struct xhci_hw_softc {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008021822.o72IMAVd029633>