Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Jan 2007 23:33:09 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 113031 for review
Message-ID:  <200701162333.l0GNX9S2059444@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=113031

Change 113031 by hselasky@hselasky_mini_itx on 2007/01/16 23:32:59

	Implement proper support for high speed isochronous and
	interrupt transfer multiplier, bits 11..12 of wMaxPacketSize.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ehci.c#15 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#13 edit
.. //depot/projects/usb/src/sys/dev/usb/ugen.c#10 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#14 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#23 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#27 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ehci.c#15 (text+ko) ====

@@ -1672,7 +1672,7 @@
 	}
 
 	qh->qh_endphub = htole32
-	  (EHCI_QH_SET_MULT(1)|
+	  (EHCI_QH_SET_MULT(xfer->max_packet_count & 3)|
 	   EHCI_QH_SET_CMASK(0xf0));
 
 	if(xfer->udev->myhsport)
@@ -2519,7 +2519,7 @@
 		}
 
 		/* set transfer multiplier */
-		td->itd_bp[2] = htole32(1);
+		td->itd_bp[2] = htole32(xfer->max_packet_count & 3);
 	}
 	return;
 }
@@ -3545,8 +3545,11 @@
 		   (xfer->pipe->methods == &ehci_device_bulk_methods) ||
 		   (xfer->pipe->methods == &ehci_device_intr_methods))
 		{
-			usbd_std_transfer_setup(xfer, setup, 0x400, 0x400);
-
+			if ((xfer->pipe->methods == &ehci_device_intr_methods) &&
+			    (udev->speed == USB_SPEED_HIGH))
+			    usbd_std_transfer_setup(xfer, setup, 0x400, 0xC00, 3);
+			else
+			    usbd_std_transfer_setup(xfer, setup, 0x400, 0x400, 1);
 			nqh = 1;
 			nqtd = (1+ /* SETUP */ 1+ /* STATUS */
 			       1  /* SHORTPKT */) +
@@ -3554,7 +3557,7 @@
 		}
 		else if(xfer->pipe->methods == &ehci_device_isoc_fs_methods)
 		{
-			usbd_std_transfer_setup(xfer, setup, 188, 188);
+			usbd_std_transfer_setup(xfer, setup, 188, 188, 1);
 
 			if(xfer->nframes == 0)
 			{
@@ -3578,7 +3581,7 @@
 		}
 		else if(xfer->pipe->methods == &ehci_device_isoc_hs_methods)
 		{
-			usbd_std_transfer_setup(xfer, setup, 0x400, 0xC00);
+			usbd_std_transfer_setup(xfer, setup, 0x400, 0xC00, 3);
 
 			if(xfer->nframes == 0)
 			{
@@ -3602,7 +3605,7 @@
 		}
 		else
 		{
-			usbd_std_transfer_setup(xfer, setup, 0x400, 0x400);
+			usbd_std_transfer_setup(xfer, setup, 0x400, 0x400, 1);
 		}
 	  }
 

==== //depot/projects/usb/src/sys/dev/usb/ohci.c#13 (text+ko) ====

@@ -2614,7 +2614,7 @@
 	  }
 	  else
 	  {
-		usbd_std_transfer_setup(xfer, setup, 0x500, 0x500);
+		usbd_std_transfer_setup(xfer, setup, 0x500, 0x500, 1);
 
 		/*
 		 * calculate ntd and nqh

==== //depot/projects/usb/src/sys/dev/usb/ugen.c#10 (text+ko) ====

@@ -642,9 +642,9 @@
 			break;
 
 		case UE_ISOCHRONOUS:
-			isize = UGETW(ed->wMaxPacketSize);
+			isize = usbd_get_max_frame_size(ed);
 
-			/* wMaxPacketSize is validated 
+			/* the maximum frame size is validated
 			 * by "usbd_fill_iface_data()" 
 			 */
 
@@ -736,14 +736,15 @@
 		switch(ed->bmAttributes & UE_XFERTYPE)
 		{
 		case UE_INTERRUPT:
+		  isize = usbd_get_max_frame_size(ed);
 		  usbd_config[0].flags = USBD_SHORT_XFER_OK;
 		  usbd_config[0].callback = ugen_interrupt_callback;
-		  usbd_config[0].bufsize = UGETW(ed->wMaxPacketSize);
+		  usbd_config[0].bufsize = isize;
 		  usbd_config[0].interval = USBD_DEFAULT_INTERVAL;
 
 		  if(ugen_allocate_blocks
 		     (sc, sce, UGEN_RD_CFG,
-		      &sce->in_queue, 1, UGETW(ed->wMaxPacketSize)) == 0)
+		      &sce->in_queue, 1, isize) == 0)
 		  {
 			return ENOMEM;
 		  }
