summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/usb/controller')
-rw-r--r--sys/dev/usb/controller/at91dci.c14
-rw-r--r--sys/dev/usb/controller/atmegadci.c13
-rw-r--r--sys/dev/usb/controller/avr32dci.c13
-rw-r--r--sys/dev/usb/controller/dwc_otg.c13
-rw-r--r--sys/dev/usb/controller/musb_otg.c13
-rw-r--r--sys/dev/usb/controller/uss820dci.c13
-rw-r--r--sys/dev/usb/controller/xhci.c123
-rw-r--r--sys/dev/usb/controller/xhci.h19
8 files changed, 157 insertions, 64 deletions
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c
index e7d5e6e..d8fdc63 100644
--- a/sys/dev/usb/controller/at91dci.c
+++ b/sys/dev/usb/controller/at91dci.c
@@ -1226,7 +1226,14 @@ at91dci_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+at91dci_xfer_stall(struct usb_xfer *xfer)
+{
+ USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
+ at91dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+at91dci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct at91dci_softc *sc;
@@ -1237,10 +1244,6 @@ at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- at91dci_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = AT9100_DCI_BUS2SC(udev->bus);
csr_reg = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2332,6 +2335,7 @@ struct usb_bus_methods at91dci_bus_methods =
.xfer_unsetup = &at91dci_xfer_unsetup,
.get_hw_ep_profile = &at91dci_get_hw_ep_profile,
.set_stall = &at91dci_set_stall,
+ .xfer_stall = &at91dci_xfer_stall,
.clear_stall = &at91dci_clear_stall,
.roothub_exec = &at91dci_roothub_exec,
.xfer_poll = &at91dci_do_poll,
diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c
index 700ca8f..d8f9111 100644
--- a/sys/dev/usb/controller/atmegadci.c
+++ b/sys/dev/usb/controller/atmegadci.c
@@ -1113,7 +1113,13 @@ atmegadci_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+atmegadci_xfer_stall(struct usb_xfer *xfer)
+{
+ atmegadci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+atmegadci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct atmegadci_softc *sc;
@@ -1123,10 +1129,6 @@ atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- atmegadci_device_done(xfer, USB_ERR_STALLED);
- }
sc = ATMEGA_BUS2SC(udev->bus);
/* get endpoint number */
ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2151,6 +2153,7 @@ struct usb_bus_methods atmegadci_bus_methods =
.xfer_setup = &atmegadci_xfer_setup,
.xfer_unsetup = &atmegadci_xfer_unsetup,
.get_hw_ep_profile = &atmegadci_get_hw_ep_profile,
+ .xfer_stall = &atmegadci_xfer_stall,
.set_stall = &atmegadci_set_stall,
.clear_stall = &atmegadci_clear_stall,
.roothub_exec = &atmegadci_roothub_exec,
diff --git a/sys/dev/usb/controller/avr32dci.c b/sys/dev/usb/controller/avr32dci.c
index 9f9cd5d..7a672f6 100644
--- a/sys/dev/usb/controller/avr32dci.c
+++ b/sys/dev/usb/controller/avr32dci.c
@@ -1080,7 +1080,13 @@ avr32dci_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+avr32dci_xfer_stall(struct usb_xfer *xfer)
+{
+ avr32dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+avr32dci_set_stall(struct usb_device *udev,
struct usb_endpoint *pipe, uint8_t *did_stall)
{
struct avr32dci_softc *sc;
@@ -1090,10 +1096,6 @@ avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
DPRINTFN(5, "pipe=%p\n", pipe);
- if (xfer) {
- /* cancel any ongoing transfers */
- avr32dci_device_done(xfer, USB_ERR_STALLED);
- }
sc = AVR32_BUS2SC(udev->bus);
/* get endpoint number */
ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
@@ -2096,6 +2098,7 @@ struct usb_bus_methods avr32dci_bus_methods =
.xfer_setup = &avr32dci_xfer_setup,
.xfer_unsetup = &avr32dci_xfer_unsetup,
.get_hw_ep_profile = &avr32dci_get_hw_ep_profile,
+ .xfer_stall = &avr32dci_xfer_stall,
.set_stall = &avr32dci_set_stall,
.clear_stall = &avr32dci_clear_stall,
.roothub_exec = &avr32dci_roothub_exec,
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index f3ef19a..e5310f2 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -1524,7 +1524,13 @@ dwc_otg_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+dwc_otg_xfer_stall(struct usb_xfer *xfer)
+{
+ dwc_otg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+dwc_otg_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct dwc_otg_softc *sc;
@@ -1534,10 +1540,6 @@ dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
- if (xfer) {
- /* cancel any ongoing transfers */
- dwc_otg_device_done(xfer, USB_ERR_STALLED);
- }
sc = DWC_OTG_BUS2SC(udev->bus);
/* get endpoint address */
@@ -2625,6 +2627,7 @@ struct usb_bus_methods dwc_otg_bus_methods =
.xfer_setup = &dwc_otg_xfer_setup,
.xfer_unsetup = &dwc_otg_xfer_unsetup,
.get_hw_ep_profile = &dwc_otg_get_hw_ep_profile,
+ .xfer_stall = &dwc_otg_xfer_stall,
.set_stall = &dwc_otg_set_stall,
.clear_stall = &dwc_otg_clear_stall,
.roothub_exec = &dwc_otg_roothub_exec,
diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c
index db0d54f..858cd0f 100644
--- a/sys/dev/usb/controller/musb_otg.c
+++ b/sys/dev/usb/controller/musb_otg.c
@@ -1472,7 +1472,13 @@ musbotg_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+musbotg_xfer_stall(struct usb_xfer *xfer)
+{
+ musbotg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+musbotg_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct musbotg_softc *sc;
@@ -1482,10 +1488,6 @@ musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
DPRINTFN(4, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- musbotg_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = MUSBOTG_BUS2SC(udev->bus);
@@ -2801,6 +2803,7 @@ struct usb_bus_methods musbotg_bus_methods =
.xfer_setup = &musbotg_xfer_setup,
.xfer_unsetup = &musbotg_xfer_unsetup,
.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
+ .xfer_stall = &musbotg_xfer_stall,
.set_stall = &musbotg_set_stall,
.clear_stall = &musbotg_clear_stall,
.roothub_exec = &musbotg_roothub_exec,
diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c
index 19229f8..5bd479d 100644
--- a/sys/dev/usb/controller/uss820dci.c
+++ b/sys/dev/usb/controller/uss820dci.c
@@ -1210,7 +1210,13 @@ uss820dci_device_done(struct usb_xfer *xfer, usb_error_t error)
}
static void
-uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+uss820dci_xfer_stall(struct usb_xfer *xfer)
+{
+ uss820dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+uss820dci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct uss820dci_softc *sc;
@@ -1223,10 +1229,6 @@ uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- uss820dci_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = USS820_DCI_BUS2SC(udev->bus);
ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2385,6 +2387,7 @@ struct usb_bus_methods uss820dci_bus_methods =
.xfer_setup = &uss820dci_xfer_setup,
.xfer_unsetup = &uss820dci_xfer_unsetup,
.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
+ .xfer_stall = &uss820dci_xfer_stall,
.set_stall = &uss820dci_set_stall,
.clear_stall = &uss820dci_clear_stall,
.roothub_exec = &uss820dci_roothub_exec,
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 1a4e432..a20d7fa 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -128,7 +128,7 @@ static usb_proc_callback_t xhci_configure_msg;
static usb_error_t xhci_configure_device(struct usb_device *);
static usb_error_t xhci_configure_endpoint(struct usb_device *,
struct usb_endpoint_descriptor *, uint64_t, uint16_t,
- uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
+ uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
static usb_error_t xhci_configure_mask(struct usb_device *,
uint32_t, uint8_t);
static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -1245,7 +1245,7 @@ xhci_set_address(struct usb_device *udev, struct mtx *mtx, uint16_t address)
&udev->ctrl_ep_desc);
err = xhci_configure_endpoint(udev,
&udev->ctrl_ep_desc, pepext->physaddr,
- 0, 1, 1, 0, mps, mps);
+ 0, 1, 1, 0, mps, mps, USB_EP_MODE_DEFAULT);
if (err != 0) {
DPRINTF("Could not configure default endpoint\n");
@@ -1800,7 +1800,8 @@ xhci_setup_generic_chain(struct usb_xfer *xfer)
/* compute multiplier for ISOCHRONOUS transfers */
mult = xfer->endpoint->ecomp ?
- (xfer->endpoint->ecomp->bmAttributes & 3) : 0;
+ UE_GET_SS_ISO_MULT(xfer->endpoint->ecomp->bmAttributes)
+ : 0;
/* check for USB 2.0 multiplier */
if (mult == 0) {
mult = (xfer->endpoint->edesc->
@@ -2055,7 +2056,8 @@ static usb_error_t
xhci_configure_endpoint(struct usb_device *udev,
struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
uint16_t interval, uint8_t max_packet_count, uint8_t mult,
- uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
+ uint8_t fps_shift, uint16_t max_packet_size,
+ uint16_t max_frame_size, uint8_t ep_mode)
{
struct usb_page_search buf_inp;
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
@@ -2090,9 +2092,20 @@ xhci_configure_endpoint(struct usb_device *udev,
if (mult == 0)
return (USB_ERR_BAD_BUFSIZE);
- temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
- XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
- XHCI_EPCTX_0_LSA_SET(0);
+ if (ep_mode == USB_EP_MODE_STREAMS) {
+ temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+ XHCI_EPCTX_0_MAXP_STREAMS_SET(XHCI_MAX_STREAMS_LOG - 1) |
+ XHCI_EPCTX_0_LSA_SET(1);
+
+ ring_addr += sizeof(struct xhci_trb) *
+ XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS;
+ } else {
+ temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+ XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
+ XHCI_EPCTX_0_LSA_SET(0);
+
+ ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
+ }
switch (udev->speed) {
case USB_SPEED_FULL:
@@ -2160,9 +2173,6 @@ xhci_configure_endpoint(struct usb_device *udev,
temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp);
-
- ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
-
xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr);
switch (edesc->bmAttributes & UE_XFERTYPE) {
@@ -2195,21 +2205,42 @@ xhci_configure_endpoint_by_xfer(struct usb_xfer *xfer)
{
struct xhci_endpoint_ext *pepext;
struct usb_endpoint_ss_comp_descriptor *ecomp;
+ usb_stream_t x;
pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
xfer->endpoint->edesc);
ecomp = xfer->endpoint->ecomp;
- pepext->trb[0].dwTrb3 = 0; /* halt any transfers */
+ for (x = 0; x != XHCI_MAX_STREAMS; x++) {
+ uint64_t temp;
+
+ /* halt any transfers */
+ pepext->trb[x * XHCI_MAX_TRANSFERS].dwTrb3 = 0;
+
+ /* compute start of TRB ring for stream "x" */
+ temp = pepext->physaddr +
+ (x * XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) +
+ XHCI_SCTX_0_SCT_SEC_TR_RING;
+
+ /* make tree structure */
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].qwTrb0 = htole64(temp);
+
+ /* reserved fields */
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].dwTrb2 = 0;
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].dwTrb3 = 0;
+ }
usb_pc_cpu_flush(pepext->page_cache);
return (xhci_configure_endpoint(xfer->xroot->udev,
xfer->endpoint->edesc, pepext->physaddr,
xfer->interval, xfer->max_packet_count,
- (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
+ (ecomp != NULL) ? UE_GET_SS_ISO_MULT(ecomp->bmAttributes) + 1 : 1,
usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
- xfer->max_frame_size));
+ xfer->max_frame_size, xfer->endpoint->ep_mode));
}
static usb_error_t
@@ -2500,7 +2531,8 @@ xhci_get_endpoint_ext(struct usb_device *udev, struct usb_endpoint_descriptor *e
pc = &sc->sc_hw.devs[index].endpoint_pc;
- usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0], &buf_ep);
+ usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->
+ trb[epno][0], &buf_ep);
pepext = &sc->sc_hw.devs[index].endp[epno];
pepext->page_cache = pc;
@@ -2539,7 +2571,7 @@ xhci_transfer_remove(struct usb_xfer *xfer, usb_error_t error)
pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
xfer->endpoint->edesc);
- pepext->trb_used--;
+ pepext->trb_used[xfer->stream_id]--;
pepext->xfer[xfer->qh_pos] = NULL;
@@ -2557,12 +2589,15 @@ xhci_transfer_insert(struct usb_xfer *xfer)
struct xhci_td *td_last;
struct xhci_endpoint_ext *pepext;
uint64_t addr;
+ usb_stream_t id;
uint8_t i;
uint8_t inext;
uint8_t trb_limit;
DPRINTFN(8, "\n");
+ id = xfer->stream_id;
+
/* check if already inserted */
if (xfer->flags_int.bandwidth_reclaimed) {
DPRINTFN(8, "Already in schedule\n");
@@ -2588,7 +2623,7 @@ xhci_transfer_insert(struct usb_xfer *xfer)
break;
}
- if (pepext->trb_used >= trb_limit) {
+ if (pepext->trb_used[id] >= trb_limit) {
DPRINTFN(8, "Too many TDs queued.\n");
return (USB_ERR_NOMEM);
}
@@ -2605,10 +2640,10 @@ xhci_transfer_insert(struct usb_xfer *xfer)
return (0);
}
- pepext->trb_used++;
+ pepext->trb_used[id]++;
/* get current TRB index */
- i = pepext->trb_index;
+ i = pepext->trb_index[id];
/* get next TRB index */
inext = (i + 1);
@@ -2617,8 +2652,12 @@ xhci_transfer_insert(struct usb_xfer *xfer)
if (inext >= (XHCI_MAX_TRANSFERS - 1))
inext = 0;
+ /* offset for stream */
+ i += id * XHCI_MAX_TRANSFERS;
+ inext += id * XHCI_MAX_TRANSFERS;
+
/* compute terminating return address */
- addr += inext * sizeof(struct xhci_trb);
+ addr += (inext * sizeof(struct xhci_trb));
/* update next pointer of last link TRB */
td_last->td_trb[td_last->ntrb].qwTrb0 = htole64(addr);
@@ -2662,7 +2701,7 @@ xhci_transfer_insert(struct usb_xfer *xfer)
xfer->flags_int.bandwidth_reclaimed = 1;
- pepext->trb_index = inext;
+ pepext->trb_index[id] = inext;
xhci_endpoint_doorbell(xfer);
@@ -2750,12 +2789,12 @@ xhci_device_generic_close(struct usb_xfer *xfer)
static void
xhci_device_generic_multi_enter(struct usb_endpoint *ep,
- struct usb_xfer *enter_xfer)
+ usb_stream_t stream_id, struct usb_xfer *enter_xfer)
{
struct usb_xfer *xfer;
/* check if there is a current transfer */
- xfer = ep->endpoint_q.curr;
+ xfer = ep->endpoint_q[stream_id].curr;
if (xfer == NULL)
return;
@@ -2767,7 +2806,7 @@ xhci_device_generic_multi_enter(struct usb_endpoint *ep,
if (!xfer->flags_int.bandwidth_reclaimed)
return;
- xfer = TAILQ_FIRST(&ep->endpoint_q.head);
+ xfer = TAILQ_FIRST(&ep->endpoint_q[stream_id].head);
if (xfer == NULL) {
/*
* In case of enter we have to consider that the
@@ -2792,7 +2831,8 @@ xhci_device_generic_enter(struct usb_xfer *xfer)
/* setup TD's and QH */
xhci_setup_generic_chain(xfer);
- xhci_device_generic_multi_enter(xfer->endpoint, xfer);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, xfer);
}
static void
@@ -2804,7 +2844,8 @@ xhci_device_generic_start(struct usb_xfer *xfer)
xhci_transfer_insert(xfer);
/* try to multi buffer */
- xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, NULL);
/* add transfer last on interrupt queue */
usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
@@ -3465,6 +3506,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
struct usb_endpoint_descriptor *edesc;
struct usb_page_cache *pcinp;
usb_error_t err;
+ usb_stream_t stream_id;
uint8_t index;
uint8_t epno;
@@ -3481,6 +3523,7 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
edesc = xfer->endpoint->edesc;
epno = edesc->bEndpointAddress;
+ stream_id = xfer->stream_id;
if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL)
epno |= UE_DIR_IN;
@@ -3516,8 +3559,10 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
if (err != 0)
DPRINTF("Could not reset endpoint %u\n", epno);
- err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr |
- XHCI_EPCTX_2_DCS_SET(1), 0, epno, index);
+ err = xhci_cmd_set_tr_dequeue_ptr(sc,
+ (pepext->physaddr + (stream_id * sizeof(struct xhci_trb) *
+ XHCI_MAX_TRANSFERS)) | XHCI_EPCTX_2_DCS_SET(1),
+ stream_id, epno, index);
if (err != 0)
DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno);
@@ -3615,7 +3660,8 @@ restart:
/* check if halted is still cleared */
if (pepext->trb_halted == 0) {
pepext->trb_running = 1;
- pepext->trb_index = 0;
+ memset(pepext->trb_index, 0,
+ sizeof(pepext->trb_index));
}
goto restart;
}
@@ -3639,7 +3685,8 @@ restart:
xhci_transfer_insert(xfer);
/* try to multi buffer */
- xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, NULL);
}
}
@@ -3946,6 +3993,23 @@ xhci_device_state_change(struct usb_device *udev)
XHCI_CMD_UNLOCK(sc);
}
+static usb_error_t
+xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
+ uint8_t ep_mode)
+{
+ switch (ep_mode) {
+ case USB_EP_MODE_DEFAULT:
+ return (0);
+ case USB_EP_MODE_STREAMS:
+ if ((ep->edesc->bmAttributes & UE_XFERTYPE) != UE_BULK ||
+ udev->speed != USB_SPEED_SUPER)
+ return (USB_ERR_INVAL);
+ return (0);
+ default:
+ return (USB_ERR_INVAL);
+ }
+}
+
struct usb_bus_methods xhci_bus_methods = {
.endpoint_init = xhci_ep_init,
.endpoint_uninit = xhci_ep_uninit,
@@ -3964,4 +4028,5 @@ struct usb_bus_methods xhci_bus_methods = {
.clear_stall = xhci_ep_clear_stall,
.device_state_change = xhci_device_state_change,
.set_hw_power_sleep = xhci_set_hw_power_sleep,
+ .set_endpoint_mode = xhci_set_endpoint_mode,
};
diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h
index 14afcaf..f6d467f 100644
--- a/sys/dev/usb/controller/xhci.h
+++ b/sys/dev/usb/controller/xhci.h
@@ -35,7 +35,15 @@
#define XHCI_MAX_COMMANDS (16 * 1)
#define XHCI_MAX_RSEG 1
#define XHCI_MAX_TRANSFERS 4
-
+#if USB_MAX_EP_STREAMS == 8
+#define XHCI_MAX_STREAMS 8
+#define XHCI_MAX_STREAMS_LOG 3
+#elif USB_MAX_EP_STREAMS == 1
+#define XHCI_MAX_STREAMS 1
+#define XHCI_MAX_STREAMS_LOG 0
+#else
+#error "The USB_MAX_EP_STREAMS value is not supported."
+#endif
#define XHCI_DEV_CTX_ADDR_ALIGN 64 /* bytes */
#define XHCI_DEV_CTX_ALIGN 64 /* bytes */
#define XHCI_INPUT_CTX_ALIGN 64 /* bytes */
@@ -307,7 +315,8 @@ struct xhci_trb {
} __aligned(4);
struct xhci_dev_endpoint_trbs {
- struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
+ struct xhci_trb trb[XHCI_MAX_ENDPOINTS]
+ [(XHCI_MAX_STREAMS * XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS];
};
#define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */
@@ -353,11 +362,11 @@ struct xhci_hw_root {
struct xhci_endpoint_ext {
struct xhci_trb *trb;
- struct usb_xfer *xfer[XHCI_MAX_TRANSFERS - 1];
+ struct usb_xfer *xfer[XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS];
struct usb_page_cache *page_cache;
uint64_t physaddr;
- uint8_t trb_used;
- uint8_t trb_index;
+ uint8_t trb_used[XHCI_MAX_STREAMS];
+ uint8_t trb_index[XHCI_MAX_STREAMS];
uint8_t trb_halted;
uint8_t trb_running;
};
OpenPOWER on IntegriCloud