--- old/usr/src/pkg/manifests/driver-serial-usbftdi.mf	Sun Dec 16 10:46:50 2012
+++ new/usr/src/pkg/manifests/driver-serial-usbftdi.mf	Sun Dec 16 10:46:50 2012
@@ -64,6 +64,7 @@
     alias=usb856,ac01 \
     alias=usb93c,0601 \
     alias=usb93c,0701 \
+    alias=usbif403,6010.config1.1 \
     alias=usbif9e88,9e8f.config1.1
 file path=kernel/drv/$(ARCH64)/usbftdi group=sys
 $(i386_ONLY)file path=kernel/drv/usbftdi group=sys
--- old/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c	Sun Dec 16 10:46:51 2012
+++ new/usr/src/uts/common/io/usb/clients/usbser/usbftdi/uftdi_dsd.c	Sun Dec 16 10:46:51 2012
@@ -25,6 +25,10 @@
  */
 
 /*
+ * Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+ */
+
+/*
  * FTDI FT232R USB UART device-specific driver
  *
  * May work on the (many) devices based on earlier versions of the chip.
@@ -220,6 +224,7 @@
 	switch (dd->idVendor) {
 	case USB_VENDOR_FTDI:
 		switch (dd->idProduct) {
+		case USB_PRODUCT_FTDI_SERIAL_2232C:
 		case USB_PRODUCT_FTDI_SERIAL_8U232AM:
 		case USB_PRODUCT_FTDI_SEMC_DSS20:
 		case USB_PRODUCT_FTDI_CFA_631:
@@ -328,23 +333,6 @@
 		return (USB_FAILURE);
 	}
 
-	if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip,
-	    &uf->uf_xfer_sz) != USB_SUCCESS) {
-		uftdi_cleanup(uf, 5);
-		return (USB_FAILURE);
-	}
-
-	/*
-	 * TODO: modern ftdi devices have deeper (and asymmetric)
-	 * fifos than this minimal 64 bytes .. but how to tell
-	 * -safely- ?
-	 */
-
-#define	FTDI_MAX_XFERSIZE	64
-
-	if (uf->uf_xfer_sz > FTDI_MAX_XFERSIZE)
-		uf->uf_xfer_sz = FTDI_MAX_XFERSIZE;
-
 	if (uftdi_dev_attach(uf) != USB_SUCCESS) {
 		uftdi_cleanup(uf, 5);
 		return (USB_FAILURE);
@@ -1501,7 +1489,13 @@
 	int ifc, alt;
 	usb_pipe_policy_t policy;
 	usb_ep_data_t *in_data, *out_data;
+	size_t max_xfer_sz;
 
+	/* get max transfer size */
+	if (usb_pipe_get_max_bulk_transfer_size(uf->uf_dip, &max_xfer_sz)
+	    != USB_SUCCESS)
+		return (USB_FAILURE);
+
 	/* get ep data */
 	ifc = uf->uf_dev_data->dev_curr_if;
 	alt = 0;
@@ -1518,6 +1512,21 @@
 		return (USB_FAILURE);
 	}
 
+	/*
+	 * Set buffer sizes. Default to UFTDI_XFER_SZ_MAX.
+	 * Use wMaxPacketSize from endpoint descriptor if it is nonzero..
+	 * Cap at a max transfer size of host controller.
+	 */
+	uf->uf_ibuf_sz = uf->uf_obuf_sz = UFTDI_XFER_SZ_MAX;
+
+	if (in_data->ep_descr.wMaxPacketSize)
+		uf->uf_ibuf_sz = in_data->ep_descr.wMaxPacketSize;
+	uf->uf_ibuf_sz = min(uf->uf_ibuf_sz, max_xfer_sz);
+
+	if (out_data->ep_descr.wMaxPacketSize)
+		uf->uf_obuf_sz = out_data->ep_descr.wMaxPacketSize;
+	uf->uf_obuf_sz = min(uf->uf_obuf_sz, max_xfer_sz);
+
 	/* open pipes */
 	policy.pp_max_async_reqs = 2;
 
@@ -1806,8 +1815,8 @@
 	uf->uf_bulkin_state = UFTDI_PIPE_BUSY;
 	mutex_exit(&uf->uf_lock);
 
-	br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_xfer_sz, USB_FLAGS_SLEEP);
-	br->bulk_len = uf->uf_xfer_sz;
+	br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_ibuf_sz, USB_FLAGS_SLEEP);
+	br->bulk_len = uf->uf_ibuf_sz;
 	br->bulk_timeout = UFTDI_BULKIN_TIMEOUT;
 	br->bulk_cb = uftdi_bulkin_cb;
 	br->bulk_exc_cb = uftdi_bulkin_cb;
@@ -1861,7 +1870,7 @@
 	ASSERT(MBLKL(uf->uf_tx_mp) > 0);
 
 	/* send as much data as port can receive */
-	len = min(msgdsize(uf->uf_tx_mp), uf->uf_xfer_sz);
+	len = min(msgdsize(uf->uf_tx_mp), uf->uf_obuf_sz);
 
 	if (len <= 0)
 		return;
--- old/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h	Sun Dec 16 10:46:52 2012
+++ new/usr/src/uts/common/sys/usb/clients/usbser/usbftdi/uftdi_var.h	Sun Dec 16 10:46:52 2012
@@ -22,6 +22,9 @@
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
+ */
 
 #ifndef _USBSER_USBFTDI_UFTDI_VAR_H
 #define	_USBSER_USBFTDI_UFTDI_VAR_H
@@ -84,7 +87,8 @@
 	int			uf_bulkout_state;	/* out pipe state */
 	usb_log_handle_t	uf_lh;			/* USBA log handle */
 	int			uf_dev_state;		/* USB device state */
-	size_t			uf_xfer_sz;		/* HCI bulk xfer size */
+	size_t			uf_ibuf_sz;		/* input buffer size */
+	size_t			uf_obuf_sz;		/* output buffer size */
 
 	uftdi_pm_t		*uf_pm;			/* PM support */
 
@@ -112,7 +116,8 @@
 	uf_usb_events
 	uf_def_ph
 	uf_lh
-	uf_xfer_sz
+	uf_ibuf_sz
+	uf_obuf_sz
 	uf_pm
 	uf_port_state
 	uf_cb
