PERFORCE change 113598 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jan 27 15:01:04 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=113598
Change 113598 by hselasky at hselasky_mini_itx on 2007/01/27 15:00:54
Make the isochronous end-of-transfer timestamp 16-bits
in width. This simplifies the USB device drivers doing
echo-cancelling for example.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/ehci.c#25 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#19 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#21 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#27 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#32 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/ehci.c#25 (text+ko) ====
@@ -2458,11 +2458,18 @@
DPRINTFN(5,("xfer=%p next=%d nframes=%d\n",
xfer, xfer->pipe->isoc_next, xfer->nframes));
+ /* get the current frame index */
+
nframes = EOREAD4(sc, EHCI_FRINDEX) / 8;
- if(((nframes - xfer->pipe->isoc_next) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT-1)) < xfer->nframes)
- {
+ /* check if the frame index is within
+ * the window where the frames will be
+ * inserted
+ */
+ buf_offset = (nframes - xfer->pipe->isoc_next) &
+ (EHCI_VIRTUAL_FRAMELIST_COUNT-1);
+
+ if (buf_offset < xfer->nframes) {
/* not in use yet, schedule it a few frames ahead */
/* data underflow */
xfer->pipe->isoc_next = (nframes + 3) &
@@ -2470,7 +2477,21 @@
DPRINTFN(2,("start next=%d\n", xfer->pipe->isoc_next));
}
- xfer->isoc_complete_time = (xfer->pipe->isoc_next + xfer->nframes) % USBD_ISOC_TIME_MAX;
+ /* compute how many milliseconds the
+ * insertion is ahead of the current
+ * frame position:
+ */
+ buf_offset = (xfer->pipe->isoc_next - nframes) &
+ (EHCI_VIRTUAL_FRAMELIST_COUNT-1);
+
+ /* pre-compute when the isochronous transfer
+ * will be finished:
+ */
+ xfer->isoc_time_complete =
+ usbd_isoc_time_expand(&(sc->sc_bus), nframes) + buf_offset +
+ xfer->nframes;
+
+ /* get the real number of frames */
nframes = xfer->nframes;
@@ -2693,11 +2714,18 @@
DPRINTFN(5,("xfer=%p next=%d nframes=%d\n",
xfer, xfer->pipe->isoc_next, xfer->nframes));
+ /* get the current frame index */
+
nframes = EOREAD4(sc, EHCI_FRINDEX) / 8;
- if(((nframes - xfer->pipe->isoc_next) &
- (EHCI_VIRTUAL_FRAMELIST_COUNT-1)) < xfer->nframes)
- {
+ /* check if the frame index is within
+ * the window where the frames will be
+ * inserted
+ */
+ buf_offset = (nframes - xfer->pipe->isoc_next) &
+ (EHCI_VIRTUAL_FRAMELIST_COUNT-1);
+
+ if (buf_offset < xfer->nframes) {
/* not in use yet, schedule it a few frames ahead */
/* data underflow */
xfer->pipe->isoc_next = (nframes + 3) &
@@ -2705,7 +2733,21 @@
DPRINTFN(2,("start next=%d\n", xfer->pipe->isoc_next));
}
- xfer->isoc_complete_time = (xfer->pipe->isoc_next + ((xfer->nframes+7)/8)) % USBD_ISOC_TIME_MAX;
+ /* compute how many milliseconds the
+ * insertion is ahead of the current
+ * frame position:
+ */
+ buf_offset = (xfer->pipe->isoc_next - nframes) &
+ (EHCI_VIRTUAL_FRAMELIST_COUNT-1);
+
+ /* pre-compute when the isochronous transfer
+ * will be finished:
+ */
+ xfer->isoc_time_complete =
+ usbd_isoc_time_expand(&(sc->sc_bus), nframes) + buf_offset +
+ ((xfer->nframes+7)/8);
+
+ /* get the real number of frames */
nframes = xfer->nframes;
==== //depot/projects/usb/src/sys/dev/usb/ohci.c#19 (text+ko) ====
@@ -1896,16 +1896,34 @@
nframes = le32toh(hw_ptr->hcca.hcca_frame_number);
usbd_page_dma_enter(&(sc->sc_hw_page));
- if((((nframes - xfer->pipe->isoc_next) & ((1<<16)-1)) < xfer->nframes) ||
- (((xfer->pipe->isoc_next - nframes) & ((1<<16)-1)) >= 256))
+ /* check if the frame index is within
+ * the window where the frames will be
+ * inserted and if the delay until start
+ * is too long
+ */
+ if ((((nframes - xfer->pipe->isoc_next) & 0xFFFF) < xfer->nframes) ||
+ (((xfer->pipe->isoc_next - nframes) & 0xFFFF) >= 128))
{
/* not in use yet, schedule it a few frames ahead */
/* data underflow */
- xfer->pipe->isoc_next = (nframes + 5) & ((1<<16)-1);
+ xfer->pipe->isoc_next = (nframes + 3) & 0xFFFF;
DPRINTFN(2,("start next=%d\n", xfer->pipe->isoc_next));
}
- xfer->isoc_complete_time = (xfer->pipe->isoc_next + xfer->nframes) % USBD_ISOC_TIME_MAX;
+ /* compute how many milliseconds the
+ * insertion is ahead of the current
+ * frame position:
+ */
+ buf_offset = ((xfer->pipe->isoc_next - nframes) & 0xFFFF);
+
+ /* pre-compute when the isochronous transfer
+ * will be finished:
+ */
+ xfer->isoc_time_complete =
+ (usbd_isoc_time_expand(&(sc->sc_bus), nframes) + buf_offset +
+ xfer->nframes);
+
+ /* get the real number of frames */
nframes = xfer->nframes;
==== //depot/projects/usb/src/sys/dev/usb/uhci.c#21 (text+ko) ====
@@ -1998,16 +1998,31 @@
nframes = UREAD2(sc, UHCI_FRNUM);
- if(((nframes - xfer->pipe->isoc_next) &
- (UHCI_VFRAMELIST_COUNT-1)) < xfer->nframes)
- {
+ buf_offset = (nframes - xfer->pipe->isoc_next) &
+ (UHCI_VFRAMELIST_COUNT-1);
+
+ if (buf_offset < xfer->nframes) {
/* not in use yet, schedule it a few frames ahead */
/* data underflow */
xfer->pipe->isoc_next = (nframes + 3) & (UHCI_VFRAMELIST_COUNT-1);
DPRINTFN(2,("start next=%d\n", xfer->pipe->isoc_next));
}
- xfer->isoc_complete_time = (xfer->pipe->isoc_next + xfer->nframes) % USBD_ISOC_TIME_MAX;
+ /* compute how many milliseconds the
+ * insertion is ahead of the current
+ * frame position:
+ */
+ buf_offset = (xfer->pipe->isoc_next - nframes) &
+ (UHCI_VFRAMELIST_COUNT-1);
+
+ /* pre-compute when the isochronous transfer
+ * will be finished:
+ */
+ xfer->isoc_time_complete =
+ usbd_isoc_time_expand(&(sc->sc_bus), nframes) + buf_offset +
+ xfer->nframes;
+
+ /* get the real number of frames */
nframes = xfer->nframes;
==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#27 (text+ko) ====
@@ -2774,3 +2774,30 @@
USETW(edesc->wMaxPacketSize, n);
return;
}
+
+/*---------------------------------------------------------------------------*
+ * usbd_isoc_time_expand - expand time counter from 7-bit to 16-bit
+ *---------------------------------------------------------------------------*/
+uint16_t
+usbd_isoc_time_expand(struct usbd_bus *bus, uint16_t isoc_time_curr)
+{
+ uint16_t rem;
+
+ mtx_assert(&(bus->mtx), MA_OWNED);
+
+ rem = bus->isoc_time_last & (USBD_ISOC_TIME_MAX-1);
+
+ isoc_time_curr &= (USBD_ISOC_TIME_MAX-1);
+
+ if (isoc_time_curr < rem) {
+ /* the time counter wrapped around */
+ bus->isoc_time_last += USBD_ISOC_TIME_MAX;
+ }
+
+ /* update the remainder */
+
+ bus->isoc_time_last &= ~(USBD_ISOC_TIME_MAX-1);
+ bus->isoc_time_last |= isoc_time_curr;
+
+ return bus->isoc_time_last;
+}
==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#32 (text+ko) ====
@@ -178,6 +178,9 @@
uint32_t no_intrs;
+ uint16_t isoc_time_last; /* ms */
+#define USBD_ISOC_TIME_MAX 128 /* ms */
+
uint8_t is_exploring;
uint8_t wait_explore;
uint8_t needs_explore;/* Set if a hub signalled a change.
@@ -361,10 +364,8 @@
uint16_t max_packet_size;
uint16_t max_frame_size;
uint16_t qh_pos;
+ uint16_t isoc_time_complete; /* in ms */
-#define USBD_ISOC_TIME_MAX 128 /* ms */
-
- uint8_t isoc_complete_time; /* in ms */
uint8_t address;
uint8_t endpoint;
uint8_t interval; /* milliseconds */
@@ -602,6 +603,7 @@
uint16_t usbd_get_max_packet_count(usb_endpoint_descriptor_t *edesc);
uint16_t usbd_get_max_frame_size(usb_endpoint_descriptor_t *edesc);
void usbd_set_max_packet_size_count(usb_endpoint_descriptor_t *edesc, uint16_t size, uint16_t count);
+uint16_t usbd_isoc_time_expand(struct usbd_bus *bus, uint16_t isoc_time_curr);
/* prototypes from usb.c */
More information about the p4-projects
mailing list