@@ -786,9 +787,11 @@
 
 		case UE_ISOCHRONOUS:
 
-		  isize = UGETW(ed->wMaxPacketSize);
+		  isize = usbd_get_max_frame_size(ed);
 
-		  /* wMaxPacketSize is validated by "usbd_fill_iface_data()" */
+		  /* the maximum frame size is validated
+		   * by "usbd_fill_iface_data()" 
+		   */
 
 		  if(usbd_get_speed(sc->sc_udev) == USB_SPEED_HIGH)
 		  {
@@ -1385,7 +1388,7 @@
 	plen1 = xfer->frlengths;
 	ptr1 = xfer->buffer;
 
-	isize = UGETW(sce->pipe_in->edesc->wMaxPacketSize);
+	isize = usbd_get_max_frame_size(sce->pipe_in->edesc);
 	n = sce->in_frames;
 	while(n--)
 	{
@@ -1423,7 +1426,7 @@
 
  tr_setup:
  tr_error:
-	isize = UGETW(sce->pipe_in->edesc->wMaxPacketSize);
+	isize = usbd_get_max_frame_size(sce->pipe_in->edesc);
 	for(n = 0; n < sce->in_frames; n++)
 	{
 		/* setup size for next transfer */
@@ -1454,7 +1457,7 @@
 	plen1 = xfer->frlengths;
 	ptr1 = xfer->buffer;
 
-	isize = UGETW(sce->pipe_out->edesc->wMaxPacketSize);
+	isize = usbd_get_max_frame_size(sce->pipe_out->edesc);
 	n = sce->out_frames;
 	while(n--)
 	{
@@ -1663,7 +1666,7 @@
 	case USB_GET_FRAME_SIZE:
 		if(sce->pipe_in)
 		{
-			*(int *)addr = UGETW(sce->pipe_in->edesc->wMaxPacketSize);
+			*(int *)addr = usbd_get_max_frame_size(sce->pipe_in->edesc);
 		}
 		else
 		{

==== //depot/projects/usb/src/sys/dev/usb/uhci.c#14 (text+ko) ====

@@ -2873,7 +2873,7 @@
 	  }
 	  else
 	  {
-		usbd_std_transfer_setup(xfer, setup, 0x500, 0x500);
+		usbd_std_transfer_setup(xfer, setup, 0x500, 0x500, 1);
 
 		/*
 		 * compute ntd and nqh

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#23 (text+ko) ====

@@ -512,38 +512,27 @@
 
 		if(udev->speed == USB_SPEED_HIGH)
 		{
-			u_int16_t mps;
-			/* control and bulk endpoints have max packet limits */
+			/* control and bulk endpoints have fixed max packet sizes */
 			switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
 			case UE_CONTROL:
-				mps = USB_2_MAX_CTRL_PACKET;
-				goto check;
+				USETW(ed->wMaxPacketSize, USB_2_MAX_CTRL_PACKET);
+				break;
 			case UE_BULK:
-				mps = USB_2_MAX_BULK_PACKET;
-			check:
-				if(UGETW(ed->wMaxPacketSize) != mps)
-				{
-					USETW(ed->wMaxPacketSize, mps);
-#ifdef DIAGNOSTIC
-					printf("%s: bad wMaxPacketSize, addr=%d!\n",
-					       __FUNCTION__, udev->address);
-#endif
-				}
-				break;
-			default:
+				USETW(ed->wMaxPacketSize, USB_2_MAX_BULK_PACKET);
 				break;
 			}
 		}
-		if(UGETW(ed->wMaxPacketSize) == 0)
-		{
+
+		if (usbd_get_max_frame_size(ed) == 0) {
 #ifdef USB_DEBUG
-			printf("%s: invalid wMaxPacketSize, addr=%d!\n",
-			     __FUNCTION__, udev->address);
+			printf("%s: invalid wMaxPacketSize=0x%04x, addr=%d!\n",
+			       __FUNCTION__, UGETW(ed->wMaxPacketSize),
+			       udev->address);
 #endif
-		      /* avoid division by zero 
-		       * (in EHCI/UHCI/OHCI drivers) 
-		       */
-		      USETW(ed->wMaxPacketSize, USB_MAX_IPACKET);
+			/* avoid division by zero 
+			 * (in EHCI/UHCI/OHCI drivers) 
+			 */
+			usbd_set_max_packet_size_count(ed, USB_MAX_IPACKET, 1);
 		}
 
 		/* find a free pipe */
@@ -1293,20 +1282,13 @@
 	if(speed == USB_SPEED_HIGH)
 	{
 		/* max packet size must be 64 (sec 5.5.3) */
-		if(udev->ddesc.bMaxPacketSize != USB_2_MAX_CTRL_PACKET)
-		{
-#ifdef DIAGNOSTIC
-			printf("%s: addr=%d bad max packet size\n",
-			       __FUNCTION__, udev->address);
-#endif
-			udev->ddesc.bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
-		}
+		udev->ddesc.bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
 	}
 
 	if(udev->ddesc.bMaxPacketSize == 0)
 	{
 #ifdef USB_DEBUG
-		printf("%s: addr=%d invalid bMaxPacketSize!\n",
+		printf("%s: addr=%d invalid bMaxPacketSize=0x00!\n",
 		       __FUNCTION__, udev->address);
 #endif
 		/* avoid division by zero */
@@ -2212,7 +2194,8 @@
 void
 usbd_std_transfer_setup(struct usbd_xfer *xfer, 
 			const struct usbd_config *setup, 
-			u_int16_t max_packet_size, u_int16_t max_frame_size)
+			u_int16_t max_packet_size, u_int16_t max_frame_size,
+			uint8_t max_packet_count)
 {
 	__callout_init_mtx(&xfer->timeout_handle, xfer->usb_mtx,
 			   CALLOUT_RETURNUNLOCKED);
@@ -2223,16 +2206,18 @@
 	xfer->callback = setup->callback;
 	xfer->interval = setup->interval;
 	xfer->endpoint = xfer->pipe->edesc->bEndpointAddress;
-	xfer->max_packet_size = UGETW(xfer->pipe->edesc->wMaxPacketSize);
+	xfer->max_packet_size = usbd_get_max_packet_size(xfer->pipe->edesc);
+	xfer->max_packet_count = usbd_get_max_packet_count(xfer->pipe->edesc);
+	xfer->max_frame_size = usbd_get_max_frame_size(xfer->pipe->edesc);
 	xfer->length = setup->bufsize;
 
-	if(xfer->interval == 0)
-	{
+	/* check interrupt interval */
+
+	if (xfer->interval == 0) {
 	    xfer->interval = xfer->pipe->edesc->bInterval;
 	}
 
-	if(xfer->interval == 0)
-	{
+	if (xfer->interval == 0) {
 	    /* one is the smallest interval */
 	    xfer->interval = 1;
 	}
@@ -2247,18 +2232,27 @@
 	    xfer->max_packet_size = max_packet_size;
 	}
 
-	/* frame_size: isochronous frames only */
+	/* check the maximum packet count */
+
+	if (xfer->max_packet_count == 0) {
+	    xfer->max_packet_count = 1;
+	}
+
+	if (xfer->max_packet_count > max_packet_count) {
+	    xfer->max_packet_count = max_packet_count;
+	}
+
+	/* check the maximum frame size */
 
-	xfer->max_frame_size = max_frame_size;
+	if (xfer->max_frame_size > max_frame_size) {
+	    xfer->max_frame_size = max_frame_size;
+	}
 
 	if (xfer->length == 0) {
-	    xfer->length = xfer->max_packet_size;
+	    xfer->length = xfer->max_frame_size;
 	    if (xfer->nframes) {
 	        xfer->length *= xfer->nframes;
 	    }
-	    if (setup->sub_frames) {
-	        xfer->length *= setup->sub_frames;
-	    }
 	}
 	return;
 }
@@ -2677,3 +2671,45 @@
 	}
 	return error;
 }
+
+/*---------------------------------------------------------------------------*
+ * usbd_get_max_packet_size - get maximum packet size
+ *---------------------------------------------------------------------------*/
+uint16_t
+usbd_get_max_packet_size(usb_endpoint_descriptor_t *edesc)
+{
+	return (UGETW(edesc->wMaxPacketSize) & 0x7FF);
+}
+
+/*---------------------------------------------------------------------------*
+ * usbd_get_max_packet_count - get maximum packet count
+ *---------------------------------------------------------------------------*/
+uint16_t
+usbd_get_max_packet_count(usb_endpoint_descriptor_t *edesc)
+{
+	return (1 + ((UGETW(edesc->wMaxPacketSize) >> 11) & 3));
+}
+
+/*---------------------------------------------------------------------------*
+ * usbd_get_max_frame_size - get maximum frame size
+ *---------------------------------------------------------------------------*/
+uint16_t
+usbd_get_max_frame_size(usb_endpoint_descriptor_t *edesc)
+{
+	uint16_t n;
+	n = UGETW(edesc->wMaxPacketSize);
+	return (n & 0x7FF) * (1 + ((n >> 11) & 3));
+}
+
+/*---------------------------------------------------------------------------*
+ * usbd_set_max_packet_size_count - set maximum packet size and count
+ *---------------------------------------------------------------------------*/
+void
+usbd_set_max_packet_size_count(usb_endpoint_descriptor_t *edesc,
+			       uint16_t size, uint16_t count)
+{
+	uint16_t n;
+	n = (size & 0x7FF)|(((count-1) & 3) << 11);
+	USETW(edesc->wMaxPacketSize, n);
+	return;
+}

==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#27 (text+ko) ====

@@ -279,11 +279,6 @@
 					 * used in isochronous
 					 * mode
 					 */
-	u_int8_t	sub_frames;	/* number of sub-frames
-					 * contained within each
-					 * frame. Used in High-Speed
-					 * isochronous mode.
-					 */
 	u_int8_t	index;	/* pipe index to use, if more
 				 * than one descriptor matches
 				 * type, address, direction ...
@@ -376,6 +371,7 @@
 	u_int8_t		address;
 	u_int8_t		endpoint;
 	u_int8_t		interval; /* milliseconds */
+	uint8_t			max_packet_count;
 
 	u_int16_t		max_packet_size;
 	u_int16_t		max_frame_size;
@@ -702,9 +698,8 @@
 #endif
 #endif
 
-void
-usbd_std_transfer_setup(struct usbd_xfer *xfer, const struct usbd_config *setup,
-			u_int16_t max_packet_size, u_int16_t max_frame_size);
+void usbd_std_transfer_setup(struct usbd_xfer *xfer, const struct usbd_config *setup, u_int16_t max_packet_size, u_int16_t max_frame_size, uint8_t max_packet_count);
+
 u_int8_t
 usbd_make_str_desc(void *ptr, u_int16_t max_len, const char *s);
 
@@ -741,6 +736,12 @@
 
 int32_t device_delete_all_children(device_t dev);
 
+uint16_t usbd_get_max_packet_size(usb_endpoint_descriptor_t *edesc);
+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);
+
 /* routines from usb.c */
 
 #if 0



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701162333.l0GNX9S2059444>