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