mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-24 11:29:10 +00:00
Add support for Multi-TT mode of modern USB HUBs.
This will give you more bandwidth for isochronous FULL speed applications connected through a High Speed HUB. This patch has been tested with XHCI and EHCI. MFC after: 1 week
This commit is contained in:
parent
d7af8cf14b
commit
0a4cc48fe5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234803
@ -2398,9 +2398,9 @@ ehci_device_isoc_fs_open(struct usb_xfer *xfer)
|
||||
EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
|
||||
EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
|
||||
|
||||
if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN) {
|
||||
if (UE_GET_DIR(xfer->endpointno) == UE_DIR_IN)
|
||||
sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
|
||||
}
|
||||
|
||||
sitd_portaddr = htohc32(sc, sitd_portaddr);
|
||||
|
||||
/* initialize all TD's */
|
||||
@ -2436,9 +2436,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
{
|
||||
struct usb_page_search buf_res;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
struct usb_fs_isoc_schedule *fss_start;
|
||||
struct usb_fs_isoc_schedule *fss_end;
|
||||
struct usb_fs_isoc_schedule *fss;
|
||||
ehci_sitd_t *td;
|
||||
ehci_sitd_t *td_last = NULL;
|
||||
ehci_sitd_t **pp_last;
|
||||
@ -2450,7 +2447,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
uint16_t tlen;
|
||||
uint8_t sa;
|
||||
uint8_t sb;
|
||||
uint8_t error;
|
||||
|
||||
#ifdef USB_DEBUG
|
||||
uint8_t once = 1;
|
||||
@ -2495,9 +2491,8 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
* pre-compute when the isochronous transfer will be finished:
|
||||
*/
|
||||
xfer->isoc_time_complete =
|
||||
usbd_fs_isoc_schedule_isoc_time_expand
|
||||
(xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
|
||||
xfer->nframes;
|
||||
usb_isoc_time_expand(&sc->sc_bus, nframes) +
|
||||
buf_offset + xfer->nframes;
|
||||
|
||||
/* get the real number of frames */
|
||||
|
||||
@ -2520,19 +2515,14 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
|
||||
xfer->qh_pos = xfer->endpoint->isoc_next;
|
||||
|
||||
fss = fss_start + (xfer->qh_pos % USB_ISOC_TIME_MAX);
|
||||
|
||||
while (nframes--) {
|
||||
if (td == NULL) {
|
||||
panic("%s:%d: out of TD's\n",
|
||||
__FUNCTION__, __LINE__);
|
||||
}
|
||||
if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT]) {
|
||||
if (pp_last >= &sc->sc_isoc_fs_p_last[EHCI_VIRTUAL_FRAMELIST_COUNT])
|
||||
pp_last = &sc->sc_isoc_fs_p_last[0];
|
||||
}
|
||||
if (fss >= fss_end) {
|
||||
fss = fss_start;
|
||||
}
|
||||
|
||||
/* reuse sitd_portaddr and sitd_back from last transfer */
|
||||
|
||||
if (*plen > xfer->max_frame_size) {
|
||||
@ -2547,17 +2537,19 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
#endif
|
||||
*plen = xfer->max_frame_size;
|
||||
}
|
||||
/*
|
||||
* We currently don't care if the ISOCHRONOUS schedule is
|
||||
* full!
|
||||
*/
|
||||
error = usbd_fs_isoc_schedule_alloc(fss, &sa, *plen);
|
||||
if (error) {
|
||||
|
||||
/* allocate a slot */
|
||||
|
||||
sa = usbd_fs_isoc_schedule_alloc_slot(xfer,
|
||||
xfer->isoc_time_complete - nframes - 1);
|
||||
|
||||
if (sa == 255) {
|
||||
/*
|
||||
* The FULL speed schedule is FULL! Set length
|
||||
* to zero.
|
||||
* Schedule is FULL, set length to zero:
|
||||
*/
|
||||
|
||||
*plen = 0;
|
||||
sa = USB_FS_ISOC_UFRAME_MAX - 1;
|
||||
}
|
||||
if (*plen) {
|
||||
/*
|
||||
@ -2637,7 +2629,6 @@ ehci_device_isoc_fs_enter(struct usb_xfer *xfer)
|
||||
pp_last++;
|
||||
|
||||
plen++;
|
||||
fss++;
|
||||
td_last = td;
|
||||
td = td->obj_next;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ struct xhci_std_temp {
|
||||
uint8_t tbc;
|
||||
uint8_t tlbpc;
|
||||
uint8_t step_td;
|
||||
uint8_t do_isoc_sync;
|
||||
};
|
||||
|
||||
static void xhci_do_poll(struct usb_bus *);
|
||||
@ -1657,11 +1658,15 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
||||
td->td_trb[x].dwTrb2 = htole32(dword);
|
||||
|
||||
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
||||
XHCI_TRB_3_TYPE_SET(temp->trb_type) |
|
||||
XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8) |
|
||||
XHCI_TRB_3_TYPE_SET(temp->trb_type) |
|
||||
(temp->do_isoc_sync ?
|
||||
XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8) :
|
||||
XHCI_TRB_3_ISO_SIA_BIT) |
|
||||
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
||||
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
||||
|
||||
temp->do_isoc_sync = 0;
|
||||
|
||||
if (temp->direction == UE_DIR_IN) {
|
||||
dword |= XHCI_TRB_3_DIR_IN;
|
||||
|
||||
@ -1764,6 +1769,7 @@ xhci_setup_generic_chain(struct usb_xfer *xfer)
|
||||
uint32_t y;
|
||||
uint8_t mult;
|
||||
|
||||
temp.do_isoc_sync = 0;
|
||||
temp.step_td = 0;
|
||||
temp.tbc = 0;
|
||||
temp.tlbpc = 0;
|
||||
@ -1841,6 +1847,8 @@ xhci_setup_generic_chain(struct usb_xfer *xfer)
|
||||
*/
|
||||
xfer->endpoint->isoc_next = XHCI_MFINDEX_GET(x + (3 * 8));
|
||||
xfer->endpoint->is_synced = 1;
|
||||
temp.do_isoc_sync = 1;
|
||||
|
||||
DPRINTFN(3, "start next=%d\n", xfer->endpoint->isoc_next);
|
||||
}
|
||||
|
||||
@ -1931,7 +1939,10 @@ xhci_setup_generic_chain(struct usb_xfer *xfer)
|
||||
|
||||
uint8_t tdpc;
|
||||
|
||||
/* isochronous transfers don't have short packet termination */
|
||||
/*
|
||||
* Isochronous transfers don't have short
|
||||
* packet termination:
|
||||
*/
|
||||
|
||||
temp.shortpkt = 1;
|
||||
|
||||
@ -2271,12 +2282,29 @@ xhci_configure_device(struct usb_device *udev)
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
temp |= XHCI_SCTX_0_SPEED_SET(2);
|
||||
if (udev->parent_hs_hub != NULL &&
|
||||
udev->parent_hs_hub->ddesc.bDeviceProtocol ==
|
||||
UDPROTO_HSHUBMTT) {
|
||||
DPRINTF("Device inherits MTT\n");
|
||||
temp |= XHCI_SCTX_0_MTT_SET(1);
|
||||
}
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
temp |= XHCI_SCTX_0_SPEED_SET(3);
|
||||
if (sc->sc_hw.devs[index].nports != 0 &&
|
||||
udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) {
|
||||
DPRINTF("HUB supports MTT\n");
|
||||
temp |= XHCI_SCTX_0_MTT_SET(1);
|
||||
}
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
temp |= XHCI_SCTX_0_SPEED_SET(1);
|
||||
if (udev->parent_hs_hub != NULL &&
|
||||
udev->parent_hs_hub->ddesc.bDeviceProtocol ==
|
||||
UDPROTO_HSHUBMTT) {
|
||||
DPRINTF("Device inherits MTT\n");
|
||||
temp |= XHCI_SCTX_0_MTT_SET(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
temp |= XHCI_SCTX_0_SPEED_SET(4);
|
||||
@ -2287,15 +2315,8 @@ xhci_configure_device(struct usb_device *udev)
|
||||
(udev->speed == USB_SPEED_SUPER ||
|
||||
udev->speed == USB_SPEED_HIGH);
|
||||
|
||||
if (is_hub) {
|
||||
if (is_hub)
|
||||
temp |= XHCI_SCTX_0_HUB_SET(1);
|
||||
#if 0
|
||||
if (udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) {
|
||||
DPRINTF("HUB supports MTT\n");
|
||||
temp |= XHCI_SCTX_0_MTT_SET(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
|
||||
|
||||
@ -2327,8 +2348,10 @@ xhci_configure_device(struct usb_device *udev)
|
||||
|
||||
temp = XHCI_SCTX_2_IRQ_TARGET_SET(0);
|
||||
|
||||
if (is_hub)
|
||||
temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(sc->sc_hw.devs[index].tt);
|
||||
if (is_hub) {
|
||||
temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(
|
||||
sc->sc_hw.devs[index].tt);
|
||||
}
|
||||
|
||||
hubdev = udev->parent_hs_hub;
|
||||
|
||||
|
@ -231,7 +231,8 @@ void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
|
||||
uint8_t usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, usb_bus_mem_cb_t *cb);
|
||||
void usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb);
|
||||
uint16_t usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr);
|
||||
uint16_t usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev, struct usb_fs_isoc_schedule **pp_start, struct usb_fs_isoc_schedule **pp_end, uint16_t isoc_time);
|
||||
uint8_t usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
uint8_t usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time);
|
||||
#endif
|
||||
|
||||
#endif /* _USB_CONTROLLER_H_ */
|
||||
|
@ -109,6 +109,7 @@ struct uhub_softc {
|
||||
#define UHUB_PROTO(sc) ((sc)->sc_udev->ddesc.bDeviceProtocol)
|
||||
#define UHUB_IS_HIGH_SPEED(sc) (UHUB_PROTO(sc) != UDPROTO_FSHUB)
|
||||
#define UHUB_IS_SINGLE_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBSTT)
|
||||
#define UHUB_IS_MULTI_TT(sc) (UHUB_PROTO(sc) == UDPROTO_HSHUBMTT)
|
||||
#define UHUB_IS_SUPER_SPEED(sc) (UHUB_PROTO(sc) == UDPROTO_SSHUB)
|
||||
|
||||
/* prototypes for type checking: */
|
||||
@ -948,6 +949,16 @@ uhub_attach(device_t dev)
|
||||
"bus powered HUB. HUB ignored\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (UHUB_IS_MULTI_TT(sc)) {
|
||||
err = usbd_set_alt_interface_index(udev, 0, 1);
|
||||
if (err) {
|
||||
device_printf(dev, "MTT could not be enabled\n");
|
||||
goto error;
|
||||
}
|
||||
device_printf(dev, "MTT enabled\n");
|
||||
}
|
||||
|
||||
/* get HUB descriptor */
|
||||
|
||||
DPRINTFN(2, "Getting HUB descriptor\n");
|
||||
@ -1057,10 +1068,6 @@ uhub_attach(device_t dev)
|
||||
}
|
||||
udev->hub = hub;
|
||||
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
/* init FULL-speed ISOCHRONOUS schedule */
|
||||
usbd_fs_isoc_schedule_init_all(hub->fs_isoc_schedule);
|
||||
#endif
|
||||
/* initialize HUB structure */
|
||||
hub->hubsoftc = sc;
|
||||
hub->explore = &uhub_explore;
|
||||
@ -1655,42 +1662,6 @@ usb_hs_bandwidth_free(struct usb_xfer *xfer)
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_fs_isoc_schedule_init_sub
|
||||
*
|
||||
* This function initialises an USB FULL speed isochronous schedule
|
||||
* entry.
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
static void
|
||||
usbd_fs_isoc_schedule_init_sub(struct usb_fs_isoc_schedule *fss)
|
||||
{
|
||||
fss->total_bytes = (USB_FS_ISOC_UFRAME_MAX *
|
||||
USB_FS_BYTES_PER_HS_UFRAME);
|
||||
fss->frame_bytes = (USB_FS_BYTES_PER_HS_UFRAME);
|
||||
fss->frame_slot = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_fs_isoc_schedule_init_all
|
||||
*
|
||||
* This function will reset the complete USB FULL speed isochronous
|
||||
* bandwidth schedule.
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
void
|
||||
usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss)
|
||||
{
|
||||
struct usb_fs_isoc_schedule *fss_end = fss + USB_ISOC_TIME_MAX;
|
||||
|
||||
while (fss != fss_end) {
|
||||
usbd_fs_isoc_schedule_init_sub(fss);
|
||||
fss++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_isoc_time_expand
|
||||
*
|
||||
@ -1723,114 +1694,130 @@ usb_isoc_time_expand(struct usb_bus *bus, uint16_t isoc_time_curr)
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_fs_isoc_schedule_isoc_time_expand
|
||||
*
|
||||
* This function does multiple things. First of all it will expand the
|
||||
* passed isochronous time, which is the return value. Then it will
|
||||
* store where the current FULL speed isochronous schedule is
|
||||
* positioned in time and where the end is. See "pp_start" and
|
||||
* "pp_end" arguments.
|
||||
*
|
||||
* Returns:
|
||||
* Expanded version of "isoc_time".
|
||||
*
|
||||
* NOTE: This function depends on being called regularly with
|
||||
* intervals less than "USB_ISOC_TIME_MAX".
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
uint16_t
|
||||
usbd_fs_isoc_schedule_isoc_time_expand(struct usb_device *udev,
|
||||
struct usb_fs_isoc_schedule **pp_start,
|
||||
struct usb_fs_isoc_schedule **pp_end,
|
||||
uint16_t isoc_time)
|
||||
{
|
||||
struct usb_fs_isoc_schedule *fss_end;
|
||||
struct usb_fs_isoc_schedule *fss_a;
|
||||
struct usb_fs_isoc_schedule *fss_b;
|
||||
struct usb_hub *hs_hub;
|
||||
|
||||
isoc_time = usb_isoc_time_expand(udev->bus, isoc_time);
|
||||
|
||||
hs_hub = udev->parent_hs_hub->hub;
|
||||
|
||||
if (hs_hub != NULL) {
|
||||
|
||||
fss_a = hs_hub->fs_isoc_schedule +
|
||||
(hs_hub->isoc_last_time % USB_ISOC_TIME_MAX);
|
||||
|
||||
hs_hub->isoc_last_time = isoc_time;
|
||||
|
||||
fss_b = hs_hub->fs_isoc_schedule +
|
||||
(isoc_time % USB_ISOC_TIME_MAX);
|
||||
|
||||
fss_end = hs_hub->fs_isoc_schedule + USB_ISOC_TIME_MAX;
|
||||
|
||||
*pp_start = hs_hub->fs_isoc_schedule;
|
||||
*pp_end = fss_end;
|
||||
|
||||
while (fss_a != fss_b) {
|
||||
if (fss_a == fss_end) {
|
||||
fss_a = hs_hub->fs_isoc_schedule;
|
||||
continue;
|
||||
}
|
||||
usbd_fs_isoc_schedule_init_sub(fss_a);
|
||||
fss_a++;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
*pp_start = NULL;
|
||||
*pp_end = NULL;
|
||||
}
|
||||
return (isoc_time);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usbd_fs_isoc_schedule_alloc
|
||||
* usbd_fs_isoc_schedule_alloc_slot
|
||||
*
|
||||
* This function will allocate bandwidth for an isochronous FULL speed
|
||||
* transaction in the FULL speed schedule. The microframe slot where
|
||||
* the transaction should be started is stored in the byte pointed to
|
||||
* by "pstart". The "len" argument specifies the length of the
|
||||
* transaction in bytes.
|
||||
* transaction in the FULL speed schedule.
|
||||
*
|
||||
* Returns:
|
||||
* 0: Success
|
||||
* <8: Success
|
||||
* Else: Error
|
||||
*------------------------------------------------------------------------*/
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
uint8_t
|
||||
usbd_fs_isoc_schedule_alloc(struct usb_fs_isoc_schedule *fss,
|
||||
uint8_t *pstart, uint16_t len)
|
||||
usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time)
|
||||
{
|
||||
uint8_t slot = fss->frame_slot;
|
||||
struct usb_xfer *xfer;
|
||||
struct usb_xfer *pipe_xfer;
|
||||
struct usb_bus *bus;
|
||||
usb_frlength_t len;
|
||||
usb_frlength_t data_len;
|
||||
uint16_t delta;
|
||||
uint16_t slot;
|
||||
uint8_t retval;
|
||||
|
||||
/* Compute overhead and bit-stuffing */
|
||||
data_len = 0;
|
||||
slot = 0;
|
||||
|
||||
len += 8;
|
||||
bus = isoc_xfer->xroot->bus;
|
||||
|
||||
len *= 7;
|
||||
len /= 6;
|
||||
TAILQ_FOREACH(xfer, &bus->intr_q.head, wait_entry) {
|
||||
|
||||
if (len > fss->total_bytes) {
|
||||
*pstart = 0; /* set some dummy value */
|
||||
return (1); /* error */
|
||||
}
|
||||
if (len > 0) {
|
||||
/* skip self, if any */
|
||||
|
||||
fss->total_bytes -= len;
|
||||
if (xfer == isoc_xfer)
|
||||
continue;
|
||||
|
||||
while (len >= fss->frame_bytes) {
|
||||
len -= fss->frame_bytes;
|
||||
fss->frame_bytes = USB_FS_BYTES_PER_HS_UFRAME;
|
||||
fss->frame_slot++;
|
||||
/* check if this USB transfer is going through the same TT */
|
||||
|
||||
if (xfer->xroot->udev->parent_hs_hub !=
|
||||
isoc_xfer->xroot->udev->parent_hs_hub) {
|
||||
continue;
|
||||
}
|
||||
if ((isoc_xfer->xroot->udev->parent_hs_hub->
|
||||
ddesc.bDeviceProtocol == UDPROTO_HSHUBMTT) &&
|
||||
(xfer->xroot->udev->hs_port_no !=
|
||||
isoc_xfer->xroot->udev->hs_port_no)) {
|
||||
continue;
|
||||
}
|
||||
if (xfer->endpoint->methods != isoc_xfer->endpoint->methods)
|
||||
continue;
|
||||
|
||||
/* check if isoc_time is part of this transfer */
|
||||
|
||||
delta = xfer->isoc_time_complete - isoc_time;
|
||||
if (delta > 0 && delta <= xfer->nframes) {
|
||||
delta = xfer->nframes - delta;
|
||||
|
||||
len = xfer->frlengths[delta];
|
||||
len += 8;
|
||||
len *= 7;
|
||||
len /= 6;
|
||||
|
||||
data_len += len;
|
||||
}
|
||||
|
||||
fss->frame_bytes -= len;
|
||||
/* check double buffered transfers */
|
||||
|
||||
TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head,
|
||||
wait_entry) {
|
||||
|
||||
/* skip self, if any */
|
||||
|
||||
if (pipe_xfer == isoc_xfer)
|
||||
continue;
|
||||
|
||||
/* check if isoc_time is part of this transfer */
|
||||
|
||||
delta = pipe_xfer->isoc_time_complete - isoc_time;
|
||||
if (delta > 0 && delta <= pipe_xfer->nframes) {
|
||||
delta = pipe_xfer->nframes - delta;
|
||||
|
||||
len = pipe_xfer->frlengths[delta];
|
||||
len += 8;
|
||||
len *= 7;
|
||||
len /= 6;
|
||||
|
||||
data_len += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
*pstart = slot;
|
||||
return (0); /* success */
|
||||
|
||||
while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
|
||||
data_len -= USB_FS_BYTES_PER_HS_UFRAME;
|
||||
slot++;
|
||||
}
|
||||
|
||||
/* check for overflow */
|
||||
|
||||
if (slot >= USB_FS_ISOC_UFRAME_MAX)
|
||||
return (255);
|
||||
|
||||
retval = slot;
|
||||
|
||||
delta = isoc_xfer->isoc_time_complete - isoc_time;
|
||||
if (delta > 0 && delta <= isoc_xfer->nframes) {
|
||||
delta = isoc_xfer->nframes - delta;
|
||||
|
||||
len = isoc_xfer->frlengths[delta];
|
||||
len += 8;
|
||||
len *= 7;
|
||||
len /= 6;
|
||||
|
||||
data_len += len;
|
||||
}
|
||||
|
||||
while (data_len >= USB_FS_BYTES_PER_HS_UFRAME) {
|
||||
data_len -= USB_FS_BYTES_PER_HS_UFRAME;
|
||||
slot++;
|
||||
}
|
||||
|
||||
/* check for overflow */
|
||||
|
||||
if (slot >= USB_FS_ISOC_UFRAME_MAX)
|
||||
return (255);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -37,23 +37,10 @@ struct usb_port {
|
||||
enum usb_hc_mode usb_mode; /* host or device mode */
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure defines how many bytes are
|
||||
* left in an 1ms USB time slot.
|
||||
*/
|
||||
struct usb_fs_isoc_schedule {
|
||||
uint16_t total_bytes;
|
||||
uint8_t frame_bytes;
|
||||
uint8_t frame_slot;
|
||||
};
|
||||
|
||||
/*
|
||||
* The following structure defines an USB HUB.
|
||||
*/
|
||||
struct usb_hub {
|
||||
#if USB_HAVE_TT_SUPPORT
|
||||
struct usb_fs_isoc_schedule fs_isoc_schedule[USB_ISOC_TIME_MAX];
|
||||
#endif
|
||||
struct usb_device *hubudev; /* the HUB device */
|
||||
usb_error_t (*explore) (struct usb_device *hub);
|
||||
void *hubsoftc;
|
||||
@ -68,7 +55,6 @@ struct usb_hub {
|
||||
|
||||
void usb_hs_bandwidth_alloc(struct usb_xfer *xfer);
|
||||
void usb_hs_bandwidth_free(struct usb_xfer *xfer);
|
||||
void usbd_fs_isoc_schedule_init_all(struct usb_fs_isoc_schedule *fss);
|
||||
void usb_bus_port_set_device(struct usb_bus *bus, struct usb_port *up,
|
||||
struct usb_device *udev, uint8_t device_index);
|
||||
struct usb_device *usb_bus_port_get_device(struct usb_bus *bus,
|
||||
|
Loading…
Reference in New Issue
Block a user