[Midnightbsd-cvs] src [9518] stable/0.8/sys: Upgrade USB stack to FreeBSD 9-stable version.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Aug 18 22:11:51 EDT 2017


Revision: 9518
          http://svnweb.midnightbsd.org/src/?rev=9518
Author:   laffer1
Date:     2017-08-18 22:11:51 -0400 (Fri, 18 Aug 2017)
Log Message:
-----------
Upgrade USB stack to FreeBSD 9-stable version. (from yesterday)

Modified Paths:
--------------
    stable/0.8/sys/dev/usb/controller/at91dci.c
    stable/0.8/sys/dev/usb/controller/at91dci.h
    stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c
    stable/0.8/sys/dev/usb/controller/atmegadci.c
    stable/0.8/sys/dev/usb/controller/atmegadci.h
    stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c
    stable/0.8/sys/dev/usb/controller/avr32dci.c
    stable/0.8/sys/dev/usb/controller/avr32dci.h
    stable/0.8/sys/dev/usb/controller/ehci.c
    stable/0.8/sys/dev/usb/controller/ehci.h
    stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c
    stable/0.8/sys/dev/usb/controller/ehci_mv.c
    stable/0.8/sys/dev/usb/controller/ehci_pci.c
    stable/0.8/sys/dev/usb/controller/ehcireg.h
    stable/0.8/sys/dev/usb/controller/musb_otg.c
    stable/0.8/sys/dev/usb/controller/musb_otg.h
    stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c
    stable/0.8/sys/dev/usb/controller/ohci.c
    stable/0.8/sys/dev/usb/controller/ohci.h
    stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c
    stable/0.8/sys/dev/usb/controller/ohci_pci.c
    stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c
    stable/0.8/sys/dev/usb/controller/ohcireg.h
    stable/0.8/sys/dev/usb/controller/uhci.c
    stable/0.8/sys/dev/usb/controller/uhci.h
    stable/0.8/sys/dev/usb/controller/uhci_pci.c
    stable/0.8/sys/dev/usb/controller/uhcireg.h
    stable/0.8/sys/dev/usb/controller/usb_controller.c
    stable/0.8/sys/dev/usb/controller/uss820dci.c
    stable/0.8/sys/dev/usb/controller/uss820dci.h
    stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c
    stable/0.8/sys/dev/usb/controller/xhci.c
    stable/0.8/sys/dev/usb/controller/xhci.h
    stable/0.8/sys/dev/usb/controller/xhci_pci.c
    stable/0.8/sys/dev/usb/controller/xhcireg.h
    stable/0.8/sys/dev/usb/input/atp.c
    stable/0.8/sys/dev/usb/input/uep.c
    stable/0.8/sys/dev/usb/input/uhid.c
    stable/0.8/sys/dev/usb/input/ukbd.c
    stable/0.8/sys/dev/usb/input/ums.c
    stable/0.8/sys/dev/usb/input/usb_rdesc.h
    stable/0.8/sys/dev/usb/misc/udbp.c
    stable/0.8/sys/dev/usb/misc/udbp.h
    stable/0.8/sys/dev/usb/misc/ufm.c
    stable/0.8/sys/dev/usb/net/if_aue.c
    stable/0.8/sys/dev/usb/net/if_auereg.h
    stable/0.8/sys/dev/usb/net/if_axe.c
    stable/0.8/sys/dev/usb/net/if_axereg.h
    stable/0.8/sys/dev/usb/net/if_cdce.c
    stable/0.8/sys/dev/usb/net/if_cdcereg.h
    stable/0.8/sys/dev/usb/net/if_cue.c
    stable/0.8/sys/dev/usb/net/if_cuereg.h
    stable/0.8/sys/dev/usb/net/if_ipheth.c
    stable/0.8/sys/dev/usb/net/if_iphethvar.h
    stable/0.8/sys/dev/usb/net/if_kue.c
    stable/0.8/sys/dev/usb/net/if_kuefw.h
    stable/0.8/sys/dev/usb/net/if_kuereg.h
    stable/0.8/sys/dev/usb/net/if_mos.c
    stable/0.8/sys/dev/usb/net/if_mosreg.h
    stable/0.8/sys/dev/usb/net/if_rue.c
    stable/0.8/sys/dev/usb/net/if_ruereg.h
    stable/0.8/sys/dev/usb/net/if_udav.c
    stable/0.8/sys/dev/usb/net/if_udavreg.h
    stable/0.8/sys/dev/usb/net/if_usie.c
    stable/0.8/sys/dev/usb/net/if_usievar.h
    stable/0.8/sys/dev/usb/net/ruephy.c
    stable/0.8/sys/dev/usb/net/ruephyreg.h
    stable/0.8/sys/dev/usb/net/uhso.c
    stable/0.8/sys/dev/usb/net/usb_ethernet.c
    stable/0.8/sys/dev/usb/net/usb_ethernet.h
    stable/0.8/sys/dev/usb/quirk/usb_quirk.c
    stable/0.8/sys/dev/usb/quirk/usb_quirk.h
    stable/0.8/sys/dev/usb/serial/u3g.c
    stable/0.8/sys/dev/usb/serial/uark.c
    stable/0.8/sys/dev/usb/serial/ubsa.c
    stable/0.8/sys/dev/usb/serial/ubser.c
    stable/0.8/sys/dev/usb/serial/uchcom.c
    stable/0.8/sys/dev/usb/serial/ucycom.c
    stable/0.8/sys/dev/usb/serial/ufoma.c
    stable/0.8/sys/dev/usb/serial/uftdi.c
    stable/0.8/sys/dev/usb/serial/uftdi_reg.h
    stable/0.8/sys/dev/usb/serial/ugensa.c
    stable/0.8/sys/dev/usb/serial/uipaq.c
    stable/0.8/sys/dev/usb/serial/ulpt.c
    stable/0.8/sys/dev/usb/serial/umcs.c
    stable/0.8/sys/dev/usb/serial/umcs.h
    stable/0.8/sys/dev/usb/serial/umct.c
    stable/0.8/sys/dev/usb/serial/umodem.c
    stable/0.8/sys/dev/usb/serial/umoscom.c
    stable/0.8/sys/dev/usb/serial/uplcom.c
    stable/0.8/sys/dev/usb/serial/usb_serial.c
    stable/0.8/sys/dev/usb/serial/usb_serial.h
    stable/0.8/sys/dev/usb/serial/uslcom.c
    stable/0.8/sys/dev/usb/serial/uvisor.c
    stable/0.8/sys/dev/usb/serial/uvscom.c
    stable/0.8/sys/dev/usb/storage/rio500_usb.h
    stable/0.8/sys/dev/usb/storage/umass.c
    stable/0.8/sys/dev/usb/storage/urio.c
    stable/0.8/sys/dev/usb/storage/ustorage_fs.c
    stable/0.8/sys/dev/usb/template/usb_template.c
    stable/0.8/sys/dev/usb/template/usb_template.h
    stable/0.8/sys/dev/usb/template/usb_template_audio.c
    stable/0.8/sys/dev/usb/template/usb_template_cdce.c
    stable/0.8/sys/dev/usb/template/usb_template_kbd.c
    stable/0.8/sys/dev/usb/template/usb_template_modem.c
    stable/0.8/sys/dev/usb/template/usb_template_mouse.c
    stable/0.8/sys/dev/usb/template/usb_template_msc.c
    stable/0.8/sys/dev/usb/template/usb_template_mtp.c
    stable/0.8/sys/dev/usb/ufm_ioctl.h
    stable/0.8/sys/dev/usb/usb.h
    stable/0.8/sys/dev/usb/usb_bus.h
    stable/0.8/sys/dev/usb/usb_busdma.c
    stable/0.8/sys/dev/usb/usb_busdma.h
    stable/0.8/sys/dev/usb/usb_cdc.h
    stable/0.8/sys/dev/usb/usb_compat_linux.c
    stable/0.8/sys/dev/usb/usb_compat_linux.h
    stable/0.8/sys/dev/usb/usb_controller.h
    stable/0.8/sys/dev/usb/usb_core.c
    stable/0.8/sys/dev/usb/usb_core.h
    stable/0.8/sys/dev/usb/usb_debug.c
    stable/0.8/sys/dev/usb/usb_debug.h
    stable/0.8/sys/dev/usb/usb_dev.c
    stable/0.8/sys/dev/usb/usb_dev.h
    stable/0.8/sys/dev/usb/usb_device.c
    stable/0.8/sys/dev/usb/usb_device.h
    stable/0.8/sys/dev/usb/usb_dynamic.c
    stable/0.8/sys/dev/usb/usb_dynamic.h
    stable/0.8/sys/dev/usb/usb_endian.h
    stable/0.8/sys/dev/usb/usb_error.c
    stable/0.8/sys/dev/usb/usb_freebsd.h
    stable/0.8/sys/dev/usb/usb_generic.c
    stable/0.8/sys/dev/usb/usb_generic.h
    stable/0.8/sys/dev/usb/usb_handle_request.c
    stable/0.8/sys/dev/usb/usb_hid.c
    stable/0.8/sys/dev/usb/usb_hub.c
    stable/0.8/sys/dev/usb/usb_hub.h
    stable/0.8/sys/dev/usb/usb_if.m
    stable/0.8/sys/dev/usb/usb_ioctl.h
    stable/0.8/sys/dev/usb/usb_lookup.c
    stable/0.8/sys/dev/usb/usb_mbuf.c
    stable/0.8/sys/dev/usb/usb_mbuf.h
    stable/0.8/sys/dev/usb/usb_msctest.c
    stable/0.8/sys/dev/usb/usb_msctest.h
    stable/0.8/sys/dev/usb/usb_parse.c
    stable/0.8/sys/dev/usb/usb_pci.h
    stable/0.8/sys/dev/usb/usb_pf.c
    stable/0.8/sys/dev/usb/usb_pf.h
    stable/0.8/sys/dev/usb/usb_process.c
    stable/0.8/sys/dev/usb/usb_process.h
    stable/0.8/sys/dev/usb/usb_request.c
    stable/0.8/sys/dev/usb/usb_request.h
    stable/0.8/sys/dev/usb/usb_transfer.c
    stable/0.8/sys/dev/usb/usb_transfer.h
    stable/0.8/sys/dev/usb/usb_util.c
    stable/0.8/sys/dev/usb/usb_util.h
    stable/0.8/sys/dev/usb/usbdevs
    stable/0.8/sys/dev/usb/usbdi.h
    stable/0.8/sys/dev/usb/usbdi_util.h
    stable/0.8/sys/dev/usb/usbhid.h
    stable/0.8/sys/dev/usb/wlan/if_rum.c
    stable/0.8/sys/dev/usb/wlan/if_rumfw.h
    stable/0.8/sys/dev/usb/wlan/if_rumreg.h
    stable/0.8/sys/dev/usb/wlan/if_rumvar.h
    stable/0.8/sys/dev/usb/wlan/if_run.c
    stable/0.8/sys/dev/usb/wlan/if_runreg.h
    stable/0.8/sys/dev/usb/wlan/if_runvar.h
    stable/0.8/sys/dev/usb/wlan/if_uath.c
    stable/0.8/sys/dev/usb/wlan/if_uathreg.h
    stable/0.8/sys/dev/usb/wlan/if_uathvar.h
    stable/0.8/sys/dev/usb/wlan/if_upgt.c
    stable/0.8/sys/dev/usb/wlan/if_upgtvar.h
    stable/0.8/sys/dev/usb/wlan/if_ural.c
    stable/0.8/sys/dev/usb/wlan/if_uralreg.h
    stable/0.8/sys/dev/usb/wlan/if_uralvar.h
    stable/0.8/sys/dev/usb/wlan/if_urtw.c
    stable/0.8/sys/dev/usb/wlan/if_urtwreg.h
    stable/0.8/sys/dev/usb/wlan/if_urtwvar.h
    stable/0.8/sys/dev/usb/wlan/if_zyd.c
    stable/0.8/sys/dev/usb/wlan/if_zydfw.h
    stable/0.8/sys/dev/usb/wlan/if_zydreg.h
    stable/0.8/sys/fs/devfs/devfs_int.h
    stable/0.8/sys/kern/kern_conf.c
    stable/0.8/sys/sys/conf.h

Added Paths:
-----------
    stable/0.8/sys/dev/usb/input/wsp.c
    stable/0.8/sys/dev/usb/net/if_axge.c
    stable/0.8/sys/dev/usb/net/if_axgereg.h
    stable/0.8/sys/dev/usb/net/if_urndis.c
    stable/0.8/sys/dev/usb/net/if_urndisreg.h
    stable/0.8/sys/dev/usb/uftdiio.h

Property Changed:
----------------
    stable/0.8/sys/fs/devfs/devfs_int.h

Modified: stable/0.8/sys/dev/usb/controller/at91dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/at91dci.c 257040 2013-10-24 06:06:17Z hselasky $");
 
 /*-
  * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -2277,10 +2277,6 @@
 
 	if (udev->device_index != sc->sc_rt_addr) {
 
-		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
-			/* not supported */
-			return;
-		}
 		if (udev->speed != USB_SPEED_FULL) {
 			/* not supported */
 			return;

Modified: stable/0.8/sys/dev/usb/controller/at91dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/at91dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
 /*-
  * Copyright (c) 2006 ATMEL
  * Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>

Modified: stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/at91dci_atmelarm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/at91dci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /*-
  * Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -159,6 +159,7 @@
 	sc->sc_dci.sc_bus.parent = dev;
 	sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
 	sc->sc_dci.sc_bus.devices_max = AT91_MAX_DEVICES;
+	sc->sc_dci.sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
@@ -261,14 +262,8 @@
 at91_udp_detach(device_t dev)
 {
 	struct at91_udp_softc *sc = device_get_softc(dev);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_dci.sc_bus.bdev) {
-		bdev = sc->sc_dci.sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(dev);
 

Modified: stable/0.8/sys/dev/usb/controller/atmegadci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/atmegadci.c 257040 2013-10-24 06:06:17Z hselasky $");
 
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -2110,10 +2110,6 @@
 
 	if (udev->device_index != sc->sc_rt_addr) {
 
-		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
-			/* not supported */
-			return;
-		}
 		if (udev->speed != USB_SPEED_FULL) {
 			/* not supported */
 			return;

Modified: stable/0.8/sys/dev/usb/controller/atmegadci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/atmegadci.h 229096 2011-12-31 14:22:02Z hselasky $ */
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/atmegadci_atmelarm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/atmegadci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -101,6 +101,7 @@
 	sc->sc_otg.sc_bus.parent = dev;
 	sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
 	sc->sc_otg.sc_bus.devices_max = ATMEGA_MAX_DEVICES;
+	sc->sc_otg.sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
@@ -154,14 +155,8 @@
 atmegadci_detach(device_t dev)
 {
 	struct atmegadci_super_softc *sc = device_get_softc(dev);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_otg.sc_bus.bdev) {
-		bdev = sc->sc_otg.sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(dev);
 

Modified: stable/0.8/sys/dev/usb/controller/avr32dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/avr32dci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/avr32dci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/avr32dci.c 257040 2013-10-24 06:06:17Z hselasky $");
 
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -2054,10 +2054,6 @@
 
 	if (udev->device_index != sc->sc_rt_addr) {
 
-		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
-			/* not supported */
-			return;
-		}
 		if ((udev->speed != USB_SPEED_FULL) &&
 		    (udev->speed != USB_SPEED_HIGH)) {
 			/* not supported */

Modified: stable/0.8/sys/dev/usb/controller/avr32dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/avr32dci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/avr32dci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/avr32dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
 /*-
  * Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/controller/ehci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci.c 273887 2014-10-31 07:59:07Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -212,7 +212,7 @@
 			return (0);
 		}
 	}
-	device_printf(sc->sc_bus.bdev, "Reset timeout\n");
+	device_printf(sc->sc_bus.bdev, "reset timeout\n");
 	return (USB_ERR_IOERROR);
 }
 
@@ -256,7 +256,7 @@
 		DPRINTF("HCC uses 64-bit structures\n");
 
 		/* MUST clear segment register if 64 bit capable */
-		EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
+		EOWRITE4(sc, EHCI_CTRLDSSEGMENT, 0);
 	}
 
 	usbd_get_page(&sc->sc_hw.pframes_pc, 0, &buf_res);
@@ -287,7 +287,7 @@
 		}
 	}
 	if (hcr) {
-		device_printf(sc->sc_bus.bdev, "Run timeout\n");
+		device_printf(sc->sc_bus.bdev, "run timeout\n");
 		return (USB_ERR_IOERROR);
 	}
 	return (USB_ERR_NORMAL_COMPLETION);
@@ -1195,9 +1195,16 @@
 		    (status & EHCI_QTD_PINGSTATE) ? "[PING]" : "");
 	}
 #endif
-
-	return ((status & EHCI_QTD_HALTED) ?
-	    USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION);
+	if (status & EHCI_QTD_HALTED) {
+		if ((xfer->xroot->udev->parent_hs_hub != NULL) ||
+		    (xfer->xroot->udev->address != 0)) {
+			/* try to separate I/O errors from STALL */
+			if (EHCI_QTD_GET_CERR(status) == 0)
+				return (USB_ERR_IOERROR);
+		}
+		return (USB_ERR_STALLED);
+	}
+	return (USB_ERR_NORMAL_COMPLETION);
 }
 
 static void
@@ -1651,12 +1658,17 @@
 			}
 			td->len = 0;
 
+			/* properly reset reserved fields */
 			td->qtd_buffer[0] = 0;
+			td->qtd_buffer[1] = 0;
+			td->qtd_buffer[2] = 0;
+			td->qtd_buffer[3] = 0;
+			td->qtd_buffer[4] = 0;
 			td->qtd_buffer_hi[0] = 0;
-
-			td->qtd_buffer[1] = 0;
 			td->qtd_buffer_hi[1] = 0;
-
+			td->qtd_buffer_hi[2] = 0;
+			td->qtd_buffer_hi[3] = 0;
+			td->qtd_buffer_hi[4] = 0;
 		} else {
 
 			uint8_t x;
@@ -1711,6 +1723,12 @@
 			    htohc32(temp->sc,
 			    buf_res.physaddr & (~0xFFF));
 			td->qtd_buffer_hi[x] = 0;
+
+			/* properly reset reserved fields */
+			while (++x < EHCI_QTD_NBUFFERS) {
+				td->qtd_buffer[x] = 0;
+				td->qtd_buffer_hi[x] = 0;
+			}
 		}
 
 		if (td_next) {
@@ -1998,6 +2016,18 @@
 	qh->qh_qtd.qtd_altnext =
 	    htohc32(temp.sc, EHCI_LINK_TERMINATE);
 
+	/* properly reset reserved fields */
+	qh->qh_qtd.qtd_buffer[0] = 0;
+	qh->qh_qtd.qtd_buffer[1] = 0;
+	qh->qh_qtd.qtd_buffer[2] = 0;
+	qh->qh_qtd.qtd_buffer[3] = 0;
+	qh->qh_qtd.qtd_buffer[4] = 0;
+	qh->qh_qtd.qtd_buffer_hi[0] = 0;
+	qh->qh_qtd.qtd_buffer_hi[1] = 0;
+	qh->qh_qtd.qtd_buffer_hi[2] = 0;
+	qh->qh_qtd.qtd_buffer_hi[3] = 0;
+	qh->qh_qtd.qtd_buffer_hi[4] = 0;
+
 	usb_pc_cpu_flush(qh->page_cache);
 
 	if (xfer->xroot->udev->flags.self_suspended == 0) {
@@ -2228,10 +2258,26 @@
 }
 
 static void
+ehci_doorbell_async(struct ehci_softc *sc)
+{
+	uint32_t temp;
+
+	/*
+	 * XXX Performance quirk: Some Host Controllers have a too low
+	 * interrupt rate. Issue an IAAD to stimulate the Host
+	 * Controller after queueing the BULK transfer.
+	 *
+	 * XXX Force the host controller to refresh any QH caches.
+	 */
+	temp = EOREAD4(sc, EHCI_USBCMD);
+	if (!(temp & EHCI_CMD_IAAD))
+		EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
+}
+
+static void
 ehci_device_bulk_start(struct usb_xfer *xfer)
 {
 	ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-	uint32_t temp;
 
 	/* setup TD's and QH */
 	ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
@@ -2246,13 +2292,7 @@
 	if (sc->sc_flags & EHCI_SCFLG_IAADBUG)
 		return;
 
-	/* XXX Performance quirk: Some Host Controllers have a too low
-	 * interrupt rate. Issue an IAAD to stimulate the Host
-	 * Controller after queueing the BULK transfer.
-	 */
-	temp = EOREAD4(sc, EHCI_USBCMD);
-	if (!(temp & EHCI_CMD_IAAD))
-		EOWRITE4(sc, EHCI_USBCMD, temp | EHCI_CMD_IAAD);
+	ehci_doorbell_async(sc);
 }
 
 struct usb_pipe_methods ehci_device_bulk_methods =
@@ -3705,10 +3745,6 @@
 	    edesc->bEndpointAddress, udev->flags.usb_mode,
 	    sc->sc_addr);
 
-	if (udev->flags.usb_mode != USB_MODE_HOST) {
-		/* not supported */
-		return;
-	}
 	if (udev->device_index != sc->sc_addr) {
 
 		if ((udev->speed != USB_SPEED_HIGH) &&
@@ -3752,7 +3788,7 @@
 	 * Wait until the hardware has finished any possible use of
 	 * the transfer descriptor(s) and QH
 	 */
-	*pus = (188);			/* microseconds */
+	*pus = (1125);			/* microseconds */
 }
 
 static void
@@ -3873,6 +3909,41 @@
 	return;
 }
 
+static void
+ehci_start_dma_delay_second(struct usb_xfer *xfer)
+{
+	struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
+
+	DPRINTF("\n");
+
+	/* trigger doorbell */
+	ehci_doorbell_async(sc);
+
+	/* give the doorbell 4ms */
+	usbd_transfer_timeout_ms(xfer,
+	    (void (*)(void *))&usb_dma_delay_done_cb, 4);
+}
+
+/*
+ * Ring the doorbell twice before freeing any DMA descriptors. Some host
+ * controllers apparently cache the QH descriptors and need a message
+ * that the cache needs to be discarded.
+ */
+static void
+ehci_start_dma_delay(struct usb_xfer *xfer)
+{
+	struct ehci_softc *sc = EHCI_BUS2SC(xfer->xroot->bus);
+
+	DPRINTF("\n");
+
+	/* trigger doorbell */
+	ehci_doorbell_async(sc);
+
+	/* give the doorbell 4ms */
+	usbd_transfer_timeout_ms(xfer,
+	    (void (*)(void *))&ehci_start_dma_delay_second, 4);
+}
+
 struct usb_bus_methods ehci_bus_methods =
 {
 	.endpoint_init = ehci_ep_init,
@@ -3885,4 +3956,5 @@
 	.set_hw_power_sleep = ehci_set_hw_power_sleep,
 	.roothub_exec = ehci_roothub_exec,
 	.xfer_poll = ehci_do_poll,
+	.start_dma_delay = ehci_start_dma_delay,
 };

Modified: stable/0.8/sys/dev/usb/controller/ehci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ehci.h 242776 2012-11-08 16:17:52Z hselasky $ */
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_ixp4xx.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_ixp4xx.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 #include "opt_bus.h"
 
@@ -107,6 +107,7 @@
 	sc->sc_bus.parent = self;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -206,14 +207,8 @@
 {
 	struct ixp_ehci_softc *isc = device_get_softc(self);
 	ehci_softc_t *sc = &isc->base;
-	device_t bdev;
 	int err;
 
- 	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 

Modified: stable/0.8/sys/dev/usb/controller/ehci_mv.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_mv.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_mv.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_mv.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 #include "opt_bus.h"
 
@@ -123,6 +123,7 @@
 	sc->sc_bus.parent = self;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -238,14 +239,8 @@
 mv_ehci_detach(device_t self)
 {
 	ehci_softc_t *sc = device_get_softc(self);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 

Modified: stable/0.8/sys/dev/usb/controller/ehci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehci_pci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehci_pci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ehci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /*
  * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
@@ -120,10 +120,16 @@
 	case 0x43961002:
 		return ("AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller");
 
+	case 0x1d268086:
+		return ("Intel Patsburg USB 2.0 controller");
+	case 0x1d2d8086:
+		return ("Intel Patsburg USB 2.0 controller");
 	case 0x1e268086:
 		return ("Intel Panther Point USB 2.0 controller");
 	case 0x1e2d8086:
 		return ("Intel Panther Point USB 2.0 controller");
+	case 0x1f2c8086:
+		return ("Intel Avoton USB 2.0 controller");
 	case 0x25ad8086:
 		return "Intel 6300ESB USB 2.0 controller";
 	case 0x24cd8086:
@@ -152,6 +158,14 @@
 		return ("Intel PCH USB 2.0 controller USB-A");
 	case 0x3b3c8086:
 		return ("Intel PCH USB 2.0 controller USB-B");
+	case 0x8c268086:
+		return ("Intel Lynx Point USB 2.0 controller USB-A");
+	case 0x8c2d8086:
+		return ("Intel Lynx Point USB 2.0 controller USB-B");
+	case 0x8ca68086:
+		return ("Intel Wildcat Point USB 2.0 controller USB-A");
+	case 0x8cad8086:
+		return ("Intel Wildcat Point USB 2.0 controller USB-B");
 
 	case 0x00e01033:
 		return ("NEC uPD 720100 USB 2.0 controller");
@@ -165,7 +179,7 @@
 	case 0x00e810de:
 		return "NVIDIA nForce3 250 USB 2.0 controller";
 	case 0x005b10de:
-		return "NVIDIA nForce4 USB 2.0 controller";
+		return "NVIDIA nForce CK804 USB 2.0 controller";
 	case 0x036d10de:
 		return "NVIDIA nForce MCP55 USB 2.0 controller";
 	case 0x03f210de:
@@ -264,6 +278,7 @@
 	sc->sc_bus.parent = self;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -452,13 +467,7 @@
 ehci_pci_detach(device_t self)
 {
 	ehci_softc_t *sc = device_get_softc(self);
-	device_t bdev;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 

Modified: stable/0.8/sys/dev/usb/controller/ehcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ehcireg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ehcireg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ehcireg.h 214349 2010-10-25 15:51:43Z nwhitehorn $ */
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/musb_otg.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/musb_otg.c 279280 2015-02-25 12:26:45Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -90,6 +90,8 @@
     &musbotgdebug, 0, "Debug level");
 #endif
 
+#define	MAX_NAK_TO	16
+
 /* prototypes */
 
 struct usb_bus_methods musbotg_bus_methods;
@@ -98,17 +100,35 @@
 struct usb_pipe_methods musbotg_device_intr_methods;
 struct usb_pipe_methods musbotg_device_isoc_methods;
 
-static musbotg_cmd_t musbotg_setup_rx;
-static musbotg_cmd_t musbotg_setup_data_rx;
-static musbotg_cmd_t musbotg_setup_data_tx;
-static musbotg_cmd_t musbotg_setup_status;
-static musbotg_cmd_t musbotg_data_rx;
-static musbotg_cmd_t musbotg_data_tx;
+/* Control transfers: Device mode */
+static musbotg_cmd_t musbotg_dev_ctrl_setup_rx;
+static musbotg_cmd_t musbotg_dev_ctrl_data_rx;
+static musbotg_cmd_t musbotg_dev_ctrl_data_tx;
+static musbotg_cmd_t musbotg_dev_ctrl_status;
+
+/* Control transfers: Host mode */
+static musbotg_cmd_t musbotg_host_ctrl_setup_tx;
+static musbotg_cmd_t musbotg_host_ctrl_data_rx;
+static musbotg_cmd_t musbotg_host_ctrl_data_tx;
+static musbotg_cmd_t musbotg_host_ctrl_status_rx;
+static musbotg_cmd_t musbotg_host_ctrl_status_tx;
+
+/* Bulk, Interrupt, Isochronous: Device mode */
+static musbotg_cmd_t musbotg_dev_data_rx;
+static musbotg_cmd_t musbotg_dev_data_tx;
+
+/* Bulk, Interrupt, Isochronous: Host mode */
+static musbotg_cmd_t musbotg_host_data_rx;
+static musbotg_cmd_t musbotg_host_data_tx;
+
 static void	musbotg_device_done(struct usb_xfer *, usb_error_t);
 static void	musbotg_do_poll(struct usb_bus *);
 static void	musbotg_standard_done(struct usb_xfer *);
 static void	musbotg_interrupt_poll(struct musbotg_softc *);
 static void	musbotg_root_intr(struct musbotg_softc *);
+static int	musbotg_channel_alloc(struct musbotg_softc *, struct musbotg_td *td);
+static void	musbotg_channel_free(struct musbotg_softc *, struct musbotg_td *td);
+static void	musbotg_ep_int_set(struct musbotg_softc *sc, int channel, int on);
 
 /*
  * Here is a configuration that the chip supports.
@@ -123,6 +143,64 @@
 	}
 };
 
+static int
+musbotg_channel_alloc(struct musbotg_softc *sc, struct musbotg_td *td)
+{
+	int ch;
+	int ep;
+
+	ep = td->ep_no;
+
+	/* In device mode each EP got its own channel */
+	if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+		musbotg_ep_int_set(sc, ep, 1);
+		return (ep);
+	}
+
+	/*
+	 * All control transactions go through EP0
+	 */
+	if (ep == 0) {
+		if (sc->sc_channel_mask & (1 << 0))
+			return (-1);
+		sc->sc_channel_mask |= (1 << 0);
+		musbotg_ep_int_set(sc, ep, 1);
+		return (0);
+	}
+
+	for (ch = 1; ch < MUSB2_EP_MAX; ch++) {
+		if (!(sc->sc_channel_mask & (1 << ch))) {
+			sc->sc_channel_mask |= (1 << ch);
+			musbotg_ep_int_set(sc, ch, 1);
+			return (ch);
+		}
+	}
+
+	DPRINTFN(-1, "No available channels. Mask: %04x\n",  sc->sc_channel_mask);
+
+	return (-1);
+}
+
+static void	
+musbotg_channel_free(struct musbotg_softc *sc, struct musbotg_td *td)
+{
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	if (sc->sc_mode == MUSB2_DEVICE_MODE)
+		return;
+
+	if (td == NULL)
+		return;
+	if (td->channel == -1)
+		return;
+
+	musbotg_ep_int_set(sc, td->channel, 0);
+	sc->sc_channel_mask &= ~(1 << td->channel);
+
+	td->channel = -1;
+}
+
 static void
 musbotg_get_hw_ep_profile(struct usb_device *udev,
     const struct usb_hw_ep_profile **ppf, uint8_t ep_addr)
@@ -213,6 +291,46 @@
 }
 
 static void
+musbotg_suspend_host(struct musbotg_softc *sc)
+{
+	uint8_t temp;
+
+	if (sc->sc_flags.status_suspend) {
+		return;
+	}
+
+	temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+	temp |= MUSB2_MASK_SUSPMODE;
+	MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+	sc->sc_flags.status_suspend = 1;
+}
+
+static void
+musbotg_wakeup_host(struct musbotg_softc *sc)
+{
+	uint8_t temp;
+
+	if (!(sc->sc_flags.status_suspend)) {
+		return;
+	}
+
+	temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+	temp &= ~MUSB2_MASK_SUSPMODE;
+	temp |= MUSB2_MASK_RESUME;
+	MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+
+	/* wait 20 milliseconds */
+	/* Wait for reset to complete. */
+	usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 50);
+
+	temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+	temp &= ~MUSB2_MASK_RESUME;
+	MUSB2_WRITE_1(sc, MUSB2_REG_POWER, temp);
+
+	sc->sc_flags.status_suspend = 0;
+}
+
+static void
 musbotg_wakeup_peer(struct musbotg_softc *sc)
 {
 	uint8_t temp;
@@ -243,7 +361,7 @@
 }
 
 static uint8_t
-musbotg_setup_rx(struct musbotg_td *td)
+musbotg_dev_ctrl_setup_rx(struct musbotg_td *td)
 {
 	struct musbotg_softc *sc;
 	struct usb_device_request req;
@@ -253,6 +371,15 @@
 	/* get pointer to softc */
 	sc = MUSBOTG_PC2SC(td->pc);
 
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
 	/* select endpoint 0 */
 	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
 
@@ -269,8 +396,10 @@
 		/* do not stall at this point */
 		td->did_stall = 1;
 		/* wait for interrupt */
+		DPRINTFN(1, "CSR0 DATAEND\n");
 		goto not_complete;
 	}
+
 	if (csr & MUSB2_MASK_CSR0L_SENTSTALL) {
 		/* clear SENTSTALL */
 		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
@@ -289,31 +418,37 @@
 		sc->sc_ep0_busy = 0;
 	}
 	if (sc->sc_ep0_busy) {
+		DPRINTFN(1, "EP0 BUSY\n");
 		goto not_complete;
 	}
 	if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
 		goto not_complete;
 	}
-	/* clear did stall flag */
-	td->did_stall = 0;
 	/* get the packet byte count */
 	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
 
 	/* verify data length */
 	if (count != td->remainder) {
-		DPRINTFN(0, "Invalid SETUP packet "
+		DPRINTFN(1, "Invalid SETUP packet "
 		    "length, %d bytes\n", count);
 		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
 		      MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+		/* don't clear stall */
+		td->did_stall = 1;
 		goto not_complete;
 	}
 	if (count != sizeof(req)) {
-		DPRINTFN(0, "Unsupported SETUP packet "
+		DPRINTFN(1, "Unsupported SETUP packet "
 		    "length, %d bytes\n", count);
 		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
 		      MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+		/* don't clear stall */
+		td->did_stall = 1;
 		goto not_complete;
 	}
+	/* clear did stall flag */
+	td->did_stall = 0;
+
 	/* receive data */
 	bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
 	    MUSB2_REG_EPFIFO(0), (void *)&req, sizeof(req));
@@ -337,6 +472,8 @@
 	} else {
 		sc->sc_dv_addr = 0xFF;
 	}
+
+	musbotg_channel_free(sc, td);
 	return (0);			/* complete */
 
 not_complete:
@@ -350,10 +487,117 @@
 	return (1);			/* not complete */
 }
 
+static uint8_t
+musbotg_host_ctrl_setup_tx(struct musbotg_td *td)
+{
+	struct musbotg_softc *sc;
+	struct usb_device_request req;
+	uint8_t csr, csrh;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	/* select endpoint 0 */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+	/* read out FIFO status */
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	/* Not ready yet yet */
+	if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+		return (1);
+
+	/* Failed */
+	if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+	    MUSB2_MASK_CSR0L_ERROR))
+	{
+		/* Clear status bit */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+		td->error = 1;
+	}
+
+	if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+		DPRINTFN(1, "NAK timeout\n");
+
+		if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+			csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+			csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+			MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+			csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+				csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+				csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+				MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+				csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			}
+		}
+
+		csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		td->error = 1;
+	}
+
+	if (td->error) {
+		musbotg_channel_free(sc, td);
+		return (0);
+	}
+
+	/* Fifo is not empty and there is no NAK timeout */
+	if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+		return (1);
+
+	/* check if we are complete */
+	if (td->remainder == 0) {
+		/* we are complete */
+		musbotg_channel_free(sc, td);
+		return (0);
+	}
+
+	/* copy data into real buffer */
+	usbd_copy_out(td->pc, 0, &req, sizeof(req));
+
+	/* send data */
+	bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+	    MUSB2_REG_EPFIFO(0), (void *)&req, sizeof(req));
+
+	/* update offset and remainder */
+	td->offset += sizeof(req);
+	td->remainder -= sizeof(req);
+
+
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+	/* write command */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+	    MUSB2_MASK_CSR0L_TXPKTRDY | 
+	    MUSB2_MASK_CSR0L_SETUPPKT);
+
+	/* Just to be consistent, not used above */
+	td->transaction_started = 1;
+
+	return (1);			/* in progress */
+}
+
 /* Control endpoint only data handling functions (RX/TX/SYNC) */
 
 static uint8_t
-musbotg_setup_data_rx(struct musbotg_td *td)
+musbotg_dev_ctrl_data_rx(struct musbotg_td *td)
 {
 	struct usb_page_search buf_res;
 	struct musbotg_softc *sc;
@@ -496,7 +740,7 @@
 }
 
 static uint8_t
-musbotg_setup_data_tx(struct musbotg_td *td)
+musbotg_dev_ctrl_data_tx(struct musbotg_td *td)
 {
 	struct usb_page_search buf_res;
 	struct musbotg_softc *sc;
@@ -614,17 +858,373 @@
 }
 
 static uint8_t
-musbotg_setup_status(struct musbotg_td *td)
+musbotg_host_ctrl_data_rx(struct musbotg_td *td)
 {
+	struct usb_page_search buf_res;
 	struct musbotg_softc *sc;
+	uint16_t count;
 	uint8_t csr;
+	uint8_t got_short;
 
 	/* get pointer to softc */
 	sc = MUSBOTG_PC2SC(td->pc);
 
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
 	/* select endpoint 0 */
 	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
 
+	/* read out FIFO status */
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	got_short = 0;
+	if (!td->transaction_started) {
+		td->transaction_started = 1;
+
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(0),
+		    td->dev_addr);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(0), td->haddr);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(0), td->hport);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+		    MUSB2_MASK_CSR0L_REQPKT);
+
+		return (1);
+	}
+
+	if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+		csr &= ~MUSB2_MASK_CSR0L_REQPKT;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		td->error = 1;
+	}
+
+	/* Failed */
+	if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+	    MUSB2_MASK_CSR0L_ERROR))
+	{
+		/* Clear status bit */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+		td->error = 1;
+	}
+
+	if (td->error) {
+		musbotg_channel_free(sc, td);
+		return (0);	/* we are complete */
+	}
+
+	if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY))
+		return (1); /* not yet */
+
+	/* get the packet byte count */
+	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
+
+	/* verify the packet byte count */
+	if (count != td->max_frame_size) {
+		if (count < td->max_frame_size) {
+			/* we have a short packet */
+			td->short_pkt = 1;
+			got_short = 1;
+		} else {
+			/* invalid USB packet */
+			td->error = 1;
+			musbotg_channel_free(sc, td);
+			return (0);	/* we are complete */
+		}
+	}
+	/* verify the packet byte count */
+	if (count > td->remainder) {
+		/* invalid USB packet */
+		td->error = 1;
+		musbotg_channel_free(sc, td);
+		return (0);		/* we are complete */
+	}
+	while (count > 0) {
+		uint32_t temp;
+
+		usbd_get_page(td->pc, td->offset, &buf_res);
+
+		/* get correct length */
+		if (buf_res.length > count) {
+			buf_res.length = count;
+		}
+		/* check for unaligned memory address */
+		if (USB_P2U(buf_res.buffer) & 3) {
+
+			temp = count & ~3;
+
+			if (temp) {
+				/* receive data 4 bytes at a time */
+				bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+				    MUSB2_REG_EPFIFO(0), sc->sc_bounce_buf,
+				    temp / 4);
+			}
+			temp = count & 3;
+			if (temp) {
+				/* receive data 1 byte at a time */
+				bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+				    MUSB2_REG_EPFIFO(0),
+				    (void *)(&sc->sc_bounce_buf[count / 4]), temp);
+			}
+			usbd_copy_in(td->pc, td->offset,
+			    sc->sc_bounce_buf, count);
+
+			/* update offset and remainder */
+			td->offset += count;
+			td->remainder -= count;
+			break;
+		}
+		/* check if we can optimise */
+		if (buf_res.length >= 4) {
+
+			/* receive data 4 bytes at a time */
+			bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+			    MUSB2_REG_EPFIFO(0), buf_res.buffer,
+			    buf_res.length / 4);
+
+			temp = buf_res.length & ~3;
+
+			/* update counters */
+			count -= temp;
+			td->offset += temp;
+			td->remainder -= temp;
+			continue;
+		}
+		/* receive data */
+		bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+		    MUSB2_REG_EPFIFO(0), buf_res.buffer, buf_res.length);
+
+		/* update counters */
+		count -= buf_res.length;
+		td->offset += buf_res.length;
+		td->remainder -= buf_res.length;
+	}
+
+	csr &= ~MUSB2_MASK_CSR0L_RXPKTRDY;
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+	/* check if we are complete */
+	if ((td->remainder == 0) || got_short) {
+		if (td->short_pkt) {
+			/* we are complete */
+
+			musbotg_channel_free(sc, td);
+			return (0);
+		}
+		/* else need to receive a zero length packet */
+	}
+
+	td->transaction_started = 1;
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+	    MUSB2_MASK_CSR0L_REQPKT);
+
+	return (1);			/* not complete */
+}
+
+static uint8_t
+musbotg_host_ctrl_data_tx(struct musbotg_td *td)
+{
+	struct usb_page_search buf_res;
+	struct musbotg_softc *sc;
+	uint16_t count;
+	uint8_t csr, csrh;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* No free EPs */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	/* select endpoint */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+	/* read out FIFO status */
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+	    MUSB2_MASK_CSR0L_ERROR)) {
+		/* clear status bits */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		td->error = 1;
+	}
+
+	if (csr & MUSB2_MASK_CSR0L_NAKTIMO ) {
+
+		if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+			csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+			csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+			MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+			csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
+				csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+				csrh |= MUSB2_MASK_CSR0H_FFLUSH;
+				MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+				csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			}
+		}
+
+		csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		td->error = 1;
+	}
+
+
+	if (td->error) {
+		musbotg_channel_free(sc, td);
+		return (0);	/* complete */
+	}
+
+	/*
+	 * Wait while FIFO is empty. 
+	 * Do not flush it because it will cause transactions
+	 * with size more then packet size. It might upset
+	 * some devices
+	 */
+	if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY)
+		return (1);
+
+	/* Packet still being processed */
+	if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+		return (1);
+
+	if (td->transaction_started) {
+		/* check remainder */
+		if (td->remainder == 0) {
+			if (td->short_pkt) {
+				musbotg_channel_free(sc, td);
+				return (0);	/* complete */
+			}
+			/* else we need to transmit a short packet */
+		}
+
+		/* We're not complete - more transactions required */
+		td->transaction_started = 0;
+	}
+
+	/* check for short packet */
+	count = td->max_frame_size;
+	if (td->remainder < count) {
+		/* we have a short packet */
+		td->short_pkt = 1;
+		count = td->remainder;
+	}
+
+	while (count > 0) {
+		uint32_t temp;
+
+		usbd_get_page(td->pc, td->offset, &buf_res);
+
+		/* get correct length */
+		if (buf_res.length > count) {
+			buf_res.length = count;
+		}
+		/* check for unaligned memory address */
+		if (USB_P2U(buf_res.buffer) & 3) {
+
+			usbd_copy_out(td->pc, td->offset,
+			    sc->sc_bounce_buf, count);
+
+			temp = count & ~3;
+
+			if (temp) {
+				/* transmit data 4 bytes at a time */
+				bus_space_write_multi_4(sc->sc_io_tag,
+				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(0),
+				    sc->sc_bounce_buf, temp / 4);
+			}
+			temp = count & 3;
+			if (temp) {
+				/* receive data 1 byte at a time */
+				bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+				    MUSB2_REG_EPFIFO(0),
+				    ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+			}
+			/* update offset and remainder */
+			td->offset += count;
+			td->remainder -= count;
+			break;
+		}
+		/* check if we can optimise */
+		if (buf_res.length >= 4) {
+
+			/* transmit data 4 bytes at a time */
+			bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+			    MUSB2_REG_EPFIFO(0), buf_res.buffer,
+			    buf_res.length / 4);
+
+			temp = buf_res.length & ~3;
+
+			/* update counters */
+			count -= temp;
+			td->offset += temp;
+			td->remainder -= temp;
+			continue;
+		}
+		/* transmit data */
+		bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+		    MUSB2_REG_EPFIFO(0), buf_res.buffer,
+		    buf_res.length);
+
+		/* update counters */
+		count -= buf_res.length;
+		td->offset += buf_res.length;
+		td->remainder -= buf_res.length;
+	}
+
+	/* Function address */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+	/* TX NAK timeout */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+	/* write command */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+	    MUSB2_MASK_CSR0L_TXPKTRDY);
+
+	td->transaction_started = 1;
+
+	return (1);			/* not complete */
+}
+
+static uint8_t
+musbotg_dev_ctrl_status(struct musbotg_td *td)
+{
+	struct musbotg_softc *sc;
+	uint8_t csr;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	/* select endpoint 0 */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
 	if (sc->sc_ep0_busy) {
 		sc->sc_ep0_busy = 0;
 		sc->sc_ep0_cmd |= MUSB2_MASK_CSR0L_DATAEND;
@@ -644,12 +1244,167 @@
 		/* write function address */
 		musbotg_set_address(sc, sc->sc_dv_addr);
 	}
+
+	musbotg_channel_free(sc, td);
 	return (0);			/* complete */
 }
 
 static uint8_t
-musbotg_data_rx(struct musbotg_td *td)
+musbotg_host_ctrl_status_rx(struct musbotg_td *td)
 {
+	struct musbotg_softc *sc;
+	uint8_t csr, csrh;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	/* select endpoint 0 */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+	if (!td->transaction_started) {
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(0),
+		    td->dev_addr);
+
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(0), td->haddr);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(0), td->hport);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+		/* RX NAK timeout */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+		td->transaction_started = 1;
+
+		/* Disable PING */
+		csrh = MUSB2_READ_1(sc, MUSB2_REG_RXCSRH);
+		csrh |= MUSB2_MASK_CSR0H_PING_DIS;
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, csrh);
+
+		/* write command */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+		    MUSB2_MASK_CSR0L_STATUSPKT | 
+		    MUSB2_MASK_CSR0L_REQPKT);
+
+		return (1); /* Just started */
+
+	}
+
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+
+	DPRINTFN(4, "IN STATUS csr=0x%02x\n", csr);
+
+	if (csr & MUSB2_MASK_CSR0L_RXPKTRDY) {
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+		    MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
+		musbotg_channel_free(sc, td);
+		return (0); /* complete */
+	}
+
+	if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
+		csr &= ~ (MUSB2_MASK_CSR0L_STATUSPKT |
+		    MUSB2_MASK_CSR0L_REQPKT);
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+		td->error = 1;
+	}
+
+	/* Failed */
+	if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+	    MUSB2_MASK_CSR0L_ERROR))
+	{
+		/* Clear status bit */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+		td->error = 1;
+	}
+
+	if (td->error) {
+		musbotg_channel_free(sc, td);
+		return (0);
+	}
+
+	return (1);			/* Not ready yet */
+}
+
+static uint8_t
+musbotg_host_ctrl_status_tx(struct musbotg_td *td)
+{
+	struct musbotg_softc *sc;
+	uint8_t csr;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d/%d [%d@%d.%d/%02x]\n", td->channel, td->transaction_started, 
+			td->dev_addr,td->haddr,td->hport, td->transfer_type);
+
+	/* select endpoint 0 */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, 0);
+
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	/* Not yet */
+	if (csr & MUSB2_MASK_CSR0L_TXPKTRDY)
+		return (1);
+
+	/* Failed */
+	if (csr & (MUSB2_MASK_CSR0L_RXSTALL |
+	    MUSB2_MASK_CSR0L_ERROR))
+	{
+		/* Clear status bit */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		DPRINTFN(1, "error bit set, csr=0x%02x\n", csr);
+		td->error = 1;
+		musbotg_channel_free(sc, td);
+		return (0); /* complete */
+	}
+
+	if (td->transaction_started) {
+		musbotg_channel_free(sc, td);
+		return (0); /* complete */
+	} 
+
+	MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, MUSB2_MASK_CSR0H_PING_DIS);
+
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(0), td->dev_addr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(0), td->haddr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(0), td->hport);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+	/* TX NAK timeout */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+	td->transaction_started = 1;
+
+	/* write command */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+	    MUSB2_MASK_CSR0L_STATUSPKT | 
+	    MUSB2_MASK_CSR0L_TXPKTRDY);
+
+	return (1);			/* wait for interrupt */
+}
+
+static uint8_t
+musbotg_dev_data_rx(struct musbotg_td *td)
+{
 	struct usb_page_search buf_res;
 	struct musbotg_softc *sc;
 	uint16_t count;
@@ -663,8 +1418,15 @@
 	/* get pointer to softc */
 	sc = MUSBOTG_PC2SC(td->pc);
 
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
 	/* select endpoint */
-	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
 
 repeat:
 	/* read out FIFO status */
@@ -678,10 +1440,11 @@
 		MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
 		    MUSB2_MASK_CSRL_RXPKTRDY);
 	}
+
 	/* check status */
-	if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY)) {
-		return (1);		/* not complete */
-	}
+	if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY))
+		return (1); /* not complete */
+
 	/* get the packet byte count */
 	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
 
@@ -698,6 +1461,7 @@
 		} else {
 			/* invalid USB packet */
 			td->error = 1;
+			musbotg_channel_free(sc, td);
 			return (0);	/* we are complete */
 		}
 	}
@@ -705,6 +1469,7 @@
 	if (count > td->remainder) {
 		/* invalid USB packet */
 		td->error = 1;
+		musbotg_channel_free(sc, td);
 		return (0);		/* we are complete */
 	}
 	while (count > 0) {
@@ -724,7 +1489,7 @@
 			if (temp) {
 				/* receive data 4 bytes at a time */
 				bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
-				    MUSB2_REG_EPFIFO(td->ep_no), sc->sc_bounce_buf,
+				    MUSB2_REG_EPFIFO(td->channel), sc->sc_bounce_buf,
 				    temp / 4);
 			}
 			temp = count & 3;
@@ -731,7 +1496,7 @@
 			if (temp) {
 				/* receive data 1 byte at a time */
 				bus_space_read_multi_1(sc->sc_io_tag,
-				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
+				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
 				    ((void *)&sc->sc_bounce_buf[count / 4]), temp);
 			}
 			usbd_copy_in(td->pc, td->offset,
@@ -747,7 +1512,7 @@
 
 			/* receive data 4 bytes at a time */
 			bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
-			    MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+			    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
 			    buf_res.length / 4);
 
 			temp = buf_res.length & ~3;
@@ -760,7 +1525,7 @@
 		}
 		/* receive data */
 		bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
-		    MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+		    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
 		    buf_res.length);
 
 		/* update counters */
@@ -776,6 +1541,7 @@
 	if ((td->remainder == 0) || got_short) {
 		if (td->short_pkt) {
 			/* we are complete */
+			musbotg_channel_free(sc, td);
 			return (0);
 		}
 		/* else need to receive a zero length packet */
@@ -787,7 +1553,7 @@
 }
 
 static uint8_t
-musbotg_data_tx(struct musbotg_td *td)
+musbotg_dev_data_tx(struct musbotg_td *td)
 {
 	struct usb_page_search buf_res;
 	struct musbotg_softc *sc;
@@ -800,8 +1566,15 @@
 	/* get pointer to softc */
 	sc = MUSBOTG_PC2SC(td->pc);
 
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* EP0 is busy, wait */
+	if (td->channel == -1)
+		return (1);
+
 	/* select endpoint */
-	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->ep_no);
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
 
 repeat:
 
@@ -845,7 +1618,7 @@
 			if (temp) {
 				/* transmit data 4 bytes at a time */
 				bus_space_write_multi_4(sc->sc_io_tag,
-				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->ep_no),
+				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
 				    sc->sc_bounce_buf, temp / 4);
 			}
 			temp = count & 3;
@@ -852,7 +1625,7 @@
 			if (temp) {
 				/* receive data 1 byte at a time */
 				bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
-				    MUSB2_REG_EPFIFO(td->ep_no),
+				    MUSB2_REG_EPFIFO(td->channel),
 				    ((void *)&sc->sc_bounce_buf[count / 4]), temp);
 			}
 			/* update offset and remainder */
@@ -865,7 +1638,7 @@
 
 			/* transmit data 4 bytes at a time */
 			bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
-			    MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+			    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
 			    buf_res.length / 4);
 
 			temp = buf_res.length & ~3;
@@ -878,7 +1651,7 @@
 		}
 		/* transmit data */
 		bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
-		    MUSB2_REG_EPFIFO(td->ep_no), buf_res.buffer,
+		    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
 		    buf_res.length);
 
 		/* update counters */
@@ -887,6 +1660,9 @@
 		td->remainder -= buf_res.length;
 	}
 
+	/* Max packet size */
+	MUSB2_WRITE_2(sc, MUSB2_REG_TXMAXP, td->reg_max_packet);
+
 	/* write command */
 	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
 	    MUSB2_MASK_CSRL_TXPKTRDY);
@@ -894,6 +1670,7 @@
 	/* check remainder */
 	if (td->remainder == 0) {
 		if (td->short_pkt) {
+			musbotg_channel_free(sc, td);
 			return (0);	/* complete */
 		}
 		/* else we need to transmit a short packet */
@@ -905,6 +1682,433 @@
 }
 
 static uint8_t
+musbotg_host_data_rx(struct musbotg_td *td)
+{
+	struct usb_page_search buf_res;
+	struct musbotg_softc *sc;
+	uint16_t count;
+	uint8_t csr, csrh;
+	uint8_t to;
+	uint8_t got_short;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* No free EPs */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	to = 8;				/* don't loop forever! */
+	got_short = 0;
+
+	/* select endpoint */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
+
+repeat:
+	/* read out FIFO status */
+	csr = MUSB2_READ_1(sc, MUSB2_REG_RXCSRL);
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	if (!td->transaction_started) {
+		/* Function address */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXFADDR(td->channel),
+		    td->dev_addr);
+
+		/* SPLIT transaction */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHADDR(td->channel), 
+		    td->haddr);
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXHUBPORT(td->channel), 
+		    td->hport);
+
+		/* RX NAK timeout */
+		if (td->transfer_type & MUSB2_MASK_TI_PROTO_ISOC)
+			MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, 0);
+		else
+			MUSB2_WRITE_1(sc, MUSB2_REG_RXNAKLIMIT, MAX_NAK_TO);
+
+		/* Protocol, speed, device endpoint */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXTI, td->transfer_type);
+
+		/* Max packet size */
+		MUSB2_WRITE_2(sc, MUSB2_REG_RXMAXP, td->reg_max_packet);
+
+		/* Data Toggle */
+		csrh = MUSB2_READ_1(sc, MUSB2_REG_RXCSRH);
+		DPRINTFN(4, "csrh=0x%02x\n", csrh);
+
+		csrh |= MUSB2_MASK_CSRH_RXDT_WREN;
+		if (td->toggle)
+			csrh |= MUSB2_MASK_CSRH_RXDT_VAL;
+		else
+			csrh &= ~MUSB2_MASK_CSRH_RXDT_VAL;
+
+		/* Set data toggle */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRH, csrh);
+
+		/* write command */
+		MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL,
+		    MUSB2_MASK_CSRL_RXREQPKT);
+
+		td->transaction_started = 1;
+		return (1);
+	}
+
+	/* clear NAK timeout */
+	if (csr & MUSB2_MASK_CSRL_RXNAKTO) {
+		DPRINTFN(4, "NAK Timeout\n");
+		if (csr & MUSB2_MASK_CSRL_RXREQPKT) {
+			csr &= ~MUSB2_MASK_CSRL_RXREQPKT;
+			MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, csr);
+
+			csr &= ~MUSB2_MASK_CSRL_RXNAKTO;
+			MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, csr);
+		}
+
+		td->error = 1;
+	}
+
+	if (csr & MUSB2_MASK_CSRL_RXERROR) {
+		DPRINTFN(4, "RXERROR\n");
+		td->error = 1;
+	}
+
+	if (csr & MUSB2_MASK_CSRL_RXSTALL) {
+		DPRINTFN(4, "RXSTALL\n");
+		td->error = 1;
+	}
+
+	if (td->error) {
+		musbotg_channel_free(sc, td);
+		return (0);	/* we are complete */
+	}
+
+	if (!(csr & MUSB2_MASK_CSRL_RXPKTRDY)) {
+		/* No data available yet */
+		return (1);
+	}
+
+	td->toggle ^= 1;
+	/* get the packet byte count */
+	count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
+	DPRINTFN(4, "count=0x%04x\n", count);
+
+	/*
+	 * Check for short or invalid packet:
+	 */
+	if (count != td->max_frame_size) {
+		if (count < td->max_frame_size) {
+			/* we have a short packet */
+			td->short_pkt = 1;
+			got_short = 1;
+		} else {
+			/* invalid USB packet */
+			td->error = 1;
+			musbotg_channel_free(sc, td);
+			return (0);	/* we are complete */
+		}
+	}
+
+	/* verify the packet byte count */
+	if (count > td->remainder) {
+		/* invalid USB packet */
+		td->error = 1;
+		musbotg_channel_free(sc, td);
+		return (0);		/* we are complete */
+	}
+
+	while (count > 0) {
+		uint32_t temp;
+
+		usbd_get_page(td->pc, td->offset, &buf_res);
+
+		/* get correct length */
+		if (buf_res.length > count) {
+			buf_res.length = count;
+		}
+		/* check for unaligned memory address */
+		if (USB_P2U(buf_res.buffer) & 3) {
+
+			temp = count & ~3;
+
+			if (temp) {
+				/* receive data 4 bytes at a time */
+				bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+				    MUSB2_REG_EPFIFO(td->channel), sc->sc_bounce_buf,
+				    temp / 4);
+			}
+			temp = count & 3;
+			if (temp) {
+				/* receive data 1 byte at a time */
+				bus_space_read_multi_1(sc->sc_io_tag,
+				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
+				    ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+			}
+			usbd_copy_in(td->pc, td->offset,
+			    sc->sc_bounce_buf, count);
+
+			/* update offset and remainder */
+			td->offset += count;
+			td->remainder -= count;
+			break;
+		}
+		/* check if we can optimise */
+		if (buf_res.length >= 4) {
+
+			/* receive data 4 bytes at a time */
+			bus_space_read_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+			    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+			    buf_res.length / 4);
+
+			temp = buf_res.length & ~3;
+
+			/* update counters */
+			count -= temp;
+			td->offset += temp;
+			td->remainder -= temp;
+			continue;
+		}
+		/* receive data */
+		bus_space_read_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+		    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+		    buf_res.length);
+
+		/* update counters */
+		count -= buf_res.length;
+		td->offset += buf_res.length;
+		td->remainder -= buf_res.length;
+	}
+
+	/* clear status bits */
+	MUSB2_WRITE_1(sc, MUSB2_REG_RXCSRL, 0);
+
+	/* check if we are complete */
+	if ((td->remainder == 0) || got_short) {
+		if (td->short_pkt) {
+			/* we are complete */
+			musbotg_channel_free(sc, td);
+			return (0);
+		}
+		/* else need to receive a zero length packet */
+	}
+
+	/* Reset transaction state and restart */
+	td->transaction_started = 0;
+
+	if (--to)
+		goto repeat;
+
+	return (1);			/* not complete */
+}
+
+static uint8_t
+musbotg_host_data_tx(struct musbotg_td *td)
+{
+	struct usb_page_search buf_res;
+	struct musbotg_softc *sc;
+	uint16_t count;
+	uint8_t csr, csrh;
+
+	/* get pointer to softc */
+	sc = MUSBOTG_PC2SC(td->pc);
+
+	if (td->channel == -1)
+		td->channel = musbotg_channel_alloc(sc, td);
+
+	/* No free EPs */
+	if (td->channel == -1)
+		return (1);
+
+	DPRINTFN(1, "ep_no=%d\n", td->channel);
+
+	/* select endpoint */
+	MUSB2_WRITE_1(sc, MUSB2_REG_EPINDEX, td->channel);
+
+	/* read out FIFO status */
+	csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+	DPRINTFN(4, "csr=0x%02x\n", csr);
+
+	if (csr & (MUSB2_MASK_CSRL_TXSTALLED |
+	    MUSB2_MASK_CSRL_TXERROR)) {
+		/* clear status bits */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, 0);
+		td->error = 1;
+		musbotg_channel_free(sc, td);
+		return (0);	/* complete */
+	}
+
+	if (csr & MUSB2_MASK_CSRL_TXNAKTO) {
+		/* 
+		 * Flush TX FIFO before clearing NAK TO
+		 */
+		if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
+			csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+			MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+			csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
+				csr |= MUSB2_MASK_CSRL_TXFFLUSH;
+				MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+				csr = MUSB2_READ_1(sc, MUSB2_REG_TXCSRL);
+			}
+		}
+
+		csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL, csr);
+
+		td->error = 1;
+		musbotg_channel_free(sc, td);
+		return (0);	/* complete */
+	}
+
+	/*
+	 * Wait while FIFO is empty. 
+	 * Do not flush it because it will cause transactions
+	 * with size more then packet size. It might upset
+	 * some devices
+	 */
+	if (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY)
+		return (1);
+
+	/* Packet still being processed */
+	if (csr & MUSB2_MASK_CSRL_TXPKTRDY)
+		return (1);
+
+	if (td->transaction_started) {
+		/* check remainder */
+		if (td->remainder == 0) {
+			if (td->short_pkt) {
+				musbotg_channel_free(sc, td);
+				return (0);	/* complete */
+			}
+			/* else we need to transmit a short packet */
+		}
+
+		/* We're not complete - more transactions required */
+		td->transaction_started = 0;
+	}
+
+	/* check for short packet */
+	count = td->max_frame_size;
+	if (td->remainder < count) {
+		/* we have a short packet */
+		td->short_pkt = 1;
+		count = td->remainder;
+	}
+
+	while (count > 0) {
+		uint32_t temp;
+
+		usbd_get_page(td->pc, td->offset, &buf_res);
+
+		/* get correct length */
+		if (buf_res.length > count) {
+			buf_res.length = count;
+		}
+		/* check for unaligned memory address */
+		if (USB_P2U(buf_res.buffer) & 3) {
+
+			usbd_copy_out(td->pc, td->offset,
+			    sc->sc_bounce_buf, count);
+
+			temp = count & ~3;
+
+			if (temp) {
+				/* transmit data 4 bytes at a time */
+				bus_space_write_multi_4(sc->sc_io_tag,
+				    sc->sc_io_hdl, MUSB2_REG_EPFIFO(td->channel),
+				    sc->sc_bounce_buf, temp / 4);
+			}
+			temp = count & 3;
+			if (temp) {
+				/* receive data 1 byte at a time */
+				bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+				    MUSB2_REG_EPFIFO(td->channel),
+				    ((void *)&sc->sc_bounce_buf[count / 4]), temp);
+			}
+			/* update offset and remainder */
+			td->offset += count;
+			td->remainder -= count;
+			break;
+		}
+		/* check if we can optimise */
+		if (buf_res.length >= 4) {
+
+			/* transmit data 4 bytes at a time */
+			bus_space_write_multi_4(sc->sc_io_tag, sc->sc_io_hdl,
+			    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+			    buf_res.length / 4);
+
+			temp = buf_res.length & ~3;
+
+			/* update counters */
+			count -= temp;
+			td->offset += temp;
+			td->remainder -= temp;
+			continue;
+		}
+		/* transmit data */
+		bus_space_write_multi_1(sc->sc_io_tag, sc->sc_io_hdl,
+		    MUSB2_REG_EPFIFO(td->channel), buf_res.buffer,
+		    buf_res.length);
+
+		/* update counters */
+		count -= buf_res.length;
+		td->offset += buf_res.length;
+		td->remainder -= buf_res.length;
+	}
+
+	/* Function address */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXFADDR(td->channel),
+	    td->dev_addr);
+
+	/* SPLIT transaction */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHADDR(td->channel), 
+	    td->haddr);
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXHUBPORT(td->channel), 
+	    td->hport);
+
+	/* TX NAK timeout */
+	if (td->transfer_type & MUSB2_MASK_TI_PROTO_ISOC)
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, 0);
+	else
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXNAKLIMIT, MAX_NAK_TO);
+
+	/* Protocol, speed, device endpoint */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXTI, td->transfer_type);
+
+	/* Max packet size */
+	MUSB2_WRITE_2(sc, MUSB2_REG_TXMAXP, td->reg_max_packet);
+
+	if (!td->transaction_started) {
+		csrh = MUSB2_READ_1(sc, MUSB2_REG_TXCSRH);
+		DPRINTFN(4, "csrh=0x%02x\n", csrh);
+
+		csrh |= MUSB2_MASK_CSRH_TXDT_WREN;
+		if (td->toggle)
+			csrh |= MUSB2_MASK_CSRH_TXDT_VAL;
+		else
+			csrh &= ~MUSB2_MASK_CSRH_TXDT_VAL;
+
+		/* Set data toggle */
+		MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRH, csrh);
+	}
+
+	/* write command */
+	MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+	    MUSB2_MASK_CSRL_TXPKTRDY);
+
+	/* Update Data Toggle */
+	td->toggle ^= 1;
+	td->transaction_started = 1;
+
+	return (1);			/* not complete */
+}
+
+static uint8_t
 musbotg_xfer_do_fifo(struct usb_xfer *xfer)
 {
 	struct musbotg_softc *sc;
@@ -911,13 +2115,16 @@
 	struct musbotg_td *td;
 
 	DPRINTFN(8, "\n");
+	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
 
 	td = xfer->td_transfer_cache;
 	while (1) {
+
 		if ((td->func) (td)) {
 			/* operation in progress */
 			break;
 		}
+
 		if (((void *)td) == xfer->td_transfer_last) {
 			goto done;
 		}
@@ -939,13 +2146,10 @@
 		td = td->obj_next;
 		xfer->td_transfer_cache = td;
 	}
+
 	return (1);			/* not complete */
-
 done:
-	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
 	/* compute all actual lengths */
-
 	musbotg_standard_done(xfer);
 
 	return (0);			/* complete */
@@ -995,8 +2199,20 @@
 }
 
 void
-musbotg_interrupt(struct musbotg_softc *sc)
+musbotg_connect_interrupt(struct musbotg_softc *sc)
 {
+	USB_BUS_LOCK(&sc->sc_bus);
+	sc->sc_flags.change_connect = 1;
+
+	/* complete root HUB interrupt endpoint */
+	musbotg_root_intr(sc);
+	USB_BUS_UNLOCK(&sc->sc_bus);
+}
+
+void
+musbotg_interrupt(struct musbotg_softc *sc,
+    uint16_t rxstat, uint16_t txstat, uint8_t stat)
+{
 	uint16_t rx_status;
 	uint16_t tx_status;
 	uint8_t usb_status;
@@ -1013,11 +2229,21 @@
 	/* read all FIFO interrupts */
 	rx_status = MUSB2_READ_2(sc, MUSB2_REG_INTRX);
 	tx_status = MUSB2_READ_2(sc, MUSB2_REG_INTTX);
+	rx_status |= rxstat;
+	tx_status |= txstat;
+	usb_status |= stat;
 
+	/* Clear platform flags after first time */
+	rxstat = 0;
+	txstat = 0;
+	stat = 0;
+
 	/* check for any bus state change interrupts */
 
 	if (usb_status & (MUSB2_MASK_IRESET |
-	    MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP)) {
+	    MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP | 
+	    MUSB2_MASK_ICONN | MUSB2_MASK_IDISC |
+	    MUSB2_MASK_IVBUSERR)) {
 
 		DPRINTFN(4, "real bus interrupt 0x%08x\n", usb_status);
 
@@ -1080,6 +2306,27 @@
 				MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, temp);
 			}
 		}
+		if (usb_status & 
+		    (MUSB2_MASK_ICONN | MUSB2_MASK_IDISC))
+			sc->sc_flags.change_connect = 1;
+
+		/* 
+		 * Host Mode: There is no IRESET so assume bus is 
+		 * always in reset state once device is connected.
+		 */
+		if (sc->sc_mode == MUSB2_HOST_MODE) {
+		    /* check for VBUS error in USB host mode */
+		    if (usb_status & MUSB2_MASK_IVBUSERR) {
+			temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+			temp |= MUSB2_MASK_SESS;
+			MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+		    }
+		    if (usb_status & MUSB2_MASK_ICONN)
+			sc->sc_flags.status_bus_reset = 1;
+		    if (usb_status & MUSB2_MASK_IDISC)
+			sc->sc_flags.status_bus_reset = 0;
+		}
+
 		/* complete root HUB interrupt endpoint */
 		musbotg_root_intr(sc);
 	}
@@ -1117,9 +2364,15 @@
 	td->offset = temp->offset;
 	td->remainder = temp->len;
 	td->error = 0;
+	td->transaction_started = 0;
 	td->did_stall = temp->did_stall;
 	td->short_pkt = temp->short_pkt;
 	td->alt_next = temp->setup_alt_next;
+	td->channel = temp->channel;
+	td->dev_addr = temp->dev_addr;
+	td->haddr = temp->haddr;
+	td->hport = temp->hport;
+	td->transfer_type = temp->transfer_type;
 }
 
 static void
@@ -1130,11 +2383,18 @@
 	struct musbotg_td *td;
 	uint32_t x;
 	uint8_t ep_no;
+	uint8_t xfer_type;
+	enum usb_dev_speed speed;
+	int tx;
+	int dev_addr;
 
 	DPRINTFN(8, "addr=%d endpt=%d sumlen=%d speed=%d\n",
 	    xfer->address, UE_GET_ADDR(xfer->endpointno),
 	    xfer->sumlen, usbd_get_speed(xfer->xroot->udev));
 
+	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
+	ep_no = (xfer->endpointno & UE_ADDR);
+
 	temp.max_frame_size = xfer->max_frame_size;
 
 	td = xfer->td_start[0];
@@ -1142,7 +2402,10 @@
 	xfer->td_transfer_cache = td;
 
 	/* setup temp */
+	dev_addr = xfer->address;
 
+	xfer_type = xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE;
+
 	temp.pc = NULL;
 	temp.td = NULL;
 	temp.td_next = xfer->td_start[0];
@@ -1149,16 +2412,63 @@
 	temp.offset = 0;
 	temp.setup_alt_next = xfer->flags_int.short_frames_ok;
 	temp.did_stall = !xfer->flags_int.control_stall;
+	temp.channel = -1;
+	temp.dev_addr = dev_addr;
+	temp.haddr = xfer->xroot->udev->hs_hub_addr;
+	temp.hport = xfer->xroot->udev->hs_port_no;
 
-	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-	ep_no = (xfer->endpointno & UE_ADDR);
+	if (xfer->flags_int.usb_mode == USB_MODE_HOST) {
+		speed =  usbd_get_speed(xfer->xroot->udev);
 
+		switch (speed) {
+			case USB_SPEED_LOW:
+				temp.transfer_type = MUSB2_MASK_TI_SPEED_LO;
+				break;
+			case USB_SPEED_FULL:
+				temp.transfer_type = MUSB2_MASK_TI_SPEED_FS;
+				break;
+			case USB_SPEED_HIGH:
+				temp.transfer_type = MUSB2_MASK_TI_SPEED_HS;
+				break;
+			default:
+				temp.transfer_type = 0;
+				DPRINTFN(-1, "Invalid USB speed: %d\n", speed);
+				break;
+		}
+
+		switch (xfer_type) {
+			case UE_CONTROL:
+				temp.transfer_type |= MUSB2_MASK_TI_PROTO_CTRL;
+				break;
+			case UE_ISOCHRONOUS:
+				temp.transfer_type |= MUSB2_MASK_TI_PROTO_ISOC;
+				break;
+			case UE_BULK:
+				temp.transfer_type |= MUSB2_MASK_TI_PROTO_BULK;
+				break;
+			case UE_INTERRUPT:
+				temp.transfer_type |= MUSB2_MASK_TI_PROTO_INTR;
+				break;
+			default:
+				DPRINTFN(-1, "Invalid USB transfer type: %d\n",
+						xfer_type);
+				break;
+		}
+
+		temp.transfer_type |= ep_no;
+		td->toggle = xfer->endpoint->toggle_next;
+	}
+
 	/* check if we should prepend a setup message */
 
 	if (xfer->flags_int.control_xfr) {
 		if (xfer->flags_int.control_hdr) {
 
-			temp.func = &musbotg_setup_rx;
+			if (xfer->flags_int.usb_mode == USB_MODE_DEVICE)
+				temp.func = &musbotg_dev_ctrl_setup_rx;
+			else
+				temp.func = &musbotg_host_ctrl_setup_tx;
+
 			temp.len = xfer->frlengths[0];
 			temp.pc = xfer->frbuffers + 0;
 			temp.short_pkt = temp.len ? 1 : 0;
@@ -1170,17 +2480,39 @@
 		x = 0;
 	}
 
+	tx = 0;
+
 	if (x != xfer->nframes) {
-		if (xfer->endpointno & UE_DIR_IN) {
-			if (xfer->flags_int.control_xfr)
-				temp.func = &musbotg_setup_data_tx;
-			else
-				temp.func = &musbotg_data_tx;
+		if (xfer->endpointno & UE_DIR_IN)
+		    	tx = 1;
+
+		if (xfer->flags_int.usb_mode == USB_MODE_HOST) {
+			tx = !tx;
+
+			if (tx) {
+				if (xfer->flags_int.control_xfr)
+					temp.func = &musbotg_host_ctrl_data_tx;
+				else
+					temp.func = &musbotg_host_data_tx;
+			} else {
+				if (xfer->flags_int.control_xfr)
+					temp.func = &musbotg_host_ctrl_data_rx;
+				else
+					temp.func = &musbotg_host_data_rx;
+			}
+
 		} else {
-			if (xfer->flags_int.control_xfr)
-				temp.func = &musbotg_setup_data_rx;
-			else
-				temp.func = &musbotg_data_rx;
+			if (tx) {
+				if (xfer->flags_int.control_xfr)
+					temp.func = &musbotg_dev_ctrl_data_tx;
+				else
+					temp.func = &musbotg_dev_data_tx;
+			} else {
+				if (xfer->flags_int.control_xfr)
+					temp.func = &musbotg_dev_ctrl_data_rx;
+				else
+					temp.func = &musbotg_dev_data_rx;
+			}
 		}
 
 		/* setup "pc" pointer */
@@ -1211,9 +2543,14 @@
 
 		} else {
 
-			/* regular data transfer */
-
-			temp.short_pkt = (xfer->flags.force_short_xfer) ? 0 : 1;
+			if (xfer->flags_int.isochronous_xfr) {
+				/* isochronous data transfer */
+				/* don't force short */
+				temp.short_pkt = 1;
+			} else {
+				/* regular data transfer */
+				temp.short_pkt = (xfer->flags.force_short_xfer ? 0 : 1);
+			}
 		}
 
 		musbotg_setup_standard_chain_sub(&temp);
@@ -1241,7 +2578,14 @@
 			 * Send a DATA1 message and invert the current
 			 * endpoint direction.
 			 */
-			temp.func = &musbotg_setup_status;
+			if (sc->sc_mode == MUSB2_DEVICE_MODE)
+				temp.func = &musbotg_dev_ctrl_status;
+			else {
+				if (xfer->endpointno & UE_DIR_IN)
+					temp.func = musbotg_host_ctrl_status_tx;
+				else
+					temp.func = musbotg_host_ctrl_status_rx;
+			}
 			musbotg_setup_standard_chain_sub(&temp);
 		}
 	}
@@ -1264,11 +2608,9 @@
 }
 
 static void
-musbotg_ep_int_set(struct usb_xfer *xfer, uint8_t on)
+musbotg_ep_int_set(struct musbotg_softc *sc, int channel, int on)
 {
-	struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
 	uint16_t temp;
-	uint8_t ep_no = xfer->endpointno & UE_ADDR;
 
 	/*
 	 * Only enable the endpoint interrupt when we are
@@ -1275,7 +2617,12 @@
 	 * actually waiting for data, hence we are dealing
 	 * with level triggered interrupts !
 	 */
-	if (ep_no == 0) {
+	DPRINTFN(1, "ep_no=%d, on=%d\n", channel, on);
+
+	if (channel == -1)
+		return;
+
+	if (channel == 0) {
 		temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
 		if (on)
 			temp |= MUSB2_MASK_EPINT(0);
@@ -1284,23 +2631,23 @@
 
 		MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
 	} else {
-		if (USB_GET_DATA_ISREAD(xfer)) {
-			temp = MUSB2_READ_2(sc, MUSB2_REG_INTRXE);
-			if (on)
-				temp |= MUSB2_MASK_EPINT(ep_no);
-			else
-				temp &= ~MUSB2_MASK_EPINT(ep_no);
-			MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, temp);
+		temp = MUSB2_READ_2(sc, MUSB2_REG_INTRXE);
+		if (on)
+			temp |= MUSB2_MASK_EPINT(channel);
+		else
+			temp &= ~MUSB2_MASK_EPINT(channel);
+		MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, temp);
 
-		} else {
-			temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
-			if (on)
-				temp |= MUSB2_MASK_EPINT(ep_no);
-			else
-				temp &= ~MUSB2_MASK_EPINT(ep_no);
-			MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
-		}
+		temp = MUSB2_READ_2(sc, MUSB2_REG_INTTXE);
+		if (on)
+			temp |= MUSB2_MASK_EPINT(channel);
+		else
+			temp &= ~MUSB2_MASK_EPINT(channel);
+		MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, temp);
 	}
+
+	if (sc->sc_ep_int_set)
+		sc->sc_ep_int_set(sc, channel, on);
 }
 
 static void
@@ -1311,8 +2658,6 @@
 	/* poll one time */
 	if (musbotg_xfer_do_fifo(xfer)) {
 
-		musbotg_ep_int_set(xfer, 1);
-
 		DPRINTFN(14, "enabled interrupts on endpoint\n");
 
 		/* put transfer on interrupt queue */
@@ -1354,6 +2699,8 @@
 	do {
 		len = td->remainder;
 
+		xfer->endpoint->toggle_next = td->toggle;
+
 		if (xfer->aframes != xfer->nframes) {
 			/*
 		         * Verify the length and subtract
@@ -1456,17 +2803,22 @@
 static void
 musbotg_device_done(struct usb_xfer *xfer, usb_error_t error)
 {
+	struct musbotg_td *td;
+	struct musbotg_softc *sc;
+
 	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
 
-	DPRINTFN(2, "xfer=%p, endpoint=%p, error=%d\n",
+	DPRINTFN(1, "xfer=%p, endpoint=%p, error=%d\n",
 	    xfer, xfer->endpoint, error);
 
-	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+	DPRINTFN(14, "disabled interrupts on endpoint\n");
 
-		musbotg_ep_int_set(xfer, 0);
+	sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
+	td = xfer->td_transfer_cache;
 
-		DPRINTFN(14, "disabled interrupts on endpoint\n");
-	}
+	if (td && (td->channel != -1))
+		musbotg_channel_free(sc, td);
+
 	/* dequeue transfer and start next transfer */
 	usbd_transfer_done(xfer, error);
 }
@@ -1709,11 +3061,15 @@
 	if (sc->sc_clocks_on) {
 		(sc->sc_clocks_on) (sc->sc_clocks_arg);
 	}
+
 	/* wait a little for things to stabilise */
 	usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 1000);
 
 	/* disable all interrupts */
 
+	temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+	DPRINTF("pre-DEVCTL=0x%02x\n", temp);
+
 	MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0);
 	MUSB2_WRITE_2(sc, MUSB2_REG_INTTXE, 0);
 	MUSB2_WRITE_2(sc, MUSB2_REG_INTRXE, 0);
@@ -1725,6 +3081,7 @@
 	/* wait a little bit (10ms) */
 	usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 100);
 
+
 	/* disable double packet buffering */
 	MUSB2_WRITE_2(sc, MUSB2_REG_RXDBDIS, 0xFFFF);
 	MUSB2_WRITE_2(sc, MUSB2_REG_TXDBDIS, 0xFFFF);
@@ -1734,11 +3091,20 @@
 	MUSB2_WRITE_1(sc, MUSB2_REG_POWER,
 	    MUSB2_MASK_HSENAB | MUSB2_MASK_ISOUPD);
 
-	/* clear Session bit, if set */
+	if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+		/* clear Session bit, if set */
+		temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+		temp &= ~MUSB2_MASK_SESS;
+		MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+	} else {
+		/* Enter session for Host mode */
+		temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
+		temp |= MUSB2_MASK_SESS;
+		MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+	}
 
-	temp = MUSB2_READ_1(sc, MUSB2_REG_DEVCTL);
-	temp &= ~MUSB2_MASK_SESS;
-	MUSB2_WRITE_1(sc, MUSB2_REG_DEVCTL, temp);
+	/* wait a little for things to stabilise */
+	usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 10);
 
 	DPRINTF("DEVCTL=0x%02x\n", temp);
 
@@ -1806,7 +3172,12 @@
 
 		if (dynfifo) {
 			if (frx && (temp <= nrx)) {
-				if (temp < 8) {
+				if (temp == 1) {
+					frx = 12;	/* 4K */
+					MUSB2_WRITE_1(sc, MUSB2_REG_RXFIFOSZ, 
+					    MUSB2_VAL_FIFOSZ_4096 |
+					    MUSB2_MASK_FIFODB);
+				} else if (temp < 8) {
 					frx = 10;	/* 1K */
 					MUSB2_WRITE_1(sc, MUSB2_REG_RXFIFOSZ, 
 					    MUSB2_VAL_FIFOSZ_512 |
@@ -1823,7 +3194,12 @@
 				offset += (1 << frx);
 			}
 			if (ftx && (temp <= ntx)) {
-				if (temp < 8) {
+				if (temp == 1) {
+					ftx = 12;	/* 4K */
+					MUSB2_WRITE_1(sc, MUSB2_REG_TXFIFOSZ,
+	 				    MUSB2_VAL_FIFOSZ_4096 |
+	 				    MUSB2_MASK_FIFODB);
+				} else if (temp < 8) {
 					ftx = 10;	/* 1K */
 					MUSB2_WRITE_1(sc, MUSB2_REG_TXFIFOSZ,
 	 				    MUSB2_VAL_FIFOSZ_512 |
@@ -1874,8 +3250,11 @@
 
 	/* turn on default interrupts */
 
-	MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE,
-	    MUSB2_MASK_IRESET);
+	if (sc->sc_mode == MUSB2_HOST_MODE)
+		MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE, 0xff);
+	else
+		MUSB2_WRITE_1(sc, MUSB2_REG_INTUSBE,
+		    MUSB2_MASK_IRESET);
 
 	musbotg_clocks_off(sc);
 
@@ -2229,6 +3608,7 @@
 	uint16_t len;
 	uint16_t value;
 	uint16_t index;
+	uint8_t reg;
 	usb_error_t err;
 
 	USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -2408,6 +3788,13 @@
 		len = sizeof(musbotg_devd);
 		ptr = (const void *)&musbotg_devd;
 		goto tr_valid;
+	case UDESC_DEVICE_QUALIFIER:
+		if (value & 0xff) {
+			goto tr_stalled;
+		}
+		len = sizeof(musbotg_odevd);
+		ptr = (const void *)&musbotg_odevd;
+		goto tr_valid;
 	case UDESC_CONFIG:
 		if (value & 0xff) {
 			goto tr_stalled;
@@ -2492,7 +3879,10 @@
 
 	switch (value) {
 	case UHF_PORT_SUSPEND:
-		musbotg_wakeup_peer(sc);
+		if (sc->sc_mode == MUSB2_HOST_MODE)
+			musbotg_wakeup_host(sc);
+		else
+			musbotg_wakeup_peer(sc);
 		break;
 
 	case UHF_PORT_ENABLE:
@@ -2499,13 +3889,23 @@
 		sc->sc_flags.port_enabled = 0;
 		break;
 
-	case UHF_PORT_TEST:
-	case UHF_PORT_INDICATOR:
 	case UHF_C_PORT_ENABLE:
+		sc->sc_flags.change_enabled = 0;
+		break;
+
 	case UHF_C_PORT_OVER_CURRENT:
+		sc->sc_flags.change_over_current = 0;
+		break;
+
 	case UHF_C_PORT_RESET:
+		sc->sc_flags.change_reset = 0;
+		break;
+
+	case UHF_PORT_TEST:
+	case UHF_PORT_INDICATOR:
 		/* nops */
 		break;
+
 	case UHF_PORT_POWER:
 		sc->sc_flags.port_powered = 0;
 		musbotg_pull_down(sc);
@@ -2534,7 +3934,35 @@
 		sc->sc_flags.port_enabled = 1;
 		break;
 	case UHF_PORT_SUSPEND:
+		if (sc->sc_mode == MUSB2_HOST_MODE)
+			musbotg_suspend_host(sc);
+		break;
+
 	case UHF_PORT_RESET:
+		if (sc->sc_mode == MUSB2_HOST_MODE) {
+			reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+			reg |= MUSB2_MASK_RESET;
+			MUSB2_WRITE_1(sc, MUSB2_REG_POWER, reg);
+
+			/* Wait for 20 msec */
+			usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 5);
+
+			reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+			reg &= ~MUSB2_MASK_RESET;
+			MUSB2_WRITE_1(sc, MUSB2_REG_POWER, reg);
+
+			/* determine line speed */
+			reg = MUSB2_READ_1(sc, MUSB2_REG_POWER);
+			if (reg & MUSB2_MASK_HSMODE)
+				sc->sc_flags.status_high_speed = 1;
+			else
+				sc->sc_flags.status_high_speed = 0;
+
+			sc->sc_flags.change_reset = 1;
+		} else
+			err = USB_ERR_IOERROR;
+		break;
+
 	case UHF_PORT_TEST:
 	case UHF_PORT_INDICATOR:
 		/* nops */
@@ -2564,7 +3992,10 @@
 	}
 
 	/* Select Device Side Mode */
-	value = UPS_PORT_MODE_DEVICE;
+	if (sc->sc_mode == MUSB2_DEVICE_MODE)
+		value = UPS_PORT_MODE_DEVICE;
+	else
+		value = 0;
 
 	if (sc->sc_flags.status_high_speed) {
 		value |= UPS_HIGH_SPEED;
@@ -2575,6 +4006,10 @@
 	if (sc->sc_flags.port_enabled) {
 		value |= UPS_PORT_ENABLED;
 	}
+
+	if (sc->sc_flags.port_over_current)
+		value |= UPS_OVERCURRENT_INDICATOR;
+
 	if (sc->sc_flags.status_vbus &&
 	    sc->sc_flags.status_bus_reset) {
 		value |= UPS_CURRENT_CONNECT_STATUS;
@@ -2589,16 +4024,22 @@
 	if (sc->sc_flags.change_connect) {
 		value |= UPS_C_CONNECT_STATUS;
 
-		if (sc->sc_flags.status_vbus &&
-		    sc->sc_flags.status_bus_reset) {
-			/* reset EP0 state */
-			sc->sc_ep0_busy = 0;
-			sc->sc_ep0_cmd = 0;
+		if (sc->sc_mode == MUSB2_DEVICE_MODE) {
+			if (sc->sc_flags.status_vbus &&
+			    sc->sc_flags.status_bus_reset) {
+				/* reset EP0 state */
+				sc->sc_ep0_busy = 0;
+				sc->sc_ep0_cmd = 0;
+			}
 		}
 	}
-	if (sc->sc_flags.change_suspend) {
+	if (sc->sc_flags.change_suspend)
 		value |= UPS_C_SUSPEND;
-	}
+	if (sc->sc_flags.change_reset)
+		value |= UPS_C_PORT_RESET;
+	if (sc->sc_flags.change_over_current)
+		value |= UPS_C_OVERCURRENT_INDICATOR;
+
 	USETW(sc->sc_hub_temp.ps.wPortChange, value);
 	len = sizeof(sc->sc_hub_temp.ps);
 	goto tr_valid;
@@ -2623,7 +4064,6 @@
 static void
 musbotg_xfer_setup(struct usb_setup_params *parm)
 {
-	const struct usb_hw_ep_profile *pf;
 	struct musbotg_softc *sc;
 	struct usb_xfer *xfer;
 	void *last_obj;
@@ -2640,7 +4080,7 @@
 	 * reasonable dummies:
 	 */
 	parm->hc_max_packet_size = 0x400;
-	parm->hc_max_frame_size = 0x400;
+	parm->hc_max_frame_size = 0xc00;
 
 	if ((parm->methods == &musbotg_device_isoc_methods) ||
 	    (parm->methods == &musbotg_device_intr_methods))
@@ -2685,12 +4125,14 @@
 	 */
 	last_obj = NULL;
 
+	ep_no = xfer->endpointno & UE_ADDR;
+
 	/*
-	 * get profile stuff
+	 * Check for a valid endpoint profile in USB device mode:
 	 */
-	if (ntd) {
+	if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+		const struct usb_hw_ep_profile *pf;
 
-		ep_no = xfer->endpointno & UE_ADDR;
 		musbotg_get_hw_ep_profile(parm->udev, &pf, ep_no);
 
 		if (pf == NULL) {
@@ -2698,9 +4140,6 @@
 			parm->err = USB_ERR_INVAL;
 			return;
 		}
-	} else {
-		ep_no = 0;
-		pf = NULL;
 	}
 
 	/* align data */
@@ -2716,6 +4155,8 @@
 
 			/* init TD */
 			td->max_frame_size = xfer->max_frame_size;
+			td->reg_max_packet = xfer->max_packet_size |
+			    ((xfer->max_packet_count - 1) << 11);
 			td->ep_no = ep_no;
 			td->obj_next = last_obj;
 
@@ -2734,6 +4175,17 @@
 }
 
 static void
+musbotg_get_dma_delay(struct usb_device *udev, uint32_t *pus)
+{
+	struct musbotg_softc *sc = MUSBOTG_BUS2SC(udev->bus);
+
+	if (sc->sc_mode == MUSB2_HOST_MODE)
+	        *pus = 2000;                   /* microseconds */
+	else
+		*pus = 0;
+}
+
+static void
 musbotg_ep_init(struct usb_device *udev, struct usb_endpoint_descriptor *edesc,
     struct usb_endpoint *ep)
 {
@@ -2745,16 +4197,6 @@
 	    sc->sc_rt_addr);
 
 	if (udev->device_index != sc->sc_rt_addr) {
-
-		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
-			/* not supported */
-			return;
-		}
-		if ((udev->speed != USB_SPEED_FULL) &&
-		    (udev->speed != USB_SPEED_HIGH)) {
-			/* not supported */
-			return;
-		}
 		switch (edesc->bmAttributes & UE_XFERTYPE) {
 		case UE_CONTROL:
 			ep->methods = &musbotg_device_ctrl_methods;
@@ -2798,6 +4240,7 @@
 struct usb_bus_methods musbotg_bus_methods =
 {
 	.endpoint_init = &musbotg_ep_init,
+	.get_dma_delay = &musbotg_get_dma_delay,
 	.xfer_setup = &musbotg_xfer_setup,
 	.xfer_unsetup = &musbotg_xfer_unsetup,
 	.get_hw_ep_profile = &musbotg_get_hw_ep_profile,

Modified: stable/0.8/sys/dev/usb/controller/musb_otg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/musb_otg.h 257041 2013-10-24 06:22:43Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -32,7 +32,7 @@
 #ifndef _MUSB2_OTG_H_
 #define	_MUSB2_OTG_H_
 
-#define	MUSB2_MAX_DEVICES (USB_MIN_DEVICES + 1)
+#define	MUSB2_MAX_DEVICES USB_MAX_DEVICES
 
 /* Common registers */
 
@@ -105,7 +105,8 @@
 #define	MUSB2_MASK_CSRL_TXSENTSTALL 0x20/* Device Mode */
 #define	MUSB2_MASK_CSRL_TXSTALLED 0x20	/* Host Mode */
 #define	MUSB2_MASK_CSRL_TXDT_CLR 0x40
-#define	MUSB2_MASK_CSRL_TXINCOMP 0x80
+#define	MUSB2_MASK_CSRL_TXINCOMP 0x80 /* Device mode */
+#define	MUSB2_MASK_CSRL_TXNAKTO 0x80 /* Host mode */
 
 /* Device Side Mode */
 #define	MUSB2_MASK_CSR0L_RXPKTRDY 0x01
@@ -118,6 +119,7 @@
 #define	MUSB2_MASK_CSR0L_SETUPEND_CLR 0x80
 
 /* Host Side Mode */
+#define	MUSB2_MASK_CSR0L_TXFIFONEMPTY 0x02
 #define	MUSB2_MASK_CSR0L_RXSTALL 0x04
 #define	MUSB2_MASK_CSR0L_SETUPPKT 0x08
 #define	MUSB2_MASK_CSR0L_ERROR 0x10
@@ -127,7 +129,7 @@
 
 #define	MUSB2_REG_TXCSRH (0x0003 + MUSB2_REG_INDEXED_CSR)
 #define	MUSB2_MASK_CSRH_TXDT_VAL 0x01	/* Host Mode */
-#define	MUSB2_MASK_CSRH_TXDT_WR 0x02	/* Host Mode */
+#define	MUSB2_MASK_CSRH_TXDT_WREN 0x02	/* Host Mode */
 #define	MUSB2_MASK_CSRH_TXDMAREQMODE 0x04
 #define	MUSB2_MASK_CSRH_TXDT_SWITCH 0x08
 #define	MUSB2_MASK_CSRH_TXDMAREQENA 0x10
@@ -138,14 +140,16 @@
 
 #define	MUSB2_MASK_CSR0H_FFLUSH 0x01	/* Device Side flush FIFO */
 #define	MUSB2_MASK_CSR0H_DT 0x02	/* Host Side data toggle */
-#define	MUSB2_MASK_CSR0H_DT_SET 0x04	/* Host Side */
+#define	MUSB2_MASK_CSR0H_DT_WREN 0x04	/* Host Side */
 #define	MUSB2_MASK_CSR0H_PING_DIS 0x08	/* Host Side */
 
 #define	MUSB2_REG_RXCSRL (0x0006 + MUSB2_REG_INDEXED_CSR)
 #define	MUSB2_MASK_CSRL_RXPKTRDY 0x01
 #define	MUSB2_MASK_CSRL_RXFIFOFULL 0x02
-#define	MUSB2_MASK_CSRL_RXOVERRUN 0x04
-#define	MUSB2_MASK_CSRL_RXDATAERR 0x08
+#define	MUSB2_MASK_CSRL_RXOVERRUN 0x04 /* Device Mode */
+#define	MUSB2_MASK_CSRL_RXERROR 0x04 /* Host Mode */
+#define	MUSB2_MASK_CSRL_RXDATAERR 0x08 /* Device Mode */
+#define	MUSB2_MASK_CSRL_RXNAKTO 0x08 /* Host Mode */
 #define	MUSB2_MASK_CSRL_RXFFLUSH 0x10
 #define	MUSB2_MASK_CSRL_RXSENDSTALL 0x20/* Device Mode */
 #define	MUSB2_MASK_CSRL_RXREQPKT 0x20	/* Host Mode */
@@ -156,7 +160,7 @@
 #define	MUSB2_REG_RXCSRH (0x0007 + MUSB2_REG_INDEXED_CSR)
 #define	MUSB2_MASK_CSRH_RXINCOMP 0x01
 #define	MUSB2_MASK_CSRH_RXDT_VAL 0x02	/* Host Mode */
-#define	MUSB2_MASK_CSRH_RXDT_SET 0x04	/* Host Mode */
+#define	MUSB2_MASK_CSRH_RXDT_WREN 0x04	/* Host Mode */
 #define	MUSB2_MASK_CSRH_RXDMAREQMODE 0x08
 #define	MUSB2_MASK_CSRH_RXNYET 0x10
 #define	MUSB2_MASK_CSRH_RXDMAREQENA 0x20
@@ -273,10 +277,13 @@
 #define	MUSB2_REG_TXHUBPORT(n) (0x0083 + (8*(n)))
 #define	MUSB2_REG_RXFADDR(n) (0x0084 + (8*(n)))
 #define	MUSB2_REG_RXHADDR(n) (0x0086 + (8*(n)))
-#define	MUSB2_REG_RXHPORT(n) (0x0087 + (8*(n)))
+#define	MUSB2_REG_RXHUBPORT(n) (0x0087 + (8*(n)))
 
 #define	MUSB2_EP_MAX 16			/* maximum number of endpoints */
 
+#define	MUSB2_DEVICE_MODE	0
+#define	MUSB2_HOST_MODE		1
+
 #define	MUSB2_READ_2(sc, reg) \
   bus_space_read_2((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
 
@@ -309,7 +316,9 @@
 	uint32_t offset;
 	uint32_t remainder;
 	uint16_t max_frame_size;	/* packet_size * mult */
+	uint16_t reg_max_packet;
 	uint8_t	ep_no;
+	uint8_t	transfer_type;
 	uint8_t	error:1;
 	uint8_t	alt_next:1;
 	uint8_t	short_pkt:1;
@@ -316,6 +325,12 @@
 	uint8_t	support_multi_buffer:1;
 	uint8_t	did_stall:1;
 	uint8_t	dma_enabled:1;
+	uint8_t	transaction_started:1;
+	uint8_t dev_addr;
+	uint8_t toggle;
+	int8_t channel;
+	uint8_t haddr;
+	uint8_t hport;
 };
 
 struct musbotg_std_temp {
@@ -333,6 +348,11 @@
          */
 	uint8_t	setup_alt_next;
 	uint8_t did_stall;
+	uint8_t dev_addr;
+	int8_t channel;
+	uint8_t haddr;
+	uint8_t hport;
+	uint8_t	transfer_type;
 };
 
 struct musbotg_config_desc {
@@ -349,6 +369,9 @@
 struct musbotg_flags {
 	uint8_t	change_connect:1;
 	uint8_t	change_suspend:1;
+	uint8_t	change_reset:1;
+	uint8_t	change_over_current:1;
+	uint8_t	change_enabled:1;
 	uint8_t	status_suspend:1;	/* set if suspended */
 	uint8_t	status_vbus:1;		/* set if present */
 	uint8_t	status_bus_reset:1;	/* set if reset complete */
@@ -358,6 +381,7 @@
 	uint8_t	clocks_off:1;
 	uint8_t	port_powered:1;
 	uint8_t	port_enabled:1;
+	uint8_t	port_over_current:1;
 	uint8_t	d_pulled_up:1;
 };
 
@@ -376,6 +400,7 @@
 
 	void    (*sc_clocks_on) (void *arg);
 	void    (*sc_clocks_off) (void *arg);
+	void    (*sc_ep_int_set) (struct musbotg_softc *sc, int ep, int on);
 	void   *sc_clocks_arg;
 
 	uint32_t sc_bounce_buf[(1024 * 3) / 4];	/* bounce buffer */
@@ -390,8 +415,12 @@
 	uint8_t	sc_conf_data;		/* copy of hardware register */
 
 	uint8_t	sc_hub_idata[1];
+	uint16_t sc_channel_mask;	/* 16 endpoints */
 
 	struct musbotg_flags sc_flags;
+	uint8_t	sc_id;
+	uint8_t	sc_mode;
+	void *sc_platform_data;
 };
 
 /* prototypes */
@@ -398,7 +427,9 @@
 
 usb_error_t musbotg_init(struct musbotg_softc *sc);
 void	musbotg_uninit(struct musbotg_softc *sc);
-void	musbotg_interrupt(struct musbotg_softc *sc);
+void	musbotg_interrupt(struct musbotg_softc *sc,
+    uint16_t rxstat, uint16_t txstat, uint8_t stat);
 void	musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on);
+void	musbotg_connect_interrupt(struct musbotg_softc *sc);
 
 #endif					/* _MUSB2_OTG_H_ */

Modified: stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/musb_otg_atmelarm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/musb_otg_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -94,6 +94,26 @@
 #endif
 }
 
+static void
+musbotg_wrapper_interrupt(void *arg)
+{
+
+	/* 
+	 * Nothing to do.
+	 * Main driver takes care about everything 
+	 */
+	musbotg_interrupt(arg, 0, 0, 0);
+}
+
+static void
+musbotg_ep_int_set(struct musbotg_softc *sc, int ep, int on)
+{
+	/* 
+	 * Nothing to do.
+	 * Main driver takes care about everything 
+	 */
+}
+
 static int
 musbotg_probe(device_t dev)
 {
@@ -117,6 +137,7 @@
 	sc->sc_otg.sc_bus.parent = dev;
 	sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
 	sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;
+	sc->sc_otg.sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
@@ -147,12 +168,16 @@
 	}
 	device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);
 
+	sc->sc_otg.sc_id = 0;
+	sc->sc_otg.sc_platform_data = sc;
+	sc->sc_otg.sc_mode = MUSB2_DEVICE_MODE;
+
 #if (__FreeBSD_version >= 700031)
 	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
-	    NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+	    NULL, (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
 #else
 	err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
-	    (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+	    (driver_intr_t *)musbotg_wrapper_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
 #endif
 	if (err) {
 		sc->sc_otg.sc_intr_hdl = NULL;
@@ -179,14 +204,8 @@
 musbotg_detach(device_t dev)
 {
 	struct musbotg_super_softc *sc = device_get_softc(dev);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_otg.sc_bus.bdev) {
-		bdev = sc->sc_otg.sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(dev);
 

Modified: stable/0.8/sys/dev/usb/controller/ohci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci.c 257040 2013-10-24 06:06:17Z hselasky $");
 
 /*
  * USB Open Host Controller driver.
@@ -2314,6 +2314,7 @@
 		}
 		v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
 		DPRINTFN(9, "port status=0x%04x\n", v);
+		v &= ~UPS_PORT_MODE_DEVICE;	/* force host mode */
 		USETW(sc->sc_hub_desc.ps.wPortStatus, v);
 		USETW(sc->sc_hub_desc.ps.wPortChange, v >> 16);
 		len = sizeof(sc->sc_hub_desc.ps);
@@ -2550,10 +2551,6 @@
 	    edesc->bEndpointAddress, udev->flags.usb_mode,
 	    sc->sc_addr);
 
-	if (udev->flags.usb_mode != USB_MODE_HOST) {
-		/* not supported */
-		return;
-	}
 	if (udev->device_index != sc->sc_addr) {
 		switch (edesc->bmAttributes & UE_XFERTYPE) {
 		case UE_CONTROL:

Modified: stable/0.8/sys/dev/usb/controller/ohci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ohci.h 229096 2011-12-31 14:22:02Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_atmelarm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_atmelarm.c 278279 2015-02-05 20:15:42Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -91,6 +91,7 @@
 	sc->sc_ohci.sc_bus.parent = dev;
 	sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
 	sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
+	sc->sc_ohci.sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,

Modified: stable/0.8/sys/dev/usb/controller/ohci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_pci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_pci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /*
  * USB Open Host Controller driver.
@@ -154,6 +154,8 @@
 	case 0x00d710de:
 		return ("nVidia nForce3 USB Controller");
 
+	case 0x005a10de:
+		return ("nVidia nForce CK804 USB Controller");
 	case 0x036c10de:
 		return ("nVidia nForce MCP55 USB Controller");
 	case 0x03f110de:
@@ -209,6 +211,7 @@
 	sc->sc_bus.parent = self;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
@@ -329,13 +332,7 @@
 ohci_pci_detach(device_t self)
 {
 	ohci_softc_t *sc = device_get_softc(self);
-	device_t bdev;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 

Modified: stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohci_s3c24x0.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/ohci_s3c24x0.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -84,6 +84,7 @@
 	sc->sc_bus.parent = dev;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(dev),
@@ -147,14 +148,8 @@
 ohci_s3c24x0_detach(device_t dev)
 {
 	struct ohci_softc *sc = device_get_softc(dev);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(dev);
 

Modified: stable/0.8/sys/dev/usb/controller/ohcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/ohcireg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/ohcireg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/ohcireg.h 204632 2010-03-03 10:18:03Z joel $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/uhci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uhci.c 261106 2014-01-24 07:57:21Z hselasky $");
 
 /*
  * USB Universal Host Controller driver.
@@ -1176,8 +1176,13 @@
 		    (status & UHCI_TD_SPD) ? "[SPD]" : "");
 	}
 #endif
-	return (status & UHCI_TD_STALLED) ?
-	    USB_ERR_STALLED : USB_ERR_NORMAL_COMPLETION;
+	if (status & UHCI_TD_STALLED) {
+		/* try to separate I/O errors from STALL */
+		if (UHCI_TD_GET_ERRCNT(status) == 0)
+			return (USB_ERR_IOERROR);
+		return (USB_ERR_STALLED);
+	}
+	return (USB_ERR_NORMAL_COMPLETION);
 }
 
 static void
@@ -3029,10 +3034,6 @@
 	    edesc->bEndpointAddress, udev->flags.usb_mode,
 	    sc->sc_addr);
 
-	if (udev->flags.usb_mode != USB_MODE_HOST) {
-		/* not supported */
-		return;
-	}
 	if (udev->device_index != sc->sc_addr) {
 		switch (edesc->bmAttributes & UE_XFERTYPE) {
 		case UE_CONTROL:

Modified: stable/0.8/sys/dev/usb/controller/uhci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uhci.h 293147 2016-01-04 07:29:19Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -97,7 +97,7 @@
 #define	UHCI_TD_GET_ENDPT(s)	(((s) >> 15) & 0xf)
 #define	UHCI_TD_SET_DT(t)	((t) << 19)
 #define	UHCI_TD_GET_DT(s)	(((s) >> 19) & 1)
-#define	UHCI_TD_SET_MAXLEN(l)	(((l)-1) << 21)
+#define	UHCI_TD_SET_MAXLEN(l)	(((l)-1U) << 21)
 #define	UHCI_TD_GET_MAXLEN(s)	((((s) >> 21) + 1) & 0x7ff)
 #define	UHCI_TD_MAXLEN_MASK	0xffe00000
 	volatile uint32_t td_buffer;

Modified: stable/0.8/sys/dev/usb/controller/uhci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhci_pci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhci_pci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uhci_pci.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /* Universal Host Controller Interface
  *
@@ -77,6 +77,7 @@
 #include "usb_if.h"
 
 #define	PCI_UHCI_VENDORID_INTEL		0x8086
+#define	PCI_UHCI_VENDORID_HP		0x103c
 #define	PCI_UHCI_VENDORID_VIA		0x1106
 
 /* PIIX4E has no separate stepping */
@@ -222,6 +223,9 @@
 	case 0x76028086:
 		return ("Intel 82372FB/82468GX USB controller");
 
+	case 0x3300103c:
+		return ("HP iLO Standard Virtual USB controller");
+
 	case 0x30381106:
 		return ("VIA 83C572 USB controller");
 
@@ -261,6 +265,7 @@
 	sc->sc_bus.parent = self;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = UHCI_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
@@ -308,6 +313,9 @@
 	case PCI_UHCI_VENDORID_INTEL:
 		sprintf(sc->sc_vendor, "Intel");
 		break;
+	case PCI_UHCI_VENDORID_HP:
+		sprintf(sc->sc_vendor, "HP");
+		break;
 	case PCI_UHCI_VENDORID_VIA:
 		sprintf(sc->sc_vendor, "VIA");
 		break;
@@ -379,13 +387,7 @@
 uhci_pci_detach(device_t self)
 {
 	uhci_softc_t *sc = device_get_softc(self);
-	device_t bdev;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 

Modified: stable/0.8/sys/dev/usb/controller/uhcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uhcireg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uhcireg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uhcireg.h 204632 2010-03-03 10:18:03Z joel $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/usb_controller.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/usb_controller.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/usb_controller.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/usb_controller.c 278291 2015-02-05 21:37:59Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -56,6 +56,7 @@
 #include <dev/usb/usb_busdma.h>
 #include <dev/usb/usb_dynamic.h>
 #include <dev/usb/usb_device.h>
+#include <dev/usb/usb_dev.h>
 #include <dev/usb/usb_hub.h>
 
 #include <dev/usb/usb_controller.h>
@@ -126,7 +127,7 @@
 /* Device Only Drivers */
 DRIVER_MODULE(usbus, at91_udp, usb_driver, usb_devclass, 0, 0);
 DRIVER_MODULE(usbus, musbotg, usb_driver, usb_devclass, 0, 0);
-DRIVER_MODULE(usbus, uss820, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usbus, uss820dci, usb_driver, usb_devclass, 0, 0);
 
 /*------------------------------------------------------------------------*
  *	usb_probe
@@ -205,6 +206,11 @@
 	usb_proc_mwait(&bus->explore_proc,
 	    &bus->detach_msg[0], &bus->detach_msg[1]);
 
+#if USB_HAVE_UGEN
+	/* Wait for cleanup to complete */
+	usb_proc_mwait(&bus->explore_proc,
+	    &bus->cleanup_msg[0], &bus->cleanup_msg[1]);
+#endif
 	USB_BUS_UNLOCK(bus);
 
 	/* Get rid of USB callback processes */
@@ -278,6 +284,28 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usb_bus_reset_async_locked
+ *------------------------------------------------------------------------*/
+void
+usb_bus_reset_async_locked(struct usb_bus *bus)
+{
+	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
+
+	DPRINTF("\n");
+
+	if (bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL ||
+	    bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL) {
+		DPRINTF("Reset already pending\n");
+		return;
+	}
+
+	device_printf(bus->parent, "Resetting controller\n");
+
+	usb_proc_msignal(&bus->explore_proc,
+	    &bus->reset_msg[0], &bus->reset_msg[1]);
+}
+
+/*------------------------------------------------------------------------*
  *	usb_shutdown
  *------------------------------------------------------------------------*/
 static int
@@ -292,7 +320,7 @@
 		return (0);
 	}
 
-	device_printf(bus->bdev, "Controller shutdown\n");
+	DPRINTF("%s: Controller shutdown\n", device_get_nameunit(bus->bdev));
 
 	USB_BUS_LOCK(bus);
 	usb_proc_msignal(&bus->explore_proc,
@@ -304,7 +332,8 @@
 	}
 	USB_BUS_UNLOCK(bus);
 
-	device_printf(bus->bdev, "Controller shutdown complete\n");
+	DPRINTF("%s: Controller shutdown complete\n",
+	    device_get_nameunit(bus->bdev));
 
 	return (0);
 }
@@ -326,8 +355,14 @@
 	if (bus->no_explore != 0)
 		return;
 
-	if (udev && udev->hub) {
+	if (udev != NULL) {
+		USB_BUS_UNLOCK(bus);
+		uhub_explore_handle_re_enumerate(udev);
+		USB_BUS_LOCK(bus);
+	}
 
+	if (udev != NULL && udev->hub != NULL) {
+
 		if (bus->do_probe) {
 			bus->do_probe = 0;
 			bus->driver_added_refcount++;
@@ -399,7 +434,7 @@
 /*------------------------------------------------------------------------*
  *	usb_bus_suspend
  *
- * This function is used to suspend the USB contoller.
+ * This function is used to suspend the USB controller.
  *------------------------------------------------------------------------*/
 static void
 usb_bus_suspend(struct usb_proc_msg *pm)
@@ -409,6 +444,8 @@
 	usb_error_t err;
 	uint8_t do_unlock;
 
+	DPRINTF("\n");
+
 	bus = ((struct usb_bus_msg *)pm)->bus;
 	udev = bus->devices[USB_ROOT_HUB_ADDR];
 
@@ -454,7 +491,7 @@
 /*------------------------------------------------------------------------*
  *	usb_bus_resume
  *
- * This function is used to resume the USB contoller.
+ * This function is used to resume the USB controller.
  *------------------------------------------------------------------------*/
 static void
 usb_bus_resume(struct usb_proc_msg *pm)
@@ -464,6 +501,8 @@
 	usb_error_t err;
 	uint8_t do_unlock;
 
+	DPRINTF("\n");
+
 	bus = ((struct usb_bus_msg *)pm)->bus;
 	udev = bus->devices[USB_ROOT_HUB_ADDR];
 
@@ -513,9 +552,31 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usb_bus_reset
+ *
+ * This function is used to reset the USB controller.
+ *------------------------------------------------------------------------*/
+static void
+usb_bus_reset(struct usb_proc_msg *pm)
+{
+	struct usb_bus *bus;
+
+	DPRINTF("\n");
+
+	bus = ((struct usb_bus_msg *)pm)->bus;
+
+	if (bus->bdev == NULL || bus->no_explore != 0)
+		return;
+
+	/* a suspend and resume will reset the USB controller */
+	usb_bus_suspend(pm);
+	usb_bus_resume(pm);
+}
+
+/*------------------------------------------------------------------------*
  *	usb_bus_shutdown
  *
- * This function is used to shutdown the USB contoller.
+ * This function is used to shutdown the USB controller.
  *------------------------------------------------------------------------*/
 static void
 usb_bus_shutdown(struct usb_proc_msg *pm)
@@ -558,7 +619,33 @@
 	USB_BUS_LOCK(bus);
 }
 
+/*------------------------------------------------------------------------*
+ *	usb_bus_cleanup
+ *
+ * This function is used to cleanup leftover USB character devices.
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_UGEN
 static void
+usb_bus_cleanup(struct usb_proc_msg *pm)
+{
+	struct usb_bus *bus;
+	struct usb_fs_privdata *pd;
+
+	bus = ((struct usb_bus_msg *)pm)->bus;
+
+	while ((pd = LIST_FIRST(&bus->pd_cleanup_list)) != NULL) {
+
+		LIST_REMOVE(pd, pd_next);
+		USB_BUS_UNLOCK(bus);
+
+		usb_destroy_dev_sync(pd);
+
+		USB_BUS_LOCK(bus);
+	}
+}
+#endif
+
+static void
 usb_power_wdog(void *arg)
 {
 	struct usb_bus *bus = arg;
@@ -728,11 +815,24 @@
 	bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume;
 	bus->resume_msg[1].bus = bus;
 
+	bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset;
+	bus->reset_msg[0].bus = bus;
+	bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset;
+	bus->reset_msg[1].bus = bus;
+
 	bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown;
 	bus->shutdown_msg[0].bus = bus;
 	bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown;
 	bus->shutdown_msg[1].bus = bus;
 
+#if USB_HAVE_UGEN
+	LIST_INIT(&bus->pd_cleanup_list);
+	bus->cleanup_msg[0].hdr.pm_callback = &usb_bus_cleanup;
+	bus->cleanup_msg[0].bus = bus;
+	bus->cleanup_msg[1].hdr.pm_callback = &usb_bus_cleanup;
+	bus->cleanup_msg[1].bus = bus;
+#endif
+
 	/* Create USB explore and callback processes */
 
 	if (usb_proc_create(&bus->giant_callback_proc,
@@ -830,7 +930,7 @@
 
 #if USB_HAVE_BUSDMA
 	usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
-	    dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
+	    dmat, &bus->bus_mtx, NULL, bus->dma_bits, USB_BUS_DMA_TAG_MAX);
 #endif
 	if ((bus->devices_max > USB_MAX_DEVICES) ||
 	    (bus->devices_max < USB_MIN_DEVICES) ||

Modified: stable/0.8/sys/dev/usb/controller/uss820dci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uss820dci.c 262457 2014-02-24 20:29:39Z dim $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
  * All rights reserved.
@@ -2004,6 +2004,13 @@
 		len = sizeof(uss820dci_devd);
 		ptr = (const void *)&uss820dci_devd;
 		goto tr_valid;
+	case UDESC_DEVICE_QUALIFIER:
+		if (value & 0xff) {
+			goto tr_stalled;
+		}
+		len = sizeof(uss820dci_odevd);
+		ptr = (const void *)&uss820dci_odevd;
+		goto tr_valid;
 	case UDESC_CONFIG:
 		if (value & 0xff) {
 			goto tr_stalled;
@@ -2331,10 +2338,6 @@
 
 	if (udev->device_index != sc->sc_rt_addr) {
 
-		if (udev->flags.usb_mode != USB_MODE_DEVICE) {
-			/* not supported */
-			return;
-		}
 		if (udev->speed != USB_SPEED_FULL) {
 			/* not supported */
 			return;

Modified: stable/0.8/sys/dev/usb/controller/uss820dci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/uss820dci.h 229096 2011-12-31 14:22:02Z hselasky $ */
 /*-
  * Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/uss820dci_atmelarm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/uss820dci_atmelarm.c 308403 2016-11-07 09:23:07Z hselasky $");
 
 /*-
  * Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
@@ -77,7 +77,7 @@
 };
 
 static driver_t uss820dci_driver = {
-	.name = "uss820",
+	.name = "uss820dci",
 	.methods = uss820dci_methods,
 	.size = sizeof(struct uss820dci_softc),
 };
@@ -84,8 +84,8 @@
 
 static devclass_t uss820dci_devclass;
 
-DRIVER_MODULE(uss820, atmelarm, uss820dci_driver, uss820dci_devclass, 0, 0);
-MODULE_DEPEND(uss820, usb, 1, 1, 1);
+DRIVER_MODULE(uss820dci, atmelarm, uss820dci_driver, uss820dci_devclass, 0, 0);
+MODULE_DEPEND(uss820dci, usb, 1, 1, 1);
 
 static const char *const uss820_desc = "USS820 USB Device Controller";
 
@@ -107,6 +107,7 @@
 	sc->sc_bus.parent = dev;
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = USS820_MAX_DEVICES;
+	sc->sc_bus.dma_bits = 32;
 
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
@@ -168,14 +169,8 @@
 uss820_atmelarm_detach(device_t dev)
 {
 	struct uss820dci_softc *sc = device_get_softc(dev);
-	device_t bdev;
 	int err;
 
-	if (sc->sc_bus.bdev) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(dev, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(dev);
 

Modified: stable/0.8/sys/dev/usb/controller/xhci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/xhci.c 315253 2017-03-14 15:30:46Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -86,6 +86,8 @@
 #ifdef USB_DEBUG
 static int xhcidebug;
 static int xhciroute;
+static int xhcipolling;
+static int xhcidma32;
 
 static SYSCTL_NODE(_hw_usb, OID_AUTO, xhci, CTLFLAG_RW, 0, "USB XHCI");
 SYSCTL_INT(_hw_usb_xhci, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN,
@@ -92,10 +94,17 @@
     &xhcidebug, 0, "Debug level");
 TUNABLE_INT("hw.usb.xhci.debug", &xhcidebug);
 SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN,
-    &xhciroute, 0, "Routing bitmap for switching EHCI ports to XHCI controller");
+    &xhciroute, 0, "Routing bitmap for switching EHCI ports to the XHCI controller");
 TUNABLE_INT("hw.usb.xhci.xhci_port_route", &xhciroute);
+SYSCTL_INT(_hw_usb_xhci, OID_AUTO, use_polling, CTLFLAG_RW | CTLFLAG_TUN,
+    &xhcipolling, 0, "Set to enable software interrupt polling for the XHCI controller");
+TUNABLE_INT("hw.usb.xhci.use_polling", &xhcipolling);
+SYSCTL_INT(_hw_usb_xhci, OID_AUTO, dma32, CTLFLAG_RWTUN,
+    &xhcidma32, 0, "Set to only use 32-bit DMA for the XHCI controller");
+TUNABLE_INT("hw.usb.xhci.dma32", &xhcidma32);
 #else
 #define	xhciroute 0
+#define	xhcidma32 0
 #endif
 
 #define	XHCI_INTR_ENDPT 1
@@ -131,8 +140,8 @@
 static usb_proc_callback_t xhci_configure_msg;
 static usb_error_t xhci_configure_device(struct usb_device *);
 static usb_error_t xhci_configure_endpoint(struct usb_device *,
-		    struct usb_endpoint_descriptor *, uint64_t, uint16_t,
-		    uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
+    struct usb_endpoint_descriptor *, struct xhci_endpoint_ext *,
+    uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
 static usb_error_t xhci_configure_mask(struct usb_device *,
 		    uint32_t, uint8_t);
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -181,11 +190,21 @@
 }
 #endif
 
+uint8_t
+xhci_use_polling(void)
+{
+#ifdef USB_DEBUG
+	return (xhcipolling != 0);
+#else
+	return (0);
+#endif
+}
+
 static void
 xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb)
 {
 	struct xhci_softc *sc = XHCI_BUS2SC(bus);
-	uint8_t i;
+	uint16_t i;
 
 	cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg,
 	   sizeof(struct xhci_hw_root), XHCI_PAGE_SIZE);
@@ -193,7 +212,7 @@
 	cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg,
 	   sizeof(struct xhci_dev_ctx_addr), XHCI_PAGE_SIZE);
 
-	for (i = 0; i != XHCI_MAX_SCRATCHPADS; i++) {
+	for (i = 0; i != sc->sc_noscratch; i++) {
 		cb(bus, &sc->sc_hw.scratch_pc[i], &sc->sc_hw.scratch_pg[i],
 		    XHCI_PAGE_SIZE, XHCI_PAGE_SIZE);
 	}
@@ -253,111 +272,97 @@
 }
 #endif
 
-usb_error_t
-xhci_start_controller(struct xhci_softc *sc)
+static int
+xhci_reset_command_queue_locked(struct xhci_softc *sc)
 {
 	struct usb_page_search buf_res;
 	struct xhci_hw_root *phwr;
-	struct xhci_dev_ctx_addr *pdctxa;
 	uint64_t addr;
 	uint32_t temp;
-	uint16_t i;
 
 	DPRINTF("\n");
 
-	sc->sc_capa_off = 0;
-	sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
-	sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
-	sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
+	temp = XREAD4(sc, oper, XHCI_CRCR_LO);
+	if (temp & XHCI_CRCR_LO_CRR) {
+		DPRINTF("Command ring running\n");
+		temp &= ~(XHCI_CRCR_LO_CS | XHCI_CRCR_LO_CA);
 
-	DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
-	DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
-	DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
+		/*
+		 * Try to abort the last command as per section
+		 * 4.6.1.2 "Aborting a Command" of the XHCI
+		 * specification:
+		 */
 
-	sc->sc_event_ccs = 1;
-	sc->sc_event_idx = 0;
-	sc->sc_command_ccs = 1;
-	sc->sc_command_idx = 0;
+		/* stop and cancel */
+		XWRITE4(sc, oper, XHCI_CRCR_LO, temp | XHCI_CRCR_LO_CS);
+		XWRITE4(sc, oper, XHCI_CRCR_HI, 0);
 
-	DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+		XWRITE4(sc, oper, XHCI_CRCR_LO, temp | XHCI_CRCR_LO_CA);
+		XWRITE4(sc, oper, XHCI_CRCR_HI, 0);
 
-	temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+ 		/* wait 250ms */
+ 		usb_pause_mtx(&sc->sc_bus.bus_mtx, hz / 4);
 
-	DPRINTF("HCS0 = 0x%08x\n", temp);
-
-	if (XHCI_HCS0_CSZ(temp)) {
-		sc->sc_ctx_is_64_byte = 1;
-		device_printf(sc->sc_bus.parent, "64 byte context size.\n");
-	} else {
-		sc->sc_ctx_is_64_byte = 0;
-		device_printf(sc->sc_bus.parent, "32 byte context size.\n");
+		/* check if command ring is still running */
+		temp = XREAD4(sc, oper, XHCI_CRCR_LO);
+		if (temp & XHCI_CRCR_LO_CRR) {
+			DPRINTF("Comand ring still running\n");
+			return (USB_ERR_IOERROR);
+		}
 	}
 
-	/* Reset controller */
-	XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
+	/* reset command ring */
+	sc->sc_command_ccs = 1;
+	sc->sc_command_idx = 0;
 
-	for (i = 0; i != 100; i++) {
-		usb_pause_mtx(NULL, hz / 100);
-		temp = XREAD4(sc, oper, XHCI_USBCMD) &
-		    (XHCI_CMD_HCRST | XHCI_STS_CNR);
-		if (!temp)
-			break;
-	}
+	usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
 
-	if (temp) {
-		device_printf(sc->sc_bus.parent, "Controller "
-		    "reset timeout.\n");
-		return (USB_ERR_IOERROR);
-	}
+	/* set up command ring control base address */
+	addr = buf_res.physaddr;
+	phwr = buf_res.buffer;
+	addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[0];
 
-	if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) {
-		device_printf(sc->sc_bus.parent, "Controller does "
-		    "not support 4K page size.\n");
-		return (USB_ERR_IOERROR);
-	}
+	DPRINTF("CRCR=0x%016llx\n", (unsigned long long)addr);
 
-	temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
+	memset(phwr->hwr_commands, 0, sizeof(phwr->hwr_commands));
+	phwr->hwr_commands[XHCI_MAX_COMMANDS - 1].qwTrb0 = htole64(addr);
 
-	i = XHCI_HCS1_N_PORTS(temp);
+	usb_pc_cpu_flush(&sc->sc_hw.root_pc);
 
-	if (i == 0) {
-		device_printf(sc->sc_bus.parent, "Invalid number "
-		    "of ports: %u\n", i);
-		return (USB_ERR_IOERROR);
-	}
+	XWRITE4(sc, oper, XHCI_CRCR_LO, ((uint32_t)addr) | XHCI_CRCR_LO_RCS);
+	XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32));
 
-	sc->sc_noport = i;
-	sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp);
+	return (0);
+}
 
-	if (sc->sc_noslot > XHCI_MAX_DEVICES)
-		sc->sc_noslot = XHCI_MAX_DEVICES;
+usb_error_t
+xhci_start_controller(struct xhci_softc *sc)
+{
+	struct usb_page_search buf_res;
+	struct xhci_hw_root *phwr;
+	struct xhci_dev_ctx_addr *pdctxa;
+	usb_error_t err;
+	uint64_t addr;
+	uint32_t temp;
+	uint16_t i;
 
-	/* setup number of device slots */
+	DPRINTF("\n");
 
+	sc->sc_event_ccs = 1;
+	sc->sc_event_idx = 0;
+	sc->sc_command_ccs = 1;
+	sc->sc_command_idx = 0;
+
+	err = xhci_reset_controller(sc);
+	if (err)
+		return (err);
+
+	/* set up number of device slots */
 	DPRINTF("CONFIG=0x%08x -> 0x%08x\n",
 	    XREAD4(sc, oper, XHCI_CONFIG), sc->sc_noslot);
 
 	XWRITE4(sc, oper, XHCI_CONFIG, sc->sc_noslot);
 
-	DPRINTF("Max slots: %u\n", sc->sc_noslot);
-
-	temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
-
-	sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
-
-	if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
-		device_printf(sc->sc_bus.parent, "XHCI request "
-		    "too many scratchpads\n");
-		return (USB_ERR_NOMEM);
-	}
-
-	DPRINTF("Max scratch: %u\n", sc->sc_noscratch);
-
-	temp = XREAD4(sc, capa, XHCI_HCSPARAMS3);
-
-	sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) +
-	    XHCI_HCS3_U2_DEL(temp) + 250 /* us */;
-
 	temp = XREAD4(sc, oper, XHCI_USBSTS);
 
 	/* clear interrupts */
@@ -365,7 +370,7 @@
 	/* disable all device notifications */
 	XWRITE4(sc, oper, XHCI_DNCTRL, 0);
 
-	/* setup device context base address */
+	/* set up device context base address */
 	usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res);
 	pdctxa = buf_res.buffer;
 	memset(pdctxa, 0, sizeof(*pdctxa));
@@ -389,26 +394,14 @@
 	XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
 	XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32));
 
-	/* Setup event table size */
-
-	temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
-
-	DPRINTF("HCS2=0x%08x\n", temp);
-
-	temp = XHCI_HCS2_ERST_MAX(temp);
-	temp = 1U << temp;
-	if (temp > XHCI_MAX_RSEG)
-		temp = XHCI_MAX_RSEG;
-
-	sc->sc_erst_max = temp;
-
+	/* set up event table size */
 	DPRINTF("ERSTSZ=0x%08x -> 0x%08x\n",
-	    XREAD4(sc, runt, XHCI_ERSTSZ(0)), temp);
+	    XREAD4(sc, runt, XHCI_ERSTSZ(0)), sc->sc_erst_max);
 
-	XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(temp));
+	XWRITE4(sc, runt, XHCI_ERSTSZ(0), XHCI_ERSTS_SET(sc->sc_erst_max));
 
-	/* Setup interrupt rate */
-	XWRITE4(sc, runt, XHCI_IMOD(0), XHCI_IMOD_DEFAULT);
+	/* set up interrupt rate */
+	XWRITE4(sc, runt, XHCI_IMOD(0), sc->sc_imod_default);
 
 	usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
 
@@ -427,7 +420,7 @@
 	XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr);
 	XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
 
-	addr = (uint64_t)buf_res.physaddr;
+	addr = buf_res.physaddr;
 
 	DPRINTF("ERSTBA(0)=0x%016llx\n", (unsigned long long)addr);
 
@@ -434,13 +427,12 @@
 	XWRITE4(sc, runt, XHCI_ERSTBA_LO(0), (uint32_t)addr);
 	XWRITE4(sc, runt, XHCI_ERSTBA_HI(0), (uint32_t)(addr >> 32));
 
-	/* Setup interrupter registers */
-
+	/* set up interrupter registers */
 	temp = XREAD4(sc, runt, XHCI_IMAN(0));
 	temp |= XHCI_IMAN_INTR_ENA;
 	XWRITE4(sc, runt, XHCI_IMAN(0), temp);
 
-	/* setup command ring control base address */
+	/* set up command ring control base address */
 	addr = buf_res.physaddr;
 	addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[0];
 
@@ -511,9 +503,40 @@
 }
 
 usb_error_t
-xhci_init(struct xhci_softc *sc, device_t self)
+xhci_reset_controller(struct xhci_softc *sc)
 {
-	/* initialise some bus fields */
+	uint32_t temp = 0;
+	uint16_t i;
+
+	DPRINTF("\n");
+
+	/* Reset controller */
+	XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_HCRST);
+
+	for (i = 0; i != 100; i++) {
+		usb_pause_mtx(NULL, hz / 100);
+		temp = (XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST) |
+		    (XREAD4(sc, oper, XHCI_USBSTS) & XHCI_STS_CNR);
+		if (!temp)
+			break;
+	}
+
+	if (temp) {
+		device_printf(sc->sc_bus.parent, "Controller "
+		    "reset timeout.\n");
+		return (USB_ERR_IOERROR);
+	}
+	return (0);
+}
+
+usb_error_t
+xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32)
+{
+	uint32_t temp;
+
+	DPRINTF("\n");
+
+	/* initialize some bus fields */
 	sc->sc_bus.parent = self;
 
 	/* set the bus revision */
@@ -522,14 +545,99 @@
 	/* set up the bus struct */
 	sc->sc_bus.methods = &xhci_bus_methods;
 
-	/* setup devices array */
+	/* set up devices array */
 	sc->sc_bus.devices = sc->sc_devices;
 	sc->sc_bus.devices_max = XHCI_MAX_DEVICES;
 
-	/* setup command queue mutex and condition varible */
-	cv_init(&sc->sc_cmd_cv, "CMDQ");
-	sx_init(&sc->sc_cmd_sx, "CMDQ lock");
+	/* set default cycle state in case of early interrupts */
+	sc->sc_event_ccs = 1;
+	sc->sc_command_ccs = 1;
 
+	/* set up bus space offsets */
+	sc->sc_capa_off = 0;
+	sc->sc_oper_off = XREAD1(sc, capa, XHCI_CAPLENGTH);
+	sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0x1F;
+	sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3;
+
+	DPRINTF("CAPLENGTH=0x%x\n", sc->sc_oper_off);
+	DPRINTF("RUNTIMEOFFSET=0x%x\n", sc->sc_runt_off);
+	DPRINTF("DOOROFFSET=0x%x\n", sc->sc_door_off);
+
+	DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION));
+
+	if (!(XREAD4(sc, oper, XHCI_PAGESIZE) & XHCI_PAGESIZE_4K)) {
+		device_printf(sc->sc_bus.parent, "Controller does "
+		    "not support 4K page size.\n");
+		return (ENXIO);
+	}
+
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS0);
+
+	DPRINTF("HCS0 = 0x%08x\n", temp);
+
+	/* set up context size */
+	if (XHCI_HCS0_CSZ(temp)) {
+		sc->sc_ctx_is_64_byte = 1;
+	} else {
+		sc->sc_ctx_is_64_byte = 0;
+	}
+
+	/* get DMA bits */
+	sc->sc_bus.dma_bits = (XHCI_HCS0_AC64(temp) &&
+	    xhcidma32 == 0 && dma32 == 0) ? 64 : 32;
+
+	device_printf(self, "%d bytes context size, %d-bit DMA\n",
+	    sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits);
+
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
+
+	/* get number of device slots */
+	sc->sc_noport = XHCI_HCS1_N_PORTS(temp);
+
+	if (sc->sc_noport == 0) {
+		device_printf(sc->sc_bus.parent, "Invalid number "
+		    "of ports: %u\n", sc->sc_noport);
+		return (ENXIO);
+	}
+
+	sc->sc_noport = sc->sc_noport;
+	sc->sc_noslot = XHCI_HCS1_DEVSLOT_MAX(temp);
+
+	DPRINTF("Max slots: %u\n", sc->sc_noslot);
+
+	if (sc->sc_noslot > XHCI_MAX_DEVICES)
+		sc->sc_noslot = XHCI_MAX_DEVICES;
+
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS2);
+
+	DPRINTF("HCS2=0x%08x\n", temp);
+
+	/* get number of scratchpads */
+	sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp);
+
+	if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) {
+		device_printf(sc->sc_bus.parent, "XHCI request "
+		    "too many scratchpads\n");
+		return (ENOMEM);
+	}
+
+	DPRINTF("Max scratch: %u\n", sc->sc_noscratch);
+
+	/* get event table size */
+	sc->sc_erst_max = 1U << XHCI_HCS2_ERST_MAX(temp);
+	if (sc->sc_erst_max > XHCI_MAX_RSEG)
+		sc->sc_erst_max = XHCI_MAX_RSEG;
+
+	temp = XREAD4(sc, capa, XHCI_HCSPARAMS3);
+
+	/* get maximum exit latency */
+	sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) +
+	    XHCI_HCS3_U2_DEL(temp) + 250 /* us */;
+
+	/* Check if we should use the default IMOD value. */
+	if (sc->sc_imod_default == 0)
+		sc->sc_imod_default = XHCI_IMOD_DEFAULT;
+
 	/* get all DMA memory */
 	if (usb_bus_mem_alloc_all(&sc->sc_bus,
 	    USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) {
@@ -536,10 +644,9 @@
 		return (ENOMEM);
 	}
 
-        sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
-        sc->sc_config_msg[0].bus = &sc->sc_bus;
-        sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
-        sc->sc_config_msg[1].bus = &sc->sc_bus;
+	/* set up command queue mutex and condition varible */
+	cv_init(&sc->sc_cmd_cv, "CMDQ");
+	sx_init(&sc->sc_cmd_sx, "CMDQ lock");
 
 	if (usb_proc_create(&sc->sc_config_proc,
 	    &sc->sc_bus.bus_mtx, device_get_nameunit(self), USB_PRI_MED)) {
@@ -546,6 +653,11 @@
                 printf("WARNING: Creation of XHCI configure "
                     "callback process failed.\n");
         }
+	sc->sc_config_msg[0].hdr.pm_callback = &xhci_configure_msg;
+	sc->sc_config_msg[0].bus = &sc->sc_bus;
+	sc->sc_config_msg[1].hdr.pm_callback = &xhci_configure_msg;
+	sc->sc_config_msg[1].bus = &sc->sc_bus;
+
 	return (0);
 }
 
@@ -569,10 +681,12 @@
 	case USB_HW_POWER_SUSPEND:
 		DPRINTF("Stopping the XHCI\n");
 		xhci_halt_controller(sc);
+		xhci_reset_controller(sc);
 		break;
 	case USB_HW_POWER_SHUTDOWN:
 		DPRINTF("Stopping the XHCI\n");
 		xhci_halt_controller(sc);
+		xhci_reset_controller(sc);
 		break;
 	case USB_HW_POWER_RESUME:
 		DPRINTF("Starting the XHCI\n");
@@ -1003,7 +1117,7 @@
 	 * register.
 	 */
 
-	addr = (uint32_t)buf_res.physaddr;
+	addr = buf_res.physaddr;
 	addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[i];
 
 	/* try to clear busy bit */
@@ -1025,6 +1139,7 @@
 	uint32_t temp;
 	uint8_t i;
 	uint8_t j;
+	uint8_t timeout = 0;
 	int err;
 
 	XHCI_CMD_ASSERT_LOCKED(sc);
@@ -1038,7 +1153,7 @@
 	/* Queue command */
 
 	USB_BUS_LOCK(&sc->sc_bus);
-
+retry:
 	i = sc->sc_command_idx;
 	j = sc->sc_command_ccs;
 
@@ -1109,7 +1224,35 @@
 		err = 0;
 	}
 	if (err != 0) {
-		DPRINTFN(0, "Command timeout!\n");
+		DPRINTF("Command timeout!\n");
+		/*
+		 * After some weeks of continuous operation, it has
+		 * been observed that the ASMedia Technology, ASM1042
+		 * SuperSpeed USB Host Controller can suddenly stop
+		 * accepting commands via the command queue. Try to
+		 * first reset the command queue. If that fails do a
+		 * host controller reset.
+		 */
+		if (timeout == 0 &&
+		    xhci_reset_command_queue_locked(sc) == 0) {
+			temp = le32toh(trb->dwTrb3);
+
+			/*
+			 * Avoid infinite XHCI reset loops if the set
+			 * address command fails to respond due to a
+			 * non-enumerating device:
+			 */
+			if (XHCI_TRB_3_TYPE_GET(temp) == XHCI_TRB_TYPE_ADDRESS_DEVICE &&
+			    (temp & XHCI_TRB_3_BSR_BIT) == 0) {
+				DPRINTF("Set address timeout\n");
+			} else {
+				timeout = 1;
+				goto retry;
+			}
+		} else {
+			DPRINTF("Controller reset!\n");
+			usb_bus_reset_async_locked(&sc->sc_bus);
+		}
 		err = USB_ERR_TIMEOUT;
 		trb->dwTrb2 = 0;
 		trb->dwTrb3 = 0;
@@ -1271,8 +1414,15 @@
 
 		pepext = xhci_get_endpoint_ext(udev,
 		    &udev->ctrl_ep_desc);
+
+		/* ensure the control endpoint is setup again */
+		USB_BUS_LOCK(udev->bus);
+		pepext->trb_halted = 1;
+		pepext->trb_running = 0;
+		USB_BUS_UNLOCK(udev->bus);
+
 		err = xhci_configure_endpoint(udev,
-		    &udev->ctrl_ep_desc, pepext->physaddr,
+		    &udev->ctrl_ep_desc, pepext,
 		    0, 1, 1, 0, mps, mps);
 
 		if (err != 0) {
@@ -1464,34 +1614,27 @@
 xhci_interrupt(struct xhci_softc *sc)
 {
 	uint32_t status;
-	uint32_t iman;
+	uint32_t temp;
 
 	USB_BUS_LOCK(&sc->sc_bus);
 
 	status = XREAD4(sc, oper, XHCI_USBSTS);
-	if (status == 0)
-		goto done;
 
-	/* acknowledge interrupts */
+	/* acknowledge interrupts, if any */
+	if (status != 0) {
+		XWRITE4(sc, oper, XHCI_USBSTS, status);
+		DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+	}
 
-	XWRITE4(sc, oper, XHCI_USBSTS, status);
+	temp = XREAD4(sc, runt, XHCI_IMAN(0));
 
-	DPRINTFN(16, "real interrupt (status=0x%08x)\n", status);
+	/* force clearing of pending interrupts */
+	if (temp & XHCI_IMAN_INTR_PEND)
+		XWRITE4(sc, runt, XHCI_IMAN(0), temp);
  
-	if (status & XHCI_STS_EINT) {
+	/* check for event(s) */
+	xhci_interrupt_poll(sc);
 
-		/* acknowledge pending event */
-		iman = XREAD4(sc, runt, XHCI_IMAN(0));
-
-		/* reset interrupt */
-		XWRITE4(sc, runt, XHCI_IMAN(0), iman);
- 
-		DPRINTFN(16, "real interrupt (iman=0x%08x)\n", iman);
- 
-		/* check for event(s) */
-		xhci_interrupt_poll(sc);
-	}
-
 	if (status & (XHCI_STS_PCD | XHCI_STS_HCH |
 	    XHCI_STS_HSE | XHCI_STS_HCE)) {
 
@@ -1514,7 +1657,6 @@
 			   __FUNCTION__);
 		}
 	}
-done:
 	USB_BUS_UNLOCK(&sc->sc_bus);
 }
 
@@ -1653,7 +1795,8 @@
 			/* check wLength */
 			if (td->td_trb[0].qwTrb0 &
 			   htole64(XHCI_TRB_0_WLENGTH_MASK)) {
-				if (td->td_trb[0].qwTrb0 & htole64(1))
+				if (td->td_trb[0].qwTrb0 &
+				    htole64(XHCI_TRB_0_DIR_IN_MASK))
 					dword |= XHCI_TRB_3_TRT_IN;
 				else
 					dword |= XHCI_TRB_3_TRT_OUT;
@@ -1688,7 +1831,7 @@
 				npkt_off += buf_res.length;
 			}
 
-			/* setup npkt */
+			/* set up npkt */
 			npkt = (len_old - npkt_off + temp->max_packet_size - 1) /
 			    temp->max_packet_size;
 
@@ -1726,31 +1869,34 @@
 					    XHCI_TRB_3_ISO_SIA_BIT;
 				}
 				if (temp->direction == UE_DIR_IN)
-					dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+					dword |= XHCI_TRB_3_ISP_BIT;
 				break;
 			case XHCI_TRB_TYPE_DATA_STAGE:
 				dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE) |
-				    XHCI_TRB_3_TBC_SET(temp->tbc) |
-				    XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE);
 				if (temp->direction == UE_DIR_IN)
 					dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+				/*
+				 * Section 3.2.9 in the XHCI
+				 * specification about control
+				 * transfers says that we should use a
+				 * normal-TRB if there are more TRBs
+				 * extending the data-stage
+				 * TRB. Update the "trb_type".
+				 */
+				temp->trb_type = XHCI_TRB_TYPE_NORMAL;
 				break;
 			case XHCI_TRB_TYPE_STATUS_STAGE:
 				dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE) |
-				    XHCI_TRB_3_TBC_SET(temp->tbc) |
-				    XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE);
 				if (temp->direction == UE_DIR_IN)
 					dword |= XHCI_TRB_3_DIR_IN;
 				break;
 			default:	/* XHCI_TRB_TYPE_NORMAL */
 				dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
-				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL) |
-				    XHCI_TRB_3_TBC_SET(temp->tbc) |
-				    XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
+				    XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL);
 				if (temp->direction == UE_DIR_IN)
-					dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
+					dword |= XHCI_TRB_3_ISP_BIT;
 				break;
 			}
 			td->td_trb[x].dwTrb3 = htole32(dword);
@@ -1788,7 +1934,16 @@
 		td->td_trb[x].dwTrb2 = htole32(dword);
 
 		dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
-		    XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
+		    XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT |
+		    /*
+		     * CHAIN-BIT: Ensure that a multi-TRB IN-endpoint
+		     * frame only receives a single short packet event
+		     * by setting the CHAIN bit in the LINK field. In
+		     * addition some XHCI controllers have problems
+		     * sending a ZLP unless the CHAIN-BIT is set in
+		     * the LINK TRB.
+		     */
+		    XHCI_TRB_3_CHAIN_BIT;
 
 		td->td_trb[x].dwTrb3 = htole32(dword);
 
@@ -1802,7 +1957,7 @@
 	if (precompute) {
 		precompute = 0;
 
-		/* setup alt next pointer, if any */
+		/* set up alt next pointer, if any */
 		if (temp->last_frame) {
 			td_alt_next = NULL;
 		} else {
@@ -1826,9 +1981,11 @@
 	}
 
 	/* clear TD SIZE to zero, hence this is the last TRB */
-	/* remove chain bit because this is the last TRB in the chain */
+	/* remove chain bit because this is the last data TRB in the chain */
 	td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
 	td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
+	/* remove CHAIN-BIT from last LINK TRB */
+	td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
 
 	usb_pc_cpu_flush(td->page_cache);
 
@@ -1967,7 +2124,8 @@
 		mult = 1;
 		temp.isoc_delta = 0;
 		temp.isoc_frame = 0;
-		temp.trb_type = XHCI_TRB_TYPE_DATA_STAGE;
+		temp.trb_type = xfer->flags_int.control_did_data ?
+		    XHCI_TRB_TYPE_NORMAL : XHCI_TRB_TYPE_DATA_STAGE;
 	} else {
 		x = 0;
 		mult = 1;
@@ -1977,7 +2135,7 @@
 	}
 
 	if (x != xfer->nframes) {
-                /* setup page_cache pointer */
+                /* set up page_cache pointer */
                 temp.pc = xfer->frbuffers + x;
 		/* set endpoint direction */
 		temp.direction = UE_GET_DIR(xfer->endpointno);
@@ -2065,7 +2223,11 @@
 		 * Send a DATA1 message and invert the current
 		 * endpoint direction.
 		 */
+#ifdef XHCI_STEP_STATUS_STAGE
 		temp.step_td = (xfer->nframes != 0);
+#else
+		temp.step_td = 0;
+#endif
 		temp.direction = UE_GET_DIR(xfer->endpointno) ^ UE_DIR_IN;
 		temp.len = 0;
 		temp.pc = NULL;
@@ -2123,7 +2285,14 @@
 		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
 		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
 	} else {
-		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
+		/*
+		 * Some hardware requires that we drop the endpoint
+		 * context before adding it again:
+		 */
+		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0,
+		    mask & XHCI_INCTX_NON_CTRL_MASK);
+
+		/* Add new endpoint context */
 		xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
 
 		/* find most significant set bit */
@@ -2135,27 +2304,33 @@
 		/* adjust */
 		x--;
 
-		/* figure out maximum */
-		if (x > sc->sc_hw.devs[index].context_num) {
+		/* figure out the maximum number of contexts */
+		if (x > sc->sc_hw.devs[index].context_num)
 			sc->sc_hw.devs[index].context_num = x;
-			temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
-			temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
-			temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
-			xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
-		}
+		else
+			x = sc->sc_hw.devs[index].context_num;
+
+		/* update number of contexts */
+		temp = xhci_ctx_get_le32(sc, &pinp->ctx_slot.dwSctx0);
+		temp &= ~XHCI_SCTX_0_CTX_NUM_SET(31);
+		temp |= XHCI_SCTX_0_CTX_NUM_SET(x + 1);
+		xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx0, temp);
 	}
+	usb_pc_cpu_flush(&sc->sc_hw.devs[index].input_pc);
 	return (0);
 }
 
 static usb_error_t
 xhci_configure_endpoint(struct usb_device *udev,
-    struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
-    uint16_t interval, uint8_t max_packet_count, uint8_t mult,
-    uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
+    struct usb_endpoint_descriptor *edesc, struct xhci_endpoint_ext *pepext,
+    uint16_t interval, uint8_t max_packet_count,
+    uint8_t mult, uint8_t fps_shift, uint16_t max_packet_size,
+    uint16_t max_frame_size)
 {
 	struct usb_page_search buf_inp;
 	struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
 	struct xhci_input_dev_ctx *pinp;
+	uint64_t ring_addr = pepext->physaddr;
 	uint32_t temp;
 	uint8_t index;
 	uint8_t epno;
@@ -2186,6 +2361,10 @@
 	if (mult == 0)
 		return (USB_ERR_BAD_BUFSIZE);
 
+	/* store bMaxPacketSize for control endpoints */
+	pepext->trb_ep_maxp = edesc->wMaxPacketSize[0];
+	usb_pc_cpu_flush(pepext->page_cache);
+
 	temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
 	    XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
 	    XHCI_EPCTX_0_LSA_SET(0);
@@ -2231,10 +2410,14 @@
 	    XHCI_EPCTX_1_MAXB_SET(max_packet_count) |
 	    XHCI_EPCTX_1_MAXP_SIZE_SET(max_packet_size);
 
-	if ((udev->parent_hs_hub != NULL) || (udev->address != 0)) {
-		if (type != UE_ISOCHRONOUS)
-			temp |= XHCI_EPCTX_1_CERR_SET(3);
-	}
+	/*
+	 * Always enable the "three strikes and you are gone" feature
+	 * except for ISOCHRONOUS endpoints. This is suggested by
+	 * section 4.3.3 in the XHCI specification about device slot
+	 * initialisation.
+	 */
+	if (type != UE_ISOCHRONOUS)
+		temp |= XHCI_EPCTX_1_CERR_SET(3);
 
 	switch (type) {
 	case UE_CONTROL:
@@ -2301,7 +2484,7 @@
 	usb_pc_cpu_flush(pepext->page_cache);
 
 	return (xhci_configure_endpoint(xfer->xroot->udev,
-	    xfer->endpoint->edesc, pepext->physaddr,
+	    xfer->endpoint->edesc, pepext,
 	    xfer->interval, xfer->max_packet_count,
 	    (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
 	    usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
@@ -2461,7 +2644,11 @@
 
 	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx2, temp);
 
-	temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) |
+	/*
+	 * These fields should be initialized to zero, according to
+	 * XHCI section 6.2.2 - slot context:
+	 */
+	temp = XHCI_SCTX_3_DEV_ADDR_SET(0) |
 	    XHCI_SCTX_3_SLOT_STATE_SET(0);
 
 	xhci_ctx_set_le32(sc, &pinp->ctx_slot.dwSctx3, temp);
@@ -2689,6 +2876,17 @@
 		return (USB_ERR_NOMEM);
 	}
 
+	/* check if bMaxPacketSize changed */
+	if (xfer->flags_int.control_xfr != 0 &&
+	    pepext->trb_ep_maxp != xfer->endpoint->edesc->wMaxPacketSize[0]) {
+
+		DPRINTFN(8, "Reconfigure control endpoint\n");
+
+		/* force driver to reconfigure endpoint */
+		pepext->trb_halted = 1;
+		pepext->trb_running = 0;
+	}
+
 	/* check for stopped condition, after putting transfer on interrupt queue */
 	if (pepext->trb_running == 0) {
 		struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
@@ -2889,7 +3087,7 @@
 {
 	DPRINTF("\n");
 
-	/* setup TD's and QH */
+	/* set up TD's and QH */
 	xhci_setup_generic_chain(xfer);
 
 	xhci_device_generic_multi_enter(xfer->endpoint, xfer);
@@ -3629,16 +3827,14 @@
 
 	xhci_configure_mask(udev, (1U << epno) | 1U, 0);
 
-	err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
+	if (epno > 1)
+		err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
+	else
+		err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
 
 	if (err != 0)
 		DPRINTF("Could not configure endpoint %u\n", epno);
 
-	err = xhci_cmd_configure_ep(sc, buf_inp.physaddr, 0, index);
-
-	if (err != 0)
-		DPRINTF("Could not configure endpoint %u\n", epno);
-
 	XHCI_CMD_UNLOCK(sc);
 
 	return (0);
@@ -3752,10 +3948,6 @@
 	DPRINTFN(2, "endpoint=%p, addr=%d, endpt=%d, mode=%d\n",
 	    ep, udev->address, edesc->bEndpointAddress, udev->flags.usb_mode);
 
-	if (udev->flags.usb_mode != USB_MODE_HOST) {
-		/* not supported */
-		return;
-	}
 	if (udev->parent_hub == NULL) {
 		/* root HUB has special endpoint handling */
 		return;
@@ -4018,6 +4210,10 @@
 
 		sc->sc_hw.devs[index].state = XHCI_ST_ADDRESSED;
 
+		/* set configure mask to slot only */
+		xhci_configure_mask(udev, 1, 0);
+
+		/* deconfigure all endpoints, except EP0 */
 		err = xhci_cmd_configure_ep(sc, 0, 1, index);
 
 		if (err) {

Modified: stable/0.8/sys/dev/usb/controller/xhci.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/xhci.h 315253 2017-03-14 15:30:46Z hselasky $ */
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -30,7 +30,7 @@
 
 #define	XHCI_MAX_DEVICES	MIN(USB_MAX_DEVICES, 128)
 #define	XHCI_MAX_ENDPOINTS	32	/* hardcoded - do not change */
-#define	XHCI_MAX_SCRATCHPADS	32
+#define	XHCI_MAX_SCRATCHPADS	256	/* theoretical max is 1023 */
 #define	XHCI_MAX_EVENTS		(16 * 13)
 #define	XHCI_MAX_COMMANDS	(16 * 1)
 #define	XHCI_MAX_RSEG		1
@@ -184,6 +184,7 @@
 
 struct xhci_trb {
 	volatile uint64_t	qwTrb0;
+#define	XHCI_TRB_0_DIR_IN_MASK		(0x80ULL << 0)
 #define	XHCI_TRB_0_WLENGTH_MASK		(0xFFFFULL << 48)
 	volatile uint32_t	dwTrb2;
 #define	XHCI_TRB_2_ERROR_GET(x)		(((x) >> 24) & 0xFF)
@@ -310,11 +311,23 @@
 	struct xhci_trb		trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
 };
 
-#define	XHCI_TD_PAGE_NBUF	17	/* units, room enough for 64Kbytes */
-#define	XHCI_TD_PAGE_SIZE	4096	/* bytes */
-#define	XHCI_TD_PAYLOAD_MAX	(XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1))
+#if (USB_PAGE_SIZE < 4096)
+#error "The XHCI driver needs a pagesize above or equal to 4K"
+#endif
 
+/* Define the maximum payload which we will handle in a single TRB */
+#define	XHCI_TD_PAYLOAD_MAX	65536	/* bytes */
+
+/* Define the maximum payload of a single scatter-gather list element */
+#define	XHCI_TD_PAGE_SIZE \
+  ((USB_PAGE_SIZE < XHCI_TD_PAYLOAD_MAX) ? USB_PAGE_SIZE : XHCI_TD_PAYLOAD_MAX)
+
+/* Define the maximum length of the scatter-gather list */
+#define	XHCI_TD_PAGE_NBUF \
+  (((XHCI_TD_PAYLOAD_MAX + XHCI_TD_PAGE_SIZE - 1) / XHCI_TD_PAGE_SIZE) + 1)
+
 struct xhci_td {
+	/* one LINK TRB has been added to the TRB array */
 	struct xhci_trb		td_trb[XHCI_TD_PAGE_NBUF + 1];
 
 /*
@@ -360,6 +373,7 @@
 	uint8_t			trb_index;
 	uint8_t			trb_halted;
 	uint8_t			trb_running;
+	uint8_t			trb_ep_maxp;
 };
 
 enum {
@@ -431,6 +445,8 @@
 	struct usb_process	sc_config_proc;
 	struct usb_bus_msg	sc_config_msg[2];
 
+	struct usb_callout	sc_callout;
+
 	xhci_port_route_t	*sc_port_route;
 
 	union xhci_hub_desc	sc_hub_desc;
@@ -440,7 +456,6 @@
 
 	struct usb_device	*sc_devices[XHCI_MAX_DEVICES];
 	struct resource		*sc_io_res;
-	int			sc_irq_rid;
 	struct resource		*sc_irq_res;
 
 	void			*sc_intr_hdl;
@@ -469,7 +484,11 @@
 	uint16_t		sc_erst_max;
 	uint16_t		sc_event_idx;
 	uint16_t		sc_command_idx;
+	uint16_t		sc_imod_default;
 
+	/* number of scratch pages */
+	uint16_t		sc_noscratch;
+
 	uint8_t			sc_event_ccs;
 	uint8_t			sc_command_ccs;
 	/* number of XHCI device slots */
@@ -476,11 +495,10 @@
 	uint8_t			sc_noslot;
 	/* number of ports on root HUB */
 	uint8_t			sc_noport;
-	/* number of scratch pages */
-	uint8_t			sc_noscratch;
 	/* root HUB device configuration */
 	uint8_t			sc_conf;
-	uint8_t			sc_hub_idata[2];
+	/* root HUB port event bitmap, max 256 ports */
+	uint8_t			sc_hub_idata[32];
 
 	/* size of context */
 	uint8_t			sc_ctx_is_64_byte;
@@ -495,8 +513,10 @@
 
 /* prototypes */
 
+uint8_t 	xhci_use_polling(void);
 usb_error_t xhci_halt_controller(struct xhci_softc *);
-usb_error_t xhci_init(struct xhci_softc *, device_t);
+usb_error_t xhci_reset_controller(struct xhci_softc *);
+usb_error_t xhci_init(struct xhci_softc *, device_t, uint8_t);
 usb_error_t xhci_start_controller(struct xhci_softc *);
 void	xhci_interrupt(struct xhci_softc *);
 void	xhci_uninit(struct xhci_softc *);

Modified: stable/0.8/sys/dev/usb/controller/xhci_pci.c
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhci_pci.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhci_pci.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/controller/xhci_pci.c 315253 2017-03-14 15:30:46Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -86,10 +86,9 @@
 
 static devclass_t xhci_devclass;
 
-DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, 0, 0);
+DRIVER_MODULE(xhci, pci, xhci_driver, xhci_devclass, NULL, NULL);
 MODULE_DEPEND(xhci, usb, 1, 1, 1);
 
-
 static const char *
 xhci_pci_match(device_t self)
 {
@@ -99,14 +98,29 @@
 	case 0x01941033:
 		return ("NEC uPD720200 USB 3.0 controller");
 
+	case 0x10001b73:
+		return ("Fresco Logic FL1000G USB 3.0 controller");
+
 	case 0x10421b21:
 		return ("ASMedia ASM1042 USB 3.0 controller");
+	case 0x11421b21:
+		return ("ASMedia ASM1042A USB 3.0 controller");
 
+	case 0x0f358086:
+		return ("Intel BayTrail USB 3.0 controller");
+	case 0x9c318086:
 	case 0x1e318086:
 		return ("Intel Panther Point USB 3.0 controller");
 	case 0x8c318086:
 		return ("Intel Lynx Point USB 3.0 controller");
+	case 0x8cb18086:
+		return ("Intel Wildcat Point USB 3.0 controller");
+	case 0x9cb18086:
+		return ("Broadwell Integrated PCH-LP chipset USB 3.0 controller");
 
+	case 0xa01b177d:
+		return ("Cavium ThunderX USB 3.0 controller");
+
 	default:
 		break;
 	}
@@ -135,10 +149,22 @@
 static int xhci_use_msi = 1;
 TUNABLE_INT("hw.usb.xhci.msi", &xhci_use_msi);
 
+static void
+xhci_interrupt_poll(void *_sc)
+{
+	struct xhci_softc *sc = _sc;
+	USB_BUS_UNLOCK(&sc->sc_bus);
+	xhci_interrupt(sc);
+	USB_BUS_LOCK(&sc->sc_bus);
+	usb_callout_reset(&sc->sc_callout, 1, (void *)&xhci_interrupt_poll, sc);
+}
+
 static int
 xhci_pci_port_route(device_t self, uint32_t set, uint32_t clear)
 {
 	uint32_t temp;
+	uint32_t usb3_mask;
+	uint32_t usb2_mask;
 
 	temp = pci_read_config(self, PCI_XHCI_INTEL_USB3_PSSEN, 4) |
 	    pci_read_config(self, PCI_XHCI_INTEL_XUSB2PR, 4);
@@ -146,9 +172,13 @@
 	temp |= set;
 	temp &= ~clear;
 
-	pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp, 4);
-	pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp, 4);
+	/* Don't set bits which the hardware doesn't support */
+	usb3_mask = pci_read_config(self, PCI_XHCI_INTEL_USB3PRM, 4);
+	usb2_mask = pci_read_config(self, PCI_XHCI_INTEL_USB2PRM, 4);
 
+	pci_write_config(self, PCI_XHCI_INTEL_USB3_PSSEN, temp & usb3_mask, 4);
+	pci_write_config(self, PCI_XHCI_INTEL_XUSB2PR, temp & usb2_mask, 4);
+
 	device_printf(self, "Port routing mask set to 0x%08x\n", temp);
 
 	return (0);
@@ -159,44 +189,71 @@
 {
 	struct xhci_softc *sc = device_get_softc(self);
 	int count, err, rid;
+	uint8_t usemsi = 1;
+	uint8_t usedma32 = 0;
 
-	/* XXX check for 64-bit capability */
-
-	if (xhci_init(sc, self)) {
-		device_printf(self, "Could not initialize softc\n");
-		goto error;
-	}
-
-	pci_enable_busmaster(self);
-
 	rid = PCI_XHCI_CBMEM;
 	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
 	    RF_ACTIVE);
 	if (!sc->sc_io_res) {
 		device_printf(self, "Could not map memory\n");
-		goto error;
+		return (ENOMEM);
 	}
 	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
 	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
 	sc->sc_io_size = rman_get_size(sc->sc_io_res);
 
-	sc->sc_irq_rid = 0;
-	if (xhci_use_msi) {
-		count = pci_msi_count(self);
-		if (count >= 1) {
-			count = 1;
-			if (pci_alloc_msi(self, &count) == 0) {
-				if (bootverbose)
-					device_printf(self, "MSI enabled\n");
-				sc->sc_irq_rid = 1;
-			}
+	switch (pci_get_devid(self)) {
+	case 0x01941033:	/* NEC uPD720200 USB 3.0 controller */
+	case 0x00141912:	/* NEC uPD720201 USB 3.0 controller */
+		/* Don't use 64-bit DMA on these controllers. */
+		usedma32 = 1;
+		break;
+	case 0x10001b73:	/* FL1000G */
+		/* Fresco Logic host doesn't support MSI. */
+		usemsi = 0;
+		break;
+	case 0x0f358086:	/* BayTrail */
+	case 0x9c318086:	/* Panther Point */
+	case 0x1e318086:	/* Panther Point */
+	case 0x8c318086:	/* Lynx Point */
+	case 0x8cb18086:	/* Wildcat Point */
+	case 0x9cb18086:	/* Broadwell Mobile Integrated */
+		/*
+		 * On Intel chipsets, reroute ports from EHCI to XHCI
+		 * controller and use a different IMOD value.
+		 */
+		sc->sc_port_route = &xhci_pci_port_route;
+		sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP;
+		break;
+	}
+
+	if (xhci_init(sc, self, usedma32)) {
+		device_printf(self, "Could not initialize softc\n");
+		bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
+		    sc->sc_io_res);
+		return (ENXIO);
+	}
+
+	pci_enable_busmaster(self);
+
+	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_mtx, 0);
+
+	rid = 0;
+	if (xhci_use_msi && usemsi) {
+		count = 1;
+		if (pci_alloc_msi(self, &count) == 0) {
+			if (bootverbose)
+				device_printf(self, "MSI enabled\n");
+			rid = 1;
 		}
 	}
-	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ,
-	    &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE);
+	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+	    RF_ACTIVE | (rid != 0 ? 0 : RF_SHAREABLE));
 	if (sc->sc_irq_res == NULL) {
+		pci_release_msi(self);
 		device_printf(self, "Could not allocate IRQ\n");
-		goto error;
+		/* goto error; FALLTHROUGH - use polling */
 	}
 	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
 	if (sc->sc_bus.bdev == NULL) {
@@ -207,27 +264,26 @@
 
 	sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));
 
-#if (__FreeBSD_version >= 700031)
-	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
-	    NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
-#else
-	err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
-	    (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
-#endif
-	if (err) {
-		device_printf(self, "Could not setup IRQ, err=%d\n", err);
-		sc->sc_intr_hdl = NULL;
-		goto error;
+	if (sc->sc_irq_res != NULL) {
+		err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+		    NULL, (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl);
+		if (err != 0) {
+			bus_release_resource(self, SYS_RES_IRQ,
+			    rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
+			sc->sc_irq_res = NULL;
+			pci_release_msi(self);
+			device_printf(self, "Could not setup IRQ, err=%d\n", err);
+			sc->sc_intr_hdl = NULL;
+		}
 	}
-	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
-	switch (pci_get_devid(self)) {
-	case 0x1e318086:	/* Panther Point */
-	case 0x8c318086:	/* Lynx Point */
-	case 0x8cb18086:        /* Wildcat Point */
-		sc->sc_port_route = &xhci_pci_port_route;
-		break;
-	default:
-		break;
+	if (sc->sc_irq_res == NULL || sc->sc_intr_hdl == NULL) {
+		if (xhci_use_polling() != 0) {
+			device_printf(self, "Interrupt polling at %dHz\n", hz);
+			USB_BUS_LOCK(&sc->sc_bus);
+			xhci_interrupt_poll(sc);
+			USB_BUS_UNLOCK(&sc->sc_bus);
+		} else
+			goto error;
 	}
 
 	xhci_pci_take_controller(self);
@@ -255,31 +311,25 @@
 xhci_pci_detach(device_t self)
 {
 	struct xhci_softc *sc = device_get_softc(self);
-	device_t bdev;
 
-	if (sc->sc_bus.bdev != NULL) {
-		bdev = sc->sc_bus.bdev;
-		device_detach(bdev);
-		device_delete_child(self, bdev);
-	}
 	/* during module unload there are lots of children leftover */
 	device_delete_children(self);
 
+	usb_callout_drain(&sc->sc_callout);
+	xhci_halt_controller(sc);
+	xhci_reset_controller(sc);
+
 	pci_disable_busmaster(self);
 
 	if (sc->sc_irq_res && sc->sc_intr_hdl) {
-
-		xhci_halt_controller(sc);
-
 		bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
 		sc->sc_intr_hdl = NULL;
 	}
 	if (sc->sc_irq_res) {
-		if (sc->sc_irq_rid == 1)
-			pci_release_msi(self);
-		bus_release_resource(self, SYS_RES_IRQ, sc->sc_irq_rid,
-		    sc->sc_irq_res);
+		bus_release_resource(self, SYS_RES_IRQ,
+		    rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
 		sc->sc_irq_res = NULL;
+		pci_release_msi(self);
 	}
 	if (sc->sc_io_res) {
 		bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,

Modified: stable/0.8/sys/dev/usb/controller/xhcireg.h
===================================================================
--- stable/0.8/sys/dev/usb/controller/xhcireg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/controller/xhcireg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/controller/xhcireg.h 302267 2016-06-29 10:23:19Z hselasky $ */
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -35,7 +35,9 @@
 #define	PCI_XHCI_FLADJ		0x61	/* RW frame length adjust */
 
 #define	PCI_XHCI_INTEL_XUSB2PR	0xD0	/* Intel USB2 Port Routing */
+#define	PCI_XHCI_INTEL_USB2PRM	0xD4	/* Intel USB2 Port Routing Mask */
 #define	PCI_XHCI_INTEL_USB3_PSSEN 0xD8	/* Intel USB3 Port SuperSpeed Enable */
+#define	PCI_XHCI_INTEL_USB3PRM	0xDC	/* Intel USB3 Port Routing Mask */
 
 /* XHCI capability registers */
 #define	XHCI_CAPLENGTH		0x00	/* RO capability */
@@ -50,8 +52,8 @@
 #define	XHCI_HCSPARAMS2		0x08	/* RO structual parameters 2 */
 #define	XHCI_HCS2_IST(x)	((x) & 0xF)
 #define	XHCI_HCS2_ERST_MAX(x)	(((x) >> 4) & 0xF)
-#define	XHCI_HCS2_SPR(x)	(((x) >> 24) & 0x1)
-#define	XHCI_HCS2_SPB_MAX(x)	(((x) >> 27) & 0x7F)
+#define	XHCI_HCS2_SPR(x)	(((x) >> 26) & 0x1)
+#define	XHCI_HCS2_SPB_MAX(x)	((((x) >> 16) & 0x3E0) | (((x) >> 27) & 0x1F))
 #define	XHCI_HCSPARAMS3		0x0C	/* RO structual parameters 3 */
 #define	XHCI_HCS3_U1_DEL(x)	((x) & 0xFF)
 #define	XHCI_HCS3_U2_DEL(x)	(((x) >> 16) & 0xFFFF)
@@ -166,7 +168,8 @@
 #define	XHCI_IMOD_IVAL_SET(x)	(((x) & 0xFFFF) << 0)	/* 250ns unit */
 #define	XHCI_IMOD_ICNT_GET(x)	(((x) >> 16) & 0xFFFF)	/* 250ns unit */
 #define	XHCI_IMOD_ICNT_SET(x)	(((x) & 0xFFFF) << 16)	/* 250ns unit */
-#define	XHCI_IMOD_DEFAULT	0x000003E8U	/* 8000 IRQ/second */
+#define	XHCI_IMOD_DEFAULT	0x000001F4U	/* 8000 IRQs/second */
+#define	XHCI_IMOD_DEFAULT_LP 	0x000003F8U	/* 4000 IRQs/second - LynxPoint */
 #define	XHCI_ERSTSZ(n)		(0x0028 + (0x20 * (n)))	/* XHCI event ring segment table size */
 #define	XHCI_ERSTS_GET(x)	((x) & 0xFFFF)
 #define	XHCI_ERSTS_SET(x)	((x) & 0xFFFF)

Modified: stable/0.8/sys/dev/usb/input/atp.c
===================================================================
--- stable/0.8/sys/dev/usb/input/atp.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/atp.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/atp.c 263064 2014-03-12 07:18:39Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>

Modified: stable/0.8/sys/dev/usb/input/uep.c
===================================================================
--- stable/0.8/sys/dev/usb/input/uep.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/uep.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/input/uep.c 248085 2013-03-09 02:36:32Z marius $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/input/uhid.c
===================================================================
--- stable/0.8/sys/dev/usb/input/uhid.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/uhid.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -5,7 +5,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/uhid.c 291206 2015-11-23 13:48:28Z hselasky $");
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -518,7 +518,9 @@
 	 */
 	if (fflags & FREAD) {
 		/* reset flags */
+		mtx_lock(&sc->sc_mtx);
 		sc->sc_flags &= ~UHID_FLAG_IMMED;
+		mtx_unlock(&sc->sc_mtx);
 
 		if (usb_fifo_alloc_buffer(fifo,
 		    sc->sc_isize + 1, UHID_FRAME_NUM)) {
@@ -734,7 +736,7 @@
 		if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE) {
 
 			sc->sc_repdesc_size = sizeof(uhid_graphire_report_descr);
-			sc->sc_repdesc_ptr = (void *)&uhid_graphire_report_descr;
+			sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire_report_descr);
 			sc->sc_flags |= UHID_FLAG_STATIC_DESC;
 
 		} else if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) {
@@ -755,16 +757,27 @@
 				    usbd_errstr(error));
 			}
 			sc->sc_repdesc_size = sizeof(uhid_graphire3_4x5_report_descr);
-			sc->sc_repdesc_ptr = (void *)&uhid_graphire3_4x5_report_descr;
+			sc->sc_repdesc_ptr = __DECONST(void *, &uhid_graphire3_4x5_report_descr);
 			sc->sc_flags |= UHID_FLAG_STATIC_DESC;
 		}
 	} else if ((uaa->info.bInterfaceClass == UICLASS_VENDOR) &&
-		    (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
+	    (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
 	    (uaa->info.bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD)) {
-
+		static const uint8_t reportbuf[3] = {1, 3, 0};
+		/*
+		 * Turn off the four LEDs on the gamepad which
+		 * are blinking by default:
+		 */
+		error = usbd_req_set_report(uaa->device, NULL,
+		    __DECONST(void *, reportbuf), sizeof(reportbuf),
+		    uaa->info.bIfaceIndex, UHID_OUTPUT_REPORT, 0);
+		if (error) {
+			DPRINTF("set output report failed, error=%s (ignored)\n",
+			    usbd_errstr(error));
+		}
 		/* the Xbox 360 gamepad has no report descriptor */
 		sc->sc_repdesc_size = sizeof(uhid_xb360gp_report_descr);
-		sc->sc_repdesc_ptr = (void *)&uhid_xb360gp_report_descr;
+		sc->sc_repdesc_ptr = __DECONST(void *, &uhid_xb360gp_report_descr);
 		sc->sc_flags |= UHID_FLAG_STATIC_DESC;
 	}
 	if (sc->sc_repdesc_ptr == NULL) {

Modified: stable/0.8/sys/dev/usb/input/ukbd.c
===================================================================
--- stable/0.8/sys/dev/usb/input/ukbd.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/ukbd.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/ukbd.c 305646 2016-09-09 06:41:16Z hselasky $");
 
 
 /*-
@@ -107,7 +107,7 @@
 #define	UKBD_NMOD                     8	/* units */
 #define	UKBD_NKEYCODE                 6	/* units */
 #define	UKBD_IN_BUF_SIZE  (2*(UKBD_NMOD + (2*UKBD_NKEYCODE)))	/* bytes */
-#define	UKBD_IN_BUF_FULL  (UKBD_IN_BUF_SIZE / 2)	/* bytes */
+#define	UKBD_IN_BUF_FULL  ((UKBD_IN_BUF_SIZE / 2) - 1)	/* bytes */
 #define	UKBD_NFKEY        (sizeof(fkey_tab)/sizeof(fkey_tab[0]))	/* units */
 #define	UKBD_BUFFER_SIZE	      64	/* bytes */
 
@@ -128,7 +128,8 @@
 };
 
 enum {
-	UKBD_INTR_DT,
+	UKBD_INTR_DT_0,
+	UKBD_INTR_DT_1,
 	UKBD_CTRL_LED,
 	UKBD_N_TRANSFER,
 };
@@ -197,6 +198,7 @@
 	int	sc_mode;		/* input mode (K_XLATE,K_RAW,K_CODE) */
 	int	sc_state;		/* shift/lock key state */
 	int	sc_accents;		/* accent key index (> 0) */
+	int	sc_polling;		/* polling recursion count */
 	int	sc_led_size;
 	int	sc_kbd_size;
 
@@ -298,6 +300,10 @@
  * 0x68: F13
  * 0x69: F14
  * 0x6a: F15
+ * 
+ * USB Apple Keyboard JIS generates:
+ * 0x90: Kana
+ * 0x91: Eisu
  */
 static const uint8_t ukbd_trtab[256] = {
 	0, 0, 0, 0, 30, 48, 46, 32,	/* 00 - 07 */
@@ -318,7 +324,7 @@
 	109, 110, 112, 118, 114, 116, 117, 119,	/* 78 - 7F */
 	121, 120, NN, NN, NN, NN, NN, 123,	/* 80 - 87 */
 	124, 125, 126, 127, 128, NN, NN, NN,	/* 88 - 8F */
-	NN, NN, NN, NN, NN, NN, NN, NN,	/* 90 - 97 */
+	129, 130, NN, NN, NN, NN, NN, NN,	/* 90 - 97 */
 	NN, NN, NN, NN, NN, NN, NN, NN,	/* 98 - 9F */
 	NN, NN, NN, NN, NN, NN, NN, NN,	/* A0 - A7 */
 	NN, NN, NN, NN, NN, NN, NN, NN,	/* A8 - AF */
@@ -472,7 +478,8 @@
 	if (sc->sc_inputs == 0 &&
 	    (sc->sc_flags & UKBD_FLAG_GONE) == 0) {
 		/* start transfer, if not already started */
-		usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+		usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+		usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
 	}
 
 	if (sc->sc_flags & UKBD_FLAG_POLLING)
@@ -948,7 +955,7 @@
 
 static const struct usb_config ukbd_config[UKBD_N_TRANSFER] = {
 
-	[UKBD_INTR_DT] = {
+	[UKBD_INTR_DT_0] = {
 		.type = UE_INTERRUPT,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
@@ -957,6 +964,15 @@
 		.callback = &ukbd_intr_callback,
 	},
 
+	[UKBD_INTR_DT_1] = {
+		.type = UE_INTERRUPT,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_IN,
+		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+		.bufsize = 0,	/* use wMaxPacketSize */
+		.callback = &ukbd_intr_callback,
+	},
+
 	[UKBD_CTRL_LED] = {
 		.type = UE_CONTROL,
 		.endpoint = 0x00,	/* Control pipe */
@@ -1193,9 +1209,26 @@
 
 	usb_callout_init_mtx(&sc->sc_callout, &Giant, 0);
 
+#ifdef UKBD_NO_POLLING
 	err = usbd_transfer_setup(uaa->device,
 	    &uaa->info.bIfaceIndex, sc->sc_xfer, ukbd_config,
 	    UKBD_N_TRANSFER, sc, &Giant);
+#else
+	/*
+	 * Setup the UKBD USB transfers one by one, so they are memory
+	 * independent which allows for handling panics triggered by
+	 * the keyboard driver itself, typically via CTRL+ALT+ESC
+	 * sequences. Or if the USB keyboard driver was processing a
+	 * key at the moment of panic.
+	 */
+	for (n = 0; n != UKBD_N_TRANSFER; n++) {
+		err = usbd_transfer_setup(uaa->device,
+		    &uaa->info.bIfaceIndex, sc->sc_xfer + n, ukbd_config + n,
+		    1, sc, &Giant);
+		if (err)
+			break;
+	}
+#endif
 
 	if (err) {
 		DPRINTF("error=%s\n", usbd_errstr(err));
@@ -1278,7 +1311,8 @@
 	}
 
 	/* start the keyboard */
-	usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]);
+	usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_0]);
+	usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT_1]);
 
 	return (0);			/* success */
 
@@ -1304,7 +1338,8 @@
 	/* kill any stuck keys */
 	if (sc->sc_flags & UKBD_FLAG_ATTACHED) {
 		/* stop receiving events from the USB keyboard */
-		usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT]);
+		usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_0]);
+		usbd_transfer_stop(sc->sc_xfer[UKBD_INTR_DT_1]);
 
 		/* release all leftover keys, if any */
 		memset(&sc->sc_ndata, 0, sizeof(sc->sc_ndata));
@@ -1963,7 +1998,16 @@
 	struct ukbd_softc *sc = kbd->kb_data;
 
 	UKBD_LOCK();
-	if (on) {
+	/*
+	 * Keep a reference count on polling to allow recursive
+	 * cngrab() during a panic for example.
+	 */
+	if (on)
+		sc->sc_polling++;
+	else if (sc->sc_polling > 0)
+		sc->sc_polling--;
+
+	if (sc->sc_polling != 0) {
 		sc->sc_flags |= UKBD_FLAG_POLLING;
 		sc->sc_poll_thread = curthread;
 	} else {
@@ -2051,7 +2095,7 @@
 		0x166,	/* Sun Type 6 Find */
 		0x167,	/* Sun Type 6 Cut */
 		0x125,	/* Sun Type 6 Mute */
-		/* 120 - 128 */
+		/* 120 - 130 */
 		0x11f,	/* Sun Type 6 VolumeDown */
 		0x11e,	/* Sun Type 6 VolumeUp */
 		0x120,	/* Sun Type 6 PowerDown */
@@ -2063,6 +2107,8 @@
 		0x79,	/* Keyboard Intl' 4 (Henkan) */
 		0x7b,	/* Keyboard Intl' 5 (Muhenkan) */
 		0x5c,	/* Keyboard Intl' 6 (Keypad ,) (For PC-9821 layout) */
+		0x71,   /* Apple Keyboard JIS (Kana) */
+		0x72,   /* Apple Keyboard JIS (Eisu) */
 	};
 
 	if ((code >= 89) && (code < (int)(89 + (sizeof(scan) / sizeof(scan[0]))))) {

Modified: stable/0.8/sys/dev/usb/input/ums.c
===================================================================
--- stable/0.8/sys/dev/usb/input/ums.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/ums.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/ums.c 308396 2016-11-07 08:17:23Z hselasky $");
 
 /*
  * HID spec: http://www.usb.org/developers/devclass_docs/HID1_11.pdf
@@ -258,8 +258,11 @@
 		}
 
 		if ((info->sc_flags & UMS_FLAG_T_AXIS) &&
-		    (id == info->sc_iid_t))
+		    (id == info->sc_iid_t)) {
 			dt -= hid_get_data(buf, len, &info->sc_loc_t);
+			/* T-axis is translated into button presses */
+			buttons_found |= (1UL << 5) | (1UL << 6);
+		}
 
 		for (i = 0; i < info->sc_buttons; i++) {
 			uint32_t mask;
@@ -287,10 +290,13 @@
 			    dx, dy, dz, dt, dw, buttons);
 
 			/* translate T-axis into button presses until further */
-			if (dt > 0)
-				buttons |= 1UL << 3;
-			else if (dt < 0)
-				buttons |= 1UL << 4;
+			if (dt > 0) {
+				ums_put_queue(sc, 0, 0, 0, 0, buttons);
+				buttons |= 1UL << 5;
+			} else if (dt < 0) {
+				ums_put_queue(sc, 0, 0, 0, 0, buttons);
+				buttons |= 1UL << 6;
+			}
 
 			sc->sc_status.button = buttons;
 			sc->sc_status.dx += dx;

Modified: stable/0.8/sys/dev/usb/input/usb_rdesc.h
===================================================================
--- stable/0.8/sys/dev/usb/input/usb_rdesc.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/input/usb_rdesc.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/input/usb_rdesc.h 196219 2009-08-14 20:03:53Z jhb $
  *
  * This file contains replacements for broken HID report descriptors.
  */

Added: stable/0.8/sys/dev/usb/input/wsp.c
===================================================================
--- stable/0.8/sys/dev/usb/input/wsp.c	                        (rev 0)
+++ stable/0.8/sys/dev/usb/input/wsp.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1397 @@
+/*-
+ * Copyright (c) 2012 Huang Wen Hui
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/input/wsp.c 291066 2015-11-19 10:01:50Z hselasky $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/selinfo.h>
+#include <sys/poll.h>
+#include <sys/sysctl.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbhid.h>
+
+#include "usbdevs.h"
+
+#define	USB_DEBUG_VAR wsp_debug
+#include <dev/usb/usb_debug.h>
+
+#include <sys/mouse.h>
+
+#define	WSP_DRIVER_NAME "wsp"
+#define	WSP_BUFFER_MAX	1024
+
+#define	WSP_CLAMP(x,low,high) do {		\
+	if ((x) < (low))			\
+		(x) = (low);			\
+	else if ((x) > (high))			\
+		(x) = (high);			\
+} while (0)
+
+/* Tunables */
+static	SYSCTL_NODE(_hw_usb, OID_AUTO, wsp, CTLFLAG_RW, 0, "USB wsp");
+
+#ifdef USB_DEBUG
+enum wsp_log_level {
+	WSP_LLEVEL_DISABLED = 0,
+	WSP_LLEVEL_ERROR,
+	WSP_LLEVEL_DEBUG,		/* for troubleshooting */
+	WSP_LLEVEL_INFO,		/* for diagnostics */
+};
+static int wsp_debug = WSP_LLEVEL_ERROR;/* the default is to only log errors */
+
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, debug, CTLFLAG_RW,
+    &wsp_debug, WSP_LLEVEL_ERROR, "WSP debug level");
+#endif					/* USB_DEBUG */
+
+static struct wsp_tuning {
+	int	scale_factor;
+	int	z_factor;
+	int	pressure_touch_threshold;
+	int	pressure_untouch_threshold;
+	int	pressure_tap_threshold;
+	int	scr_hor_threshold;
+}
+	wsp_tuning =
+{
+	.scale_factor = 12,
+	.z_factor = 5,
+	.pressure_touch_threshold = 50,
+	.pressure_untouch_threshold = 10,
+	.pressure_tap_threshold = 120,
+	.scr_hor_threshold = 20,
+};
+
+static void
+wsp_runing_rangecheck(struct wsp_tuning *ptun)
+{
+	WSP_CLAMP(ptun->scale_factor, 1, 63);
+	WSP_CLAMP(ptun->z_factor, 1, 63);
+	WSP_CLAMP(ptun->pressure_touch_threshold, 1, 255);
+	WSP_CLAMP(ptun->pressure_untouch_threshold, 1, 255);
+	WSP_CLAMP(ptun->pressure_tap_threshold, 1, 255);
+	WSP_CLAMP(ptun->scr_hor_threshold, 1, 255);
+}
+
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scale_factor, CTLFLAG_RW,
+    &wsp_tuning.scale_factor, 0, "movement scale factor");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, z_factor, CTLFLAG_RW,
+    &wsp_tuning.z_factor, 0, "Z-axis scale factor");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_touch_threshold, CTLFLAG_RW,
+    &wsp_tuning.pressure_touch_threshold, 0, "touch pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_untouch_threshold, CTLFLAG_RW,
+    &wsp_tuning.pressure_untouch_threshold, 0, "untouch pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_tap_threshold, CTLFLAG_RW,
+    &wsp_tuning.pressure_tap_threshold, 0, "tap pressure threshold");
+SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scr_hor_threshold, CTLFLAG_RW,
+    &wsp_tuning.scr_hor_threshold, 0, "horizontal scrolling threshold");
+
+/*
+ * Some tables, structures, definitions and constant values for the
+ * touchpad protocol has been copied from Linux's
+ * "drivers/input/mouse/bcm5974.c" which has the following copyright
+ * holders under GPLv2. All device specific code in this driver has
+ * been written from scratch. The decoding algorithm is based on
+ * output from FreeBSD's usbdump.
+ *
+ * Copyright (C) 2008      Henrik Rydberg (rydberg at euromail.se)
+ * Copyright (C) 2008      Scott Shawcroft (scott.shawcroft at gmail.com)
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg at kroah.com)
+ * Copyright (C) 2005      Johannes Berg (johannes at sipsolutions.net)
+ * Copyright (C) 2005      Stelian Pop (stelian at popies.net)
+ * Copyright (C) 2005      Frank Arnold (frank at scirocco-5v-turbo.de)
+ * Copyright (C) 2005      Peter Osterlund (petero2 at telia.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel at hansmi.ch)
+ * Copyright (C) 2006      Nicolas Boichat (nicolas at boichat.ch)
+ */
+
+/* button data structure */
+struct bt_data {
+	uint8_t	unknown1;		/* constant */
+	uint8_t	button;			/* left button */
+	uint8_t	rel_x;			/* relative x coordinate */
+	uint8_t	rel_y;			/* relative y coordinate */
+} __packed;
+
+/* trackpad header types */
+enum tp_type {
+	TYPE1,			/* plain trackpad */
+	TYPE2,			/* button integrated in trackpad */
+	TYPE3,			/* additional header fields since June 2013 */
+	TYPE4                   /* additional header field for pressure data */
+};
+
+/* trackpad finger data offsets, le16-aligned */
+#define	FINGER_TYPE1		(13 * 2)
+#define	FINGER_TYPE2		(15 * 2)
+#define	FINGER_TYPE3		(19 * 2)
+#define	FINGER_TYPE4		(23 * 2)
+
+/* trackpad button data offsets */
+#define	BUTTON_TYPE2		15
+#define	BUTTON_TYPE3		23
+#define	BUTTON_TYPE4		31
+
+/* list of device capability bits */
+#define	HAS_INTEGRATED_BUTTON	1
+
+/* trackpad finger data block size */
+#define FSIZE_TYPE1             (14 * 2)
+#define FSIZE_TYPE2             (14 * 2)
+#define FSIZE_TYPE3             (14 * 2)
+#define FSIZE_TYPE4             (15 * 2)
+
+/* trackpad finger header - little endian */
+struct tp_header {
+	uint8_t	flag;
+	uint8_t	sn0;
+	uint16_t wFixed0;
+	uint32_t dwSn1;
+	uint32_t dwFixed1;
+	uint16_t wLength;
+	uint8_t	nfinger;
+	uint8_t	ibt;
+	int16_t	wUnknown[6];
+	uint8_t	q1;
+	uint8_t	q2;
+} __packed;
+
+/* trackpad finger structure - little endian */
+struct tp_finger {
+	int16_t	origin;			/* zero when switching track finger */
+	int16_t	abs_x;			/* absolute x coodinate */
+	int16_t	abs_y;			/* absolute y coodinate */
+	int16_t	rel_x;			/* relative x coodinate */
+	int16_t	rel_y;			/* relative y coodinate */
+	int16_t	tool_major;		/* tool area, major axis */
+	int16_t	tool_minor;		/* tool area, minor axis */
+	int16_t	orientation;		/* 16384 when point, else 15 bit angle */
+	int16_t	touch_major;		/* touch area, major axis */
+	int16_t	touch_minor;		/* touch area, minor axis */
+	int16_t	unused[2];		/* zeros */
+	int16_t pressure;		/* pressure on forcetouch touchpad */
+	int16_t	multi;			/* one finger: varies, more fingers:
+				 	 * constant */
+} __packed;
+
+/* trackpad finger data size, empirically at least ten fingers */
+#define	MAX_FINGERS		16
+#define	SIZEOF_FINGER		sizeof(struct tp_finger)
+#define	SIZEOF_ALL_FINGERS	(MAX_FINGERS * SIZEOF_FINGER)
+
+#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
+#error "WSP_BUFFER_MAX is too small"
+#endif
+
+enum {
+	WSP_FLAG_WELLSPRING1,
+	WSP_FLAG_WELLSPRING2,
+	WSP_FLAG_WELLSPRING3,
+	WSP_FLAG_WELLSPRING4,
+	WSP_FLAG_WELLSPRING4A,
+	WSP_FLAG_WELLSPRING5,
+	WSP_FLAG_WELLSPRING6A,
+	WSP_FLAG_WELLSPRING6,
+	WSP_FLAG_WELLSPRING5A,
+	WSP_FLAG_WELLSPRING7,
+	WSP_FLAG_WELLSPRING7A,
+	WSP_FLAG_WELLSPRING8,
+	WSP_FLAG_WELLSPRING9,
+	WSP_FLAG_MAX,
+};
+
+/* device-specific configuration */
+struct wsp_dev_params {
+	uint8_t	caps;			/* device capability bitmask */
+	uint8_t	tp_type;		/* type of trackpad interface */
+	uint8_t	tp_button;		/* offset to button data */
+	uint8_t	tp_offset;		/* offset to trackpad finger data */
+	uint8_t tp_fsize;		/* bytes in single finger block */
+	uint8_t tp_delta;		/* offset from header to finger struct */
+	uint8_t iface_index;
+	uint8_t um_size;		/* usb control message length */
+	uint8_t um_req_val;		/* usb control message value */
+	uint8_t um_req_idx;		/* usb control message index */
+	uint8_t um_switch_idx;		/* usb control message mode switch index */
+	uint8_t um_switch_on;		/* usb control message mode switch on */
+	uint8_t um_switch_off;		/* usb control message mode switch off */
+};
+
+static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
+	[WSP_FLAG_WELLSPRING1] = {
+		.caps = 0,
+		.tp_type = TYPE1,
+		.tp_button = 0,
+		.tp_offset = FINGER_TYPE1,
+		.tp_fsize = FSIZE_TYPE1,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING2] = {
+		.caps = 0,
+		.tp_type = TYPE1,
+		.tp_button = 0,
+		.tp_offset = FINGER_TYPE1,
+		.tp_fsize = FSIZE_TYPE1,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING3] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING4] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING4A] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING5] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING6] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING5A] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING6A] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING7] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING7A] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE2,
+		.tp_button = BUTTON_TYPE2,
+		.tp_offset = FINGER_TYPE2,
+		.tp_fsize = FSIZE_TYPE2,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING8] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE3,
+		.tp_button = BUTTON_TYPE3,
+		.tp_offset = FINGER_TYPE3,
+		.tp_fsize = FSIZE_TYPE3,
+		.tp_delta = 0,
+		.iface_index = 0,
+		.um_size = 8,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x00,
+		.um_switch_idx = 0,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x08,
+	},
+	[WSP_FLAG_WELLSPRING9] = {
+		.caps = HAS_INTEGRATED_BUTTON,
+		.tp_type = TYPE4,
+		.tp_button = BUTTON_TYPE4,
+		.tp_offset = FINGER_TYPE4,
+		.tp_fsize = FSIZE_TYPE4,
+		.tp_delta = 2,
+		.iface_index = 2,
+		.um_size = 2,
+		.um_req_val = 0x03,
+		.um_req_idx = 0x02,
+		.um_switch_idx = 1,
+		.um_switch_on = 0x01,
+		.um_switch_off = 0x00,
+	},
+};
+
+#define	WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+
+static const STRUCT_USB_HOST_ID wsp_devs[] = {
+	/* MacbookAir1.1 */
+	WSP_DEV(APPLE, WELLSPRING_ANSI, WSP_FLAG_WELLSPRING1),
+	WSP_DEV(APPLE, WELLSPRING_ISO, WSP_FLAG_WELLSPRING1),
+	WSP_DEV(APPLE, WELLSPRING_JIS, WSP_FLAG_WELLSPRING1),
+
+	/* MacbookProPenryn, aka wellspring2 */
+	WSP_DEV(APPLE, WELLSPRING2_ANSI, WSP_FLAG_WELLSPRING2),
+	WSP_DEV(APPLE, WELLSPRING2_ISO, WSP_FLAG_WELLSPRING2),
+	WSP_DEV(APPLE, WELLSPRING2_JIS, WSP_FLAG_WELLSPRING2),
+
+	/* Macbook5,1 (unibody), aka wellspring3 */
+	WSP_DEV(APPLE, WELLSPRING3_ANSI, WSP_FLAG_WELLSPRING3),
+	WSP_DEV(APPLE, WELLSPRING3_ISO, WSP_FLAG_WELLSPRING3),
+	WSP_DEV(APPLE, WELLSPRING3_JIS, WSP_FLAG_WELLSPRING3),
+
+	/* MacbookAir3,2 (unibody), aka wellspring4 */
+	WSP_DEV(APPLE, WELLSPRING4_ANSI, WSP_FLAG_WELLSPRING4),
+	WSP_DEV(APPLE, WELLSPRING4_ISO, WSP_FLAG_WELLSPRING4),
+	WSP_DEV(APPLE, WELLSPRING4_JIS, WSP_FLAG_WELLSPRING4),
+
+	/* MacbookAir3,1 (unibody), aka wellspring4 */
+	WSP_DEV(APPLE, WELLSPRING4A_ANSI, WSP_FLAG_WELLSPRING4A),
+	WSP_DEV(APPLE, WELLSPRING4A_ISO, WSP_FLAG_WELLSPRING4A),
+	WSP_DEV(APPLE, WELLSPRING4A_JIS, WSP_FLAG_WELLSPRING4A),
+
+	/* Macbook8 (unibody, March 2011) */
+	WSP_DEV(APPLE, WELLSPRING5_ANSI, WSP_FLAG_WELLSPRING5),
+	WSP_DEV(APPLE, WELLSPRING5_ISO, WSP_FLAG_WELLSPRING5),
+	WSP_DEV(APPLE, WELLSPRING5_JIS, WSP_FLAG_WELLSPRING5),
+
+	/* MacbookAir4,1 (unibody, July 2011) */
+	WSP_DEV(APPLE, WELLSPRING6A_ANSI, WSP_FLAG_WELLSPRING6A),
+	WSP_DEV(APPLE, WELLSPRING6A_ISO, WSP_FLAG_WELLSPRING6A),
+	WSP_DEV(APPLE, WELLSPRING6A_JIS, WSP_FLAG_WELLSPRING6A),
+
+	/* MacbookAir4,2 (unibody, July 2011) */
+	WSP_DEV(APPLE, WELLSPRING6_ANSI, WSP_FLAG_WELLSPRING6),
+	WSP_DEV(APPLE, WELLSPRING6_ISO, WSP_FLAG_WELLSPRING6),
+	WSP_DEV(APPLE, WELLSPRING6_JIS, WSP_FLAG_WELLSPRING6),
+
+	/* Macbook8,2 (unibody) */
+	WSP_DEV(APPLE, WELLSPRING5A_ANSI, WSP_FLAG_WELLSPRING5A),
+	WSP_DEV(APPLE, WELLSPRING5A_ISO, WSP_FLAG_WELLSPRING5A),
+	WSP_DEV(APPLE, WELLSPRING5A_JIS, WSP_FLAG_WELLSPRING5A),
+
+	/* MacbookPro10,1 (unibody, June 2012) */
+	/* MacbookPro11,1-3 (unibody, June 2013) */
+	WSP_DEV(APPLE, WELLSPRING7_ANSI, WSP_FLAG_WELLSPRING7),
+	WSP_DEV(APPLE, WELLSPRING7_ISO, WSP_FLAG_WELLSPRING7),
+	WSP_DEV(APPLE, WELLSPRING7_JIS, WSP_FLAG_WELLSPRING7),
+
+	/* MacbookPro10,2 (unibody, October 2012) */
+	WSP_DEV(APPLE, WELLSPRING7A_ANSI, WSP_FLAG_WELLSPRING7A),
+	WSP_DEV(APPLE, WELLSPRING7A_ISO, WSP_FLAG_WELLSPRING7A),
+	WSP_DEV(APPLE, WELLSPRING7A_JIS, WSP_FLAG_WELLSPRING7A),
+
+	/* MacbookAir6,2 (unibody, June 2013) */
+	WSP_DEV(APPLE, WELLSPRING8_ANSI, WSP_FLAG_WELLSPRING8),
+	WSP_DEV(APPLE, WELLSPRING8_ISO, WSP_FLAG_WELLSPRING8),
+	WSP_DEV(APPLE, WELLSPRING8_JIS, WSP_FLAG_WELLSPRING8),
+
+	/* MacbookPro12,1 MacbookPro11,4 */
+	WSP_DEV(APPLE, WELLSPRING9_ANSI, WSP_FLAG_WELLSPRING9),
+	WSP_DEV(APPLE, WELLSPRING9_ISO, WSP_FLAG_WELLSPRING9),
+	WSP_DEV(APPLE, WELLSPRING9_JIS, WSP_FLAG_WELLSPRING9),
+};
+
+#define	WSP_FIFO_BUF_SIZE	 8	/* bytes */
+#define	WSP_FIFO_QUEUE_MAXLEN	50	/* units */
+
+enum {
+	WSP_INTR_DT,
+	WSP_N_TRANSFER,
+};
+
+struct wsp_softc {
+	struct usb_device *sc_usb_device;
+	struct mtx sc_mutex;		/* for synchronization */
+	struct usb_xfer *sc_xfer[WSP_N_TRANSFER];
+	struct usb_fifo_sc sc_fifo;
+
+	const struct wsp_dev_params *sc_params;	/* device configuration */
+
+	mousehw_t sc_hw;
+	mousemode_t sc_mode;
+	u_int	sc_pollrate;
+	mousestatus_t sc_status;
+	u_int	sc_state;
+#define	WSP_ENABLED	       0x01
+
+	struct tp_finger *index[MAX_FINGERS];	/* finger index data */
+	int16_t	pos_x[MAX_FINGERS];	/* position array */
+	int16_t	pos_y[MAX_FINGERS];	/* position array */
+	u_int	sc_touch;		/* touch status */
+#define	WSP_UNTOUCH		0x00
+#define	WSP_FIRST_TOUCH		0x01
+#define	WSP_SECOND_TOUCH	0x02
+#define	WSP_TOUCHING		0x04
+	int16_t	pre_pos_x;		/* previous position array */
+	int16_t	pre_pos_y;		/* previous position array */
+	int	dx_sum;			/* x axis cumulative movement */
+	int	dy_sum;			/* y axis cumulative movement */
+	int	dz_sum;			/* z axis cumulative movement */
+	int	dz_count;
+#define	WSP_DZ_MAX_COUNT	32
+	int	dt_sum;			/* T-axis cumulative movement */
+	int	rdx;			/* x axis remainder of divide by scale_factor */
+	int	rdy;			/* y axis remainder of divide by scale_factor */
+	int	rdz;			/* z axis remainder of divide by scale_factor */
+	int	tp_datalen;
+	uint8_t o_ntouch;		/* old touch finger status */
+	uint8_t	finger;			/* 0 or 1 *, check which finger moving */
+	uint16_t intr_count;
+#define	WSP_TAP_THRESHOLD	3
+#define	WSP_TAP_MAX_COUNT	20
+	int	distance;		/* the distance of 2 fingers */
+#define	MAX_DISTANCE		2500	/* the max allowed distance */
+	uint8_t	ibtn;			/* button status in tapping */
+	uint8_t	ntaps;			/* finger status in tapping */
+	uint8_t	scr_mode;		/* scroll status in movement */
+#define	WSP_SCR_NONE		0
+#define	WSP_SCR_VER		1
+#define	WSP_SCR_HOR		2
+	uint8_t tp_data[WSP_BUFFER_MAX] __aligned(4);		/* trackpad transferred data */
+};
+
+/*
+ * function prototypes
+ */
+static usb_fifo_cmd_t wsp_start_read;
+static usb_fifo_cmd_t wsp_stop_read;
+static usb_fifo_open_t wsp_open;
+static usb_fifo_close_t wsp_close;
+static usb_fifo_ioctl_t wsp_ioctl;
+
+static struct usb_fifo_methods wsp_fifo_methods = {
+	.f_open = &wsp_open,
+	.f_close = &wsp_close,
+	.f_ioctl = &wsp_ioctl,
+	.f_start_read = &wsp_start_read,
+	.f_stop_read = &wsp_stop_read,
+	.basename[0] = WSP_DRIVER_NAME,
+};
+
+/* device initialization and shutdown */
+static int wsp_enable(struct wsp_softc *sc);
+static void wsp_disable(struct wsp_softc *sc);
+
+/* updating fifo */
+static void wsp_reset_buf(struct wsp_softc *sc);
+static void wsp_add_to_queue(struct wsp_softc *, int, int, int, uint32_t);
+
+/* Device methods. */
+static device_probe_t wsp_probe;
+static device_attach_t wsp_attach;
+static device_detach_t wsp_detach;
+static usb_callback_t wsp_intr_callback;
+
+static const struct usb_config wsp_config[WSP_N_TRANSFER] = {
+	[WSP_INTR_DT] = {
+		.type = UE_INTERRUPT,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_IN,
+		.flags = {
+			.pipe_bof = 0,
+			.short_xfer_ok = 1,
+		},
+		.bufsize = WSP_BUFFER_MAX,
+		.callback = &wsp_intr_callback,
+	},
+};
+
+static usb_error_t
+wsp_set_device_mode(struct wsp_softc *sc, uint8_t on)
+{
+	const struct wsp_dev_params *params = sc->sc_params;
+	uint8_t	mode_bytes[8];
+	usb_error_t err;
+
+	/* Type 3 does not require a mode switch */
+	if (params->tp_type == TYPE3)
+		return 0;
+
+	err = usbd_req_get_report(sc->sc_usb_device, NULL,
+	    mode_bytes, params->um_size, params->iface_index,
+	    params->um_req_val, params->um_req_idx);
+
+	if (err != USB_ERR_NORMAL_COMPLETION) {
+		DPRINTF("Failed to read device mode (%d)\n", err);
+		return (err);
+	}
+
+	/*
+	 * XXX Need to wait at least 250ms for hardware to get
+	 * ready. The device mode handling appears to be handled
+	 * asynchronously and we should not issue these commands too
+	 * quickly.
+	 */
+	pause("WHW", hz / 4);
+
+	mode_bytes[params->um_switch_idx] = 
+	    on ? params->um_switch_on : params->um_switch_off;
+
+	return (usbd_req_set_report(sc->sc_usb_device, NULL,
+	    mode_bytes, params->um_size, params->iface_index, 
+	    params->um_req_val, params->um_req_idx));
+}
+
+static int
+wsp_enable(struct wsp_softc *sc)
+{
+	/* reset status */
+	memset(&sc->sc_status, 0, sizeof(sc->sc_status));
+	sc->sc_state |= WSP_ENABLED;
+
+	DPRINTFN(WSP_LLEVEL_INFO, "enabled wsp\n");
+	return (0);
+}
+
+static void
+wsp_disable(struct wsp_softc *sc)
+{
+	sc->sc_state &= ~WSP_ENABLED;
+	DPRINTFN(WSP_LLEVEL_INFO, "disabled wsp\n");
+}
+
+static int
+wsp_probe(device_t self)
+{
+	struct usb_attach_arg *uaa = device_get_ivars(self);
+	struct usb_interface_descriptor *id;
+	struct usb_interface *iface;
+	uint8_t i;
+
+	if (uaa->usb_mode != USB_MODE_HOST)
+		return (ENXIO);
+
+	/* figure out first interface matching */
+	for (i = 1;; i++) {
+		iface = usbd_get_iface(uaa->device, i);
+		if (iface == NULL || i == 3)
+			return (ENXIO);
+		id = iface->idesc;
+		if ((id == NULL) ||
+		    (id->bInterfaceClass != UICLASS_HID) ||
+		    (id->bInterfaceProtocol != 0 &&
+		    id->bInterfaceProtocol != UIPROTO_MOUSE))
+			continue;
+		break;
+	}
+	/* check if we are attaching to the first match */
+	if (uaa->info.bIfaceIndex != i)
+		return (ENXIO);
+	return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
+}
+
+static int
+wsp_attach(device_t dev)
+{
+	struct wsp_softc *sc = device_get_softc(dev);
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	usb_error_t err;
+	void *d_ptr = NULL;
+	uint16_t d_len;
+
+	DPRINTFN(WSP_LLEVEL_INFO, "sc=%p\n", sc);
+
+	/* Get HID descriptor */
+	err = usbd_req_get_hid_desc(uaa->device, NULL, &d_ptr,
+	    &d_len, M_TEMP, uaa->info.bIfaceIndex);
+
+	if (err == USB_ERR_NORMAL_COMPLETION) {
+		/* Get HID report descriptor length */
+		sc->tp_datalen = hid_report_size(d_ptr, d_len, hid_input, NULL);
+		free(d_ptr, M_TEMP);
+
+		if (sc->tp_datalen <= 0 || sc->tp_datalen > WSP_BUFFER_MAX) {
+			DPRINTF("Invalid datalength or too big "
+			    "datalength: %d\n", sc->tp_datalen);
+			return (ENXIO);
+		}
+	} else {
+		return (ENXIO);
+	}
+
+	sc->sc_usb_device = uaa->device;
+
+	/* get device specific configuration */
+	sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
+
+	/*
+	 * By default the touchpad behaves like a HID device, sending
+	 * packets with reportID = 8. Such reports contain only
+	 * limited information. They encode movement deltas and button
+	 * events, but do not include data from the pressure
+	 * sensors. The device input mode can be switched from HID
+	 * reports to raw sensor data using vendor-specific USB
+	 * control commands:
+	 */
+
+	/*
+	 * During re-enumeration of the device we need to force the
+	 * device back into HID mode before switching it to RAW
+	 * mode. Else the device does not work like expected.
+	 */
+	err = wsp_set_device_mode(sc, 0);
+	if (err != USB_ERR_NORMAL_COMPLETION) {
+		DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
+		return (ENXIO);
+	}
+
+	err = wsp_set_device_mode(sc, 1);
+	if (err != USB_ERR_NORMAL_COMPLETION) {
+		DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
+		return (ENXIO);
+	}
+
+	mtx_init(&sc->sc_mutex, "wspmtx", NULL, MTX_DEF | MTX_RECURSE);
+
+	err = usbd_transfer_setup(uaa->device,
+	    &uaa->info.bIfaceIndex, sc->sc_xfer, wsp_config,
+	    WSP_N_TRANSFER, sc, &sc->sc_mutex);
+	if (err) {
+		DPRINTF("error=%s\n", usbd_errstr(err));
+		goto detach;
+	}
+	if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex,
+	    &wsp_fifo_methods, &sc->sc_fifo,
+	    device_get_unit(dev), -1, uaa->info.bIfaceIndex,
+	    UID_ROOT, GID_OPERATOR, 0644)) {
+		goto detach;
+	}
+	device_set_usb_desc(dev);
+
+	sc->sc_hw.buttons = 3;
+	sc->sc_hw.iftype = MOUSE_IF_USB;
+	sc->sc_hw.type = MOUSE_PAD;
+	sc->sc_hw.model = MOUSE_MODEL_GENERIC;
+	sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+	sc->sc_mode.rate = -1;
+	sc->sc_mode.resolution = MOUSE_RES_UNKNOWN;
+	sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+	sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+	sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+
+	sc->sc_touch = WSP_UNTOUCH;
+	sc->scr_mode = WSP_SCR_NONE;
+
+	return (0);
+
+detach:
+	wsp_detach(dev);
+	return (ENOMEM);
+}
+
+static int
+wsp_detach(device_t dev)
+{
+	struct wsp_softc *sc = device_get_softc(dev);
+
+	(void) wsp_set_device_mode(sc, 0);
+
+	mtx_lock(&sc->sc_mutex);
+	if (sc->sc_state & WSP_ENABLED)
+		wsp_disable(sc);
+	mtx_unlock(&sc->sc_mutex);
+
+	usb_fifo_detach(&sc->sc_fifo);
+
+	usbd_transfer_unsetup(sc->sc_xfer, WSP_N_TRANSFER);
+
+	mtx_destroy(&sc->sc_mutex);
+
+	return (0);
+}
+
+static void
+wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct wsp_softc *sc = usbd_xfer_softc(xfer);
+	const struct wsp_dev_params *params = sc->sc_params;
+	struct usb_page_cache *pc;
+	struct tp_finger *f;
+	struct tp_header *h;
+	struct wsp_tuning tun = wsp_tuning;
+	int ntouch = 0;			/* the finger number in touch */
+	int ibt = 0;			/* button status */
+	int dx = 0;
+	int dy = 0;
+	int dz = 0;
+	int rdx = 0;
+	int rdy = 0;
+	int rdz = 0;
+	int len;
+	int i;
+
+	wsp_runing_rangecheck(&tun);
+
+	if (sc->dz_count == 0)
+		sc->dz_count = WSP_DZ_MAX_COUNT;
+
+	usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+
+		/* copy out received data */
+		pc = usbd_xfer_get_frame(xfer, 0);
+		usbd_copy_out(pc, 0, sc->tp_data, len);
+
+		if ((len < params->tp_offset + params->tp_fsize) ||
+		    ((len - params->tp_offset) % params->tp_fsize) != 0) {
+			DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
+			    len, sc->tp_data[0], sc->tp_data[1]);
+			goto tr_setup;
+		}
+
+		if (len < sc->tp_datalen) {
+			/* make sure we don't process old data */
+			memset(sc->tp_data + len, 0, sc->tp_datalen - len);
+		}
+
+		h = (struct tp_header *)(sc->tp_data);
+
+		if (params->tp_type >= TYPE2) {
+			ibt = sc->tp_data[params->tp_button];
+			ntouch = sc->tp_data[params->tp_button - 1];
+		}
+		/* range check */
+		if (ntouch < 0)
+			ntouch = 0;
+		else if (ntouch > MAX_FINGERS)
+			ntouch = MAX_FINGERS;
+
+		for (i = 0; i != ntouch; i++) {
+			f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
+			/* swap endianness, if any */
+			if (le16toh(0x1234) != 0x1234) {
+				f->origin = le16toh((uint16_t)f->origin);
+				f->abs_x = le16toh((uint16_t)f->abs_x);
+				f->abs_y = le16toh((uint16_t)f->abs_y);
+				f->rel_x = le16toh((uint16_t)f->rel_x);
+				f->rel_y = le16toh((uint16_t)f->rel_y);
+				f->tool_major = le16toh((uint16_t)f->tool_major);
+				f->tool_minor = le16toh((uint16_t)f->tool_minor);
+				f->orientation = le16toh((uint16_t)f->orientation);
+				f->touch_major = le16toh((uint16_t)f->touch_major);
+				f->touch_minor = le16toh((uint16_t)f->touch_minor);
+				f->pressure = le16toh((uint16_t)f->pressure);
+				f->multi = le16toh((uint16_t)f->multi);
+			}
+			DPRINTFN(WSP_LLEVEL_INFO, 
+			    "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
+			    "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
+			    "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
+			    i, ibt, ntouch, f->origin, f->abs_x, f->abs_y,
+			    f->rel_x, f->rel_y, f->tool_major, f->tool_minor, f->orientation,
+			    f->touch_major, f->touch_minor, f->pressure, f->multi);
+			sc->pos_x[i] = f->abs_x;
+			sc->pos_y[i] = -f->abs_y;
+			sc->index[i] = f;
+		}
+
+		sc->sc_status.flags &= ~MOUSE_POSCHANGED;
+		sc->sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
+		sc->sc_status.obutton = sc->sc_status.button;
+		sc->sc_status.button = 0;
+
+		if (ibt != 0) {
+			sc->sc_status.button |= MOUSE_BUTTON1DOWN;
+			sc->ibtn = 1;
+		}
+		sc->intr_count++;
+
+		if (sc->ntaps < ntouch) {
+			switch (ntouch) {
+			case 1:
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold &&
+				    sc->index[0]->tool_major <= 1200)
+					sc->ntaps = 1;
+				break;
+			case 2:
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold-30 &&
+				    sc->index[1]->touch_major > tun.pressure_tap_threshold-30)
+					sc->ntaps = 2;
+				break;
+			case 3:
+				if (sc->index[0]->touch_major > tun.pressure_tap_threshold-40 &&
+				    sc->index[1]->touch_major > tun.pressure_tap_threshold-40 &&
+				    sc->index[2]->touch_major > tun.pressure_tap_threshold-40)
+					sc->ntaps = 3;
+				break;
+			default:
+				break;
+			}
+		}
+		if (ntouch == 2) {
+			sc->distance = max(sc->distance, max(
+			    abs(sc->pos_x[0] - sc->pos_x[1]),
+			    abs(sc->pos_y[0] - sc->pos_y[1])));
+		}
+		if (sc->index[0]->touch_major < tun.pressure_untouch_threshold &&
+		    sc->sc_status.button == 0) {
+			sc->sc_touch = WSP_UNTOUCH;
+			if (sc->intr_count < WSP_TAP_MAX_COUNT &&
+			    sc->intr_count > WSP_TAP_THRESHOLD &&
+			    sc->ntaps && sc->ibtn == 0) {
+				/*
+				 * Add a pair of events (button-down and
+				 * button-up).
+				 */
+				switch (sc->ntaps) {
+				case 1:
+					if (!(params->caps & HAS_INTEGRATED_BUTTON)) {
+						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON1DOWN);
+						DPRINTFN(WSP_LLEVEL_INFO, "LEFT CLICK!\n");
+					}
+					break;
+				case 2:
+					DPRINTFN(WSP_LLEVEL_INFO, "sum_x=%5d, sum_y=%5d\n",
+					    sc->dx_sum, sc->dy_sum);
+					if (sc->distance < MAX_DISTANCE && abs(sc->dx_sum) < 5 &&
+					    abs(sc->dy_sum) < 5) {
+						wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON3DOWN);
+						DPRINTFN(WSP_LLEVEL_INFO, "RIGHT CLICK!\n");
+					}
+					break;
+				case 3:
+					wsp_add_to_queue(sc, 0, 0, 0, MOUSE_BUTTON2DOWN);
+					break;
+				default:
+					/* we don't handle taps of more than three fingers */
+					break;
+				}
+				wsp_add_to_queue(sc, 0, 0, 0, 0);	/* button release */
+			}
+			if ((sc->dt_sum / tun.scr_hor_threshold) != 0 &&
+			    sc->ntaps == 2 && sc->scr_mode == WSP_SCR_HOR) {
+
+				/*
+				 * translate T-axis into button presses
+				 * until further
+				 */
+				if (sc->dt_sum > 0)
+					wsp_add_to_queue(sc, 0, 0, 0, 1UL << 3);
+				else if (sc->dt_sum < 0)
+					wsp_add_to_queue(sc, 0, 0, 0, 1UL << 4);
+			}
+			sc->dz_count = WSP_DZ_MAX_COUNT;
+			sc->dz_sum = 0;
+			sc->intr_count = 0;
+			sc->ibtn = 0;
+			sc->ntaps = 0;
+			sc->finger = 0;
+			sc->distance = 0;
+			sc->dt_sum = 0;
+			sc->dx_sum = 0;
+			sc->dy_sum = 0;
+			sc->rdx = 0;
+			sc->rdy = 0;
+			sc->rdz = 0;
+			sc->scr_mode = WSP_SCR_NONE;
+		} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
+		    sc->sc_touch == WSP_UNTOUCH) {	/* ignore first touch */
+			sc->sc_touch = WSP_FIRST_TOUCH;
+		} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
+		    sc->sc_touch == WSP_FIRST_TOUCH) {	/* ignore second touch */
+			sc->sc_touch = WSP_SECOND_TOUCH;
+			DPRINTFN(WSP_LLEVEL_INFO, "Fist pre_x=%5d, pre_y=%5d\n",
+			    sc->pre_pos_x, sc->pre_pos_y);
+		} else {
+			if (sc->sc_touch == WSP_SECOND_TOUCH)
+				sc->sc_touch = WSP_TOUCHING;
+
+			if (ntouch != 0 &&
+			    sc->index[0]->touch_major >= tun.pressure_touch_threshold) {
+				dx = sc->pos_x[0] - sc->pre_pos_x;
+				dy = sc->pos_y[0] - sc->pre_pos_y;
+
+				/* Ignore movement during button is releasing */
+				if (sc->ibtn != 0 && sc->sc_status.button == 0)
+					dx = dy = 0;
+
+				/* Ignore movement if ntouch changed */
+				if (sc->o_ntouch != ntouch)
+					dx = dy = 0;
+
+				/* Ignore unexpeted movment when typing */
+				if (ntouch == 1 && sc->index[0]->tool_major > 1200)
+					dx = dy = 0;
+
+				if (sc->ibtn != 0 && ntouch == 1 && 
+				    sc->intr_count < WSP_TAP_MAX_COUNT && 
+				    abs(sc->dx_sum) < 1 && abs(sc->dy_sum) < 1 )
+					dx = dy = 0;
+
+				if (ntouch == 2 && sc->sc_status.button != 0) {
+					dx = sc->pos_x[sc->finger] - sc->pre_pos_x;
+					dy = sc->pos_y[sc->finger] - sc->pre_pos_y;
+					
+					/*
+					 * Ignore movement of switch finger or
+					 * movement from ibt=0 to ibt=1
+					 */
+					if (sc->index[0]->origin == 0 || sc->index[1]->origin == 0 ||
+					    sc->sc_status.obutton != sc->sc_status.button) {
+						dx = dy = 0;
+						sc->finger = 0;
+					}
+					if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) <
+					    (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
+					    sc->finger == 0) {
+						sc->sc_touch = WSP_SECOND_TOUCH;
+						dx = dy = 0;
+						sc->finger = 1;
+					}
+					if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) >=
+					    (abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
+					    sc->finger == 1) {
+						sc->sc_touch = WSP_SECOND_TOUCH;
+						dx = dy = 0;
+						sc->finger = 0;
+					}
+					DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, mov=%5d\n",
+					    dx, dy, sc->finger);
+				}
+				if (sc->dz_count--) {
+					rdz = (dy + sc->rdz) % tun.scale_factor;
+					sc->dz_sum -= (dy + sc->rdz) / tun.scale_factor;
+					sc->rdz = rdz;
+				}
+				if ((sc->dz_sum / tun.z_factor) != 0)
+					sc->dz_count = 0;
+			}
+			rdx = (dx + sc->rdx) % tun.scale_factor;
+			dx = (dx + sc->rdx) / tun.scale_factor;
+			sc->rdx = rdx;
+
+			rdy = (dy + sc->rdy) % tun.scale_factor;
+			dy = (dy + sc->rdy) / tun.scale_factor;
+			sc->rdy = rdy;
+
+			sc->dx_sum += dx;
+			sc->dy_sum += dy;
+
+			if (ntouch == 2 && sc->sc_status.button == 0) {
+				if (sc->scr_mode == WSP_SCR_NONE &&
+				    abs(sc->dx_sum) + abs(sc->dy_sum) > tun.scr_hor_threshold)
+					sc->scr_mode = abs(sc->dx_sum) >
+					    abs(sc->dy_sum) * 2 ? WSP_SCR_HOR : WSP_SCR_VER;
+				DPRINTFN(WSP_LLEVEL_INFO, "scr_mode=%5d, count=%d, dx_sum=%d, dy_sum=%d\n",
+				    sc->scr_mode, sc->intr_count, sc->dx_sum, sc->dy_sum);
+				if (sc->scr_mode == WSP_SCR_HOR)
+					sc->dt_sum += dx;
+				else
+					sc->dt_sum = 0;
+
+				dx = dy = 0;
+				if (sc->dz_count == 0)
+					dz = sc->dz_sum / tun.z_factor;
+				if (sc->scr_mode == WSP_SCR_HOR || 
+				    abs(sc->pos_x[0] - sc->pos_x[1]) > MAX_DISTANCE ||
+				    abs(sc->pos_y[0] - sc->pos_y[1]) > MAX_DISTANCE)
+					dz = 0;
+			}
+			if (ntouch == 3)
+				dx = dy = dz = 0;
+			if (sc->intr_count < WSP_TAP_MAX_COUNT &&
+			    abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3)
+				dx = dy = dz = 0;
+			else
+				sc->intr_count = WSP_TAP_MAX_COUNT;
+			if (dx || dy || dz)
+				sc->sc_status.flags |= MOUSE_POSCHANGED;
+			DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, dz=%5d, sc_touch=%x, btn=%x\n",
+			    dx, dy, dz, sc->sc_touch, sc->sc_status.button);
+			sc->sc_status.dx += dx;
+			sc->sc_status.dy += dy;
+			sc->sc_status.dz += dz;
+
+			wsp_add_to_queue(sc, dx, -dy, dz, sc->sc_status.button);
+			if (sc->dz_count == 0) {
+				sc->dz_sum = 0;
+				sc->rdz = 0;
+			}
+
+		}
+		sc->pre_pos_x = sc->pos_x[0];
+		sc->pre_pos_y = sc->pos_y[0];
+
+		if (ntouch == 2 && sc->sc_status.button != 0) {
+			sc->pre_pos_x = sc->pos_x[sc->finger];
+			sc->pre_pos_y = sc->pos_y[sc->finger];
+		}
+		sc->o_ntouch = ntouch;
+
+	case USB_ST_SETUP:
+tr_setup:
+		/* check if we can put more data into the FIFO */
+		if (usb_fifo_put_bytes_max(
+		    sc->sc_fifo.fp[USB_FIFO_RX]) != 0) {
+			usbd_xfer_set_frame_len(xfer, 0,
+			    sc->tp_datalen);
+			usbd_transfer_submit(xfer);
+		}
+		break;
+
+	default:			/* Error */
+		if (error != USB_ERR_CANCELLED) {
+			/* try clear stall first */
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		break;
+	}
+}
+
+static void
+wsp_add_to_queue(struct wsp_softc *sc, int dx, int dy, int dz,
+    uint32_t buttons_in)
+{
+	uint32_t buttons_out;
+	uint8_t buf[8];
+
+	dx = imin(dx, 254);
+	dx = imax(dx, -256);
+	dy = imin(dy, 254);
+	dy = imax(dy, -256);
+	dz = imin(dz, 126);
+	dz = imax(dz, -128);
+
+	buttons_out = MOUSE_MSC_BUTTONS;
+	if (buttons_in & MOUSE_BUTTON1DOWN)
+		buttons_out &= ~MOUSE_MSC_BUTTON1UP;
+	else if (buttons_in & MOUSE_BUTTON2DOWN)
+		buttons_out &= ~MOUSE_MSC_BUTTON2UP;
+	else if (buttons_in & MOUSE_BUTTON3DOWN)
+		buttons_out &= ~MOUSE_MSC_BUTTON3UP;
+
+	/* Encode the mouse data in standard format; refer to mouse(4) */
+	buf[0] = sc->sc_mode.syncmask[1];
+	buf[0] |= buttons_out;
+	buf[1] = dx >> 1;
+	buf[2] = dy >> 1;
+	buf[3] = dx - (dx >> 1);
+	buf[4] = dy - (dy >> 1);
+	/* Encode extra bytes for level 1 */
+	if (sc->sc_mode.level == 1) {
+		buf[5] = dz >> 1;	/* dz / 2 */
+		buf[6] = dz - (dz >> 1);/* dz - (dz / 2) */
+		buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS);
+	}
+	usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf,
+	    sc->sc_mode.packetsize, 1);
+}
+
+static void
+wsp_reset_buf(struct wsp_softc *sc)
+{
+	/* reset read queue */
+	usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]);
+}
+
+static void
+wsp_start_read(struct usb_fifo *fifo)
+{
+	struct wsp_softc *sc = usb_fifo_softc(fifo);
+	int rate;
+
+	/* Check if we should override the default polling interval */
+	rate = sc->sc_pollrate;
+	/* Range check rate */
+	if (rate > 1000)
+		rate = 1000;
+	/* Check for set rate */
+	if ((rate > 0) && (sc->sc_xfer[WSP_INTR_DT] != NULL)) {
+		/* Stop current transfer, if any */
+		usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
+		/* Set new interval */
+		usbd_xfer_set_interval(sc->sc_xfer[WSP_INTR_DT], 1000 / rate);
+		/* Only set pollrate once */
+		sc->sc_pollrate = 0;
+	}
+	usbd_transfer_start(sc->sc_xfer[WSP_INTR_DT]);
+}
+
+static void
+wsp_stop_read(struct usb_fifo *fifo)
+{
+	struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+	usbd_transfer_stop(sc->sc_xfer[WSP_INTR_DT]);
+}
+
+
+static int
+wsp_open(struct usb_fifo *fifo, int fflags)
+{
+	DPRINTFN(WSP_LLEVEL_INFO, "\n");
+
+	if (fflags & FREAD) {
+		struct wsp_softc *sc = usb_fifo_softc(fifo);
+		int rc;
+
+		if (sc->sc_state & WSP_ENABLED)
+			return (EBUSY);
+
+		if (usb_fifo_alloc_buffer(fifo,
+		    WSP_FIFO_BUF_SIZE, WSP_FIFO_QUEUE_MAXLEN)) {
+			return (ENOMEM);
+		}
+		rc = wsp_enable(sc);
+		if (rc != 0) {
+			usb_fifo_free_buffer(fifo);
+			return (rc);
+		}
+	}
+	return (0);
+}
+
+static void
+wsp_close(struct usb_fifo *fifo, int fflags)
+{
+	if (fflags & FREAD) {
+		struct wsp_softc *sc = usb_fifo_softc(fifo);
+
+		wsp_disable(sc);
+		usb_fifo_free_buffer(fifo);
+	}
+}
+
+int
+wsp_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
+{
+	struct wsp_softc *sc = usb_fifo_softc(fifo);
+	mousemode_t mode;
+	int error = 0;
+
+	mtx_lock(&sc->sc_mutex);
+
+	switch (cmd) {
+	case MOUSE_GETHWINFO:
+		*(mousehw_t *)addr = sc->sc_hw;
+		break;
+	case MOUSE_GETMODE:
+		*(mousemode_t *)addr = sc->sc_mode;
+		break;
+	case MOUSE_SETMODE:
+		mode = *(mousemode_t *)addr;
+
+		if (mode.level == -1)
+			/* Don't change the current setting */
+			;
+		else if ((mode.level < 0) || (mode.level > 1)) {
+			error = EINVAL;
+			goto done;
+		}
+		sc->sc_mode.level = mode.level;
+		sc->sc_pollrate = mode.rate;
+		sc->sc_hw.buttons = 3;
+
+		if (sc->sc_mode.level == 0) {
+			sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+			sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+			sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+			sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+		} else if (sc->sc_mode.level == 1) {
+			sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
+			sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
+			sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
+			sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
+		}
+		wsp_reset_buf(sc);
+		break;
+	case MOUSE_GETLEVEL:
+		*(int *)addr = sc->sc_mode.level;
+		break;
+	case MOUSE_SETLEVEL:
+		if (*(int *)addr < 0 || *(int *)addr > 1) {
+			error = EINVAL;
+			goto done;
+		}
+		sc->sc_mode.level = *(int *)addr;
+		sc->sc_hw.buttons = 3;
+
+		if (sc->sc_mode.level == 0) {
+			sc->sc_mode.protocol = MOUSE_PROTO_MSC;
+			sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
+			sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
+			sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
+		} else if (sc->sc_mode.level == 1) {
+			sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
+			sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
+			sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
+			sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
+		}
+		wsp_reset_buf(sc);
+		break;
+	case MOUSE_GETSTATUS:{
+			mousestatus_t *status = (mousestatus_t *)addr;
+
+			*status = sc->sc_status;
+			sc->sc_status.obutton = sc->sc_status.button;
+			sc->sc_status.button = 0;
+			sc->sc_status.dx = 0;
+			sc->sc_status.dy = 0;
+			sc->sc_status.dz = 0;
+
+			if (status->dx || status->dy || status->dz)
+				status->flags |= MOUSE_POSCHANGED;
+			if (status->button != status->obutton)
+				status->flags |= MOUSE_BUTTONSCHANGED;
+			break;
+		}
+	default:
+		error = ENOTTY;
+	}
+
+done:
+	mtx_unlock(&sc->sc_mutex);
+	return (error);
+}
+
+static device_method_t wsp_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, wsp_probe),
+	DEVMETHOD(device_attach, wsp_attach),
+	DEVMETHOD(device_detach, wsp_detach),
+	DEVMETHOD_END
+};
+
+static driver_t wsp_driver = {
+	.name = WSP_DRIVER_NAME,
+	.methods = wsp_methods,
+	.size = sizeof(struct wsp_softc)
+};
+
+static devclass_t wsp_devclass;
+
+DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0);
+MODULE_DEPEND(wsp, usb, 1, 1, 1);
+MODULE_VERSION(wsp, 1);


Property changes on: stable/0.8/sys/dev/usb/input/wsp.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/misc/udbp.c
===================================================================
--- stable/0.8/sys/dev/usb/misc/udbp.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/udbp.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/misc/udbp.c 263166 2014-03-14 10:18:53Z hselasky $");
 
 /* Driver for arbitrary double bulk pipe devices.
  * The driver assumes that there will be the same driver on the other side.
@@ -290,6 +290,7 @@
 
 static const STRUCT_USB_HOST_ID udbp_devs[] = {
 	{USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_TURBOCONNECT, 0)},
+	{USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_GADGETZERO, 0)},
 	{USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301, 0)},
 	{USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302, 0)},
 	{USB_VPI(USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZLINK, 0)},

Modified: stable/0.8/sys/dev/usb/misc/udbp.h
===================================================================
--- stable/0.8/sys/dev/usb/misc/udbp.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/udbp.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
  * This file was derived from src/sys/netgraph/ng_sample.h, revision 1.1
  * written by Julian Elischer, Whistle Communications.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/misc/udbp.h 196219 2009-08-14 20:03:53Z jhb $
  */
 
 #ifndef	_NETGRAPH_UDBP_H_

Modified: stable/0.8/sys/dev/usb/misc/ufm.c
===================================================================
--- stable/0.8/sys/dev/usb/misc/ufm.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/misc/ufm.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/misc/ufm.c 235000 2012-05-04 15:05:30Z hselasky $");
 
 
 #include <sys/stdint.h>

Modified: stable/0.8/sys/dev/usb/net/if_aue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_aue.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_aue.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_aue.c 271356 2014-09-10 06:54:05Z hselasky $");
 
 /*
  * ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver.
@@ -208,9 +208,7 @@
 static uint16_t	aue_csr_read_2(struct aue_softc *, uint16_t);
 static void	aue_csr_write_1(struct aue_softc *, uint16_t, uint8_t);
 static void	aue_csr_write_2(struct aue_softc *, uint16_t, uint16_t);
-static void	aue_eeprom_getword(struct aue_softc *, int, uint16_t *);
-static void	aue_read_eeprom(struct aue_softc *, uint8_t *, uint16_t,
-		    uint16_t);
+static uint16_t	aue_eeprom_getword(struct aue_softc *, int);
 static void	aue_reset(struct aue_softc *);
 static void	aue_reset_pegasus_II(struct aue_softc *);
 
@@ -372,11 +370,10 @@
 /*
  * Read a word of data stored in the EEPROM at address 'addr.'
  */
-static void
-aue_eeprom_getword(struct aue_softc *sc, int addr, uint16_t *dest)
+static uint16_t
+aue_eeprom_getword(struct aue_softc *sc, int addr)
 {
 	int i;
-	uint16_t word = 0;
 
 	aue_csr_write_1(sc, AUE_EE_REG, addr);
 	aue_csr_write_1(sc, AUE_EE_CTL, AUE_EECTL_READ);
@@ -391,22 +388,23 @@
 	if (i == AUE_TIMEOUT)
 		device_printf(sc->sc_ue.ue_dev, "EEPROM read timed out\n");
 
-	word = aue_csr_read_2(sc, AUE_EE_DATA);
-	*dest = word;
+	return (aue_csr_read_2(sc, AUE_EE_DATA));
 }
 
 /*
- * Read a sequence of words from the EEPROM.
+ * Read station address(offset 0) from the EEPROM.
  */
 static void
-aue_read_eeprom(struct aue_softc *sc, uint8_t *dest,
-    uint16_t off, uint16_t len)
+aue_read_mac(struct aue_softc *sc, uint8_t *eaddr)
 {
-	uint16_t *ptr = (uint16_t *)dest;
-	int i;
+	int i, offset;
+	uint16_t word;
 
-	for (i = 0; i != len; i++, ptr++)
-		aue_eeprom_getword(sc, off + i, ptr);
+	for (i = 0, offset = 0; i < ETHER_ADDR_LEN / 2; i++) {
+		word = aue_eeprom_getword(sc, offset + i);
+		eaddr[i * 2] = (uint8_t)word;
+		eaddr[i * 2 + 1] = (uint8_t)(word >> 8);
+	}
 }
 
 static int
@@ -632,7 +630,7 @@
 	aue_reset(sc);
 
 	/* get station address from the EEPROM */
-	aue_read_eeprom(sc, ue->ue_eaddr, 0, 3);
+	aue_read_mac(sc, ue->ue_eaddr);
 }
 
 /*
@@ -747,7 +745,7 @@
 
 			if (pkt.aue_txstat0)
 				ifp->if_oerrors++;
-			if (pkt.aue_txstat0 & (AUE_TXSTAT0_LATECOLL &
+			if (pkt.aue_txstat0 & (AUE_TXSTAT0_LATECOLL |
 			    AUE_TXSTAT0_EXCESSCOLL))
 				ifp->if_collisions++;
 		}

Modified: stable/0.8/sys/dev/usb/net/if_auereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_auereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_auereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_auereg.h 196219 2009-08-14 20:03:53Z jhb $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/net/if_axe.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axe.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_axe.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_axe.c 263166 2014-03-14 10:18:53Z hselasky $");
 
 /*
  * ASIX Electronics AX88172/AX88178/AX88778 USB 2.0 ethernet driver.
@@ -159,6 +159,7 @@
 	AXE_DEV(COREGA, FETHER_USB2_TX, 0),
 	AXE_DEV(DLINK, DUBE100, 0),
 	AXE_DEV(DLINK, DUBE100B1, AXE_FLAG_772),
+	AXE_DEV(DLINK, DUBE100C1, AXE_FLAG_772B),
 	AXE_DEV(GOODWAY, GWUSB2E, 0),
 	AXE_DEV(IODATA, ETGUS2, AXE_FLAG_178),
 	AXE_DEV(JVC, MP_PRX1, 0),

Modified: stable/0.8/sys/dev/usb/net/if_axereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_axereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_axereg.h 229106 2011-12-31 14:47:35Z hselasky $
  */
 
 /*

Added: stable/0.8/sys/dev/usb/net/if_axge.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axge.c	                        (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_axge.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1038 @@
+/*-
+ * Copyright (c) 2013-2014 Kevin Lo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_axge.c 268736 2014-07-16 06:18:02Z hselasky $");
+
+/*
+ * ASIX Electronics AX88178A/AX88179 USB 2.0/3.0 gigabit ethernet driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define	USB_DEBUG_VAR 	axge_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/net/usb_ethernet.h>
+#include <dev/usb/net/if_axgereg.h>
+
+/*
+ * Various supported device vendors/products.
+ */
+
+static const STRUCT_USB_HOST_ID axge_devs[] = {
+#define	AXGE_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+	AXGE_DEV(ASIX, AX88178A),
+	AXGE_DEV(ASIX, AX88179),
+	AXGE_DEV(DLINK, DUB1312),
+	AXGE_DEV(SITECOMEU, LN032),
+#undef AXGE_DEV
+};
+
+static const struct {
+	uint8_t	ctrl;
+	uint8_t timer_l;
+	uint8_t	timer_h;
+	uint8_t	size;
+	uint8_t	ifg;
+} __packed axge_bulk_size[] = {
+	{ 7, 0x4f, 0x00, 0x12, 0xff },
+	{ 7, 0x20, 0x03, 0x16, 0xff },
+	{ 7, 0xae, 0x07, 0x18, 0xff },
+	{ 7, 0xcc, 0x4c, 0x18, 0x08 }
+};
+
+/* prototypes */
+
+static device_probe_t axge_probe;
+static device_attach_t axge_attach;
+static device_detach_t axge_detach;
+
+static usb_callback_t axge_bulk_read_callback;
+static usb_callback_t axge_bulk_write_callback;
+
+static miibus_readreg_t axge_miibus_readreg;
+static miibus_writereg_t axge_miibus_writereg;
+static miibus_statchg_t axge_miibus_statchg;
+
+static uether_fn_t axge_attach_post;
+static uether_fn_t axge_init;
+static uether_fn_t axge_stop;
+static uether_fn_t axge_start;
+static uether_fn_t axge_tick;
+static uether_fn_t axge_setmulti;
+static uether_fn_t axge_setpromisc;
+
+static int	axge_read_mem(struct axge_softc *, uint8_t, uint16_t,
+		    uint16_t, void *, int);
+static void	axge_write_mem(struct axge_softc *, uint8_t, uint16_t,
+		    uint16_t, void *, int);
+static uint8_t	axge_read_cmd_1(struct axge_softc *, uint8_t, uint16_t);
+static uint16_t	axge_read_cmd_2(struct axge_softc *, uint8_t, uint16_t,
+		    uint16_t);
+static void	axge_write_cmd_1(struct axge_softc *, uint8_t, uint16_t,
+		    uint8_t);
+static void	axge_write_cmd_2(struct axge_softc *, uint8_t, uint16_t,
+		    uint16_t, uint16_t);
+static void	axge_chip_init(struct axge_softc *);
+static void	axge_reset(struct axge_softc *);
+
+static int	axge_attach_post_sub(struct usb_ether *);
+static int	axge_ifmedia_upd(struct ifnet *);
+static void	axge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int	axge_ioctl(struct ifnet *, u_long, caddr_t);
+static void	axge_rx_frame(struct usb_ether *, struct usb_page_cache *, int);
+static void	axge_rxeof(struct usb_ether *, struct usb_page_cache *,
+		    unsigned int, unsigned int, uint32_t);
+static void	axge_csum_cfg(struct usb_ether *);
+
+#define	AXGE_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
+
+#ifdef USB_DEBUG
+static int axge_debug = 0;
+
+static SYSCTL_NODE(_hw_usb, OID_AUTO, axge, CTLFLAG_RW, 0, "USB axge");
+SYSCTL_INT(_hw_usb_axge, OID_AUTO, debug, CTLFLAG_RW, &axge_debug, 0,
+    "Debug level");
+#endif
+
+static const struct usb_config axge_config[AXGE_N_TRANSFER] = {
+	[AXGE_BULK_DT_WR] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_OUT,
+		.frames = 16,
+		.bufsize = 16 * MCLBYTES,
+		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+		.callback = axge_bulk_write_callback,
+		.timeout = 10000,	/* 10 seconds */
+	},
+	[AXGE_BULK_DT_RD] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_IN,
+		.bufsize = 65536,
+		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+		.callback = axge_bulk_read_callback,
+		.timeout = 0,		/* no timeout */
+	},
+};
+
+static device_method_t axge_methods[] = {
+	/* Device interface. */
+	DEVMETHOD(device_probe,		axge_probe),
+	DEVMETHOD(device_attach,	axge_attach),
+	DEVMETHOD(device_detach,	axge_detach),
+
+	/* MII interface. */
+	DEVMETHOD(miibus_readreg,	axge_miibus_readreg),
+	DEVMETHOD(miibus_writereg,	axge_miibus_writereg),
+	DEVMETHOD(miibus_statchg,	axge_miibus_statchg),
+
+	DEVMETHOD_END
+};
+
+static driver_t axge_driver = {
+	.name = "axge",
+	.methods = axge_methods,
+	.size = sizeof(struct axge_softc),
+};
+
+static devclass_t axge_devclass;
+
+DRIVER_MODULE(axge, uhub, axge_driver, axge_devclass, NULL, NULL);
+DRIVER_MODULE(miibus, axge, miibus_driver, miibus_devclass, NULL, NULL);
+MODULE_DEPEND(axge, uether, 1, 1, 1);
+MODULE_DEPEND(axge, usb, 1, 1, 1);
+MODULE_DEPEND(axge, ether, 1, 1, 1);
+MODULE_DEPEND(axge, miibus, 1, 1, 1);
+MODULE_VERSION(axge, 1);
+
+static const struct usb_ether_methods axge_ue_methods = {
+	.ue_attach_post = axge_attach_post,
+	.ue_attach_post_sub = axge_attach_post_sub,
+	.ue_start = axge_start,
+	.ue_init = axge_init,
+	.ue_stop = axge_stop,
+	.ue_tick = axge_tick,
+	.ue_setmulti = axge_setmulti,
+	.ue_setpromisc = axge_setpromisc,
+	.ue_mii_upd = axge_ifmedia_upd,
+	.ue_mii_sts = axge_ifmedia_sts,
+};
+
+static int
+axge_read_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+    uint16_t val, void *buf, int len)
+{
+	struct usb_device_request req;
+
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	req.bmRequestType = UT_READ_VENDOR_DEVICE;
+	req.bRequest = cmd;
+	USETW(req.wValue, val);
+	USETW(req.wIndex, index);
+	USETW(req.wLength, len);
+
+	return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
+}
+
+static void
+axge_write_mem(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+    uint16_t val, void *buf, int len)
+{
+	struct usb_device_request req;
+
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = cmd;
+	USETW(req.wValue, val);
+	USETW(req.wIndex, index);
+	USETW(req.wLength, len);
+
+	if (uether_do_request(&sc->sc_ue, &req, buf, 1000)) {
+		/* Error ignored. */
+	}
+}
+
+static uint8_t
+axge_read_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg)
+{
+	uint8_t val;
+
+	axge_read_mem(sc, cmd, 1, reg, &val, 1);
+	return (val);
+}
+
+static uint16_t
+axge_read_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+    uint16_t reg)
+{
+	uint8_t val[2];
+
+	axge_read_mem(sc, cmd, index, reg, &val, 2);
+	return (UGETW(val));
+}
+
+static void
+axge_write_cmd_1(struct axge_softc *sc, uint8_t cmd, uint16_t reg, uint8_t val)
+{
+	axge_write_mem(sc, cmd, 1, reg, &val, 1);
+}
+
+static void
+axge_write_cmd_2(struct axge_softc *sc, uint8_t cmd, uint16_t index,
+    uint16_t reg, uint16_t val)
+{
+	uint8_t temp[2];
+
+	USETW(temp, val);
+	axge_write_mem(sc, cmd, index, reg, &temp, 2);
+}
+
+static int
+axge_miibus_readreg(device_t dev, int phy, int reg)
+{
+	struct axge_softc *sc;
+	uint16_t val;
+	int locked;
+
+	sc = device_get_softc(dev);
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		AXGE_LOCK(sc);
+
+	val = axge_read_cmd_2(sc, AXGE_ACCESS_PHY, reg, phy);
+
+	if (!locked)
+		AXGE_UNLOCK(sc);
+
+	return (val);
+}
+
+static int
+axge_miibus_writereg(device_t dev, int phy, int reg, int val)
+{
+	struct axge_softc *sc;
+	int locked;
+
+	sc = device_get_softc(dev);
+	if (sc->sc_phyno != phy)
+		return (0);
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		AXGE_LOCK(sc);
+
+	axge_write_cmd_2(sc, AXGE_ACCESS_PHY, reg, phy, val);
+
+	if (!locked)
+		AXGE_UNLOCK(sc);
+
+	return (0);
+}
+
+static void
+axge_miibus_statchg(device_t dev)
+{
+	struct axge_softc *sc;
+	struct mii_data *mii;
+	struct ifnet *ifp;
+	uint8_t link_status, tmp[5];
+	uint16_t val;
+	int locked;
+
+	sc = device_get_softc(dev);
+	mii = GET_MII(sc);
+	locked = mtx_owned(&sc->sc_mtx);
+	if (!locked)
+		AXGE_LOCK(sc);
+
+	ifp = uether_getifp(&sc->sc_ue);
+	if (mii == NULL || ifp == NULL ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		goto done;
+
+	sc->sc_flags &= ~AXGE_FLAG_LINK;
+	if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+	    (IFM_ACTIVE | IFM_AVALID)) {
+		switch (IFM_SUBTYPE(mii->mii_media_active)) {
+		case IFM_10_T:
+		case IFM_100_TX:
+		case IFM_1000_T:
+			sc->sc_flags |= AXGE_FLAG_LINK;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Lost link, do nothing. */
+	if ((sc->sc_flags & AXGE_FLAG_LINK) == 0)
+		goto done;
+
+	link_status = axge_read_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PLSR);
+
+	val = 0;
+	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+		val |= MSR_FD;
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+			val |= MSR_TFC;
+		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+			val |= MSR_RFC;
+	}
+	val |=  MSR_RE;
+	switch (IFM_SUBTYPE(mii->mii_media_active)) {
+	case IFM_1000_T:
+		val |= MSR_GM | MSR_EN_125MHZ;
+		if (link_status & PLSR_USB_SS)
+			memcpy(tmp, &axge_bulk_size[0], 5);
+		else if (link_status & PLSR_USB_HS)
+			memcpy(tmp, &axge_bulk_size[1], 5);
+		else
+			memcpy(tmp, &axge_bulk_size[3], 5);
+		break;
+	case IFM_100_TX:
+		val |= MSR_PS;
+		if (link_status & (PLSR_USB_SS | PLSR_USB_HS))
+			memcpy(tmp, &axge_bulk_size[2], 5);
+		else
+			memcpy(tmp, &axge_bulk_size[3], 5);
+		break;
+	case IFM_10_T:
+		memcpy(tmp, &axge_bulk_size[3], 5);
+		break;
+	}
+	/* Rx bulk configuration. */
+	axge_write_mem(sc, AXGE_ACCESS_MAC, 5, AXGE_RX_BULKIN_QCTRL, tmp, 5);
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_MSR, val);
+done:
+	if (!locked)
+		AXGE_UNLOCK(sc);
+}
+
+static void
+axge_chip_init(struct axge_softc *sc)
+{
+	/* Power up ethernet PHY. */
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, 0);
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_EPPRCR, EPPRCR_IPRL);
+	uether_pause(&sc->sc_ue, hz / 4);
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CLK_SELECT,
+	    AXGE_CLK_SELECT_ACS | AXGE_CLK_SELECT_BCS);
+	uether_pause(&sc->sc_ue, hz / 10);
+}
+
+static void
+axge_reset(struct axge_softc *sc)
+{
+	struct usb_config_descriptor *cd;
+	usb_error_t err;
+
+	cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev);
+
+	err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx,
+	    cd->bConfigurationValue);
+	if (err)
+		DPRINTF("reset failed (ignored)\n");
+
+	/* Wait a little while for the chip to get its brains in order. */
+	uether_pause(&sc->sc_ue, hz / 100);
+
+	/* Reinitialize controller to achieve full reset. */
+	axge_chip_init(sc);
+}
+
+static void
+axge_attach_post(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+
+	sc = uether_getsc(ue);
+	sc->sc_phyno = 3;
+
+	/* Initialize controller and get station address. */
+	axge_chip_init(sc);
+	axge_read_mem(sc, AXGE_ACCESS_MAC, ETHER_ADDR_LEN, AXGE_NIDR,
+	    ue->ue_eaddr, ETHER_ADDR_LEN);
+}
+
+static int
+axge_attach_post_sub(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	int error;
+
+	sc = uether_getsc(ue);
+	ifp = ue->ue_ifp;
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_start = uether_start;
+	ifp->if_ioctl = axge_ioctl;
+	ifp->if_init = uether_init;
+	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+	IFQ_SET_READY(&ifp->if_snd);
+
+	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_TXCSUM | IFCAP_RXCSUM;
+	ifp->if_hwassist = AXGE_CSUM_FEATURES;
+	ifp->if_capenable = ifp->if_capabilities;
+
+	mtx_lock(&Giant);
+	error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
+	    uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
+	    BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, MIIF_DOPAUSE);
+	mtx_unlock(&Giant);
+
+	return (error);
+}
+
+/*
+ * Set media options.
+ */
+static int
+axge_ifmedia_upd(struct ifnet *ifp)
+{
+	struct axge_softc *sc;
+	struct mii_data *mii;
+	struct mii_softc *miisc;
+	int error;
+
+	sc = ifp->if_softc;
+	mii = GET_MII(sc);
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+	    PHY_RESET(miisc);
+	error = mii_mediachg(mii);
+
+	return (error);
+}
+
+/*
+ * Report current media status.
+ */
+static void
+axge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct axge_softc *sc;
+	struct mii_data *mii;
+
+	sc = ifp->if_softc;
+	mii = GET_MII(sc);
+	AXGE_LOCK(sc);
+	mii_pollstat(mii);
+	ifmr->ifm_active = mii->mii_media_active;
+	ifmr->ifm_status = mii->mii_media_status;
+	AXGE_UNLOCK(sc);
+}
+
+/*
+ * Probe for a AX88179 chip.
+ */
+static int
+axge_probe(device_t dev)
+{
+	struct usb_attach_arg *uaa;
+
+	uaa = device_get_ivars(dev);
+	if (uaa->usb_mode != USB_MODE_HOST)
+		return (ENXIO);
+	if (uaa->info.bConfigIndex != AXGE_CONFIG_IDX)
+		return (ENXIO);
+	if (uaa->info.bIfaceIndex != AXGE_IFACE_IDX)
+		return (ENXIO);
+
+	return (usbd_lookup_id_by_uaa(axge_devs, sizeof(axge_devs), uaa));
+}
+
+/*
+ * Attach the interface. Allocate softc structures, do ifmedia
+ * setup and ethernet/BPF attach.
+ */
+static int
+axge_attach(device_t dev)
+{
+	struct usb_attach_arg *uaa;
+	struct axge_softc *sc;
+	struct usb_ether *ue;
+	uint8_t iface_index;
+	int error;
+
+	uaa = device_get_ivars(dev);
+	sc = device_get_softc(dev);
+	ue = &sc->sc_ue;
+
+	device_set_usb_desc(dev);
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+	iface_index = AXGE_IFACE_IDX;
+	error = usbd_transfer_setup(uaa->device, &iface_index,
+	    sc->sc_xfer, axge_config, AXGE_N_TRANSFER, sc, &sc->sc_mtx);
+	if (error) {
+		device_printf(dev, "allocating USB transfers failed\n");
+		goto detach;
+	}
+
+	ue->ue_sc = sc;
+	ue->ue_dev = dev;
+	ue->ue_udev = uaa->device;
+	ue->ue_mtx = &sc->sc_mtx;
+	ue->ue_methods = &axge_ue_methods;
+
+	error = uether_ifattach(ue);
+	if (error) {
+		device_printf(dev, "could not attach interface\n");
+		goto detach;
+	}
+	return (0);			/* success */
+
+detach:
+	axge_detach(dev);
+	return (ENXIO);			/* failure */
+}
+
+static int
+axge_detach(device_t dev)
+{
+	struct axge_softc *sc;
+	struct usb_ether *ue;
+
+	sc = device_get_softc(dev);
+	ue = &sc->sc_ue;
+	usbd_transfer_unsetup(sc->sc_xfer, AXGE_N_TRANSFER);
+	uether_ifdetach(ue);
+	mtx_destroy(&sc->sc_mtx);
+
+	return (0);
+}
+
+static void
+axge_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct axge_softc *sc;
+	struct usb_ether *ue;
+	struct usb_page_cache *pc;
+	int actlen;
+
+	sc = usbd_xfer_softc(xfer);
+	ue = &sc->sc_ue;
+	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		pc = usbd_xfer_get_frame(xfer, 0);
+		axge_rx_frame(ue, pc, actlen);
+
+		/* FALLTHROUGH */
+	case USB_ST_SETUP:
+tr_setup:
+		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+		usbd_transfer_submit(xfer);
+		uether_rxflush(ue);
+		break;
+
+	default:
+		if (error != USB_ERR_CANCELLED) {
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		break;
+	}
+}
+
+static void
+axge_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	struct usb_page_cache *pc;
+	struct mbuf *m;
+	uint32_t txhdr;
+	int nframes, pos;
+
+	sc = usbd_xfer_softc(xfer);
+	ifp = uether_getifp(&sc->sc_ue);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+		/* FALLTHROUGH */
+	case USB_ST_SETUP:
+tr_setup:
+		if ((sc->sc_flags & AXGE_FLAG_LINK) == 0 ||
+		    (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
+			/*
+			 * Don't send anything if there is no link or
+			 * controller is busy.
+			 */
+			return;
+		}
+
+		for (nframes = 0; nframes < 16 &&
+		    !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
+			IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+			if (m == NULL)
+				break;
+			usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
+				nframes);
+			pos = 0;
+			pc = usbd_xfer_get_frame(xfer, nframes);
+			txhdr = htole32(m->m_pkthdr.len);
+			usbd_copy_in(pc, 0, &txhdr, sizeof(txhdr));
+			txhdr = 0;
+			txhdr = htole32(txhdr);
+			usbd_copy_in(pc, 4, &txhdr, sizeof(txhdr));
+			pos += 8;
+			usbd_m_copy_in(pc, pos, m, 0, m->m_pkthdr.len);
+			pos += m->m_pkthdr.len;
+			if ((pos % usbd_xfer_max_framelen(xfer)) == 0)
+				txhdr |= 0x80008000;
+
+			/*
+			 * XXX
+			 * Update TX packet counter here. This is not
+			 * correct way but it seems that there is no way
+			 * to know how many packets are sent at the end
+			 * of transfer because controller combines
+			 * multiple writes into single one if there is
+			 * room in TX buffer of controller.
+			 */
+			ifp->if_opackets++;
+
+			/*
+			 * if there's a BPF listener, bounce a copy
+			 * of this frame to him:
+			 */
+			BPF_MTAP(ifp, m);
+
+			m_freem(m);
+
+			/* Set frame length. */
+			usbd_xfer_set_frame_len(xfer, nframes, pos);
+		}
+		if (nframes != 0) {
+			usbd_xfer_set_frames(xfer, nframes);
+			usbd_transfer_submit(xfer);
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+		}
+		return;
+		/* NOTREACHED */
+	default:
+		ifp->if_oerrors++;
+		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+		if (error != USB_ERR_CANCELLED) {
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		return;
+
+	}
+}
+
+static void
+axge_tick(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct mii_data *mii;
+
+	sc = uether_getsc(ue);
+	mii = GET_MII(sc);
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	mii_tick(mii);
+	if ((sc->sc_flags & AXGE_FLAG_LINK) == 0) {
+		axge_miibus_statchg(ue->ue_dev);
+		if ((sc->sc_flags & AXGE_FLAG_LINK) != 0)
+			axge_start(ue);
+	}
+}
+
+static void
+axge_setmulti(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	struct ifmultiaddr *ifma;
+	uint32_t h;
+	uint16_t rxmode;
+	uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+	sc = uether_getsc(ue);
+	ifp = uether_getifp(ue);
+	h = 0;
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR);
+	if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+		rxmode |= RCR_AMALL;
+		axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+		return;
+	}
+	rxmode &= ~RCR_AMALL;
+
+	if_maddr_rlock(ifp);
+	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+		if (ifma->ifma_addr->sa_family != AF_LINK)
+			continue;
+		h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
+		    ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
+		hashtbl[h / 8] |= 1 << (h % 8);
+	}
+	if_maddr_runlock(ifp);
+
+	axge_write_mem(sc, AXGE_ACCESS_MAC, 8, AXGE_MFA, (void *)&hashtbl, 8);
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+}
+
+static void
+axge_setpromisc(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	uint16_t rxmode;
+
+	sc = uether_getsc(ue);
+	ifp = uether_getifp(ue);
+	rxmode = axge_read_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR);
+
+	if (ifp->if_flags & IFF_PROMISC)
+		rxmode |= RCR_PRO;
+	else
+		rxmode &= ~RCR_PRO;
+
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+	axge_setmulti(ue);
+}
+
+static void
+axge_start(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+
+	sc = uether_getsc(ue);
+	/*
+	 * Start the USB transfers, if not already started.
+	 */
+	usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_RD]);
+	usbd_transfer_start(sc->sc_xfer[AXGE_BULK_DT_WR]);
+}
+
+static void
+axge_init(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	uint16_t rxmode;
+
+	sc = uether_getsc(ue);
+	ifp = uether_getifp(ue);
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+		return;
+
+	/*
+	 * Cancel pending I/O and free all RX/TX buffers.
+	 */
+	axge_stop(ue);
+
+	axge_reset(sc);
+
+	/* Set MAC address. */
+	axge_write_mem(sc, AXGE_ACCESS_MAC, ETHER_ADDR_LEN, AXGE_NIDR,
+	    IF_LLADDR(ifp), ETHER_ADDR_LEN);
+
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLLR, 0x34);
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_PWLHR, 0x52);
+
+	/* Configure TX/RX checksum offloading. */
+	axge_csum_cfg(ue);
+
+	/* Configure RX settings. */
+	rxmode = (RCR_AM | RCR_SO | RCR_DROP_CRCE);
+	if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
+		rxmode |= RCR_IPE;
+
+	/* If we want promiscuous mode, set the allframes bit. */
+	if (ifp->if_flags & IFF_PROMISC)
+		rxmode |= RCR_PRO;
+
+	if (ifp->if_flags & IFF_BROADCAST)
+		rxmode |= RCR_AB;
+
+	axge_write_cmd_2(sc, AXGE_ACCESS_MAC, 2, AXGE_RCR, rxmode);
+
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_MMSR, 
+	    MMSR_PME_TYPE | MMSR_PME_POL | MMSR_RWMP);
+
+	/* Load the multicast filter. */
+	axge_setmulti(ue);
+
+	usbd_xfer_set_stall(sc->sc_xfer[AXGE_BULK_DT_WR]);
+
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	/* Switch to selected media. */
+	axge_ifmedia_upd(ifp);
+}
+
+static void
+axge_stop(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+
+	sc = uether_getsc(ue);
+	ifp = uether_getifp(ue);
+
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+
+	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+	sc->sc_flags &= ~AXGE_FLAG_LINK;
+
+	/*
+	 * Stop all the transfers, if not already stopped:
+	 */
+	usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_WR]);
+	usbd_transfer_stop(sc->sc_xfer[AXGE_BULK_DT_RD]);
+}
+
+static int
+axge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+	struct usb_ether *ue;
+	struct axge_softc *sc;
+	struct ifreq *ifr;
+	int error, mask, reinit;
+
+	ue = ifp->if_softc;
+	sc = uether_getsc(ue);
+	ifr = (struct ifreq *)data;
+	error = 0;
+	reinit = 0;
+	if (cmd == SIOCSIFCAP) {
+		AXGE_LOCK(sc);
+		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+		if ((mask & IFCAP_TXCSUM) != 0 &&
+		    (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
+			ifp->if_capenable ^= IFCAP_TXCSUM;
+			if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+				ifp->if_hwassist |= AXGE_CSUM_FEATURES;
+			else
+				ifp->if_hwassist &= ~AXGE_CSUM_FEATURES;
+			reinit++;
+		}
+		if ((mask & IFCAP_RXCSUM) != 0 &&
+		    (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
+			ifp->if_capenable ^= IFCAP_RXCSUM;
+			reinit++;
+		}
+		if (reinit > 0 && ifp->if_drv_flags & IFF_DRV_RUNNING)
+			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+		else
+			reinit = 0;
+		AXGE_UNLOCK(sc);
+		if (reinit > 0)
+			uether_init(ue);
+	} else
+		error = uether_ioctl(ifp, cmd, data);
+
+	return (error);
+}
+
+static void
+axge_rx_frame(struct usb_ether *ue, struct usb_page_cache *pc, int actlen)
+{
+	uint32_t pos;
+	uint32_t pkt_cnt;
+	uint32_t rxhdr;
+	uint32_t pkt_hdr;
+	uint32_t hdr_off;
+	uint32_t pktlen; 
+
+	/* verify we have enough data */
+	if (actlen < (int)sizeof(rxhdr))
+		return;
+
+	pos = 0;
+
+	usbd_copy_out(pc, actlen - sizeof(rxhdr), &rxhdr, sizeof(rxhdr));
+	rxhdr = le32toh(rxhdr);
+
+	pkt_cnt = (uint16_t)rxhdr;
+	hdr_off = (uint16_t)(rxhdr >> 16);
+
+	while (pkt_cnt--) {
+		/* verify the header offset */
+		if ((int)(hdr_off + sizeof(pkt_hdr)) > actlen) {
+			DPRINTF("End of packet headers\n");
+			break;
+		}
+		if ((int)pos >= actlen) {
+			DPRINTF("Data position reached end\n");
+			break;
+		}
+		usbd_copy_out(pc, hdr_off, &pkt_hdr, sizeof(pkt_hdr));
+
+		pkt_hdr = le32toh(pkt_hdr);
+		pktlen = (pkt_hdr >> 16) & 0x1fff;
+		if (pkt_hdr & (AXGE_RXHDR_CRC_ERR | AXGE_RXHDR_DROP_ERR)) {
+			DPRINTF("Dropped a packet\n");
+			ue->ue_ifp->if_ierrors++;
+		}
+		if (pktlen >= 6 && (int)(pos + pktlen) <= actlen) {
+			axge_rxeof(ue, pc, pos + 2, pktlen - 6, pkt_hdr);
+		} else {
+			DPRINTF("Invalid packet pos=%d len=%d\n",
+			    (int)pos, (int)pktlen);
+		}
+		pos += (pktlen + 7) & ~7;
+		hdr_off += sizeof(pkt_hdr);
+	}
+}
+
+static void
+axge_rxeof(struct usb_ether *ue, struct usb_page_cache *pc,
+    unsigned int offset, unsigned int len, uint32_t pkt_hdr)
+{
+	struct ifnet *ifp;
+	struct mbuf *m;
+
+	ifp = ue->ue_ifp;
+	if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN) {
+		ifp->if_ierrors++;
+		return;
+	}
+
+	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+	if (m == NULL) {
+		ifp->if_iqdrops++;
+		return;
+	}
+	m->m_pkthdr.rcvif = ifp;
+	m->m_len = m->m_pkthdr.len = len + ETHER_ALIGN;
+	m_adj(m, ETHER_ALIGN);
+
+	usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);
+
+	ifp->if_ipackets++;
+
+	if ((pkt_hdr & (AXGE_RXHDR_L4CSUM_ERR | AXGE_RXHDR_L3CSUM_ERR)) == 0) {
+		if ((pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
+		    AXGE_RXHDR_L4_TYPE_TCP ||
+		    (pkt_hdr & AXGE_RXHDR_L4_TYPE_MASK) ==
+		    AXGE_RXHDR_L4_TYPE_UDP) {
+			m->m_pkthdr.csum_flags |= CSUM_DATA_VALID |
+			    CSUM_PSEUDO_HDR | CSUM_IP_CHECKED | CSUM_IP_VALID;
+			m->m_pkthdr.csum_data = 0xffff;
+		}
+	}
+
+	_IF_ENQUEUE(&ue->ue_rxq, m);
+}
+
+static void
+axge_csum_cfg(struct usb_ether *ue)
+{
+	struct axge_softc *sc;
+	struct ifnet *ifp;
+	uint8_t csum;
+
+	sc = uether_getsc(ue);
+	AXGE_LOCK_ASSERT(sc, MA_OWNED);
+	ifp = uether_getifp(ue);
+
+	csum = 0;
+	if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+		csum |= CTCR_IP | CTCR_TCP | CTCR_UDP;
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CTCR, csum);
+
+	csum = 0;
+	if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
+		csum |= CRCR_IP | CRCR_TCP | CRCR_UDP;
+	axge_write_cmd_1(sc, AXGE_ACCESS_MAC, AXGE_CRCR, csum);
+}


Property changes on: stable/0.8/sys/dev/usb/net/if_axge.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: stable/0.8/sys/dev/usb/net/if_axgereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_axgereg.h	                        (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_axgereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2013-2014 Kevin Lo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_axgereg.h 268222 2014-07-03 16:34:01Z hselasky $
+ */
+
+#define	AXGE_ACCESS_MAC			0x01
+#define	AXGE_ACCESS_PHY			0x02
+#define	AXGE_ACCESS_WAKEUP		0x03
+#define	AXGE_ACCESS_EEPROM		0x04
+#define	AXGE_ACCESS_EFUSE		0x05
+#define	AXGE_RELOAD_EEPROM_EFUSE	0x06
+#define	AXGE_WRITE_EFUSE_EN		0x09
+#define	AXGE_WRITE_EFUSE_DIS		0x0A
+#define	AXGE_ACCESS_MFAB		0x10
+
+/* Physical link status register */
+#define	AXGE_PLSR			0x02
+#define	PLSR_USB_FS			0x01
+#define	PLSR_USB_HS			0x02
+#define	PLSR_USB_SS			0x04
+
+/* EEPROM address register */
+#define	AXGE_EAR			0x07
+
+/* EEPROM data low register */
+#define	AXGE_EDLR			0x08
+
+/* EEPROM data high register */
+#define	AXGE_EDHR			0x09
+
+/* EEPROM command register */
+#define	AXGE_ECR			0x0a
+
+/* Rx control register */
+#define	AXGE_RCR			0x0b
+#define	RCR_STOP			0x0000
+#define	RCR_PRO				0x0001
+#define	RCR_AMALL			0x0002
+#define	RCR_AB				0x0008
+#define	RCR_AM				0x0010
+#define	RCR_AP				0x0020
+#define	RCR_SO				0x0080
+#define	RCR_DROP_CRCE			0x0100
+#define	RCR_IPE				0x0200
+#define	RCR_TX_CRC_PAD			0x0400
+
+/* Node id register */
+#define	AXGE_NIDR			0x10
+
+/* Multicast filter array */
+#define	AXGE_MFA			0x16
+
+/* Medium status register */
+#define	AXGE_MSR			0x22
+#define	MSR_GM				0x0001
+#define	MSR_FD				0x0002
+#define	MSR_EN_125MHZ			0x0008
+#define	MSR_RFC				0x0010
+#define	MSR_TFC				0x0020
+#define	MSR_RE				0x0100
+#define	MSR_PS				0x0200
+
+/* Monitor mode status register */
+#define	AXGE_MMSR			0x24
+#define	MMSR_RWLC			0x02
+#define	MMSR_RWMP			0x04
+#define	MMSR_RWWF			0x08
+#define	MMSR_RW_FLAG			0x10
+#define	MMSR_PME_POL			0x20
+#define	MMSR_PME_TYPE			0x40
+#define	MMSR_PME_IND			0x80
+
+/* GPIO control/status register */
+#define	AXGE_GPIOCR			0x25
+
+/* Ethernet PHY power & reset control register */
+#define	AXGE_EPPRCR			0x26
+#define	EPPRCR_BZ			0x0010
+#define	EPPRCR_IPRL			0x0020
+#define	EPPRCR_AUTODETACH		0x1000
+
+#define	AXGE_RX_BULKIN_QCTRL		0x2e
+
+#define	AXGE_CLK_SELECT			0x33
+#define	AXGE_CLK_SELECT_BCS		0x01
+#define	AXGE_CLK_SELECT_ACS		0x02
+#define	AXGE_CLK_SELECT_ACSREQ		0x10
+#define	AXGE_CLK_SELECT_ULR		0x08
+
+/* COE Rx control register */
+#define	AXGE_CRCR			0x34
+#define	CRCR_IP				0x01
+#define	CRCR_TCP			0x02
+#define	CRCR_UDP			0x04
+#define	CRCR_ICMP			0x08
+#define	CRCR_IGMP			0x10
+#define	CRCR_TCPV6			0x20
+#define	CRCR_UDPV6			0x40
+#define	CRCR_ICMPV6			0x80
+
+/* COE Tx control register */
+#define	AXGE_CTCR			0x35
+#define	CTCR_IP				0x01
+#define	CTCR_TCP			0x02
+#define	CTCR_UDP			0x04
+#define	CTCR_ICMP			0x08
+#define	CTCR_IGMP			0x10
+#define	CTCR_TCPV6			0x20
+#define	CTCR_UDPV6			0x40
+#define	CTCR_ICMPV6			0x80
+
+/* Pause water level high register */
+#define	AXGE_PWLHR			0x54
+
+/* Pause water level low register */
+#define	AXGE_PWLLR			0x55
+
+#define	AXGE_CONFIG_IDX			0	/* config number 1 */
+#define	AXGE_IFACE_IDX			0
+
+#define	AXGE_RXHDR_L4_TYPE_MASK		0x1c
+#define	AXGE_RXHDR_L4CSUM_ERR		1
+#define	AXGE_RXHDR_L3CSUM_ERR		2
+#define	AXGE_RXHDR_L4_TYPE_UDP		4
+#define	AXGE_RXHDR_L4_TYPE_TCP		16
+#define	AXGE_RXHDR_CRC_ERR		0x20000000
+#define	AXGE_RXHDR_DROP_ERR		0x80000000
+
+#define	GET_MII(sc)		uether_getmii(&(sc)->sc_ue)
+
+/* The interrupt endpoint is currently unused by the ASIX part. */
+enum {
+	AXGE_BULK_DT_WR,
+	AXGE_BULK_DT_RD,
+	AXGE_N_TRANSFER,
+};
+
+struct axge_softc {
+	struct usb_ether	sc_ue;
+	struct mtx		sc_mtx;
+	struct usb_xfer		*sc_xfer[AXGE_N_TRANSFER];
+	int			sc_phyno;
+
+	int			sc_flags;
+#define	AXGE_FLAG_LINK		0x0001	/* got a link */
+};
+
+#define	AXGE_LOCK(_sc)			mtx_lock(&(_sc)->sc_mtx)
+#define	AXGE_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
+#define	AXGE_LOCK_ASSERT(_sc, t)	mtx_assert(&(_sc)->sc_mtx, t)


Property changes on: stable/0.8/sys/dev/usb/net/if_axgereg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/net/if_cdce.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cdce.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cdce.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_cdce.c 290608 2015-11-09 11:27:31Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -1381,6 +1381,7 @@
 
 			/* check if we have a buffer */
 			if (m) {
+				m->m_len = m->m_pkthdr.len = temp + ETHER_ALIGN;
 				m_adj(m, ETHER_ALIGN);
 
 				usbd_copy_out(pc, offset, m->m_data, temp);

Modified: stable/0.8/sys/dev/usb/net/if_cdcereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cdcereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cdcereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_cdcereg.h 221077 2011-04-26 19:40:37Z hselasky $
  */
 
 #ifndef _USB_IF_CDCEREG_H_

Modified: stable/0.8/sys/dev/usb/net/if_cue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cue.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cue.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_cue.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*
  * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate

Modified: stable/0.8/sys/dev/usb/net/if_cuereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_cuereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_cuereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_cuereg.h 196219 2009-08-14 20:03:53Z jhb $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/net/if_ipheth.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_ipheth.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_ipheth.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_ipheth.c 251701 2013-06-13 20:40:39Z eadler $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>

Modified: stable/0.8/sys/dev/usb/net/if_iphethvar.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_iphethvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_iphethvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_iphethvar.h 213805 2010-10-13 21:36:42Z hselasky $ */
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 2009 Diego Giagio. All rights reserved.

Modified: stable/0.8/sys/dev/usb/net/if_kue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kue.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kue.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_kue.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*
  * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.

Modified: stable/0.8/sys/dev/usb/net/if_kuefw.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kuefw.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kuefw.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_kuefw.h 196219 2009-08-14 20:03:53Z jhb $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/net/if_kuereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_kuereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_kuereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_kuereg.h 196219 2009-08-14 20:03:53Z jhb $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/net/if_mos.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_mos.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_mos.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_mos.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*
  * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller

Modified: stable/0.8/sys/dev/usb/net/if_mosreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_mosreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_mosreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_mosreg.h 232876 2012-03-12 18:22:04Z hselasky $ */
 /*-
  * Copyright (c) 2010, 2011 Rick van der Zwet <info at rickvanderzwet.nl>
  *

Modified: stable/0.8/sys/dev/usb/net/if_rue.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_rue.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_rue.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_rue.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*
  * RealTek RTL8150 USB to fast ethernet controller driver.

Modified: stable/0.8/sys/dev/usb/net/if_ruereg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_ruereg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_ruereg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/if_ruereg.h 215335 2010-11-15 06:04:25Z kevlo $
  */
 
 #define	RUE_CONFIG_IDX		0	/* config number 1 */

Modified: stable/0.8/sys/dev/usb/net/if_udav.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_udav.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_udav.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
 /*	$NetBSD: if_udav.c,v 1.2 2003/09/04 15:17:38 tsutsui Exp $	*/
 /*	$nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/net/if_udav.c 248085 2013-03-09 02:36:32Z marius $	*/
 /*-
  * Copyright (c) 2003
  *     Shingo WATANABE <nabe at nabechan.org>.  All rights reserved.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_udav.c 248085 2013-03-09 02:36:32Z marius $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>

Modified: stable/0.8/sys/dev/usb/net/if_udavreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_udavreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_udavreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
 /*	$NetBSD: if_udavreg.h,v 1.2 2003/09/04 15:17:39 tsutsui Exp $	*/
 /*	$nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/net/if_udavreg.h 242819 2012-11-09 06:58:23Z hselasky $	*/
 /*-
  * Copyright (c) 2003
  *     Shingo WATANABE <nabe at nabechan.org>.  All rights reserved.

Added: stable/0.8/sys/dev/usb/net/if_urndis.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_urndis.c	                        (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_urndis.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,1053 @@
+/*	$OpenBSD: if_urndis.c,v 1.46 2013/12/09 15:45:29 pirofti Exp $ */
+
+/*
+ * Copyright (c) 2010 Jonathan Armani <armani at openbsd.org>
+ * Copyright (c) 2010 Fabien Romano <fabien at openbsd.org>
+ * Copyright (c) 2010 Michael Knudsen <mk at openbsd.org>
+ * Copyright (c) 2014 Hans Petter Selasky <hselasky at freebsd.org>
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_urndis.c 292793 2015-12-27 20:49:36Z marius $");
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define	USB_DEBUG_VAR urndis_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include "usb_if.h"
+
+#include <dev/usb/net/usb_ethernet.h>
+#include <dev/usb/net/if_urndisreg.h>
+
+#include <dev/usb/usb_cdc.h>
+
+static device_probe_t urndis_probe;
+static device_attach_t urndis_attach;
+static device_detach_t urndis_detach;
+static device_suspend_t urndis_suspend;
+static device_resume_t urndis_resume;
+
+static usb_callback_t urndis_bulk_write_callback;
+static usb_callback_t urndis_bulk_read_callback;
+static usb_callback_t urndis_intr_read_callback;
+
+static uether_fn_t urndis_attach_post;
+static uether_fn_t urndis_init;
+static uether_fn_t urndis_stop;
+static uether_fn_t urndis_start;
+static uether_fn_t urndis_setmulti;
+static uether_fn_t urndis_setpromisc;
+
+static uint32_t	urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+		    struct urndis_query_req *msg, uint16_t len,
+		    const void **rbuf, uint16_t *rbufsz);
+static uint32_t	urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+		    struct urndis_set_req *msg, uint16_t len);
+static uint32_t	urndis_ctrl_handle_init(struct urndis_softc *sc,
+		    const struct urndis_comp_hdr *hdr);
+static uint32_t	urndis_ctrl_handle_query(struct urndis_softc *sc,
+		    const struct urndis_comp_hdr *hdr, const void **buf,
+		    uint16_t *bufsz);
+static uint32_t	urndis_ctrl_handle_reset(struct urndis_softc *sc,
+		    const struct urndis_comp_hdr *hdr);
+static uint32_t	urndis_ctrl_init(struct urndis_softc *sc);
+static uint32_t	urndis_ctrl_halt(struct urndis_softc *sc);
+
+#ifdef USB_DEBUG
+static int urndis_debug = 0;
+static	SYSCTL_NODE(_hw_usb, OID_AUTO, urndis, CTLFLAG_RW, 0, "USB RNDIS-Ethernet");
+SYSCTL_INT(_hw_usb_urndis, OID_AUTO, debug, CTLFLAG_RW, &urndis_debug, 0,
+    "Debug level");
+#endif
+
+static const struct usb_config urndis_config[URNDIS_N_TRANSFER] = {
+	[URNDIS_BULK_RX] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_RX,
+		.if_index = 0,
+		.frames = 1,
+		.bufsize = RNDIS_RX_MAXLEN,
+		.flags = {.short_xfer_ok = 1,},
+		.callback = urndis_bulk_read_callback,
+		.timeout = 0,		/* no timeout */
+		.usb_mode = USB_MODE_HOST,
+	},
+
+	[URNDIS_BULK_TX] = {
+		.type = UE_BULK,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_TX,
+		.if_index = 0,
+		.frames = RNDIS_TX_FRAMES_MAX,
+		.bufsize = (RNDIS_TX_FRAMES_MAX * RNDIS_TX_MAXLEN),
+		.flags = {
+			.force_short_xfer = 1,
+		},
+		.callback = urndis_bulk_write_callback,
+		.timeout = 10000,	/* 10 seconds */
+		.usb_mode = USB_MODE_HOST,
+	},
+
+	[URNDIS_INTR_RX] = {
+		.type = UE_INTERRUPT,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_RX,
+		.if_index = 1,
+		.bufsize = 0,	/* use wMaxPacketSize */
+		.flags = {.short_xfer_ok = 1,.no_pipe_ok = 1,},
+		.callback = urndis_intr_read_callback,
+		.timeout = 0,
+		.usb_mode = USB_MODE_HOST,
+	},
+};
+
+static device_method_t urndis_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, urndis_probe),
+	DEVMETHOD(device_attach, urndis_attach),
+	DEVMETHOD(device_detach, urndis_detach),
+	DEVMETHOD(device_suspend, urndis_suspend),
+	DEVMETHOD(device_resume, urndis_resume),
+
+	DEVMETHOD_END
+};
+
+static driver_t urndis_driver = {
+	.name = "urndis",
+	.methods = urndis_methods,
+	.size = sizeof(struct urndis_softc),
+};
+
+static devclass_t urndis_devclass;
+
+DRIVER_MODULE(urndis, uhub, urndis_driver, urndis_devclass, NULL, NULL);
+MODULE_VERSION(urndis, 1);
+MODULE_DEPEND(urndis, uether, 1, 1, 1);
+MODULE_DEPEND(urndis, usb, 1, 1, 1);
+MODULE_DEPEND(urndis, ether, 1, 1, 1);
+
+static const struct usb_ether_methods urndis_ue_methods = {
+	.ue_attach_post = urndis_attach_post,
+	.ue_start = urndis_start,
+	.ue_init = urndis_init,
+	.ue_stop = urndis_stop,
+	.ue_setmulti = urndis_setmulti,
+	.ue_setpromisc = urndis_setpromisc,
+};
+
+static const STRUCT_USB_HOST_ID urndis_host_devs[] = {
+	/* Generic RNDIS class match */
+	{USB_IFACE_CLASS(UICLASS_CDC),
+		USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
+		USB_IFACE_PROTOCOL(0xff)},
+	{USB_IFACE_CLASS(UICLASS_WIRELESS), USB_IFACE_SUBCLASS(UISUBCLASS_RF),
+		USB_IFACE_PROTOCOL(UIPROTO_RNDIS)},
+	{USB_IFACE_CLASS(UICLASS_IAD), USB_IFACE_SUBCLASS(UISUBCLASS_SYNC),
+		USB_IFACE_PROTOCOL(UIPROTO_ACTIVESYNC)},
+	/* HP-WebOS */
+	{USB_VENDOR(USB_VENDOR_PALM), USB_IFACE_CLASS(UICLASS_CDC),
+		USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
+		USB_IFACE_PROTOCOL(0xff)},
+};
+
+static int
+urndis_probe(device_t dev)
+{
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+	return (usbd_lookup_id_by_uaa(urndis_host_devs, sizeof(urndis_host_devs), uaa));
+}
+
+static void
+urndis_attach_post(struct usb_ether *ue)
+{
+
+	/* no-op */
+}
+
+static int
+urndis_attach(device_t dev)
+{
+	static struct {
+		union {
+			struct urndis_query_req query;
+			struct urndis_set_req set;
+		} hdr;
+		union {
+			uint8_t eaddr[ETHER_ADDR_LEN];
+			uint32_t filter;
+		} ibuf;
+	} msg;
+	struct urndis_softc *sc = device_get_softc(dev);
+	struct usb_ether *ue = &sc->sc_ue;
+	struct usb_attach_arg *uaa = device_get_ivars(dev);
+	struct usb_cdc_cm_descriptor *cmd;
+	const void *buf;
+	uint16_t bufsz;
+	uint8_t iface_index[2] = { uaa->info.bIfaceIndex + 1, uaa->info.bIfaceIndex };
+	int error;
+	uint8_t i;
+
+	sc->sc_ue.ue_udev = uaa->device;
+	sc->sc_ifaceno_ctl = uaa->info.bIfaceNum;
+
+	cmd = usbd_find_descriptor(uaa->device, NULL, uaa->info.bIfaceIndex,
+	    UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_CM, 0xFF);
+	if (cmd != 0) {
+		DPRINTF("Call Mode Descriptor found, dataif=%d\n", cmd->bDataInterface);
+		iface_index[0] = cmd->bDataInterface;
+	}
+
+	device_set_usb_desc(dev);
+
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+	/* scan the alternate settings looking for a valid one */
+	for (i = 0; i != 32; i++) {
+		error = usbd_set_alt_interface_index(uaa->device,
+		    iface_index[0], i);
+
+		if (error != 0)
+			break;
+
+		error = usbd_transfer_setup(uaa->device,
+		    iface_index, sc->sc_xfer, urndis_config,
+		    URNDIS_N_TRANSFER, sc, &sc->sc_mtx);
+
+		if (error == 0)
+			break;
+	}
+	if ((error != 0) || (i == 32)) {
+		device_printf(dev, "No valid alternate setting found\n");
+		goto detach;
+	}
+
+	/* Initialize device - must be done before even querying it */
+	URNDIS_LOCK(sc);
+	error = urndis_ctrl_init(sc);
+	URNDIS_UNLOCK(sc);
+	if (error != (int)RNDIS_STATUS_SUCCESS) {
+		device_printf(dev, "Unable to initialize hardware\n");
+		goto detach;
+	}
+
+	/* Determine MAC address */
+	memset(msg.ibuf.eaddr, 0, sizeof(msg.ibuf.eaddr));
+	URNDIS_LOCK(sc);
+	error = urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS,
+	    &msg.hdr.query, sizeof(msg.hdr.query) + sizeof(msg.ibuf.eaddr),
+	    &buf, &bufsz);
+	URNDIS_UNLOCK(sc);
+	if (error != (int)RNDIS_STATUS_SUCCESS) {
+		device_printf(dev, "Unable to get hardware address\n");
+		goto detach;
+	}
+	if (bufsz != ETHER_ADDR_LEN) {
+		device_printf(dev, "Invalid address length: %d bytes\n", bufsz);
+		goto detach;
+	}
+	memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
+
+	/* Initialize packet filter */
+	sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
+	    RNDIS_PACKET_TYPE_ALL_MULTICAST;
+	msg.ibuf.filter = htole32(sc->sc_filter);
+	URNDIS_LOCK(sc);
+	error = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+	    &msg.hdr.set, sizeof(msg.hdr.set) + sizeof(msg.ibuf.filter));
+	URNDIS_UNLOCK(sc);
+	if (error != (int)RNDIS_STATUS_SUCCESS) {
+		device_printf(dev, "Unable to set data filters\n");
+		goto detach;
+	}
+
+	ue->ue_sc = sc;
+	ue->ue_dev = dev;
+	ue->ue_udev = uaa->device;
+	ue->ue_mtx = &sc->sc_mtx;
+	ue->ue_methods = &urndis_ue_methods;
+
+	error = uether_ifattach(ue);
+	if (error) {
+		device_printf(dev, "Could not attach interface\n");
+		goto detach;
+	}
+
+	URNDIS_LOCK(sc);
+	/* start interrupt endpoint, if any */
+	usbd_transfer_start(sc->sc_xfer[URNDIS_INTR_RX]);
+	URNDIS_UNLOCK(sc);
+
+	return (0);			/* success */
+
+detach:
+	(void)urndis_detach(dev);
+	return (ENXIO);			/* failure */
+}
+
+static int
+urndis_detach(device_t dev)
+{
+	struct urndis_softc *sc = device_get_softc(dev);
+	struct usb_ether *ue = &sc->sc_ue;
+
+	/* stop all USB transfers first */
+	usbd_transfer_unsetup(sc->sc_xfer, URNDIS_N_TRANSFER);
+
+	uether_ifdetach(ue);
+
+	URNDIS_LOCK(sc);
+	(void)urndis_ctrl_halt(sc);
+	URNDIS_UNLOCK(sc);
+
+	mtx_destroy(&sc->sc_mtx);
+
+	return (0);
+}
+
+static void
+urndis_start(struct usb_ether *ue)
+{
+	struct urndis_softc *sc = uether_getsc(ue);
+
+	/*
+	 * Start the USB transfers, if not already started:
+	 */
+	usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_TX]);
+	usbd_transfer_start(sc->sc_xfer[URNDIS_BULK_RX]);
+}
+
+static void
+urndis_init(struct usb_ether *ue)
+{
+	struct urndis_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+
+	URNDIS_LOCK_ASSERT(sc, MA_OWNED);
+
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+	/* stall data write direction, which depends on USB mode */
+	usbd_xfer_set_stall(sc->sc_xfer[URNDIS_BULK_TX]);
+
+	/* start data transfers */
+	urndis_start(ue);
+}
+
+static void
+urndis_stop(struct usb_ether *ue)
+{
+	struct urndis_softc *sc = uether_getsc(ue);
+	struct ifnet *ifp = uether_getifp(ue);
+
+	URNDIS_LOCK_ASSERT(sc, MA_OWNED);
+
+	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
+	/*
+	 * stop all the transfers, if not already stopped:
+	 */
+	usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_RX]);
+	usbd_transfer_stop(sc->sc_xfer[URNDIS_BULK_TX]);
+}
+
+static void
+urndis_setmulti(struct usb_ether *ue)
+{
+
+	/* no-op */
+}
+
+static void
+urndis_setpromisc(struct usb_ether *ue)
+{
+
+	/* no-op */
+}
+
+static int
+urndis_suspend(device_t dev)
+{
+
+	device_printf(dev, "Suspending\n");
+	return (0);
+}
+
+static int
+urndis_resume(device_t dev)
+{
+
+	device_printf(dev, "Resuming\n");
+	return (0);
+}
+
+static usb_error_t
+urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
+    uint16_t index, uint16_t value, void *buf, uint16_t buflen)
+{
+	usb_device_request_t req;
+
+	req.bmRequestType = rt;
+	req.bRequest = r;
+	USETW(req.wValue, value);
+	USETW(req.wIndex, index);
+	USETW(req.wLength, buflen);
+
+	return (usbd_do_request_flags(sc->sc_ue.ue_udev,
+	    &sc->sc_mtx, &req, buf, (rt & UT_READ) ?
+	    USB_SHORT_XFER_OK : 0, NULL, 2000 /* ms */ ));
+}
+
+static usb_error_t
+urndis_ctrl_send(struct urndis_softc *sc, void *buf, uint16_t len)
+{
+	usb_error_t err;
+
+	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE,
+	    UCDC_SEND_ENCAPSULATED_COMMAND, sc->sc_ifaceno_ctl, 0, buf, len);
+
+	DPRINTF("%s\n", usbd_errstr(err));
+
+	return (err);
+}
+
+static struct urndis_comp_hdr *
+urndis_ctrl_recv(struct urndis_softc *sc)
+{
+	struct urndis_comp_hdr *hdr;
+	usb_error_t err;
+
+	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE,
+	    UCDC_GET_ENCAPSULATED_RESPONSE, sc->sc_ifaceno_ctl, 0,
+	    sc->sc_response_buf, RNDIS_RESPONSE_LEN);
+
+	if (err != USB_ERR_NORMAL_COMPLETION)
+		return (NULL);
+
+	hdr = (struct urndis_comp_hdr *)sc->sc_response_buf;
+
+	DPRINTF("type 0x%x len %u\n", le32toh(hdr->rm_type),
+	    le32toh(hdr->rm_len));
+
+	if (le32toh(hdr->rm_len) > RNDIS_RESPONSE_LEN) {
+		DPRINTF("ctrl message error: wrong size %u > %u\n",
+		    le32toh(hdr->rm_len), RNDIS_RESPONSE_LEN);
+		return (NULL);
+	}
+	return (hdr);
+}
+
+static uint32_t
+urndis_ctrl_handle(struct urndis_softc *sc, struct urndis_comp_hdr *hdr,
+    const void **buf, uint16_t *bufsz)
+{
+	uint32_t rval;
+
+	DPRINTF("\n");
+
+	if (buf != NULL && bufsz != NULL) {
+		*buf = NULL;
+		*bufsz = 0;
+	}
+	switch (le32toh(hdr->rm_type)) {
+	case REMOTE_NDIS_INITIALIZE_CMPLT:
+		rval = urndis_ctrl_handle_init(sc, hdr);
+		break;
+
+	case REMOTE_NDIS_QUERY_CMPLT:
+		rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
+		break;
+
+	case REMOTE_NDIS_RESET_CMPLT:
+		rval = urndis_ctrl_handle_reset(sc, hdr);
+		break;
+
+	case REMOTE_NDIS_KEEPALIVE_CMPLT:
+	case REMOTE_NDIS_SET_CMPLT:
+		rval = le32toh(hdr->rm_status);
+		break;
+
+	default:
+		device_printf(sc->sc_ue.ue_dev,
+		    "ctrl message error: unknown event 0x%x\n",
+		    le32toh(hdr->rm_type));
+		rval = RNDIS_STATUS_FAILURE;
+		break;
+	}
+	return (rval);
+}
+
+static uint32_t
+urndis_ctrl_handle_init(struct urndis_softc *sc,
+    const struct urndis_comp_hdr *hdr)
+{
+	const struct urndis_init_comp *msg;
+
+	msg = (const struct urndis_init_comp *)hdr;
+
+	DPRINTF("len %u rid %u status 0x%x "
+	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
+	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
+	    le32toh(msg->rm_len),
+	    le32toh(msg->rm_rid),
+	    le32toh(msg->rm_status),
+	    le32toh(msg->rm_ver_major),
+	    le32toh(msg->rm_ver_minor),
+	    le32toh(msg->rm_devflags),
+	    le32toh(msg->rm_medium),
+	    le32toh(msg->rm_pktmaxcnt),
+	    le32toh(msg->rm_pktmaxsz),
+	    le32toh(msg->rm_align),
+	    le32toh(msg->rm_aflistoffset),
+	    le32toh(msg->rm_aflistsz));
+
+	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("init failed 0x%x\n", le32toh(msg->rm_status));
+		return (le32toh(msg->rm_status));
+	}
+	if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
+		DPRINTF("wrong device type (current type: 0x%x)\n",
+		    le32toh(msg->rm_devflags));
+		return (RNDIS_STATUS_FAILURE);
+	}
+	if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
+		DPRINTF("medium not 802.3 (current medium: 0x%x)\n",
+		    le32toh(msg->rm_medium));
+		return (RNDIS_STATUS_FAILURE);
+	}
+	sc->sc_lim_pktsz = le32toh(msg->rm_pktmaxsz);
+
+	return (le32toh(msg->rm_status));
+}
+
+static uint32_t
+urndis_ctrl_handle_query(struct urndis_softc *sc,
+    const struct urndis_comp_hdr *hdr, const void **buf, uint16_t *bufsz)
+{
+	const struct urndis_query_comp *msg;
+	uint64_t limit;
+
+	msg = (const struct urndis_query_comp *)hdr;
+
+	DPRINTF("len %u rid %u status 0x%x "
+	    "buflen %u bufoff %u\n",
+	    le32toh(msg->rm_len),
+	    le32toh(msg->rm_rid),
+	    le32toh(msg->rm_status),
+	    le32toh(msg->rm_infobuflen),
+	    le32toh(msg->rm_infobufoffset));
+
+	*buf = NULL;
+	*bufsz = 0;
+	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("query failed 0x%x\n", le32toh(msg->rm_status));
+		return (le32toh(msg->rm_status));
+	}
+	limit = le32toh(msg->rm_infobuflen);
+	limit += le32toh(msg->rm_infobufoffset);
+	limit += RNDIS_HEADER_OFFSET;
+
+	if (limit > (uint64_t)le32toh(msg->rm_len)) {
+		DPRINTF("ctrl message error: invalid query info "
+		    "len/offset/end_position(%u/%u/%u) -> "
+		    "go out of buffer limit %u\n",
+		    le32toh(msg->rm_infobuflen),
+		    le32toh(msg->rm_infobufoffset),
+		    le32toh(msg->rm_infobuflen) +
+		    le32toh(msg->rm_infobufoffset) + RNDIS_HEADER_OFFSET,
+		    le32toh(msg->rm_len));
+		return (RNDIS_STATUS_FAILURE);
+	}
+	*buf = ((const uint8_t *)msg) + RNDIS_HEADER_OFFSET +
+	    le32toh(msg->rm_infobufoffset);
+	*bufsz = le32toh(msg->rm_infobuflen);
+
+	return (le32toh(msg->rm_status));
+}
+
+static uint32_t
+urndis_ctrl_handle_reset(struct urndis_softc *sc,
+    const struct urndis_comp_hdr *hdr)
+{
+	const struct urndis_reset_comp *msg;
+	uint32_t rval;
+
+	msg = (const struct urndis_reset_comp *)hdr;
+
+	rval = le32toh(msg->rm_status);
+
+	DPRINTF("len %u status 0x%x "
+	    "adrreset %u\n",
+	    le32toh(msg->rm_len),
+	    rval,
+	    le32toh(msg->rm_adrreset));
+
+	if (rval != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("reset failed 0x%x\n", rval);
+		return (rval);
+	}
+	if (msg->rm_adrreset != 0) {
+		struct {
+			struct urndis_set_req hdr;
+			uint32_t filter;
+		} msg_filter;
+
+		msg_filter.filter = htole32(sc->sc_filter);
+
+		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+		    &msg_filter.hdr, sizeof(msg_filter));
+
+		if (rval != RNDIS_STATUS_SUCCESS) {
+			DPRINTF("unable to reset data filters\n");
+			return (rval);
+		}
+	}
+	return (rval);
+}
+
+static uint32_t
+urndis_ctrl_init(struct urndis_softc *sc)
+{
+	struct urndis_init_req msg;
+	struct urndis_comp_hdr *hdr;
+	uint32_t rval;
+
+	msg.rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
+	msg.rm_len = htole32(sizeof(msg));
+	msg.rm_rid = 0;
+	msg.rm_ver_major = htole32(1);
+	msg.rm_ver_minor = htole32(1);
+	msg.rm_max_xfersz = htole32(RNDIS_RX_MAXLEN);
+
+	DPRINTF("type %u len %u rid %u ver_major %u "
+	    "ver_minor %u max_xfersz %u\n",
+	    le32toh(msg.rm_type),
+	    le32toh(msg.rm_len),
+	    le32toh(msg.rm_rid),
+	    le32toh(msg.rm_ver_major),
+	    le32toh(msg.rm_ver_minor),
+	    le32toh(msg.rm_max_xfersz));
+
+	rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
+
+	if (rval != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("init failed\n");
+		return (rval);
+	}
+	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+		DPRINTF("unable to get init response\n");
+		return (RNDIS_STATUS_FAILURE);
+	}
+	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+
+	return (rval);
+}
+
+static uint32_t
+urndis_ctrl_halt(struct urndis_softc *sc)
+{
+	struct urndis_halt_req msg;
+	uint32_t rval;
+
+	msg.rm_type = htole32(REMOTE_NDIS_HALT_MSG);
+	msg.rm_len = htole32(sizeof(msg));
+	msg.rm_rid = 0;
+
+	DPRINTF("type %u len %u rid %u\n",
+	    le32toh(msg.rm_type),
+	    le32toh(msg.rm_len),
+	    le32toh(msg.rm_rid));
+
+	rval = urndis_ctrl_send(sc, &msg, sizeof(msg));
+
+	if (rval != RNDIS_STATUS_SUCCESS)
+		DPRINTF("halt failed\n");
+
+	return (rval);
+}
+
+/*
+ * NB: Querying a device has the requirment of using an input buffer the size
+ *     of the expected reply or larger, except for variably sized replies.
+ */
+static uint32_t
+urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+    struct urndis_query_req *msg, uint16_t len, const void **rbuf,
+    uint16_t *rbufsz)
+{
+	struct urndis_comp_hdr *hdr;
+	uint32_t datalen, rval;
+
+	msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
+	msg->rm_len = htole32(len);
+	msg->rm_rid = 0;		/* XXX */
+	msg->rm_oid = htole32(oid);
+	datalen = len - sizeof(*msg);
+	msg->rm_infobuflen = htole32(datalen);
+	if (datalen != 0) {
+		msg->rm_infobufoffset = htole32(sizeof(*msg) -
+		    RNDIS_HEADER_OFFSET);
+	} else {
+		msg->rm_infobufoffset = 0;
+	}
+	msg->rm_devicevchdl = 0;
+
+	DPRINTF("type %u len %u rid %u oid 0x%x "
+	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
+	    le32toh(msg->rm_type),
+	    le32toh(msg->rm_len),
+	    le32toh(msg->rm_rid),
+	    le32toh(msg->rm_oid),
+	    le32toh(msg->rm_infobuflen),
+	    le32toh(msg->rm_infobufoffset),
+	    le32toh(msg->rm_devicevchdl));
+
+	rval = urndis_ctrl_send(sc, msg, len);
+
+	if (rval != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("query failed\n");
+		return (rval);
+	}
+	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+		DPRINTF("unable to get query response\n");
+		return (RNDIS_STATUS_FAILURE);
+	}
+	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
+
+	return (rval);
+}
+
+static uint32_t
+urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid,
+    struct urndis_set_req *msg, uint16_t len)
+{
+	struct urndis_comp_hdr *hdr;
+	uint32_t datalen, rval;
+
+	msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
+	msg->rm_len = htole32(len);
+	msg->rm_rid = 0;		/* XXX */
+	msg->rm_oid = htole32(oid);
+	datalen = len - sizeof(*msg);
+	msg->rm_infobuflen = htole32(datalen);
+	if (datalen != 0) {
+		msg->rm_infobufoffset = htole32(sizeof(*msg) -
+		    RNDIS_HEADER_OFFSET);
+	} else {
+		msg->rm_infobufoffset = 0;
+	}
+	msg->rm_devicevchdl = 0;
+
+	DPRINTF("type %u len %u rid %u oid 0x%x "
+	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
+	    le32toh(msg->rm_type),
+	    le32toh(msg->rm_len),
+	    le32toh(msg->rm_rid),
+	    le32toh(msg->rm_oid),
+	    le32toh(msg->rm_infobuflen),
+	    le32toh(msg->rm_infobufoffset),
+	    le32toh(msg->rm_devicevchdl));
+
+	rval = urndis_ctrl_send(sc, msg, len);
+
+	if (rval != RNDIS_STATUS_SUCCESS) {
+		DPRINTF("set failed\n");
+		return (rval);
+	}
+	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
+		DPRINTF("unable to get set response\n");
+		return (RNDIS_STATUS_FAILURE);
+	}
+	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+	if (rval != RNDIS_STATUS_SUCCESS)
+		DPRINTF("set failed 0x%x\n", rval);
+
+	return (rval);
+}
+
+static void
+urndis_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct urndis_softc *sc = usbd_xfer_softc(xfer);
+	struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
+	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+	struct urndis_packet_msg msg;
+	struct mbuf *m;
+	int actlen;
+	int aframes;
+	int offset;
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
+
+		DPRINTFN(1, "received %u bytes in %u frames\n", actlen, aframes);
+
+		for (offset = 0; actlen >= (uint32_t)sizeof(msg);) {
+			/* copy out header */
+			usbd_copy_out(pc, offset, &msg, sizeof(msg));
+
+			if (le32toh(0x1234567U) != 0x1234567U) {
+				/* swap endianness */
+				msg.rm_type = le32toh(msg.rm_type);
+				msg.rm_len = le32toh(msg.rm_len);
+				msg.rm_dataoffset = le32toh(msg.rm_dataoffset);
+				msg.rm_datalen = le32toh(msg.rm_datalen);
+				msg.rm_oobdataoffset = le32toh(msg.rm_oobdataoffset);
+				msg.rm_oobdatalen = le32toh(msg.rm_oobdatalen);
+				msg.rm_oobdataelements = le32toh(msg.rm_oobdataelements);
+				msg.rm_pktinfooffset = le32toh(msg.rm_pktinfooffset);
+				msg.rm_pktinfolen = le32toh(msg.rm_pktinfolen);
+				msg.rm_vchandle = le32toh(msg.rm_vchandle);
+				msg.rm_reserved = le32toh(msg.rm_reserved);
+			}
+
+			DPRINTF("len %u data(off:%u len:%u) "
+			    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
+			    msg.rm_len, msg.rm_dataoffset, msg.rm_datalen,
+			    msg.rm_oobdataoffset, msg.rm_oobdatalen,
+			    msg.rm_oobdataelements, msg.rm_pktinfooffset,
+			    msg.rm_pktinfooffset);
+
+			/* sanity check the RNDIS header */
+			if (msg.rm_type != REMOTE_NDIS_PACKET_MSG) {
+				DPRINTF("invalid type 0x%x != 0x%x\n",
+				    msg.rm_type, REMOTE_NDIS_PACKET_MSG);
+				goto tr_setup;
+			} else if (msg.rm_len < (uint32_t)sizeof(msg)) {
+				DPRINTF("invalid msg len %u < %u\n",
+				    msg.rm_len, (unsigned)sizeof(msg));
+				goto tr_setup;
+			} else if (msg.rm_len > (uint32_t)actlen) {
+				DPRINTF("invalid msg len %u > buffer "
+				    "len %u\n", msg.rm_len, actlen);
+				goto tr_setup;
+			} else if (msg.rm_dataoffset >= (uint32_t)actlen) {
+				DPRINTF("invalid msg dataoffset %u > buffer "
+				    "dataoffset %u\n", msg.rm_dataoffset, actlen);
+				goto tr_setup;
+			} else if (msg.rm_datalen > (uint32_t)actlen) {
+				DPRINTF("invalid msg datalen %u > buffer "
+				    "datalen %u\n", msg.rm_datalen, actlen);
+				goto tr_setup;
+			} else if ((msg.rm_dataoffset + msg.rm_datalen +
+			    (uint32_t)__offsetof(struct urndis_packet_msg,
+			    rm_dataoffset)) > (uint32_t)actlen) {
+				DPRINTF("invalid dataoffset %u larger than %u\n",
+				    msg.rm_dataoffset + msg.rm_datalen +
+				    (uint32_t)__offsetof(struct urndis_packet_msg,
+				    rm_dataoffset), actlen);
+				goto tr_setup;
+			} else if (msg.rm_datalen < (uint32_t)sizeof(struct ether_header)) {
+				ifp->if_ierrors++;
+				DPRINTF("invalid ethernet size "
+				    "%u < %u\n", msg.rm_datalen, (unsigned)sizeof(struct ether_header));
+				goto tr_setup;
+			} else if (msg.rm_datalen > (uint32_t)(MCLBYTES - ETHER_ALIGN)) {
+				ifp->if_ierrors++;
+				DPRINTF("invalid ethernet size "
+				    "%u > %u\n",
+				    msg.rm_datalen, (unsigned)MCLBYTES);
+				goto tr_setup;
+			} else if (msg.rm_datalen > (uint32_t)(MHLEN - ETHER_ALIGN)) {
+				m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+			} else {
+				m = m_gethdr(M_NOWAIT, MT_DATA);
+			}
+
+			/* check if we have a buffer */
+			if (m != NULL) {
+				m->m_len = m->m_pkthdr.len = msg.rm_datalen + ETHER_ALIGN;
+				m_adj(m, ETHER_ALIGN);
+
+				usbd_copy_out(pc, offset + msg.rm_dataoffset +
+				    __offsetof(struct urndis_packet_msg,
+				    rm_dataoffset), m->m_data, msg.rm_datalen);
+
+				/* enqueue */
+				uether_rxmbuf(&sc->sc_ue, m, msg.rm_datalen);
+			} else {
+				ifp->if_ierrors++;
+			}
+			offset += msg.rm_len;
+			actlen -= msg.rm_len;
+		}
+
+	case USB_ST_SETUP:
+tr_setup:
+		usbd_xfer_set_frame_len(xfer, 0, RNDIS_RX_MAXLEN);
+		usbd_xfer_set_frames(xfer, 1);
+		usbd_transfer_submit(xfer);
+		uether_rxflush(&sc->sc_ue);	/* must be last */
+		break;
+
+	default:			/* Error */
+		DPRINTFN(1, "error = %s\n", usbd_errstr(error));
+
+		if (error != USB_ERR_CANCELLED) {
+			/* try to clear stall first */
+			usbd_xfer_set_stall(xfer);
+			usbd_xfer_set_frames(xfer, 0);
+			usbd_transfer_submit(xfer);
+		}
+		break;
+	}
+}
+
+static void
+urndis_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct urndis_packet_msg msg;
+	struct urndis_softc *sc = usbd_xfer_softc(xfer);
+	struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+	struct mbuf *m;
+	unsigned x;
+	int actlen;
+	int aframes;
+
+	usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
+
+	DPRINTFN(1, "\n");
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		DPRINTFN(11, "%u bytes in %u frames\n", actlen, aframes);
+
+		ifp->if_opackets++;
+
+		/* FALLTHROUGH */
+	case USB_ST_SETUP:
+tr_setup:
+		memset(&msg, 0, sizeof(msg));
+
+		for (x = 0; x != RNDIS_TX_FRAMES_MAX; x++) {
+			struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, x);
+
+			usbd_xfer_set_frame_offset(xfer, x * RNDIS_TX_MAXLEN, x);
+
+next_pkt:
+			IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+
+			if (m == NULL)
+				break;
+
+			if ((m->m_pkthdr.len + sizeof(msg)) > RNDIS_TX_MAXLEN) {
+				DPRINTF("Too big packet\n");
+				ifp->if_oerrors++;
+
+				/* Free buffer */
+				m_freem(m);
+				goto next_pkt;
+			}
+			msg.rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
+			msg.rm_len = htole32(sizeof(msg) + m->m_pkthdr.len);
+
+			msg.rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
+			msg.rm_datalen = htole32(m->m_pkthdr.len);
+
+			/* copy in all data */
+			usbd_copy_in(pc, 0, &msg, sizeof(msg));
+			usbd_m_copy_in(pc, sizeof(msg), m, 0, m->m_pkthdr.len);
+			usbd_xfer_set_frame_len(xfer, x, sizeof(msg) + m->m_pkthdr.len);
+
+			/*
+			 * If there's a BPF listener, bounce a copy of
+			 * this frame to him:
+			 */
+			BPF_MTAP(ifp, m);
+
+			/* Free buffer */
+			m_freem(m);
+		}
+		if (x != 0) {
+			usbd_xfer_set_frames(xfer, x);
+			usbd_transfer_submit(xfer);
+		}
+		break;
+
+	default:			/* Error */
+		DPRINTFN(11, "transfer error, %s\n", usbd_errstr(error));
+
+		/* count output errors */
+		ifp->if_oerrors++;
+
+		if (error != USB_ERR_CANCELLED) {
+			/* try to clear stall first */
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		break;
+	}
+}
+
+static void
+urndis_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	int actlen;
+
+	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+
+		DPRINTF("Received %d bytes\n", actlen);
+
+		/* TODO: decode some indications */
+
+		/* FALLTHROUGH */
+	case USB_ST_SETUP:
+tr_setup:
+		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+		usbd_transfer_submit(xfer);
+		break;
+
+	default:			/* Error */
+		if (error != USB_ERR_CANCELLED) {
+			/* start clear stall */
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		break;
+	}
+}


Property changes on: stable/0.8/sys/dev/usb/net/if_urndis.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: stable/0.8/sys/dev/usb/net/if_urndisreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_urndisreg.h	                        (rev 0)
+++ stable/0.8/sys/dev/usb/net/if_urndisreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,296 @@
+/*	$FreeBSD: stable/9/sys/dev/usb/net/if_urndisreg.h 262362 2014-02-23 13:20:08Z hselasky $ */
+/*	$OpenBSD: if_urndisreg.h,v 1.19 2013/11/21 14:08:05 mpi Exp $ */
+
+/*
+ * Copyright (c) 2010 Jonathan Armani <armani at openbsd.org>
+ * Copyright (c) 2010 Fabien Romano <fabien at openbsd.org>
+ * Copyright (c) 2010 Michael Knudsen <mk at openbsd.org>
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _IF_URNDISREG_H_
+#define	_IF_URNDISREG_H_
+
+#define	RNDIS_RESPONSE_LEN	1024	/* bytes */
+#define	RNDIS_RX_MAXLEN		(16 * 1024)
+#define	RNDIS_TX_FRAMES_MAX	8
+#define	RNDIS_TX_MAXLEN		MCLBYTES
+
+enum {
+	URNDIS_BULK_RX,
+	URNDIS_BULK_TX,
+	URNDIS_INTR_RX,
+	URNDIS_N_TRANSFER,
+};
+
+struct urndis_softc {
+
+	struct usb_ether sc_ue;
+	struct mtx sc_mtx;
+
+	/* RNDIS device info */
+	uint32_t sc_lim_pktsz;
+	uint32_t sc_filter;
+
+	struct usb_device *sc_udev;
+	struct usb_xfer *sc_xfer[URNDIS_N_TRANSFER];
+
+	uint8_t	sc_ifaceno_ctl;
+	uint8_t	sc_response_buf[RNDIS_RESPONSE_LEN] __aligned(4);
+};
+
+#define	URNDIS_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define	URNDIS_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define	URNDIS_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->sc_mtx, (what))
+
+#define	RNDIS_STATUS_BUFFER_OVERFLOW 	0x80000005L
+#define	RNDIS_STATUS_FAILURE 		0xC0000001L
+#define	RNDIS_STATUS_INVALID_DATA 	0xC0010015L
+#define	RNDIS_STATUS_MEDIA_CONNECT 	0x4001000BL
+#define	RNDIS_STATUS_MEDIA_DISCONNECT 	0x4001000CL
+#define	RNDIS_STATUS_NOT_SUPPORTED 	0xC00000BBL
+#define	RNDIS_STATUS_PENDING 		STATUS_PENDING	/* XXX */
+#define	RNDIS_STATUS_RESOURCES 		0xC000009AL
+#define	RNDIS_STATUS_SUCCESS 		0x00000000L
+
+#define	OID_GEN_SUPPORTED_LIST		0x00010101
+#define	OID_GEN_HARDWARE_STATUS		0x00010102
+#define	OID_GEN_MEDIA_SUPPORTED		0x00010103
+#define	OID_GEN_MEDIA_IN_USE		0x00010104
+#define	OID_GEN_MAXIMUM_LOOKAHEAD	0x00010105
+#define	OID_GEN_MAXIMUM_FRAME_SIZE	0x00010106
+#define	OID_GEN_LINK_SPEED		0x00010107
+#define	OID_GEN_TRANSMIT_BUFFER_SPACE	0x00010108
+#define	OID_GEN_RECEIVE_BUFFER_SPACE	0x00010109
+#define	OID_GEN_TRANSMIT_BLOCK_SIZE	0x0001010A
+#define	OID_GEN_RECEIVE_BLOCK_SIZE	0x0001010B
+#define	OID_GEN_VENDOR_ID		0x0001010C
+#define	OID_GEN_VENDOR_DESCRIPTION	0x0001010D
+#define	OID_GEN_CURRENT_PACKET_FILTER	0x0001010E
+#define	OID_GEN_CURRENT_LOOKAHEAD	0x0001010F
+#define	OID_GEN_DRIVER_VERSION		0x00010110
+#define	OID_GEN_MAXIMUM_TOTAL_SIZE	0x00010111
+#define	OID_GEN_PROTOCOL_OPTIONS	0x00010112
+#define	OID_GEN_MAC_OPTIONS		0x00010113
+#define	OID_GEN_MEDIA_CONNECT_STATUS	0x00010114
+#define	OID_GEN_MAXIMUM_SEND_PACKETS	0x00010115
+#define	OID_GEN_VENDOR_DRIVER_VERSION	0x00010116
+#define	OID_GEN_SUPPORTED_GUIDS		0x00010117
+#define	OID_GEN_NETWORK_LAYER_ADDRESSES	0x00010118
+#define	OID_GEN_TRANSPORT_HEADER_OFFSET	0x00010119
+#define	OID_GEN_MACHINE_NAME		0x0001021A
+#define	OID_GEN_RNDIS_CONFIG_PARAMETER	0x0001021B
+#define	OID_GEN_VLAN_ID			0x0001021C
+
+#define	OID_802_3_PERMANENT_ADDRESS	0x01010101
+#define	OID_802_3_CURRENT_ADDRESS	0x01010102
+#define	OID_802_3_MULTICAST_LIST	0x01010103
+#define	OID_802_3_MAXIMUM_LIST_SIZE	0x01010104
+#define	OID_802_3_MAC_OPTIONS		0x01010105
+#define	OID_802_3_RCV_ERROR_ALIGNMENT	0x01020101
+#define	OID_802_3_XMIT_ONE_COLLISION	0x01020102
+#define	OID_802_3_XMIT_MORE_COLLISIONS	0x01020103
+#define	OID_802_3_XMIT_DEFERRED		0x01020201
+#define	OID_802_3_XMIT_MAX_COLLISIONS	0x01020202
+#define	OID_802_3_RCV_OVERRUN		0x01020203
+#define	OID_802_3_XMIT_UNDERRUN		0x01020204
+#define	OID_802_3_XMIT_HEARTBEAT_FAILURE	0x01020205
+#define	OID_802_3_XMIT_TIMES_CRS_LOST	0x01020206
+#define	OID_802_3_XMIT_LATE_COLLISIONS	0x01020207
+
+#define	RNDIS_MEDIUM_802_3		0x00000000
+
+/* Device flags */
+#define	RNDIS_DF_CONNECTIONLESS		0x00000001
+#define	RNDIS_DF_CONNECTION_ORIENTED	0x00000002
+
+/*
+ * RNDIS data message
+ */
+#define	REMOTE_NDIS_PACKET_MSG		0x00000001
+
+struct urndis_packet_msg {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_dataoffset;
+	uint32_t rm_datalen;
+	uint32_t rm_oobdataoffset;
+	uint32_t rm_oobdatalen;
+	uint32_t rm_oobdataelements;
+	uint32_t rm_pktinfooffset;
+	uint32_t rm_pktinfolen;
+	uint32_t rm_vchandle;
+	uint32_t rm_reserved;
+};
+
+/*
+ * RNDIS control messages
+ */
+struct urndis_comp_hdr {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_status;
+};
+
+/* Initialize the device. */
+#define	REMOTE_NDIS_INITIALIZE_MSG	0x00000002
+#define	REMOTE_NDIS_INITIALIZE_CMPLT	0x80000002
+
+struct urndis_init_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_ver_major;
+	uint32_t rm_ver_minor;
+	uint32_t rm_max_xfersz;
+};
+
+struct urndis_init_comp {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_status;
+	uint32_t rm_ver_major;
+	uint32_t rm_ver_minor;
+	uint32_t rm_devflags;
+	uint32_t rm_medium;
+	uint32_t rm_pktmaxcnt;
+	uint32_t rm_pktmaxsz;
+	uint32_t rm_align;
+	uint32_t rm_aflistoffset;
+	uint32_t rm_aflistsz;
+};
+
+/* Halt the device.  No response sent. */
+#define	REMOTE_NDIS_HALT_MSG		0x00000003
+
+struct urndis_halt_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+};
+
+/* Send a query object. */
+#define	REMOTE_NDIS_QUERY_MSG		0x00000004
+#define	REMOTE_NDIS_QUERY_CMPLT		0x80000004
+
+struct urndis_query_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_oid;
+	uint32_t rm_infobuflen;
+	uint32_t rm_infobufoffset;
+	uint32_t rm_devicevchdl;
+};
+
+struct urndis_query_comp {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_status;
+	uint32_t rm_infobuflen;
+	uint32_t rm_infobufoffset;
+};
+
+/* Send a set object request. */
+#define	REMOTE_NDIS_SET_MSG		0x00000005
+#define	REMOTE_NDIS_SET_CMPLT		0x80000005
+
+struct urndis_set_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_oid;
+	uint32_t rm_infobuflen;
+	uint32_t rm_infobufoffset;
+	uint32_t rm_devicevchdl;
+};
+
+struct urndis_set_comp {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_status;
+};
+
+#define	REMOTE_NDIS_SET_PARAM_NUMERIC	0x00000000
+#define	REMOTE_NDIS_SET_PARAM_STRING	0x00000002
+
+struct urndis_set_parameter {
+	uint32_t rm_nameoffset;
+	uint32_t rm_namelen;
+	uint32_t rm_type;
+	uint32_t rm_valueoffset;
+	uint32_t rm_valuelen;
+};
+
+/* Perform a soft reset on the device. */
+#define	REMOTE_NDIS_RESET_MSG		0x00000006
+#define	REMOTE_NDIS_RESET_CMPLT		0x80000006
+
+struct urndis_reset_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+};
+
+struct urndis_reset_comp {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_status;
+	uint32_t rm_adrreset;
+};
+
+/* 802.3 link-state or undefined message error. */
+#define	REMOTE_NDIS_INDICATE_STATUS_MSG	0x00000007
+
+/* Keepalive messsage.  May be sent by device. */
+#define	REMOTE_NDIS_KEEPALIVE_MSG	0x00000008
+#define	REMOTE_NDIS_KEEPALIVE_CMPLT	0x80000008
+
+struct urndis_keepalive_req {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+};
+
+struct urndis_keepalive_comp {
+	uint32_t rm_type;
+	uint32_t rm_len;
+	uint32_t rm_rid;
+	uint32_t rm_status;
+};
+
+/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */
+#define	RNDIS_PACKET_TYPE_DIRECTED		0x00000001
+#define	RNDIS_PACKET_TYPE_MULTICAST		0x00000002
+#define	RNDIS_PACKET_TYPE_ALL_MULTICAST		0x00000004
+#define	RNDIS_PACKET_TYPE_BROADCAST		0x00000008
+#define	RNDIS_PACKET_TYPE_SOURCE_ROUTING	0x00000010
+#define	RNDIS_PACKET_TYPE_PROMISCUOUS		0x00000020
+#define	RNDIS_PACKET_TYPE_SMT			0x00000040
+#define	RNDIS_PACKET_TYPE_ALL_LOCAL		0x00000080
+#define	RNDIS_PACKET_TYPE_GROUP			0x00001000
+#define	RNDIS_PACKET_TYPE_ALL_FUNCTIONAL	0x00002000
+#define	RNDIS_PACKET_TYPE_FUNCTIONAL		0x00004000
+#define	RNDIS_PACKET_TYPE_MAC_FRAME		0x00008000
+
+/* RNDIS offsets */
+#define	RNDIS_HEADER_OFFSET	8	/* bytes */
+#define	RNDIS_DATA_OFFSET	((uint32_t)(sizeof(struct urndis_packet_msg) - RNDIS_HEADER_OFFSET))
+
+#endif					/* _IF_URNDISREG_H_ */


Property changes on: stable/0.8/sys/dev/usb/net/if_urndisreg.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/net/if_usie.c
===================================================================
--- stable/0.8/sys/dev/usb/net/if_usie.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_usie.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/if_usie.c 248085 2013-03-09 02:36:32Z marius $");
 
 #include <sys/param.h>
 #include <sys/systm.h>

Modified: stable/0.8/sys/dev/usb/net/if_usievar.h
===================================================================
--- stable/0.8/sys/dev/usb/net/if_usievar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/if_usievar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/if_usievar.h 223864 2011-07-08 10:58:56Z hselasky $ */
 
 /*-
  * Copyright (c) 2011 Anybots Inc

Modified: stable/0.8/sys/dev/usb/net/ruephy.c
===================================================================
--- stable/0.8/sys/dev/usb/net/ruephy.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/ruephy.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/ruephy.c 235000 2012-05-04 15:05:30Z hselasky $");
 
 /*
  * driver for RealTek RTL8150 internal PHY

Modified: stable/0.8/sys/dev/usb/net/ruephyreg.h
===================================================================
--- stable/0.8/sys/dev/usb/net/ruephyreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/ruephyreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/ruephyreg.h 227229 2011-11-06 17:23:49Z marius $
  */
 
 #ifndef _RUEPHYREG_H_

Modified: stable/0.8/sys/dev/usb/net/uhso.c
===================================================================
--- stable/0.8/sys/dev/usb/net/uhso.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/uhso.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
  *
  */
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/uhso.c 301447 2016-06-05 15:05:53Z pfg $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -268,6 +268,8 @@
 	UHSO_DEV(OPTION, ICON401, UHSO_AUTO_IFACE),
 	/* Option GlobeTrotter Module 382 */
 	UHSO_DEV(OPTION, GMT382, UHSO_AUTO_IFACE),
+	/* Option GTM661W */
+	UHSO_DEV(OPTION, GTM661W, UHSO_AUTO_IFACE),
 	/* Option iCON EDGE */
 	UHSO_DEV(OPTION, ICONEDGE, UHSO_STATIC_IFACE),
 	/* Option Module HSxPA */
@@ -556,8 +558,6 @@
 	mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
 	ucom_ref(&sc->sc_super_ucom);
 
-	sc->sc_ucom = NULL;
-	sc->sc_ttys = 0;
 	sc->sc_radio = 1;
 
 	id = usbd_get_interface_descriptor(uaa->iface);
@@ -677,9 +677,6 @@
 				    UHSO_CTRL_MAX);
 			}
 		}
-
-		free(sc->sc_tty, M_USBDEV);
-		free(sc->sc_ucom, M_USBDEV);
 	}
 
 	if (sc->sc_ifp != NULL) {
@@ -707,6 +704,8 @@
 uhso_free_softc(struct uhso_softc *sc)
 {
 	if (ucom_unref(&sc->sc_super_ucom)) {
+		free(sc->sc_tty, M_USBDEV);
+		free(sc->sc_ucom, M_USBDEV);
 		mtx_destroy(&sc->sc_mtx);
 		device_free_softc(sc);
 	}
@@ -814,6 +813,8 @@
 		    UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port));
 	case UHSO_PORT_TYPE_DIAG:
 	case UHSO_PORT_TYPE_DIAG2:
+	case UHSO_PORT_TYPE_GPS:
+	case UHSO_PORT_TYPE_GPSCTL:
 	case UHSO_PORT_TYPE_CTL:
 	case UHSO_PORT_TYPE_APP:
 	case UHSO_PORT_TYPE_APP2:
@@ -1222,6 +1223,7 @@
 		    ht->ht_muxport);
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
+tr_setup:
 		pc = usbd_xfer_get_frame(xfer, 1);
 		if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc,
 		    0, 32, &actlen)) {
@@ -1252,7 +1254,8 @@
 		UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
 		if (error == USB_ERR_CANCELLED)
 			break;
-		break;
+		usbd_xfer_set_stall(xfer);
+		goto tr_setup;
 	}
 }
 

Modified: stable/0.8/sys/dev/usb/net/usb_ethernet.c
===================================================================
--- stable/0.8/sys/dev/usb/net/usb_ethernet.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/usb_ethernet.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.c 262594 2014-02-28 01:35:24Z rodrigc $ */
 /*-
  * Copyright (c) 2009 Andrew Thompson (thompsa at FreeBSD.org)
  *
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.c 262594 2014-02-28 01:35:24Z rodrigc $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -207,6 +207,7 @@
 	sysctl_ctx_init(&ue->ue_sysctl_ctx);
 
 	error = 0;
+	CURVNET_SET_QUIET(vnet0);
 	ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
 		device_printf(ue->ue_dev, "could not allocate ifnet\n");
@@ -254,6 +255,8 @@
 	if (ifp->if_capabilities & IFCAP_VLAN_MTU)
 		ifp->if_hdrlen = sizeof(struct ether_vlan_header);
 
+	CURVNET_RESTORE();
+
 	snprintf(num, sizeof(num), "%u", ue->ue_unit);
 	ue->ue_sysctl_oid = SYSCTL_ADD_NODE(&ue->ue_sysctl_ctx,
 	    &SYSCTL_NODE_CHILDREN(_net, ue),
@@ -267,6 +270,7 @@
 	return;
 
 fail:
+	CURVNET_RESTORE();
 	free_unr(ueunit, ue->ue_unit);
 	if (ue->ue_ifp != NULL) {
 		if_free(ue->ue_ifp);

Modified: stable/0.8/sys/dev/usb/net/usb_ethernet.h
===================================================================
--- stable/0.8/sys/dev/usb/net/usb_ethernet.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/net/usb_ethernet.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.h 229105 2011-12-31 14:45:43Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/net/usb_ethernet.h 229105 2011-12-31 14:45:43Z hselasky $
  */
 
 #ifndef _USB_ETHERNET_H_

Modified: stable/0.8/sys/dev/usb/quirk/usb_quirk.c
===================================================================
--- stable/0.8/sys/dev/usb/quirk/usb_quirk.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/quirk/usb_quirk.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/quirk/usb_quirk.c 315250 2017-03-14 15:25:49Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -61,6 +61,7 @@
 
 #define	USB_DEV_QUIRKS_MAX 384
 #define	USB_SUB_QUIRKS_MAX 8
+#define	USB_QUIRK_ENVROOT "hw.usb.quirk."
 
 struct usb_quirk_entry {
 	uint16_t vid;
@@ -97,6 +98,7 @@
 	USB_QUIRK(REALTEK, RTL8153, 0x0000, 0xffff, UQ_CFG_INDEX_1),
 	USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
 	USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
+	USB_QUIRK(CISCOLINKSYS, USB3GIGV1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
 	/* Quirks for printer devices */
 	USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
 	USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
@@ -133,6 +135,8 @@
 	USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
 	/* Quirk for Corsair Vengeance K70 keyboard */
 	USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
+	/* Quirk for Corsair STRAFE Gaming keyboard */
+	USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
 	/* umodem(4) device quirks */
 	USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
 	USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
@@ -513,6 +517,7 @@
 	/* Non-standard USB AUDIO devices */
 	USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
 	USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
+	USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206),
 
 	/*
 	 * Quirks for manufacturers which USB devices does not respond
@@ -526,6 +531,9 @@
 
 	/* DYMO LabelManager Pnp */
 	USB_QUIRK(DYMO, LABELMANAGERPNP, 0x0000, 0xffff, UQ_MSC_DYMO_EJECT),
+
+	/* Holtek USB gaming keyboard */
+	USB_QUIRK(HOLTEK, F85, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
 };
 #undef USB_QUIRK_VP
 #undef USB_QUIRK
@@ -597,6 +605,7 @@
 	[UQ_AU_VENDOR_CLASS]		= "UQ_AU_VENDOR_CLASS",
 	[UQ_SINGLE_CMD_MIDI]		= "UQ_SINGLE_CMD_MIDI",
 	[UQ_MSC_DYMO_EJECT]		= "UQ_MSC_DYMO_EJECT",
+	[UQ_AU_SET_SPDIF_CM6206]	= "UQ_AU_SET_SPDIF_CM6206",
 };
 
 /*------------------------------------------------------------------------*
@@ -607,11 +616,35 @@
 static const char *
 usb_quirkstr(uint16_t quirk)
 {
-	return ((quirk < USB_QUIRK_MAX) ?
-	    usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
+	return ((quirk < USB_QUIRK_MAX && usb_quirk_str[quirk] != NULL) ?
+	    usb_quirk_str[quirk] : "UQ_UNKNOWN");
 }
 
 /*------------------------------------------------------------------------*
+ *	usb_strquirk
+ *
+ * This function converts a string into a USB quirk code.
+ *
+ * Returns:
+ * Less than USB_QUIRK_MAX: Quirk code
+ * Else: Quirk code not found
+ *------------------------------------------------------------------------*/
+static uint16_t
+usb_strquirk(const char *str, size_t len)
+{
+	const char *quirk;
+	uint16_t x;
+
+	for (x = 0; x != USB_QUIRK_MAX; x++) {
+		quirk = usb_quirkstr(x);
+		if (strncmp(str, quirk, len) == 0 &&
+		    quirk[len] == 0)
+			break;
+	}
+	return (x);
+}
+
+/*------------------------------------------------------------------------*
  *	usb_test_quirk_by_info
  *
  * Returns:
@@ -656,8 +689,6 @@
 				return (1);
 			}
 		}
-		/* no quirk found */
-		break;
 	}
 	mtx_unlock(&usb_quirk_mtx);
 done:
@@ -853,12 +884,122 @@
 	return (ENOIOCTL);
 }
 
+/*------------------------------------------------------------------------*
+ *	usb_quirk_strtou16
+ *
+ * Helper function to scan a 16-bit integer.
+ *------------------------------------------------------------------------*/
+static uint16_t
+usb_quirk_strtou16(const char **pptr, const char *name, const char *what)
+{
+	unsigned long value;
+	char *end;
+
+	value = strtoul(*pptr, &end, 0);
+	if (value > 65535 || *pptr == end || (*end != ' ' && *end != '\t')) {
+		printf("%s: %s 16-bit %s value set to zero\n",
+		    name, what, *end == 0 ? "incomplete" : "invalid");
+		return (0);
+	}
+	*pptr = end + 1;
+	return ((uint16_t)value);
+}
+
+/*------------------------------------------------------------------------*
+ *	usb_quirk_add_entry_from_str
+ *
+ * Add a USB quirk entry from string.
+ *     "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]"
+ *------------------------------------------------------------------------*/
 static void
+usb_quirk_add_entry_from_str(const char *name, const char *env)
+{
+	struct usb_quirk_entry entry = { };
+	struct usb_quirk_entry *new;
+	uint16_t quirk_idx;
+	uint16_t quirk;
+	const char *end;
+
+	/* check for invalid environment variable */
+	if (name == NULL || env == NULL)
+		return;
+
+	if (bootverbose)
+		printf("Adding USB QUIRK '%s' = '%s'\n", name, env);
+
+	/* parse device information */
+	entry.vid = usb_quirk_strtou16(&env, name, "Vendor ID");
+	entry.pid = usb_quirk_strtou16(&env, name, "Product ID");
+	entry.lo_rev = usb_quirk_strtou16(&env, name, "Low revision");
+	entry.hi_rev = usb_quirk_strtou16(&env, name, "High revision");
+
+	/* parse quirk information */
+	quirk_idx = 0;
+	while (*env != 0 && quirk_idx != USB_SUB_QUIRKS_MAX) {
+		/* skip whitespace before quirks */
+		while (*env == ' ' || *env == '\t')
+			env++;
+
+		/* look for quirk separation character */
+		end = strchr(env, ',');
+		if (end == NULL)
+			end = env + strlen(env);
+
+		/* lookup quirk in string table */
+		quirk = usb_strquirk(env, end - env);
+		if (quirk < USB_QUIRK_MAX) {
+			entry.quirks[quirk_idx++] = quirk;
+		} else {
+			printf("%s: unknown USB quirk '%.*s' (skipped)\n",
+			    name, (int)(end - env), env);
+		}
+		env = end;
+
+		/* skip quirk delimiter, if any */
+		if (*env != 0)
+			env++;
+	}
+
+	/* register quirk */
+	if (quirk_idx != 0) {
+		if (*env != 0) {
+			printf("%s: Too many USB quirks, only %d allowed!\n",
+			    name, USB_SUB_QUIRKS_MAX);
+		}
+		mtx_lock(&usb_quirk_mtx);
+		new = usb_quirk_get_entry(entry.vid, entry.pid,
+		    entry.lo_rev, entry.hi_rev, 1);
+		if (new == NULL)
+			printf("%s: USB quirks table is full!\n", name);
+		else
+			memcpy(new->quirks, entry.quirks, sizeof(entry.quirks));
+		mtx_unlock(&usb_quirk_mtx);
+	} else {
+		printf("%s: No USB quirks found!\n", name);
+	}
+}
+
+static void
 usb_quirk_init(void *arg)
 {
+	char envkey[sizeof(USB_QUIRK_ENVROOT) + 2];	/* 2 digits max, 0 to 99 */
+	int i;
+  
 	/* initialize mutex */
 	mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
 
+	/* look for quirks defined by the environment variable */
+	for (i = 0; i != 100; i++) {
+		snprintf(envkey, sizeof(envkey), USB_QUIRK_ENVROOT "%d", i);
+
+		/* Stop at first undefined var */
+		if (!testenv(envkey))
+			break;
+
+		/* parse environment variable */
+		usb_quirk_add_entry_from_str(envkey, getenv(envkey));
+	}
+	
 	/* register our function */
 	usb_test_quirk_p = &usb_test_quirk_by_info;
 	usb_quirk_ioctl_p = &usb_quirk_ioctl;

Modified: stable/0.8/sys/dev/usb/quirk/usb_quirk.h
===================================================================
--- stable/0.8/sys/dev/usb/quirk/usb_quirk.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/quirk/usb_quirk.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/quirk/usb_quirk.h 315250 2017-03-14 15:25:49Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -110,6 +110,7 @@
 	UQ_AU_VENDOR_CLASS,	/* audio device uses vendor and not audio class */
 	UQ_SINGLE_CMD_MIDI,	/* at most one command per USB packet */
 	UQ_MSC_DYMO_EJECT,	/* ejects Dymo MSC device */
+	UQ_AU_SET_SPDIF_CM6206,	/* enable S/PDIF audio output */
 
 	USB_QUIRK_MAX
 };

Modified: stable/0.8/sys/dev/usb/serial/u3g.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/u3g.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/u3g.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -16,7 +16,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/serial/u3g.c 306958 2016-10-10 11:48:23Z hselasky $
  */
 
 /*
@@ -75,16 +75,9 @@
 #define	U3G_MAXPORTS		12
 #define	U3G_CONFIG_INDEX	0
 #define	U3G_BSIZE		2048
+#define	U3G_TXSIZE		(U3G_BSIZE / U3G_TXFRAMES)
+#define	U3G_TXFRAMES		4
 
-#define	U3GSP_GPRS		0
-#define	U3GSP_EDGE		1
-#define	U3GSP_CDMA		2
-#define	U3GSP_UMTS		3
-#define	U3GSP_HSDPA		4
-#define	U3GSP_HSUPA		5
-#define	U3GSP_HSPA		6
-#define	U3GSP_MAX		7
-
 /* Eject methods; See also usb_quirks.h:UQ_MSC_EJECT_* */
 #define	U3GINIT_HUAWEI		1	/* Requires Huawei init command */
 #define	U3GINIT_SIERRA		2	/* Requires Sierra init command */
@@ -95,7 +88,8 @@
 #define	U3GINIT_WAIT		7	/* Device reappears after a delay */
 #define	U3GINIT_SAEL_M460	8	/* Requires vendor init */
 #define	U3GINIT_HUAWEISCSI	9	/* Requires Huawei SCSI init command */
-#define	U3GINIT_TCT		10	/* Requires TCT Mobile init command */
+#define	U3GINIT_HUAWEISCSI2	10	/* Requires Huawei SCSI init command (2) */
+#define	U3GINIT_TCT		11	/* Requires TCT Mobile init command */
 
 enum {
 	U3G_BULK_WR,
@@ -153,6 +147,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = U3G_BSIZE,/* bytes */
+		.frames = U3G_TXFRAMES,
 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
 		.callback = &u3g_write_callback,
 	},
@@ -244,9 +239,13 @@
 	U3G_DEV(DELL, U740, 0),
 	U3G_DEV(DLINK, DWR510_CD, U3GINIT_SCSIEJECT),
 	U3G_DEV(DLINK, DWR510, 0),
+	U3G_DEV(DLINK, DWM157_CD, U3GINIT_SCSIEJECT),
+	U3G_DEV(DLINK, DWM157, 0),
 	U3G_DEV(DLINK3, DWM652, 0),
 	U3G_DEV(HP, EV2200, 0),
 	U3G_DEV(HP, HS2300, 0),
+	U3G_DEV(HP, UN2420_QDL, 0),
+	U3G_DEV(HP, UN2420, 0),
 	U3G_DEV(HUAWEI, E1401, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, E1402, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, E1403, U3GINIT_HUAWEI),
@@ -317,9 +316,12 @@
 	U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, E392, U3GINIT_HUAWEISCSI),
+	U3G_DEV(HUAWEI, ME909U, U3GINIT_HUAWEISCSI2),
 	U3G_DEV(HUAWEI, MOBILE, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, E1752, U3GINIT_HUAWEISCSI),
 	U3G_DEV(HUAWEI, E1820, U3GINIT_HUAWEISCSI),
+	U3G_DEV(HUAWEI, K3772, U3GINIT_HUAWEI),
+	U3G_DEV(HUAWEI, K3772_INIT, U3GINIT_HUAWEISCSI2),
 	U3G_DEV(HUAWEI, K3765, U3GINIT_HUAWEI),
 	U3G_DEV(HUAWEI, K3765_INIT, U3GINIT_HUAWEISCSI),
 	U3G_DEV(HUAWEI, K3770, U3GINIT_HUAWEI),
@@ -343,8 +345,10 @@
 	U3G_DEV(NOVATEL, EU870D, 0),
 	U3G_DEV(NOVATEL, MC760, 0),
 	U3G_DEV(NOVATEL, MC547, 0),
+	U3G_DEV(NOVATEL, MC679, 0),
 	U3G_DEV(NOVATEL, MC950D, 0),
 	U3G_DEV(NOVATEL, MIFI2200, U3GINIT_SCSIEJECT),
+	U3G_DEV(NOVATEL, MIFI2200V, U3GINIT_SCSIEJECT),
 	U3G_DEV(NOVATEL, U720, 0),
 	U3G_DEV(NOVATEL, U727, 0),
 	U3G_DEV(NOVATEL, U727_2, 0),
@@ -387,6 +391,7 @@
 	U3G_DEV(OPTION, GTMAXHSUPA, 0),
 	U3G_DEV(OPTION, GTMAXHSUPAE, 0),
 	U3G_DEV(OPTION, VODAFONEMC3G, 0),
+	U3G_DEV(OPTION, GTM661W, 0),
 	U3G_DEV(QISDA, H20_1, 0),
 	U3G_DEV(QISDA, H20_2, 0),
 	U3G_DEV(QISDA, H21_1, 0),
@@ -395,10 +400,15 @@
 	U3G_DEV(QUALCOMM2, AC8700, 0),
 	U3G_DEV(QUALCOMM2, MF330, 0),
 	U3G_DEV(QUALCOMM2, SIM5218, 0),
+	U3G_DEV(QUALCOMM2, WM620, 0),
 	U3G_DEV(QUALCOMM2, VW110L, U3GINIT_SCSIEJECT),
 	U3G_DEV(QUALCOMM2, GOBI2000_QDL, 0),
 	U3G_DEV(QUALCOMM2, GOBI2000, 0),
+	U3G_DEV(QUALCOMM2, VT80N, 0),
+	U3G_DEV(QUALCOMM3, VFAST2, 0),
 	U3G_DEV(QUALCOMMINC, AC2726, 0),
+	U3G_DEV(QUALCOMMINC, AC682_INIT, U3GINIT_SCSIEJECT),
+	U3G_DEV(QUALCOMMINC, AC682, 0),
 	U3G_DEV(QUALCOMMINC, AC8700, 0),
 	U3G_DEV(QUALCOMMINC, AC8710, 0),
 	U3G_DEV(QUALCOMMINC, CDMA_MSM, U3GINIT_SCSIEJECT),
@@ -466,10 +476,15 @@
 	U3G_DEV(QUALCOMMINC, SURFSTICK, 0),
 	U3G_DEV(QUALCOMMINC, E2002, 0),
 	U3G_DEV(QUALCOMMINC, E2003, 0),
-	U3G_DEV(QUALCOMMINC, K3772_Z, U3GINIT_SCSIEJECT),
+	U3G_DEV(QUALCOMMINC, K3772_Z, 0),
+	U3G_DEV(QUALCOMMINC, K3772_Z_INIT, U3GINIT_SCSIEJECT),
+	U3G_DEV(QUALCOMMINC, MF195E, 0),
+	U3G_DEV(QUALCOMMINC, MF195E_INIT, U3GINIT_SCSIEJECT),
 	U3G_DEV(QUALCOMMINC, MF626, 0),
 	U3G_DEV(QUALCOMMINC, MF628, 0),
 	U3G_DEV(QUALCOMMINC, MF633R, 0),
+	/* the following is a RNDIS device, no modem features */
+	U3G_DEV(QUALCOMMINC, ZTE_MF730M, U3GINIT_SCSIEJECT),
 	U3G_DEV(QUANTA, GKE, 0),
 	U3G_DEV(QUANTA, GLE, 0),
 	U3G_DEV(QUANTA, GLX, 0),
@@ -479,6 +494,7 @@
 	U3G_DEV(SIERRA, AC595U, 0),
 	U3G_DEV(SIERRA, AC313U, 0),
 	U3G_DEV(SIERRA, AC597E, 0),
+	U3G_DEV(SIERRA, AC875, 0),
 	U3G_DEV(SIERRA, AC875E, 0),
 	U3G_DEV(SIERRA, AC875U, 0),
 	U3G_DEV(SIERRA, AC875U_2, 0),
@@ -493,7 +509,6 @@
 	U3G_DEV(SIERRA, AC885U, 0),
 	U3G_DEV(SIERRA, AIRCARD580, 0),
 	U3G_DEV(SIERRA, AIRCARD595, 0),
-	U3G_DEV(SIERRA, AIRCARD875, 0),
 	U3G_DEV(SIERRA, C22, 0),
 	U3G_DEV(SIERRA, C597, 0),
 	U3G_DEV(SIERRA, C888, 0),
@@ -508,6 +523,7 @@
 	U3G_DEV(SIERRA, MC5727, 0),
 	U3G_DEV(SIERRA, MC5727_2, 0),
 	U3G_DEV(SIERRA, MC5728, 0),
+	U3G_DEV(SIERRA, MC7430, 0),
 	U3G_DEV(SIERRA, MC8700, 0),
 	U3G_DEV(SIERRA, MC8755, 0),
 	U3G_DEV(SIERRA, MC8755_2, 0),
@@ -558,6 +574,7 @@
 	U3G_DEV(TOSHIBA, G450, 0),
 	U3G_DEV(TOSHIBA, HSDPA, 0),
 	U3G_DEV(YISO, C893, 0),
+	U3G_DEV(WETELECOM, WM_D200, 0),
 	/* Autoinstallers */
 	U3G_DEV(NOVATEL, ZEROCD, U3GINIT_SCSIEJECT),
 	U3G_DEV(OPTION, GTICON322, U3GINIT_REZERO),
@@ -610,7 +627,7 @@
 	static const uint8_t setup[][24] = {
 	     { 0x41, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 	     { 0x41, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	     { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
+	     { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
 	       0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
 	       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 	     { 0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02 },
@@ -622,7 +639,7 @@
 	     { 0x41, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 },
 	     { 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
 	       0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
-	     { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 
+	     { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
 	       0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
 	       0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
 	     { 0x41, 0x12, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -632,7 +649,7 @@
 	     { 0x41, 0x19, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
 	       0x00, 0x00, 0x00, 0x00, 0x11, 0x13 },
 	     { 0x41, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
-	       0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 
+	       0x09, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
 	       0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00 },
 	     { 0x41, 0x07, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 },
 	};
@@ -666,7 +683,7 @@
 				DPRINTFN(0, "too small buffer\n");
 				continue;
 			}
-			err = usbd_do_request(udev, NULL, &req, 
+			err = usbd_do_request(udev, NULL, &req,
 			    __DECONST(uint8_t *, &setup[n][8]));
 		}
 		if (err) {
@@ -725,6 +742,8 @@
 		method = U3GINIT_WAIT;
 	else if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEISCSI))
 		method = U3GINIT_HUAWEISCSI;
+	else if (usb_test_quirk(uaa, UQ_MSC_EJECT_HUAWEISCSI2))
+		method = U3GINIT_HUAWEISCSI2;
 	else if (usb_test_quirk(uaa, UQ_MSC_EJECT_TCT))
 		method = U3GINIT_TCT;
 	else if (usbd_lookup_id_by_uaa(u3g_devs, sizeof(u3g_devs), uaa) == 0)
@@ -745,6 +764,9 @@
 		case U3GINIT_HUAWEISCSI:
 			error = usb_msc_eject(udev, 0, MSC_EJECT_HUAWEI);
 			break;
+		case U3GINIT_HUAWEISCSI2:
+			error = usb_msc_eject(udev, 0, MSC_EJECT_HUAWEI2);
+			break;
 		case U3GINIT_SCSIEJECT:
 			error = usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT);
 			break;
@@ -836,7 +858,7 @@
 	}
 
 	/* copy in USB config */
-	for (n = 0; n != U3G_N_TRANSFER; n++) 
+	for (n = 0; n != U3G_N_TRANSFER; n++)
 		u3g_config_tmp[n] = u3g_config[n];
 
 	device_set_usb_desc(dev);
@@ -887,7 +909,7 @@
 		sc->sc_iface[nports] = id->bInterfaceNumber;
 
 		if (bootverbose && sc->sc_xfer[nports][U3G_INTR]) {
-			device_printf(dev, "port %d supports modem control",
+			device_printf(dev, "port %d supports modem control\n",
 				      nports);
 		}
 
@@ -1009,14 +1031,22 @@
 	struct ucom_softc *ucom = usbd_xfer_softc(xfer);
 	struct usb_page_cache *pc;
 	uint32_t actlen;
+	uint32_t frame;
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 	case USB_ST_SETUP:
 tr_setup:
-		pc = usbd_xfer_get_frame(xfer, 0);
-		if (ucom_get_data(ucom, pc, 0, U3G_BSIZE, &actlen)) {
-			usbd_xfer_set_frame_len(xfer, 0, actlen);
+		for (frame = 0; frame != U3G_TXFRAMES; frame++) {
+			usbd_xfer_set_frame_offset(xfer, frame * U3G_TXSIZE, frame);
+
+			pc = usbd_xfer_get_frame(xfer, frame);
+			if (ucom_get_data(ucom, pc, 0, U3G_TXSIZE, &actlen) == 0)
+				break;
+			usbd_xfer_set_frame_len(xfer, frame, actlen);
+		}
+		if (frame != 0) {
+			usbd_xfer_set_frames(xfer, frame);
 			usbd_transfer_submit(xfer);
 		}
 		break;

Modified: stable/0.8/sys/dev/usb/serial/uark.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uark.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uark.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -15,7 +15,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/serial/uark.c 240659 2012-09-18 16:28:49Z hselasky $
  */
 
 /*

Modified: stable/0.8/sys/dev/usb/serial/ubsa.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ubsa.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ubsa.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ubsa.c 263688 2014-03-24 13:50:11Z emaste $");
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -41,13 +41,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED

Modified: stable/0.8/sys/dev/usb/serial/ubser.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ubser.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ubser.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -48,13 +48,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -70,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ubser.c 263688 2014-03-24 13:50:11Z emaste $");
 
 /*
  * BWCT serial adapter driver

Modified: stable/0.8/sys/dev/usb/serial/uchcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uchcom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uchcom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -41,13 +41,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -63,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uchcom.c 263688 2014-03-24 13:50:11Z emaste $");
 
 /*
  * Driver for WinChipHead CH341/340, the worst USB-serial chip in the

Modified: stable/0.8/sys/dev/usb/serial/ucycom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ucycom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ucycom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ucycom.c 240659 2012-09-18 16:28:49Z hselasky $");
 
 /*-
  * Copyright (c) 2004 Dag-Erling Co\xEFdan Sm\xF8rgrav

Modified: stable/0.8/sys/dev/usb/serial/ufoma.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ufoma.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ufoma.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
 /*	$NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $	*/
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ufoma.c 263688 2014-03-24 13:50:11Z emaste $");
 #define UFOMA_HANDSFREE
 /*-
  * Copyright (c) 2005, Takanori Watanabe
@@ -46,13 +46,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED

Modified: stable/0.8/sys/dev/usb/serial/uftdi.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uftdi.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uftdi.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uftdi.c 283194 2015-05-21 07:50:56Z hselasky $");
 
 /*
  * NOTE: all function names beginning like "uftdi_cfg_" can only
@@ -38,7 +38,14 @@
  */
 
 /*
- * FTDI FT2232x, FT8U100AX and FT8U232AM serial adapter driver
+ * FTDI FT232x, FT2232x, FT4232x, FT8U100AX and FT8U232xM serial adapters.
+ *
+ * Note that we specifically do not do a reset or otherwise alter the state of
+ * the chip during attach, detach, open, and close, because it could be
+ * pre-initialized (via an attached serial eeprom) to power-on into a mode such
+ * as bitbang in which the pins are being driven to a specific state which we
+ * must not perturb.  The device gets reset at power-on, and doesn't need to be
+ * reset again after that to function, except as directed by ioctl() calls.
  */
 
 #include <sys/stdint.h>
@@ -63,6 +70,8 @@
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_ioctl.h>
 #include "usbdevs.h"
 
 #define	USB_DEBUG_VAR uftdi_debug
@@ -71,20 +80,46 @@
 
 #include <dev/usb/serial/usb_serial.h>
 #include <dev/usb/serial/uftdi_reg.h>
+#include <dev/usb/uftdiio.h>
 
+static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
+
 #ifdef USB_DEBUG
 static int uftdi_debug = 0;
-
-static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW, 0, "USB uftdi");
 SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
     &uftdi_debug, 0, "Debug level");
 #endif
 
 #define	UFTDI_CONFIG_INDEX	0
-#define	UFTDI_IFACE_INDEX_JTAG	0
 
-#define	UFTDI_OBUFSIZE 64		/* bytes, cannot be increased due to
-					 * do size encoding */
+/*
+ * IO buffer sizes and FTDI device procotol sizes.
+ *
+ * Note that the output packet size in the following defines is not the usb
+ * protocol packet size based on bus speed, it is the size dictated by the FTDI
+ * device itself, and is used only on older chips.
+ *
+ * We allocate buffers bigger than the hardware's packet size, and process
+ * multiple packets within each buffer.  This allows the controller to make
+ * optimal use of the usb bus by conducting multiple transfers with the device
+ * during a single bus timeslice to fill or drain the chip's fifos.
+ *
+ * The output data on newer chips has no packet header, and we are able to pack
+ * any number of output bytes into a buffer.  On some older chips, each output
+ * packet contains a 1-byte header and up to 63 bytes of payload.  The size is
+ * encoded in 6 bits of the header, hence the 64-byte limit on packet size.  We
+ * loop to fill the buffer with many of these header+payload packets.
+ *
+ * The input data on all chips consists of packets which contain a 2-byte header
+ * followed by data payload.  The total size of the packet is wMaxPacketSize
+ * which can change based on the bus speed (e.g., 64 for full speed, 512 for
+ * high speed).  We loop to extract the headers and payloads from the packets
+ * packed into an input buffer.
+ */
+#define	UFTDI_IBUFSIZE	2048
+#define	UFTDI_IHDRSIZE	   2
+#define	UFTDI_OBUFSIZE	2048
+#define	UFTDI_OPKTSIZE	  64
 
 enum {
 	UFTDI_BULK_DT_WR,
@@ -92,6 +127,21 @@
 	UFTDI_N_TRANSFER,
 };
 
+enum {
+	DEVT_SIO,
+	DEVT_232A,
+	DEVT_232B,
+	DEVT_2232D,	/* Includes 2232C */
+	DEVT_232R,
+	DEVT_2232H,
+	DEVT_4232H,
+	DEVT_232H,
+	DEVT_230X,
+};
+
+#define	DEVF_BAUDBITS_HINDEX	0x01	/* Baud bits in high byte of index. */
+#define	DEVF_BAUDCLK_12M	0X02	/* Base baud clock is 12MHz. */
+
 struct uftdi_softc {
 	struct ucom_super_softc sc_super_ucom;
 	struct ucom_softc sc_ucom;
@@ -104,9 +154,10 @@
 	uint32_t sc_unit;
 
 	uint16_t sc_last_lcr;
+	uint16_t sc_bcdDevice;
 
-	uint8_t sc_type;
-	uint8_t	sc_iface_index;
+	uint8_t sc_devtype;
+	uint8_t sc_devflags;
 	uint8_t	sc_hdrlen;
 	uint8_t	sc_msr;
 	uint8_t	sc_lsr;
@@ -113,7 +164,8 @@
 };
 
 struct uftdi_param_config {
-	uint16_t rate;
+	uint16_t baud_lobits;
+	uint16_t baud_hibits;
 	uint16_t lcr;
 	uint8_t	v_start;
 	uint8_t	v_stop;
@@ -132,20 +184,29 @@
 
 static void	uftdi_free(struct ucom_softc *);
 static void	uftdi_cfg_open(struct ucom_softc *);
+static void	uftdi_cfg_close(struct ucom_softc *);
 static void	uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t);
 static void	uftdi_cfg_set_rts(struct ucom_softc *, uint8_t);
 static void	uftdi_cfg_set_break(struct ucom_softc *, uint8_t);
-static int	uftdi_set_parm_soft(struct termios *,
-		    struct uftdi_param_config *, uint8_t);
+static int	uftdi_set_parm_soft(struct ucom_softc *, struct termios *,
+		    struct uftdi_param_config *);
 static int	uftdi_pre_param(struct ucom_softc *, struct termios *);
 static void	uftdi_cfg_param(struct ucom_softc *, struct termios *);
 static void	uftdi_cfg_get_status(struct ucom_softc *, uint8_t *,
 		    uint8_t *);
+static int	uftdi_reset(struct ucom_softc *, int);
+static int	uftdi_set_bitmode(struct ucom_softc *, uint8_t, uint8_t);
+static int	uftdi_get_bitmode(struct ucom_softc *, uint8_t *);
+static int	uftdi_set_latency(struct ucom_softc *, int);
+static int	uftdi_get_latency(struct ucom_softc *, int *);
+static int	uftdi_set_event_char(struct ucom_softc *, int);
+static int	uftdi_set_error_char(struct ucom_softc *, int);
+static int	uftdi_ioctl(struct ucom_softc *, uint32_t, caddr_t, int,
+		    struct thread *);
 static void	uftdi_start_read(struct ucom_softc *);
 static void	uftdi_stop_read(struct ucom_softc *);
 static void	uftdi_start_write(struct ucom_softc *);
 static void	uftdi_stop_write(struct ucom_softc *);
-static uint8_t	uftdi_8u232am_getrate(uint32_t, uint16_t *);
 static void	uftdi_poll(struct ucom_softc *ucom);
 
 static const struct usb_config uftdi_config[UFTDI_N_TRANSFER] = {
@@ -163,7 +224,7 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = 0,		/* use wMaxPacketSize */
+		.bufsize = UFTDI_IBUFSIZE,
 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
 		.callback = &uftdi_read_callback,
 	},
@@ -176,7 +237,9 @@
 	.ucom_cfg_set_break = &uftdi_cfg_set_break,
 	.ucom_cfg_param = &uftdi_cfg_param,
 	.ucom_cfg_open = &uftdi_cfg_open,
+	.ucom_cfg_close = &uftdi_cfg_close,
 	.ucom_pre_param = &uftdi_pre_param,
+	.ucom_ioctl = &uftdi_ioctl,
 	.ucom_start_read = &uftdi_start_read,
 	.ucom_stop_read = &uftdi_stop_read,
 	.ucom_start_write = &uftdi_start_write,
@@ -209,641 +272,779 @@
 static const STRUCT_USB_HOST_ID uftdi_devs[] = {
 #define	UFTDI_DEV(v, p, i) \
   { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
-	UFTDI_DEV(ACTON, SPECTRAPRO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ALTI2, N3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ANALOGDEVICES, GNICE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(ANALOGDEVICES, GNICEPLUS, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(ATMEL, STK541, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(BAYER, CONTOUR_CABLE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, 232USB9M, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, 485USB9F_2W, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, 485USB9F_4W, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, 485USBTB_2W, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, 485USBTB_4W, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, TTL3USB9M, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, TTL5USB9M, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USO9ML2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USO9ML2DR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USO9ML2DR_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USOPTL4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USOPTL4DR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USOPTL4DR2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USOTL4, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(BBELECTRONICS, USPTL4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, USTL4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(CONTEC, COM1USBH, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(ELEKTOR, FT323R, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(EVOLUTION, ER1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(EVOLUTION, HYBRID, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(EVOLUTION, RCM4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FALCOM, SAMBA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FALCOM, TWIST, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, 232H, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, 232RL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, 4N_GALAXY_DE_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, 4N_GALAXY_DE_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, 8U232AM_ALT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ACCESSO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ACG_HFDUAL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ACTIVE_ROBOTS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ACTZWAVE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, AMC232, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ARTEMIS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ASK_RDR400, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ATIK_ATK16, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ATIK_ATK16C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ATIK_ATK16HR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ATIK_ATK16HRC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ATIK_ATK16IC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, BCS_SE923, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, XDS100V2, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CANDAPTER, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CANUSB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSICDU20_0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSICDU40_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSICDU64_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSLOAD_N_GO_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSMACHX_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CCSPRIME8_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CFA_631, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CFA_632, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CFA_633, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CFA_634, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CFA_635, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CHAMSYS_24_MASTER_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_MAXI_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_MEDIA_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_MIDI_TIMECODE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_MINI_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_PC_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_USB_DMX, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CHAMSYS_WING, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, COM4SM, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CONVERTER_7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, CTI_USB_MINI_485, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, CTI_USB_NANO_485, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, DMX4ALL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, DOMINTELL_DGQG, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, DOMINTELL_DUSB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, DOTEC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ECLO_COM_1WIRE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ECO_PRO_CDS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, EISCOU, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, ELSTER_UNICOM, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_ALC8500, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_CLI7000, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_CSI8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_EC3000, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_EM1000DL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_EM1010PC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_FEM, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_FHZ1000PC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_FHZ1300PC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_FM3RX, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_FS20SIG, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_HS485, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_KL100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_MSM1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_PCD200, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_PCK100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_PPS7330, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_RFP500, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_T1100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_TFD128, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_TFM100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_TWS550, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UAD8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UDA7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UDF77, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UIO88, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_ULA200, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UM100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UMS100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UO100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UR100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_USI2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_USR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_UTP8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS300PC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS444PC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS500, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS550, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS777, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, ELV_WS888, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, EMCU2D, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, EMCU2H, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, FUTURE_0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, FUTURE_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, FUTURE_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GAMMASCOUT, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, GENERIC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E808, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E809, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E80F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E88D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E88E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, GUDEADS_E88F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, HD_RADIO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, HO720, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, HO730, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, HO820, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, HO870, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_APP70, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_PCMCIA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_PEDO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_PICPRO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_PK1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_PROD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_RS232MON, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IBS_US485, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IPLUS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IPLUS2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, IRTRANS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, KBS, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, KTLINK, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, LENZ_LIUSB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, LK202, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, LK204, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, LM3S_DEVEL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, LM3S_EVAL_BOARD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, MASTERDEVEL2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MAXSTREAM, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, MHAM_DB9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_IC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_KW, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_RS232, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_Y6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_Y8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_Y9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MHAM_YS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MICRO_CHAMELEON, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MTXORB_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MTXORB_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, MX2_3, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, MX4_5, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, NXTCAM, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OCEANIC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OOCDLINK, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, OPENDCC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OPENDCC_GATEWAY, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OPENDCC_GBM, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OPENDCC_SNIFFER, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, OPENDCC_THROTTLE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, PCDJ_DAC2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, PCMSFU, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, PERLE_ULTRAPORT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, PHI_FISCO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, PIEGROUP, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, PROPOX_JTAGCABLEII, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, R2000KU_TRUE_RNG, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, R2X0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, RELAIS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, REU_TINY, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, RMP200, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, RM_CANVIEW, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, RRCIRKITS_LOCOBUFFER, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCIENCESCOPE_HS_LOGBOOK, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCIENCESCOPE_LOGBOOKML, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCIENCESCOPE_LS_LOGBOOK, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SCS_DEVICE_7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SDMUSBQSS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SEMC_DSS20, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SERIAL_2232D, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SERIAL_232RL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SERIAL_4232H, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SERIAL_8U100AX, UFTDI_TYPE_SIO),
-	UFTDI_DEV(FTDI, SERIAL_8U232AM, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SERIAL_8U232AM4, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, SIGNALYZER_SH2, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, SIGNALYZER_SH4, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, SIGNALYZER_SLITE, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, SIGNALYZER_ST, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, SPECIAL_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SPECIAL_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SPECIAL_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SPROG_II, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SR_RADIO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, SUUNTO_SPORTS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13M, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13S, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13U, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, TAVIR_STK500, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TERATRONIK_D2XX, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TERATRONIK_VCP, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, THORLABS, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TNC_X, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TTUSB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, TURTELIZER2, UFTDI_TYPE_8U232AM | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(FTDI, UOPTBR, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, USBSERIAL, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, USBX_707, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, USB_UIRT, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(FTDI, USINT_CAT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, USINT_RS232, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, USINT_WKEY, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, VARDAAN, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, VNHCPCUSB_D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, WESTREX_MODEL_777, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, WESTREX_MODEL_8900F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, XF_547, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, XF_640, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, XF_642, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, XM_RADIO, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(FTDI, YEI_SERVOCENTER31, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(GNOTOMETRICS, USB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, SP1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, OPC_U_UC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2C1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2C2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2KVR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2KVT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2VR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP2VT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP4KVR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(ICOM, RP4KVT, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(IDTECH, IDT1221U, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(INTERBIOMETRICS, IOBOARD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(INTERBIOMETRICS, MINI_IOBOARD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(INTREPIDCS, NEOVI, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(INTREPIDCS, VALUECAN, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(IONICS, PLUGCOMPUTER, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(JETI, SPC1201, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(KOBIL, CONV_B1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(KOBIL, CONV_KAAN, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MARVELL, SHEEVAPLUG, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0103, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0104, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0105, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0106, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0107, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0108, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0109, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0110, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0111, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0112, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0113, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0114, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0115, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0116, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0117, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0118, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0119, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0120, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0121, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0122, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0123, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0124, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0125, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0126, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0128, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0129, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0130, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0131, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0132, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0133, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0134, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0135, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0136, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0137, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0138, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0139, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0140, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0141, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0142, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0143, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0144, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0145, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0146, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0147, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0148, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0149, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0150, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0151, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0152, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0159, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0160, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0161, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0162, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0163, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0164, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0165, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0166, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0167, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0168, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0169, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0170, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0171, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0172, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0173, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0174, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0175, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0176, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0177, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0178, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0179, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0180, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0181, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0182, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0183, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0184, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0185, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0186, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0187, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0188, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0189, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0190, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0191, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0192, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0193, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0194, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0195, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0196, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0197, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0198, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0199, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019A, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019D, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019E, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019F, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01ED, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F0, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F9, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FA, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FD, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FF, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MATRIXORBITAL, MOUA, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(MELCO, PCOPRS1, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(METAGEEK, TELLSTICK, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(MOBILITY, USB_SERIAL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(OLIMEX, ARM_USB_OCD, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(OLIMEX, ARM_USB_OCD_H, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(OPTO, CRD7734, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(OPTO, CRD7734_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, AD4USB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, AP485, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, AP485_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, DRAK5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, DRAK6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, GMSR, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, GMUX, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, IRAMP, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, LEC, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, MU, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO10X1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO2X16, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO2X2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO30X3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO3X32, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO4X4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO60X3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, QUIDO8X8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB232, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB422, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB422_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB485, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB485C, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB485S, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SB485_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, SIMUKEY, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, TMU, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(PAPOUCH, UPSUSB, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(POSIFLEX, PP7000, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(QIHARDWARE, JTAGSERIAL, UFTDI_TYPE_AUTO | UFTDI_FLAG_JTAG),
-	UFTDI_DEV(RATOC, REXUSB60F, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(RTSYSTEMS, CT29B, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(RTSYSTEMS, SERIAL_VX7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2101, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2102, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2103, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2104, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2106, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2201_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2201_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2202_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2202_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2203_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2203_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2401_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2401_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2401_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2401_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2402_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2402_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2402_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2402_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2403_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2403_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2403_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2403_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2801_8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2802_8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_1, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_2, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_3, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_4, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_5, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_6, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_7, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SEALEVEL, 2803_8, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SIIG2, DK201, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(SIIG2, US2308, UFTDI_TYPE_8U232AM),
-	UFTDI_DEV(TESTO, USB_INTERFACE, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(TML, USB_SERIAL, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(TTI, QL355P, UFTDI_TYPE_AUTO),
-	UFTDI_DEV(UNKNOWN4, NF_RIC, UFTDI_TYPE_AUTO),
+	UFTDI_DEV(ACTON, SPECTRAPRO, 0),
+	UFTDI_DEV(ALTI2, N3, 0),
+	UFTDI_DEV(ANALOGDEVICES, GNICE, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(ANALOGDEVICES, GNICEPLUS, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(ATMEL, STK541, 0),
+	UFTDI_DEV(BAYER, CONTOUR_CABLE, 0),
+	UFTDI_DEV(BBELECTRONICS, 232USB9M, 0),
+	UFTDI_DEV(BBELECTRONICS, 485USB9F_2W, 0),
+	UFTDI_DEV(BBELECTRONICS, 485USB9F_4W, 0),
+	UFTDI_DEV(BBELECTRONICS, 485USBTB_2W, 0),
+	UFTDI_DEV(BBELECTRONICS, 485USBTB_4W, 0),
+	UFTDI_DEV(BBELECTRONICS, TTL3USB9M, 0),
+	UFTDI_DEV(BBELECTRONICS, TTL5USB9M, 0),
+	UFTDI_DEV(BBELECTRONICS, USO9ML2, 0),
+	UFTDI_DEV(BBELECTRONICS, USO9ML2DR, 0),
+	UFTDI_DEV(BBELECTRONICS, USO9ML2DR_2, 0),
+	UFTDI_DEV(BBELECTRONICS, USOPTL4, 0),
+	UFTDI_DEV(BBELECTRONICS, USOPTL4DR, 0),
+	UFTDI_DEV(BBELECTRONICS, USOPTL4DR2, 0),
+	UFTDI_DEV(BBELECTRONICS, USOTL4, 0),
+	UFTDI_DEV(BBELECTRONICS, USPTL4, 0),
+	UFTDI_DEV(BBELECTRONICS, USTL4, 0),
+	UFTDI_DEV(BBELECTRONICS, ZZ_PROG1_USB, 0),
+	UFTDI_DEV(CONTEC, COM1USBH, 0),
+	UFTDI_DEV(DRESDENELEKTRONIK, SENSORTERMINALBOARD, 0),
+	UFTDI_DEV(DRESDENELEKTRONIK, WIRELESSHANDHELDTERMINAL, 0),
+	UFTDI_DEV(DRESDENELEKTRONIK, DE_RFNODE, 0),
+	UFTDI_DEV(DRESDENELEKTRONIK, LEVELSHIFTERSTICKLOWCOST, 0),
+	UFTDI_DEV(ELEKTOR, FT323R, 0),
+	UFTDI_DEV(EVOLUTION, ER1, 0),
+	UFTDI_DEV(EVOLUTION, HYBRID, 0),
+	UFTDI_DEV(EVOLUTION, RCM4, 0),
+	UFTDI_DEV(FALCOM, SAMBA, 0),
+	UFTDI_DEV(FALCOM, TWIST, 0),
+	UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FIC, NEO1973_DEBUG, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, 232EX, 0),
+	UFTDI_DEV(FTDI, 232H, 0),
+	UFTDI_DEV(FTDI, 232RL, 0),
+	UFTDI_DEV(FTDI, 4N_GALAXY_DE_1, 0),
+	UFTDI_DEV(FTDI, 4N_GALAXY_DE_2, 0),
+	UFTDI_DEV(FTDI, 4N_GALAXY_DE_3, 0),
+	UFTDI_DEV(FTDI, 8U232AM_ALT, 0),
+	UFTDI_DEV(FTDI, ACCESSO, 0),
+	UFTDI_DEV(FTDI, ACG_HFDUAL, 0),
+	UFTDI_DEV(FTDI, ACTIVE_ROBOTS, 0),
+	UFTDI_DEV(FTDI, ACTZWAVE, 0),
+	UFTDI_DEV(FTDI, AMC232, 0),
+	UFTDI_DEV(FTDI, ARTEMIS, 0),
+	UFTDI_DEV(FTDI, ASK_RDR400, 0),
+	UFTDI_DEV(FTDI, ATIK_ATK16, 0),
+	UFTDI_DEV(FTDI, ATIK_ATK16C, 0),
+	UFTDI_DEV(FTDI, ATIK_ATK16HR, 0),
+	UFTDI_DEV(FTDI, ATIK_ATK16HRC, 0),
+	UFTDI_DEV(FTDI, ATIK_ATK16IC, 0),
+	UFTDI_DEV(FTDI, BCS_SE923, 0),
+	UFTDI_DEV(FTDI, CANDAPTER, 0),
+	UFTDI_DEV(FTDI, CANUSB, 0),
+	UFTDI_DEV(FTDI, CCSICDU20_0, 0),
+	UFTDI_DEV(FTDI, CCSICDU40_1, 0),
+	UFTDI_DEV(FTDI, CCSICDU64_4, 0),
+	UFTDI_DEV(FTDI, CCSLOAD_N_GO_3, 0),
+	UFTDI_DEV(FTDI, CCSMACHX_2, 0),
+	UFTDI_DEV(FTDI, CCSPRIME8_5, 0),
+	UFTDI_DEV(FTDI, CFA_631, 0),
+	UFTDI_DEV(FTDI, CFA_632, 0),
+	UFTDI_DEV(FTDI, CFA_633, 0),
+	UFTDI_DEV(FTDI, CFA_634, 0),
+	UFTDI_DEV(FTDI, CFA_635, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_24_MASTER_WING, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_MAXI_WING, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_MEDIA_WING, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_MIDI_TIMECODE, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_MINI_WING, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_PC_WING, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_USB_DMX, 0),
+	UFTDI_DEV(FTDI, CHAMSYS_WING, 0),
+	UFTDI_DEV(FTDI, COM4SM, 0),
+	UFTDI_DEV(FTDI, CONVERTER_0, 0),
+	UFTDI_DEV(FTDI, CONVERTER_1, 0),
+	UFTDI_DEV(FTDI, CONVERTER_2, 0),
+	UFTDI_DEV(FTDI, CONVERTER_3, 0),
+	UFTDI_DEV(FTDI, CONVERTER_4, 0),
+	UFTDI_DEV(FTDI, CONVERTER_5, 0),
+	UFTDI_DEV(FTDI, CONVERTER_6, 0),
+	UFTDI_DEV(FTDI, CONVERTER_7, 0),
+	UFTDI_DEV(FTDI, CTI_USB_MINI_485, 0),
+	UFTDI_DEV(FTDI, CTI_USB_NANO_485, 0),
+	UFTDI_DEV(FTDI, DMX4ALL, 0),
+	UFTDI_DEV(FTDI, DOMINTELL_DGQG, 0),
+	UFTDI_DEV(FTDI, DOMINTELL_DUSB, 0),
+	UFTDI_DEV(FTDI, DOTEC, 0),
+	UFTDI_DEV(FTDI, ECLO_COM_1WIRE, 0),
+	UFTDI_DEV(FTDI, ECO_PRO_CDS, 0),
+	UFTDI_DEV(FTDI, EISCOU, 0),
+	UFTDI_DEV(FTDI, ELSTER_UNICOM, 0),
+	UFTDI_DEV(FTDI, ELV_ALC8500, 0),
+	UFTDI_DEV(FTDI, ELV_CLI7000, 0),
+	UFTDI_DEV(FTDI, ELV_CSI8, 0),
+	UFTDI_DEV(FTDI, ELV_EC3000, 0),
+	UFTDI_DEV(FTDI, ELV_EM1000DL, 0),
+	UFTDI_DEV(FTDI, ELV_EM1010PC, 0),
+	UFTDI_DEV(FTDI, ELV_FEM, 0),
+	UFTDI_DEV(FTDI, ELV_FHZ1000PC, 0),
+	UFTDI_DEV(FTDI, ELV_FHZ1300PC, 0),
+	UFTDI_DEV(FTDI, ELV_FM3RX, 0),
+	UFTDI_DEV(FTDI, ELV_FS20SIG, 0),
+	UFTDI_DEV(FTDI, ELV_HS485, 0),
+	UFTDI_DEV(FTDI, ELV_KL100, 0),
+	UFTDI_DEV(FTDI, ELV_MSM1, 0),
+	UFTDI_DEV(FTDI, ELV_PCD200, 0),
+	UFTDI_DEV(FTDI, ELV_PCK100, 0),
+	UFTDI_DEV(FTDI, ELV_PPS7330, 0),
+	UFTDI_DEV(FTDI, ELV_RFP500, 0),
+	UFTDI_DEV(FTDI, ELV_T1100, 0),
+	UFTDI_DEV(FTDI, ELV_TFD128, 0),
+	UFTDI_DEV(FTDI, ELV_TFM100, 0),
+	UFTDI_DEV(FTDI, ELV_TWS550, 0),
+	UFTDI_DEV(FTDI, ELV_UAD8, 0),
+	UFTDI_DEV(FTDI, ELV_UDA7, 0),
+	UFTDI_DEV(FTDI, ELV_UDF77, 0),
+	UFTDI_DEV(FTDI, ELV_UIO88, 0),
+	UFTDI_DEV(FTDI, ELV_ULA200, 0),
+	UFTDI_DEV(FTDI, ELV_UM100, 0),
+	UFTDI_DEV(FTDI, ELV_UMS100, 0),
+	UFTDI_DEV(FTDI, ELV_UO100, 0),
+	UFTDI_DEV(FTDI, ELV_UR100, 0),
+	UFTDI_DEV(FTDI, ELV_USI2, 0),
+	UFTDI_DEV(FTDI, ELV_USR, 0),
+	UFTDI_DEV(FTDI, ELV_UTP8, 0),
+	UFTDI_DEV(FTDI, ELV_WS300PC, 0),
+	UFTDI_DEV(FTDI, ELV_WS444PC, 0),
+	UFTDI_DEV(FTDI, ELV_WS500, 0),
+	UFTDI_DEV(FTDI, ELV_WS550, 0),
+	UFTDI_DEV(FTDI, ELV_WS777, 0),
+	UFTDI_DEV(FTDI, ELV_WS888, 0),
+	UFTDI_DEV(FTDI, EMCU2D, 0),
+	UFTDI_DEV(FTDI, EMCU2H, 0),
+	UFTDI_DEV(FTDI, FUTURE_0, 0),
+	UFTDI_DEV(FTDI, FUTURE_1, 0),
+	UFTDI_DEV(FTDI, FUTURE_2, 0),
+	UFTDI_DEV(FTDI, GAMMASCOUT, 0),
+	UFTDI_DEV(FTDI, GENERIC, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E808, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E809, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80A, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80B, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80C, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80D, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80E, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E80F, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E88D, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E88E, 0),
+	UFTDI_DEV(FTDI, GUDEADS_E88F, 0),
+	UFTDI_DEV(FTDI, HD_RADIO, 0),
+	UFTDI_DEV(FTDI, HO720, 0),
+	UFTDI_DEV(FTDI, HO730, 0),
+	UFTDI_DEV(FTDI, HO820, 0),
+	UFTDI_DEV(FTDI, HO870, 0),
+	UFTDI_DEV(FTDI, IBS_APP70, 0),
+	UFTDI_DEV(FTDI, IBS_PCMCIA, 0),
+	UFTDI_DEV(FTDI, IBS_PEDO, 0),
+	UFTDI_DEV(FTDI, IBS_PICPRO, 0),
+	UFTDI_DEV(FTDI, IBS_PK1, 0),
+	UFTDI_DEV(FTDI, IBS_PROD, 0),
+	UFTDI_DEV(FTDI, IBS_RS232MON, 0),
+	UFTDI_DEV(FTDI, IBS_US485, 0),
+	UFTDI_DEV(FTDI, IPLUS, 0),
+	UFTDI_DEV(FTDI, IPLUS2, 0),
+	UFTDI_DEV(FTDI, IRTRANS, 0),
+	UFTDI_DEV(FTDI, KBS, 0),
+	UFTDI_DEV(FTDI, KTLINK, 0),
+	UFTDI_DEV(FTDI, LENZ_LIUSB, 0),
+	UFTDI_DEV(FTDI, LK202, 0),
+	UFTDI_DEV(FTDI, LK204, 0),
+	UFTDI_DEV(FTDI, LM3S_DEVEL_BOARD, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, LM3S_EVAL_BOARD, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, LM3S_ICDI_B_BOARD, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, MASTERDEVEL2, 0),
+	UFTDI_DEV(FTDI, MAXSTREAM, 0),
+	UFTDI_DEV(FTDI, MHAM_DB9, 0),
+	UFTDI_DEV(FTDI, MHAM_IC, 0),
+	UFTDI_DEV(FTDI, MHAM_KW, 0),
+	UFTDI_DEV(FTDI, MHAM_RS232, 0),
+	UFTDI_DEV(FTDI, MHAM_Y6, 0),
+	UFTDI_DEV(FTDI, MHAM_Y8, 0),
+	UFTDI_DEV(FTDI, MHAM_Y9, 0),
+	UFTDI_DEV(FTDI, MHAM_YS, 0),
+	UFTDI_DEV(FTDI, MICRO_CHAMELEON, 0),
+	UFTDI_DEV(FTDI, MTXORB_5, 0),
+	UFTDI_DEV(FTDI, MTXORB_6, 0),
+	UFTDI_DEV(FTDI, MX2_3, 0),
+	UFTDI_DEV(FTDI, MX4_5, 0),
+	UFTDI_DEV(FTDI, NXTCAM, 0),
+	UFTDI_DEV(FTDI, OCEANIC, 0),
+	UFTDI_DEV(FTDI, OOCDLINK, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, OPENDCC, 0),
+	UFTDI_DEV(FTDI, OPENDCC_GATEWAY, 0),
+	UFTDI_DEV(FTDI, OPENDCC_GBM, 0),
+	UFTDI_DEV(FTDI, OPENDCC_SNIFFER, 0),
+	UFTDI_DEV(FTDI, OPENDCC_THROTTLE, 0),
+	UFTDI_DEV(FTDI, PCDJ_DAC2, 0),
+	UFTDI_DEV(FTDI, PCMSFU, 0),
+	UFTDI_DEV(FTDI, PERLE_ULTRAPORT, 0),
+	UFTDI_DEV(FTDI, PHI_FISCO, 0),
+	UFTDI_DEV(FTDI, PIEGROUP, 0),
+	UFTDI_DEV(FTDI, PROPOX_JTAGCABLEII, 0),
+	UFTDI_DEV(FTDI, R2000KU_TRUE_RNG, 0),
+	UFTDI_DEV(FTDI, R2X0, 0),
+	UFTDI_DEV(FTDI, RELAIS, 0),
+	UFTDI_DEV(FTDI, REU_TINY, 0),
+	UFTDI_DEV(FTDI, RMP200, 0),
+	UFTDI_DEV(FTDI, RM_CANVIEW, 0),
+	UFTDI_DEV(FTDI, RRCIRKITS_LOCOBUFFER, 0),
+	UFTDI_DEV(FTDI, SCIENCESCOPE_HS_LOGBOOK, 0),
+	UFTDI_DEV(FTDI, SCIENCESCOPE_LOGBOOKML, 0),
+	UFTDI_DEV(FTDI, SCIENCESCOPE_LS_LOGBOOK, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_0, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_1, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_2, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_3, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_4, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_5, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_6, 0),
+	UFTDI_DEV(FTDI, SCS_DEVICE_7, 0),
+	UFTDI_DEV(FTDI, SCX8_USB_PHOENIX, 0),
+	UFTDI_DEV(FTDI, SDMUSBQSS, 0),
+	UFTDI_DEV(FTDI, SEMC_DSS20, 0),
+	UFTDI_DEV(FTDI, SERIAL_2232C, UFTDI_JTAG_CHECK_STRING),
+	UFTDI_DEV(FTDI, SERIAL_2232D, 0),
+	UFTDI_DEV(FTDI, SERIAL_232RL, 0),
+	UFTDI_DEV(FTDI, SERIAL_4232H, 0),
+	UFTDI_DEV(FTDI, SERIAL_8U100AX, 0),
+	UFTDI_DEV(FTDI, SERIAL_8U232AM, 0),
+	UFTDI_DEV(FTDI, SERIAL_8U232AM4, 0),
+	UFTDI_DEV(FTDI, SIGNALYZER_SH2, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, SIGNALYZER_SH4, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, SIGNALYZER_SLITE, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, SIGNALYZER_ST, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, SPECIAL_1, 0),
+	UFTDI_DEV(FTDI, SPECIAL_3, 0),
+	UFTDI_DEV(FTDI, SPECIAL_4, 0),
+	UFTDI_DEV(FTDI, SPROG_II, 0),
+	UFTDI_DEV(FTDI, SR_RADIO, 0),
+	UFTDI_DEV(FTDI, SUUNTO_SPORTS, 0),
+	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13M, 0),
+	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13S, 0),
+	UFTDI_DEV(FTDI, TACTRIX_OPENPORT_13U, 0),
+	UFTDI_DEV(FTDI, TAVIR_STK500, 0),
+	UFTDI_DEV(FTDI, TERATRONIK_D2XX, 0),
+	UFTDI_DEV(FTDI, TERATRONIK_VCP, 0),
+	UFTDI_DEV(FTDI, THORLABS, 0),
+	UFTDI_DEV(FTDI, TNC_X, 0),
+	UFTDI_DEV(FTDI, TTUSB, 0),
+	UFTDI_DEV(FTDI, TURTELIZER2, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, UOPTBR, 0),
+	UFTDI_DEV(FTDI, USBSERIAL, 0),
+	UFTDI_DEV(FTDI, USBX_707, 0),
+	UFTDI_DEV(FTDI, USB_UIRT, 0),
+	UFTDI_DEV(FTDI, USINT_CAT, 0),
+	UFTDI_DEV(FTDI, USINT_RS232, 0),
+	UFTDI_DEV(FTDI, USINT_WKEY, 0),
+	UFTDI_DEV(FTDI, VARDAAN, 0),
+	UFTDI_DEV(FTDI, VNHCPCUSB_D, 0),
+	UFTDI_DEV(FTDI, WESTREX_MODEL_777, 0),
+	UFTDI_DEV(FTDI, WESTREX_MODEL_8900F, 0),
+	UFTDI_DEV(FTDI, XDS100V2, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, XDS100V3, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(FTDI, XF_547, 0),
+	UFTDI_DEV(FTDI, XF_640, 0),
+	UFTDI_DEV(FTDI, XF_642, 0),
+	UFTDI_DEV(FTDI, XM_RADIO, 0),
+	UFTDI_DEV(FTDI, YEI_SERVOCENTER31, 0),
+	UFTDI_DEV(GNOTOMETRICS, USB, 0),
+	UFTDI_DEV(ICOM, SP1, 0),
+	UFTDI_DEV(ICOM, OPC_U_UC, 0),
+	UFTDI_DEV(ICOM, RP2C1, 0),
+	UFTDI_DEV(ICOM, RP2C2, 0),
+	UFTDI_DEV(ICOM, RP2D, 0),
+	UFTDI_DEV(ICOM, RP2KVR, 0),
+	UFTDI_DEV(ICOM, RP2KVT, 0),
+	UFTDI_DEV(ICOM, RP2VR, 0),
+	UFTDI_DEV(ICOM, RP2VT, 0),
+	UFTDI_DEV(ICOM, RP4KVR, 0),
+	UFTDI_DEV(ICOM, RP4KVT, 0),
+	UFTDI_DEV(IDTECH, IDT1221U, 0),
+	UFTDI_DEV(INTERBIOMETRICS, IOBOARD, 0),
+	UFTDI_DEV(INTERBIOMETRICS, MINI_IOBOARD, 0),
+	UFTDI_DEV(INTREPIDCS, NEOVI, 0),
+	UFTDI_DEV(INTREPIDCS, VALUECAN, 0),
+	UFTDI_DEV(IONICS, PLUGCOMPUTER, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(JETI, SPC1201, 0),
+	UFTDI_DEV(KOBIL, CONV_B1, 0),
+	UFTDI_DEV(KOBIL, CONV_KAAN, 0),
+	UFTDI_DEV(LARSENBRUSGAARD, ALTITRACK, 0),
+	UFTDI_DEV(MARVELL, SHEEVAPLUG, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0100, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0101, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0102, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0103, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0104, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0105, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0106, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0107, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0108, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0109, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_010F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0110, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0111, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0112, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0113, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0114, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0115, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0116, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0117, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0118, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0119, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_011F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0120, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0121, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0122, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0123, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0124, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0125, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0126, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0128, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0129, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_012F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0130, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0131, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0132, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0133, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0134, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0135, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0136, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0137, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0138, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0139, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_013F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0140, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0141, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0142, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0143, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0144, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0145, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0146, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0147, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0148, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0149, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_014F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0150, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0151, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0152, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0159, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_015F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0160, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0161, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0162, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0163, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0164, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0165, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0166, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0167, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0168, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0169, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_016F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0170, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0171, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0172, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0173, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0174, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0175, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0176, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0177, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0178, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0179, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_017F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0180, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0181, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0182, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0183, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0184, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0185, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0186, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0187, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0188, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0189, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_018F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0190, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0191, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0192, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0193, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0194, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0195, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0196, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0197, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0198, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_0199, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019A, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019B, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019C, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019D, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019E, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_019F, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01A9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AD, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01AF, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01B9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BD, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01BF, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01C9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CD, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01CF, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01D9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DD, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01DF, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01E9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01ED, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01EF, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F0, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F1, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F2, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F3, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F4, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F5, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F6, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F7, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F8, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01F9, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FA, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FB, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FC, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FD, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FE, 0),
+	UFTDI_DEV(MATRIXORBITAL, FTDI_RANGE_01FF, 0),
+	UFTDI_DEV(MATRIXORBITAL, MOUA, 0),
+	UFTDI_DEV(MELCO, PCOPRS1, 0),
+	UFTDI_DEV(METAGEEK, TELLSTICK, 0),
+	UFTDI_DEV(MOBILITY, USB_SERIAL, 0),
+	UFTDI_DEV(OLIMEX, ARM_USB_OCD, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(OLIMEX, ARM_USB_OCD_H, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(OPTO, CRD7734, 0),
+	UFTDI_DEV(OPTO, CRD7734_1, 0),
+	UFTDI_DEV(PAPOUCH, AD4USB, 0),
+	UFTDI_DEV(PAPOUCH, AP485, 0),
+	UFTDI_DEV(PAPOUCH, AP485_2, 0),
+	UFTDI_DEV(PAPOUCH, DRAK5, 0),
+	UFTDI_DEV(PAPOUCH, DRAK6, 0),
+	UFTDI_DEV(PAPOUCH, GMSR, 0),
+	UFTDI_DEV(PAPOUCH, GMUX, 0),
+	UFTDI_DEV(PAPOUCH, IRAMP, 0),
+	UFTDI_DEV(PAPOUCH, LEC, 0),
+	UFTDI_DEV(PAPOUCH, MU, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO10X1, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO2X16, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO2X2, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO30X3, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO3X32, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO4X4, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO60X3, 0),
+	UFTDI_DEV(PAPOUCH, QUIDO8X8, 0),
+	UFTDI_DEV(PAPOUCH, SB232, 0),
+	UFTDI_DEV(PAPOUCH, SB422, 0),
+	UFTDI_DEV(PAPOUCH, SB422_2, 0),
+	UFTDI_DEV(PAPOUCH, SB485, 0),
+	UFTDI_DEV(PAPOUCH, SB485C, 0),
+	UFTDI_DEV(PAPOUCH, SB485S, 0),
+	UFTDI_DEV(PAPOUCH, SB485_2, 0),
+	UFTDI_DEV(PAPOUCH, SIMUKEY, 0),
+	UFTDI_DEV(PAPOUCH, TMU, 0),
+	UFTDI_DEV(PAPOUCH, UPSUSB, 0),
+	UFTDI_DEV(POSIFLEX, PP7000, 0),
+	UFTDI_DEV(QIHARDWARE, JTAGSERIAL, UFTDI_JTAG_IFACE(0)),
+	UFTDI_DEV(RATOC, REXUSB60F, 0),
+	UFTDI_DEV(RTSYSTEMS, CT29B, 0),
+	UFTDI_DEV(RTSYSTEMS, SERIAL_VX7, 0),
+	UFTDI_DEV(SEALEVEL, 2101, 0),
+	UFTDI_DEV(SEALEVEL, 2102, 0),
+	UFTDI_DEV(SEALEVEL, 2103, 0),
+	UFTDI_DEV(SEALEVEL, 2104, 0),
+	UFTDI_DEV(SEALEVEL, 2106, 0),
+	UFTDI_DEV(SEALEVEL, 2201_1, 0),
+	UFTDI_DEV(SEALEVEL, 2201_2, 0),
+	UFTDI_DEV(SEALEVEL, 2202_1, 0),
+	UFTDI_DEV(SEALEVEL, 2202_2, 0),
+	UFTDI_DEV(SEALEVEL, 2203_1, 0),
+	UFTDI_DEV(SEALEVEL, 2203_2, 0),
+	UFTDI_DEV(SEALEVEL, 2401_1, 0),
+	UFTDI_DEV(SEALEVEL, 2401_2, 0),
+	UFTDI_DEV(SEALEVEL, 2401_3, 0),
+	UFTDI_DEV(SEALEVEL, 2401_4, 0),
+	UFTDI_DEV(SEALEVEL, 2402_1, 0),
+	UFTDI_DEV(SEALEVEL, 2402_2, 0),
+	UFTDI_DEV(SEALEVEL, 2402_3, 0),
+	UFTDI_DEV(SEALEVEL, 2402_4, 0),
+	UFTDI_DEV(SEALEVEL, 2403_1, 0),
+	UFTDI_DEV(SEALEVEL, 2403_2, 0),
+	UFTDI_DEV(SEALEVEL, 2403_3, 0),
+	UFTDI_DEV(SEALEVEL, 2403_4, 0),
+	UFTDI_DEV(SEALEVEL, 2801_1, 0),
+	UFTDI_DEV(SEALEVEL, 2801_2, 0),
+	UFTDI_DEV(SEALEVEL, 2801_3, 0),
+	UFTDI_DEV(SEALEVEL, 2801_4, 0),
+	UFTDI_DEV(SEALEVEL, 2801_5, 0),
+	UFTDI_DEV(SEALEVEL, 2801_6, 0),
+	UFTDI_DEV(SEALEVEL, 2801_7, 0),
+	UFTDI_DEV(SEALEVEL, 2801_8, 0),
+	UFTDI_DEV(SEALEVEL, 2802_1, 0),
+	UFTDI_DEV(SEALEVEL, 2802_2, 0),
+	UFTDI_DEV(SEALEVEL, 2802_3, 0),
+	UFTDI_DEV(SEALEVEL, 2802_4, 0),
+	UFTDI_DEV(SEALEVEL, 2802_5, 0),
+	UFTDI_DEV(SEALEVEL, 2802_6, 0),
+	UFTDI_DEV(SEALEVEL, 2802_7, 0),
+	UFTDI_DEV(SEALEVEL, 2802_8, 0),
+	UFTDI_DEV(SEALEVEL, 2803_1, 0),
+	UFTDI_DEV(SEALEVEL, 2803_2, 0),
+	UFTDI_DEV(SEALEVEL, 2803_3, 0),
+	UFTDI_DEV(SEALEVEL, 2803_4, 0),
+	UFTDI_DEV(SEALEVEL, 2803_5, 0),
+	UFTDI_DEV(SEALEVEL, 2803_6, 0),
+	UFTDI_DEV(SEALEVEL, 2803_7, 0),
+	UFTDI_DEV(SEALEVEL, 2803_8, 0),
+	UFTDI_DEV(SIIG2, DK201, 0),
+	UFTDI_DEV(SIIG2, US2308, 0),
+	UFTDI_DEV(TESTO, USB_INTERFACE, 0),
+	UFTDI_DEV(TML, USB_SERIAL, 0),
+	UFTDI_DEV(TTI, QL355P, 0),
+	UFTDI_DEV(UNKNOWN4, NF_RIC, 0),
 #undef UFTDI_DEV
 };
 
+/*
+ * Jtag product name strings table.  Some products have one or more interfaces
+ * dedicated to jtag or gpio, but use a product ID that's the same as other
+ * products which don't.  They are marked with a flag in the table above, and
+ * the following string table is checked for flagged products.  The string check
+ * is done with strstr(); in effect there is an implicit wildcard at the
+ * beginning and end of each product name string in table.
+ */
+static const struct jtag_by_name {
+	const char *	product_name;
+	uint32_t	jtag_interfaces;
+} jtag_products_by_name[] = {
+        /* TI Beaglebone and TI XDS100Vn jtag product line. */
+	{"XDS100V",	UFTDI_JTAG_IFACE(0)},
+};
+
+/*
+ * Set up a sysctl and tunable to en/disable the feature of skipping the
+ * creation of tty devices for jtag interfaces.  Enabled by default.
+ */
+static int skip_jtag_interfaces = 1;
+TUNABLE_INT("hw.usb.uftdi.skip_jtag_interfaces", &skip_jtag_interfaces);
+SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, skip_jtag_interfaces, CTLFLAG_RWTUN,
+    &skip_jtag_interfaces, 1, "Skip creating tty devices for jtag interfaces");
+
+static boolean_t
+is_jtag_interface(struct usb_attach_arg *uaa, const struct usb_device_id *id)
+{
+	int i, iface_bit;
+	const char * product_name;
+	const struct jtag_by_name *jbn;
+
+	/* We only allocate 8 flag bits for jtag interface flags. */
+	if (uaa->info.bIfaceIndex >= UFTDI_JTAG_IFACES_MAX)
+		return (0);
+	iface_bit = UFTDI_JTAG_IFACE(uaa->info.bIfaceIndex);
+
+	/*
+	 * If requested, search the name strings table and use the interface
+	 * bits from that table when the product name string matches, else use
+	 * the jtag interface bits from the main ID table.
+	 */
+	if ((id->driver_info & UFTDI_JTAG_MASK) == UFTDI_JTAG_CHECK_STRING) {
+		product_name = usb_get_product(uaa->device);
+		for (i = 0; i < nitems(jtag_products_by_name); i++) {
+			jbn = &jtag_products_by_name[i];
+			if (strstr(product_name, jbn->product_name) != NULL &&
+			    (jbn->jtag_interfaces & iface_bit) != 0)
+				return (1);
+		}
+	} else if ((id->driver_info & iface_bit) != 0)
+		return (1);
+
+	return (0);
+}
+
+/*
+ * Set up softc fields whose value depends on the device type.
+ *
+ * Note that the 2232C and 2232D devices are the same for our purposes.  In the
+ * silicon the difference is that the D series has CPU FIFO mode and C doesn't.
+ * I haven't found any way of determining the C/D difference from info provided
+ * by the chip other than trying to set CPU FIFO mode and having it work or not.
+ * 
+ * Due to a hardware bug, a 232B chip without an eeprom reports itself as a 
+ * 232A, but if the serial number is also zero we know it's really a 232B. 
+ */
+static void
+uftdi_devtype_setup(struct uftdi_softc *sc, struct usb_attach_arg *uaa)
+{
+	struct usb_device_descriptor *dd;
+
+	sc->sc_bcdDevice = uaa->info.bcdDevice;
+
+	switch (uaa->info.bcdDevice) {
+	case 0x200:
+		dd = usbd_get_device_descriptor(sc->sc_udev);
+		if (dd->iSerialNumber == 0) {
+			sc->sc_devtype = DEVT_232B;
+		} else {
+			sc->sc_devtype = DEVT_232A;
+		}
+		sc->sc_ucom.sc_portno = 0;
+		break;
+	case 0x400:
+		sc->sc_devtype = DEVT_232B;
+		sc->sc_ucom.sc_portno = 0;
+		break;
+	case 0x500:
+		sc->sc_devtype = DEVT_2232D;
+		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
+		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+		break;
+	case 0x600:
+		sc->sc_devtype = DEVT_232R;
+		sc->sc_ucom.sc_portno = 0;
+		break;
+	case 0x700:
+		sc->sc_devtype = DEVT_2232H;
+		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+		break;
+	case 0x800:
+		sc->sc_devtype = DEVT_4232H;
+		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+		break;
+	case 0x900:
+		sc->sc_devtype = DEVT_232H;
+		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX | DEVF_BAUDCLK_12M;
+		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+		break;
+	case 0x1000:
+		sc->sc_devtype = DEVT_230X;
+		sc->sc_devflags |= DEVF_BAUDBITS_HINDEX;
+		sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
+		break;
+	default:
+		if (uaa->info.bcdDevice < 0x200) {
+			sc->sc_devtype = DEVT_SIO;
+			sc->sc_hdrlen = 1;
+		} else {
+			sc->sc_devtype = DEVT_232R;
+			device_printf(sc->sc_dev, "Warning: unknown FTDI "
+			    "device type, bcdDevice=0x%04x, assuming 232R\n", 
+			    uaa->info.bcdDevice);
+		}
+		sc->sc_ucom.sc_portno = 0;
+		break;
+	}
+}
+
 static int
 uftdi_probe(device_t dev)
 {
@@ -865,10 +1066,12 @@
 	    &uaa->info);
 	if (id == NULL)
 		return (ENXIO);
-	if ((id->driver_info & UFTDI_FLAG_JTAG) != 0 &&
-	    uaa->info.bIfaceIndex == UFTDI_IFACE_INDEX_JTAG) {
-		printf("%s: skipping JTAG interface at %u.%u\n",
-		    device_get_name(dev), usbd_get_bus_index(uaa->device),
+	if (skip_jtag_interfaces && is_jtag_interface(uaa, id)) {
+		printf("%s: skipping JTAG interface #%d for '%s' at %u.%u\n",
+		    device_get_name(dev),
+		    uaa->info.bIfaceIndex,
+		    usb_get_product(uaa->device),
+		    usbd_get_bus_index(uaa->device),
 		    usbd_get_device_index(uaa->device));
 		return (ENXIO);
 	}
@@ -883,6 +1086,8 @@
 	struct uftdi_softc *sc = device_get_softc(dev);
 	int error;
 
+	DPRINTF("\n");
+
 	sc->sc_udev = uaa->device;
 	sc->sc_dev = dev;
 	sc->sc_unit = device_get_unit(dev);
@@ -891,34 +1096,11 @@
 	mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
 	ucom_ref(&sc->sc_super_ucom);
 
-	DPRINTF("\n");
 
-	sc->sc_iface_index = uaa->info.bIfaceIndex;
-	sc->sc_type = USB_GET_DRIVER_INFO(uaa) & UFTDI_TYPE_MASK;
+	uftdi_devtype_setup(sc, uaa);
 
-	switch (sc->sc_type) {
-	case UFTDI_TYPE_AUTO:
-		/* simplified type check */
-		if (uaa->info.bcdDevice >= 0x0200 ||
-		    usbd_get_iface(uaa->device, 1) != NULL) {
-			sc->sc_type = UFTDI_TYPE_8U232AM;
-			sc->sc_hdrlen = 0;
-		} else {
-			sc->sc_type = UFTDI_TYPE_SIO;
-			sc->sc_hdrlen = 1;
-		}
-		break;
-	case UFTDI_TYPE_SIO:
-		sc->sc_hdrlen = 1;
-		break;
-	case UFTDI_TYPE_8U232AM:
-	default:
-		sc->sc_hdrlen = 0;
-		break;
-	}
-
 	error = usbd_transfer_setup(uaa->device,
-	    &sc->sc_iface_index, sc->sc_xfer, uftdi_config,
+	    &uaa->info.bIfaceIndex, sc->sc_xfer, uftdi_config,
 	    UFTDI_N_TRANSFER, sc, &sc->sc_mtx);
 
 	if (error) {
@@ -926,8 +1108,6 @@
 		    "transfers failed\n");
 		goto detach;
 	}
-	sc->sc_ucom.sc_portno = FTDI_PIT_SIOA + uaa->info.bIfaceNum;
-
 	/* clear stall at first run */
 	mtx_lock(&sc->sc_mtx);
 	usbd_xfer_set_stall(sc->sc_xfer[UFTDI_BULK_DT_WR]);
@@ -990,37 +1170,25 @@
 static void
 uftdi_cfg_open(struct ucom_softc *ucom)
 {
-	struct uftdi_softc *sc = ucom->sc_parent;
-	uint16_t wIndex = ucom->sc_portno;
-	struct usb_device_request req;
 
+	/*
+	 * This do-nothing open routine exists for the sole purpose of this
+	 * DPRINTF() so that you can see the point at which open gets called
+	 * when debugging is enabled.
+	 */
 	DPRINTF("");
+}
 
-	/* perform a full reset on the device */
+static void
+uftdi_cfg_close(struct ucom_softc *ucom)
+{
 
-	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-	req.bRequest = FTDI_SIO_RESET;
-	USETW(req.wValue, FTDI_SIO_RESET_SIO);
-	USETW(req.wIndex, wIndex);
-	USETW(req.wLength, 0);
-	ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000);
-
-	/* turn on RTS/CTS flow control */
-
-	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-	req.bRequest = FTDI_SIO_SET_FLOW_CTRL;
-	USETW(req.wValue, 0);
-	USETW2(req.wIndex, FTDI_SIO_RTS_CTS_HS, wIndex);
-	USETW(req.wLength, 0);
-	ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000);
-
 	/*
-	 * NOTE: with the new UCOM layer there will always be a
-	 * "uftdi_cfg_param()" call after "open()", so there is no need for
-	 * "open()" to configure anything
+	 * This do-nothing close routine exists for the sole purpose of this
+	 * DPRINTF() so that you can see the point at which close gets called
+	 * when debugging is enabled.
 	 */
+	DPRINTF("");
 }
 
 static void
@@ -1028,35 +1196,53 @@
 {
 	struct uftdi_softc *sc = usbd_xfer_softc(xfer);
 	struct usb_page_cache *pc;
-	uint32_t actlen;
+	uint32_t pktlen;
+	uint32_t buflen;
 	uint8_t buf[1];
 
 	switch (USB_GET_STATE(xfer)) {
+	default:			/* Error */
+		if (error != USB_ERR_CANCELLED) {
+			/* try to clear stall first */
+			usbd_xfer_set_stall(xfer);
+		}
+		/* FALLTHROUGH */
 	case USB_ST_SETUP:
 	case USB_ST_TRANSFERRED:
-tr_setup:
+		/*
+		 * If output packets don't require headers (the common case) we
+		 * can just load the buffer up with payload bytes all at once.
+		 * Otherwise, loop to format packets into the buffer while there
+		 * is data available, and room for a packet header and at least
+		 * one byte of payload.
+		 *
+		 * NOTE: The FTDI chip doesn't accept zero length
+		 * packets. This cannot happen because the "pktlen"
+		 * will always be non-zero when "ucom_get_data()"
+		 * returns non-zero which we check below.
+		 */
 		pc = usbd_xfer_get_frame(xfer, 0);
-		if (ucom_get_data(&sc->sc_ucom, pc,
-		    sc->sc_hdrlen, UFTDI_OBUFSIZE - sc->sc_hdrlen,
-		    &actlen)) {
-
-			if (sc->sc_hdrlen > 0) {
-				buf[0] =
-				    FTDI_OUT_TAG(actlen, sc->sc_ucom.sc_portno);
-				usbd_copy_in(pc, 0, buf, 1);
+		if (sc->sc_hdrlen == 0) {
+			if (ucom_get_data(&sc->sc_ucom, pc, 0, UFTDI_OBUFSIZE, 
+			    &buflen) == 0)
+				break;
+		} else {
+			buflen = 0;
+			while (buflen < UFTDI_OBUFSIZE - sc->sc_hdrlen - 1 &&
+			    ucom_get_data(&sc->sc_ucom, pc, buflen + 
+			    sc->sc_hdrlen, UFTDI_OPKTSIZE - sc->sc_hdrlen, 
+			    &pktlen) != 0) {
+				buf[0] = FTDI_OUT_TAG(pktlen, 
+				    sc->sc_ucom.sc_portno);
+				usbd_copy_in(pc, buflen, buf, 1);
+				buflen += pktlen + sc->sc_hdrlen;
 			}
-			usbd_xfer_set_frame_len(xfer, 0, actlen + sc->sc_hdrlen);
+		}
+		if (buflen != 0) {
+			usbd_xfer_set_frame_len(xfer, 0, buflen);
 			usbd_transfer_submit(xfer);
 		}
-		return;
-
-	default:			/* Error */
-		if (error != USB_ERR_CANCELLED) {
-			/* try to clear stall first */
-			usbd_xfer_set_stall(xfer);
-			goto tr_setup;
-		}
-		return;
+		break;
 	}
 }
 
@@ -1069,23 +1255,47 @@
 	uint8_t ftdi_msr;
 	uint8_t msr;
 	uint8_t lsr;
-	int actlen;
+	int buflen;
+	int pktlen;
+	int pktmax;
+	int offset;
 
-	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+	usbd_xfer_status(xfer, &buflen, NULL, NULL, NULL);
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
-
-		if (actlen < 2) {
+		if (buflen < UFTDI_IHDRSIZE)
 			goto tr_setup;
+		pc = usbd_xfer_get_frame(xfer, 0);
+		pktmax = xfer->max_packet_size - UFTDI_IHDRSIZE;
+		lsr = 0;
+		msr = 0;
+		offset = 0;
+		/*
+		 * Extract packet headers and payload bytes from the buffer.
+		 * Feed payload bytes to ucom/tty layer; OR-accumulate header
+		 * status bits which are transient and could toggle with each
+		 * packet. After processing all packets in the buffer, process
+		 * the accumulated transient MSR and LSR values along with the
+		 * non-transient bits from the last packet header.
+		 */
+		while (buflen >= UFTDI_IHDRSIZE) {
+			usbd_copy_out(pc, offset, buf, UFTDI_IHDRSIZE);
+			offset += UFTDI_IHDRSIZE;
+			buflen -= UFTDI_IHDRSIZE;
+			lsr |= FTDI_GET_LSR(buf);
+			if (FTDI_GET_MSR(buf) & FTDI_SIO_RI_MASK)
+				msr |= SER_RI;
+			pktlen = min(buflen, pktmax);
+			if (pktlen != 0) {
+				ucom_put_data(&sc->sc_ucom, pc, offset, 
+				    pktlen);
+				offset += pktlen;
+				buflen -= pktlen;
+			}
 		}
-		pc = usbd_xfer_get_frame(xfer, 0);
-		usbd_copy_out(pc, 0, buf, 2);
-
 		ftdi_msr = FTDI_GET_MSR(buf);
-		lsr = FTDI_GET_LSR(buf);
 
-		msr = 0;
 		if (ftdi_msr & FTDI_SIO_CTS_MASK)
 			msr |= SER_CTS;
 		if (ftdi_msr & FTDI_SIO_DSR_MASK)
@@ -1106,11 +1316,7 @@
 
 			ucom_status_change(&sc->sc_ucom);
 		}
-		actlen -= 2;
-
-		if (actlen > 0) {
-			ucom_put_data(&sc->sc_ucom, pc, 2, actlen);
-		}
+		/* FALLTHROUGH */
 	case USB_ST_SETUP:
 tr_setup:
 		usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
@@ -1190,58 +1396,162 @@
 	    &req, NULL, 0, 1000);
 }
 
+/*
+ * Return true if the given speed is within operational tolerance of the target
+ * speed.  FTDI recommends that the hardware speed be within 3% of nominal.
+ */
+static inline boolean_t
+uftdi_baud_within_tolerance(uint64_t speed, uint64_t target)
+{
+	return ((speed >= (target * 100) / 103) &&
+	    (speed <= (target * 100) / 97));
+}
+
 static int
-uftdi_set_parm_soft(struct termios *t,
-    struct uftdi_param_config *cfg, uint8_t type)
+uftdi_sio_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
+	struct uftdi_param_config *cfg)
 {
+	u_int i;
+	const speed_t sio_speeds[] = {
+		300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
+	};
 
-	memset(cfg, 0, sizeof(*cfg));
-
-	switch (type) {
-	case UFTDI_TYPE_SIO:
-		switch (t->c_ospeed) {
-		case 300:
-			cfg->rate = ftdi_sio_b300;
-			break;
-		case 600:
-			cfg->rate = ftdi_sio_b600;
-			break;
-		case 1200:
-			cfg->rate = ftdi_sio_b1200;
-			break;
-		case 2400:
-			cfg->rate = ftdi_sio_b2400;
-			break;
-		case 4800:
-			cfg->rate = ftdi_sio_b4800;
-			break;
-		case 9600:
-			cfg->rate = ftdi_sio_b9600;
-			break;
-		case 19200:
-			cfg->rate = ftdi_sio_b19200;
-			break;
-		case 38400:
-			cfg->rate = ftdi_sio_b38400;
-			break;
-		case 57600:
-			cfg->rate = ftdi_sio_b57600;
-			break;
-		case 115200:
-			cfg->rate = ftdi_sio_b115200;
-			break;
-		default:
-			return (EINVAL);
+	/*
+	 * The original SIO chips were limited to a small choice of speeds
+	 * listed in an internal table of speeds chosen by an index value.
+	 */
+	for (i = 0; i < nitems(sio_speeds); ++i) {
+		if (speed == sio_speeds[i]) {
+			cfg->baud_lobits = i;
+			cfg->baud_hibits = 0;
+			return (0);
 		}
-		break;
+	}
+	return (ERANGE);
+}
 
-	case UFTDI_TYPE_8U232AM:
-		if (uftdi_8u232am_getrate(t->c_ospeed, &cfg->rate)) {
-			return (EINVAL);
-		}
-		break;
+static int
+uftdi_encode_baudrate(struct uftdi_softc *sc, speed_t speed,
+	struct uftdi_param_config *cfg)
+{
+	static const uint8_t encoded_fraction[8] = {0, 3, 2, 4, 1, 5, 6, 7};
+	static const uint8_t roundoff_232a[16] = {
+		0,  1,  0,  1,  0, -1,  2,  1,
+		0, -1, -2, -3,  4,  3,  2,  1,
+	};
+	uint32_t clk, divisor, fastclk_flag, frac, hwspeed;
+
+	/*
+	 * If this chip has the fast clock capability and the speed is within
+	 * range, use the 12MHz clock, otherwise the standard clock is 3MHz.
+	 */
+	if ((sc->sc_devflags & DEVF_BAUDCLK_12M) && speed >= 1200) {
+		clk = 12000000;
+		fastclk_flag = (1 << 17);
+	} else {
+		clk = 3000000;
+		fastclk_flag = 0;
 	}
 
+	/*
+	 * Make sure the requested speed is reachable with the available clock
+	 * and a 14-bit divisor.
+	 */
+	if (speed < (clk >> 14) || speed > clk)
+		return (ERANGE);
+
+	/*
+	 * Calculate the divisor, initially yielding a fixed point number with a
+	 * 4-bit (1/16ths) fraction, then round it to the nearest fraction the
+	 * hardware can handle.  When the integral part of the divisor is
+	 * greater than one, the fractional part is in 1/8ths of the base clock.
+	 * The FT8U232AM chips can handle only 0.125, 0.250, and 0.5 fractions.
+	 * Later chips can handle all 1/8th fractions.
+	 *
+	 * If the integral part of the divisor is 1, a special rule applies: the
+	 * fractional part can only be .0 or .5 (this is a limitation of the
+	 * hardware).  We handle this by truncating the fraction rather than
+	 * rounding, because this only applies to the two fastest speeds the
+	 * chip can achieve and rounding doesn't matter, either you've asked for
+	 * that exact speed or you've asked for something the chip can't do.
+	 *
+	 * For the FT8U232AM chips, use a roundoff table to adjust the result
+	 * to the nearest 1/8th fraction that is supported by the hardware,
+	 * leaving a fixed-point number with a 3-bit fraction which exactly
+	 * represents the math the hardware divider will do.  For later-series
+	 * chips that support all 8 fractional divisors, just round 16ths to
+	 * 8ths by adding 1 and dividing by 2.
+	 */
+	divisor = (clk << 4) / speed;
+	if ((divisor & 0xf) == 1)
+		divisor &= 0xfffffff8;
+	else if (sc->sc_devtype == DEVT_232A)
+		divisor += roundoff_232a[divisor & 0x0f];
+	else
+		divisor += 1;  /* Rounds odd 16ths up to next 8th. */
+	divisor >>= 1;
+
+	/*
+	 * Ensure the resulting hardware speed will be within operational
+	 * tolerance (within 3% of nominal).
+	 */
+	hwspeed = (clk << 3) / divisor;
+	if (!uftdi_baud_within_tolerance(hwspeed, speed))
+		return (ERANGE);
+
+	/*
+	 * Re-pack the divisor into hardware format. The lower 14-bits hold the
+	 * integral part, while the upper bits specify the fraction by indexing
+	 * a table of fractions within the hardware which is laid out as:
+	 *    {0.0, 0.5, 0.25, 0.125, 0.325, 0.625, 0.725, 0.875}
+	 * The A-series chips only have the first four table entries; the
+	 * roundoff table logic above ensures that the fractional part for those
+	 * chips will be one of the first four values.
+	 *
+	 * When the divisor is 1 a special encoding applies:  1.0 is encoded as
+	 * 0.0, and 1.5 is encoded as 1.0.  The rounding logic above has already
+	 * ensured that the fraction is either .0 or .5 if the integral is 1.
+	 */
+	frac = divisor & 0x07;
+	divisor >>= 3;
+	if (divisor == 1) {
+		if (frac == 0)
+			divisor = 0;  /* 1.0 becomes 0.0 */
+		else
+			frac = 0;     /* 1.5 becomes 1.0 */
+	}
+	divisor |= (encoded_fraction[frac] << 14) | fastclk_flag;
+        
+	cfg->baud_lobits = (uint16_t)divisor;
+	cfg->baud_hibits = (uint16_t)(divisor >> 16);
+
+	/*
+	 * If this chip requires the baud bits to be in the high byte of the
+	 * index word, move the bits up to that location.
+	 */
+	if (sc->sc_devflags & DEVF_BAUDBITS_HINDEX) {
+		cfg->baud_hibits <<= 8;
+	}
+
+	return (0);
+}
+
+static int
+uftdi_set_parm_soft(struct ucom_softc *ucom, struct termios *t,
+    struct uftdi_param_config *cfg)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	int err;
+
+	memset(cfg, 0, sizeof(*cfg));
+
+	if (sc->sc_devtype == DEVT_SIO)
+		err = uftdi_sio_encode_baudrate(sc, t->c_ospeed, cfg);
+	else
+		err = uftdi_encode_baudrate(sc, t->c_ospeed, cfg);
+	if (err != 0)
+		return (err);
+
 	if (t->c_cflag & CSTOPB)
 		cfg->lcr = FTDI_SIO_SET_DATA_STOP_BITS_2;
 	else
@@ -1291,12 +1601,11 @@
 static int
 uftdi_pre_param(struct ucom_softc *ucom, struct termios *t)
 {
-	struct uftdi_softc *sc = ucom->sc_parent;
 	struct uftdi_param_config cfg;
 
 	DPRINTF("\n");
 
-	return (uftdi_set_parm_soft(t, &cfg, sc->sc_type));
+	return (uftdi_set_parm_soft(ucom, t, &cfg));
 }
 
 static void
@@ -1307,7 +1616,7 @@
 	struct uftdi_param_config cfg;
 	struct usb_device_request req;
 
-	if (uftdi_set_parm_soft(t, &cfg, sc->sc_type)) {
+	if (uftdi_set_parm_soft(ucom, t, &cfg)) {
 		/* should not happen */
 		return;
 	}
@@ -1317,8 +1626,8 @@
 
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = FTDI_SIO_SET_BAUD_RATE;
-	USETW(req.wValue, cfg.rate);
-	USETW(req.wIndex, wIndex);
+	USETW(req.wValue, cfg.baud_lobits);
+	USETW(req.wIndex, cfg.baud_hibits | wIndex);
 	USETW(req.wLength, 0);
 	ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
 	    &req, NULL, 0, 1000);
@@ -1352,6 +1661,187 @@
 	*lsr = sc->sc_lsr;
 }
 
+static int
+uftdi_reset(struct ucom_softc *ucom, int reset_type)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_RESET;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 0);
+	USETW(req.wValue, reset_type);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_set_bitmode(struct ucom_softc *ucom, uint8_t bitmode, uint8_t iomask)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_SET_BITMODE;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 0);
+
+	if (bitmode == UFTDI_BITMODE_NONE)
+	    USETW2(req.wValue, 0, 0);
+	else
+	    USETW2(req.wValue, (1 << bitmode), iomask);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *iomask)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_GET_BITMODE;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 1);
+	USETW(req.wValue,  0);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, iomask));
+}
+
+static int
+uftdi_set_latency(struct ucom_softc *ucom, int latency)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+
+	if (latency < 0 || latency > 255)
+		return (USB_ERR_INVAL);
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_SET_LATENCY;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 0);
+	USETW2(req.wValue, 0, latency);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_get_latency(struct ucom_softc *ucom, int *latency)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+	usb_error_t err;
+	uint8_t buf;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_GET_LATENCY;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 1);
+	USETW(req.wValue, 0);
+
+	err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &buf);
+	*latency = buf;
+
+	return (err);
+}
+
+static int
+uftdi_set_event_char(struct ucom_softc *ucom, int echar)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+	uint8_t enable;
+
+	enable = (echar == -1) ? 0 : 1;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_SET_EVENT_CHAR;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 0);
+	USETW2(req.wValue, enable, echar & 0xff);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_set_error_char(struct ucom_softc *ucom, int echar)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	usb_device_request_t req;
+	uint8_t enable;
+
+	enable = (echar == -1) ? 0 : 1;
+
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = FTDI_SIO_SET_ERROR_CHAR;
+
+	USETW(req.wIndex, sc->sc_ucom.sc_portno);
+	USETW(req.wLength, 0);
+	USETW2(req.wValue, enable, echar & 0xff);
+
+	return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+}
+
+static int
+uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
+    int flag, struct thread *td)
+{
+	struct uftdi_softc *sc = ucom->sc_parent;
+	int err;
+	struct uftdi_bitmode * mode;
+
+	DPRINTF("portno: %d cmd: %#x\n", ucom->sc_portno, cmd);
+
+	switch (cmd) {
+	case UFTDIIOC_RESET_IO:
+	case UFTDIIOC_RESET_RX:
+	case UFTDIIOC_RESET_TX:
+		err = uftdi_reset(ucom, 
+		    cmd == UFTDIIOC_RESET_IO ? FTDI_SIO_RESET_SIO :
+		    (cmd == UFTDIIOC_RESET_RX ? FTDI_SIO_RESET_PURGE_RX :
+		    FTDI_SIO_RESET_PURGE_TX));
+		break;
+	case UFTDIIOC_SET_BITMODE:
+		mode = (struct uftdi_bitmode *)data;
+		err = uftdi_set_bitmode(ucom, mode->mode, mode->iomask);
+		break;
+	case UFTDIIOC_GET_BITMODE:
+		mode = (struct uftdi_bitmode *)data;
+		err = uftdi_get_bitmode(ucom, &mode->iomask);
+		break;
+	case UFTDIIOC_SET_LATENCY:
+		err = uftdi_set_latency(ucom, *((int *)data));
+		break;
+	case UFTDIIOC_GET_LATENCY:
+		err = uftdi_get_latency(ucom, (int *)data);
+		break;
+	case UFTDIIOC_SET_ERROR_CHAR:
+		err = uftdi_set_error_char(ucom, *(int *)data);
+		break;
+	case UFTDIIOC_SET_EVENT_CHAR:
+		err = uftdi_set_event_char(ucom, *(int *)data);
+		break;
+	case UFTDIIOC_GET_HWREV:
+		*(int *)data = sc->sc_bcdDevice;
+		err = 0;
+		break;
+	default:
+		return (ENOIOCTL);
+	}
+	if (err != USB_ERR_NORMAL_COMPLETION)
+		return (EIO);
+	return (0);
+}
+
 static void
 uftdi_start_read(struct ucom_softc *ucom)
 {
@@ -1384,75 +1874,6 @@
 	usbd_transfer_stop(sc->sc_xfer[UFTDI_BULK_DT_WR]);
 }
 
-/*------------------------------------------------------------------------*
- *	uftdi_8u232am_getrate
- *
- * Return values:
- *    0: Success
- * Else: Failure
- *------------------------------------------------------------------------*/
-static uint8_t
-uftdi_8u232am_getrate(uint32_t speed, uint16_t *rate)
-{
-	/* Table of the nearest even powers-of-2 for values 0..15. */
-	static const uint8_t roundoff[16] = {
-		0, 2, 2, 4, 4, 4, 8, 8,
-		8, 8, 8, 8, 16, 16, 16, 16,
-	};
-	uint32_t d;
-	uint32_t freq;
-	uint16_t result;
-
-	if ((speed < 178) || (speed > ((3000000 * 100) / 97)))
-		return (1);		/* prevent numerical overflow */
-
-	/* Special cases for 2M and 3M. */
-	if ((speed >= ((3000000 * 100) / 103)) &&
-	    (speed <= ((3000000 * 100) / 97))) {
-		result = 0;
-		goto done;
-	}
-	if ((speed >= ((2000000 * 100) / 103)) &&
-	    (speed <= ((2000000 * 100) / 97))) {
-		result = 1;
-		goto done;
-	}
-	d = (FTDI_8U232AM_FREQ << 4) / speed;
-	d = (d & ~15) + roundoff[d & 15];
-
-	if (d < FTDI_8U232AM_MIN_DIV)
-		d = FTDI_8U232AM_MIN_DIV;
-	else if (d > FTDI_8U232AM_MAX_DIV)
-		d = FTDI_8U232AM_MAX_DIV;
-
-	/*
-	 * Calculate the frequency needed for "d" to exactly divide down to
-	 * our target "speed", and check that the actual frequency is within
-	 * 3% of this.
-	 */
-	freq = (speed * d);
-	if ((freq < ((FTDI_8U232AM_FREQ * 1600ULL) / 103)) ||
-	    (freq > ((FTDI_8U232AM_FREQ * 1600ULL) / 97)))
-		return (1);
-
-	/*
-	 * Pack the divisor into the resultant value.  The lower 14-bits
-	 * hold the integral part, while the upper 2 bits encode the
-	 * fractional component: either 0, 0.5, 0.25, or 0.125.
-	 */
-	result = (d >> 4);
-	if (d & 8)
-		result |= 0x4000;
-	else if (d & 4)
-		result |= 0x8000;
-	else if (d & 2)
-		result |= 0xc000;
-
-done:
-	*rate = result;
-	return (0);
-}
-
 static void
 uftdi_poll(struct ucom_softc *ucom)
 {

Modified: stable/0.8/sys/dev/usb/serial/uftdi_reg.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/uftdi_reg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uftdi_reg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ */
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/serial/uftdi_reg.h 273888 2014-10-31 08:00:22Z hselasky $	*/
 
 /*
  * Definitions for the FTDI USB Single Port Serial Converter -
@@ -28,6 +28,10 @@
 					 * reg */
 #define	FTDI_SIO_SET_EVENT_CHAR	6	/* Set the event character */
 #define	FTDI_SIO_SET_ERROR_CHAR	7	/* Set the error character */
+#define	FTDI_SIO_SET_LATENCY	9	/* Set the latency timer */
+#define	FTDI_SIO_GET_LATENCY	10	/* Read the latency timer */
+#define	FTDI_SIO_SET_BITMODE	11	/* Set the bit bang I/O mode */
+#define	FTDI_SIO_GET_BITMODE	12	/* Read pin states in bit bang mode */
 
 /* Port Identifier Table */
 #define	FTDI_PIT_DEFAULT 	0	/* SIOA */
@@ -36,12 +40,10 @@
 #define	FTDI_PIT_PARALLEL	3	/* Parallel */
 
 /* Values for driver_info */
-#define	UFTDI_TYPE_MASK		0x000000ff
-#define	UFTDI_TYPE_SIO		0x00000001
-#define	UFTDI_TYPE_8U232AM	0x00000002
-#define	UFTDI_TYPE_AUTO		(UFTDI_TYPE_SIO | UFTDI_TYPE_8U232AM)
-#define	UFTDI_FLAG_MASK		0x0000ff00
-#define	UFTDI_FLAG_JTAG		0x00000100
+#define	UFTDI_JTAG_IFACE(i)	(1 << i)	/* Flag interface as jtag */
+#define	UFTDI_JTAG_IFACES_MAX	8		/* Allow up to 8 jtag intfs */
+#define	UFTDI_JTAG_CHECK_STRING	0xff		/* Check product names table */
+#define	UFTDI_JTAG_MASK		0xff
 
 /*
  * BmRequestType:  0100 0000B
@@ -75,31 +77,13 @@
 /*
  * BmRequestType:  0100 0000B
  * bRequest:       FTDI_SIO_SET_BAUDRATE
- * wValue:         BaudRate value - see below
- * wIndex:         Port
+ * wValue:         BaudRate low bits
+ * wIndex:         Port and BaudRate high bits 
  * wLength:        0
  * Data:           None
  */
 /* FTDI_SIO_SET_BAUDRATE */
-enum {
-	ftdi_sio_b300 = 0,
-	ftdi_sio_b600 = 1,
-	ftdi_sio_b1200 = 2,
-	ftdi_sio_b2400 = 3,
-	ftdi_sio_b4800 = 4,
-	ftdi_sio_b9600 = 5,
-	ftdi_sio_b19200 = 6,
-	ftdi_sio_b38400 = 7,
-	ftdi_sio_b57600 = 8,
-	ftdi_sio_b115200 = 9
-};
 
-#define	FTDI_8U232AM_FREQ 3000000
-
-/* Bounds for normal divisors as 4-bit fixed precision ints. */
-#define	FTDI_8U232AM_MIN_DIV 0x20
-#define	FTDI_8U232AM_MAX_DIV 0x3fff8
-
 /*
  * BmRequestType:  0100 0000B
  * bRequest:       FTDI_SIO_SET_DATA

Modified: stable/0.8/sys/dev/usb/serial/ugensa.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ugensa.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ugensa.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/ugensa.c 240659 2012-09-18 16:28:49Z hselasky $ */
 /*	$NetBSD: ugensa.c,v 1.9.2.1 2007/03/24 14:55:50 yamt Exp $	*/
 
 /*

Modified: stable/0.8/sys/dev/usb/serial/uipaq.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uipaq.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uipaq.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uipaq.c 240659 2012-09-18 16:28:49Z hselasky $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>

Modified: stable/0.8/sys/dev/usb/serial/ulpt.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/ulpt.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/ulpt.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/ulpt.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*	$NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $	*/
 

Modified: stable/0.8/sys/dev/usb/serial/umcs.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umcs.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umcs.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -38,7 +38,7 @@
  *
  */
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umcs.c 269721 2014-08-08 14:56:04Z joerg $");
 
 #include <sys/stdint.h>
 #include <sys/stddef.h>
@@ -121,8 +121,6 @@
 
 	uint8_t	sc_lcr;			/* local line control register */
 	uint8_t	sc_mcr;			/* local modem control register */
-	uint8_t	sc_lsr;			/* local line status register */
-	uint8_t	sc_msr;			/* local modem status register */
 };
 
 struct umcs7840_softc {
@@ -535,12 +533,7 @@
 	if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_control, data))
 		return;
 
-	/* Read LSR & MSR */
-	if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
-		return;
-	if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
-		return;
-	DPRINTF("Port %d has been opened, LSR=%02x MSR=%02x\n", pn, sc->sc_ports[pn].sc_lsr, sc->sc_ports[pn].sc_msr);
+	DPRINTF("Port %d has been opened\n", pn);
 }
 
 static void
@@ -748,9 +741,17 @@
 umcs7840_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
 {
 	struct umcs7840_softc *sc = ucom->sc_parent;
+	uint8_t pn = ucom->sc_portno;
+	uint8_t	hw_lsr = 0;	/* local line status register */
+	uint8_t	hw_msr = 0;	/* local modem status register */
 
-	*lsr = sc->sc_ports[ucom->sc_portno].sc_lsr;
-	*msr = sc->sc_ports[ucom->sc_portno].sc_msr;
+	/* Read LSR & MSR */
+	umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &hw_lsr);
+	umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &hw_msr);
+
+	*lsr = hw_lsr;
+	*msr = hw_msr;
+
 	DPRINTF("Port %d status: LSR=%02x MSR=%02x\n", ucom->sc_portno, *lsr, *msr);
 }
 
@@ -781,21 +782,11 @@
 				case MCS7840_UART_ISR_RXERR:
 				case MCS7840_UART_ISR_RXHASDATA:
 				case MCS7840_UART_ISR_RXTIMEOUT:
-					/* Read new LSR */
-					if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
-						break;	/* Inner switch */
+				case MCS7840_UART_ISR_MSCHANGE:
 					ucom_status_change(&sc->sc_ucom[subunit]);
-					/* Inner switch */
 					break;
-				case MCS7840_UART_ISR_TXEMPTY:
+				default:
 					/* Do nothing */
-					break;	/* Inner switch */
-				case MCS7840_UART_ISR_MSCHANGE:
-					/* Read new MSR */
-					if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
-						break;	/* Inner switch */
-					DPRINTF("Port %d: new MSR %02x\n", pn, sc->sc_ports[pn].sc_msr);
-					ucom_status_change(&sc->sc_ucom[subunit]);
 					break;
 				}
 			}
@@ -1092,7 +1083,10 @@
 
 	for (i = 0; i < umcs7840_baudrate_divisors_len - 1 &&
 	    !(rate > umcs7840_baudrate_divisors[i] && rate <= umcs7840_baudrate_divisors[i + 1]); ++i);
-	*divisor = umcs7840_baudrate_divisors[i + 1] / rate;
+	if (rate == 0)
+		*divisor = 1;	/* XXX */
+	else
+		*divisor = umcs7840_baudrate_divisors[i + 1] / rate;
 	/* 0x00 .. 0x70 */
 	*clk = i << MCS7840_DEV_SPx_CLOCK_SHIFT;
 	return (0);

Modified: stable/0.8/sys/dev/usb/serial/umcs.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/umcs.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umcs.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/umcs.h 222696 2011-06-04 20:40:24Z hselasky $ */
 /*-
  * Copyright (c) 2010 Lev Serebryakov <lev at FreeBSD.org>.
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/serial/umct.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umct.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umct.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umct.c 240659 2012-09-18 16:28:49Z hselasky $");
 
 /*-
  * Copyright (c) 2003 Scott Long

Modified: stable/0.8/sys/dev/usb/serial/umodem.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umodem.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umodem.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
 /*	$NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $	*/
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/umodem.c 277410 2015-01-20 05:14:07Z hselasky $");
 
 /*-
  * Copyright (c) 2003, M. Warner Losh <imp at FreeBSD.org>.
@@ -45,13 +45,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -105,6 +98,7 @@
 #include <dev/usb/usbhid.h>
 #include <dev/usb/usb_cdc.h>
 #include "usbdevs.h"
+#include "usb_if.h"
 
 #include <dev/usb/usb_ioctl.h>
 
@@ -123,13 +117,16 @@
     &umodem_debug, 0, "Debug level");
 #endif
 
-static const STRUCT_USB_HOST_ID umodem_devs[] = {
+static const STRUCT_USB_DUAL_ID umodem_dual_devs[] = {
 	/* Generic Modem class match */
 	{USB_IFACE_CLASS(UICLASS_CDC),
 		USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
 		USB_IFACE_PROTOCOL(UIPROTO_CDC_AT)},
+};
+
+static const STRUCT_USB_HOST_ID umodem_host_devs[] = {
 	/* Huawei Modem class match */
-	{USB_IFACE_CLASS(UICLASS_CDC),
+	{USB_VENDOR(USB_VENDOR_HUAWEI),USB_IFACE_CLASS(UICLASS_CDC),
 		USB_IFACE_SUBCLASS(UISUBCLASS_ABSTRACT_CONTROL_MODEL),
 		USB_IFACE_PROTOCOL(0xFF)},
 	/* Kyocera AH-K3001V */
@@ -149,6 +146,7 @@
 enum {
 	UMODEM_BULK_WR,
 	UMODEM_BULK_RD,
+	UMODEM_INTR_WR,
 	UMODEM_INTR_RD,
 	UMODEM_N_TRANSFER,
 };
@@ -173,14 +171,19 @@
 	uint8_t	sc_cm_over_data;
 	uint8_t	sc_cm_cap;		/* CM capabilities */
 	uint8_t	sc_acm_cap;		/* ACM capabilities */
+	uint8_t	sc_line_coding[32];	/* used in USB device mode */
+	uint8_t	sc_abstract_state[32];	/* used in USB device mode */
 };
 
 static device_probe_t umodem_probe;
 static device_attach_t umodem_attach;
 static device_detach_t umodem_detach;
+static usb_handle_request_t umodem_handle_request;
+
 static void umodem_free_softc(struct umodem_softc *);
 
-static usb_callback_t umodem_intr_callback;
+static usb_callback_t umodem_intr_read_callback;
+static usb_callback_t umodem_intr_write_callback;
 static usb_callback_t umodem_write_callback;
 static usb_callback_t umodem_read_callback;
 
@@ -211,31 +214,45 @@
 	[UMODEM_BULK_WR] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
-		.direction = UE_DIR_OUT,
+		.direction = UE_DIR_TX,
 		.if_index = 0,
 		.bufsize = UMODEM_BUF_SIZE,
 		.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
 		.callback = &umodem_write_callback,
+		.usb_mode = USB_MODE_DUAL,
 	},
 
 	[UMODEM_BULK_RD] = {
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
-		.direction = UE_DIR_IN,
+		.direction = UE_DIR_RX,
 		.if_index = 0,
 		.bufsize = UMODEM_BUF_SIZE,
 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
 		.callback = &umodem_read_callback,
+		.usb_mode = USB_MODE_DUAL,
 	},
 
+	[UMODEM_INTR_WR] = {
+		.type = UE_INTERRUPT,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_TX,
+		.if_index = 1,
+		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
+		.bufsize = 0,	/* use wMaxPacketSize */
+		.callback = &umodem_intr_write_callback,
+		.usb_mode = USB_MODE_DEVICE,
+	},
+
 	[UMODEM_INTR_RD] = {
 		.type = UE_INTERRUPT,
 		.endpoint = UE_ADDR_ANY,
-		.direction = UE_DIR_IN,
+		.direction = UE_DIR_RX,
 		.if_index = 1,
 		.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
 		.bufsize = 0,	/* use wMaxPacketSize */
-		.callback = &umodem_intr_callback,
+		.callback = &umodem_intr_read_callback,
+		.usb_mode = USB_MODE_HOST,
 	},
 };
 
@@ -256,6 +273,10 @@
 };
 
 static device_method_t umodem_methods[] = {
+	/* USB interface */
+	DEVMETHOD(usb_handle_request, umodem_handle_request),
+
+	/* Device interface */
 	DEVMETHOD(device_probe, umodem_probe),
 	DEVMETHOD(device_attach, umodem_attach),
 	DEVMETHOD(device_detach, umodem_detach),
@@ -283,13 +304,14 @@
 
 	DPRINTFN(11, "\n");
 
-	if (uaa->usb_mode != USB_MODE_HOST)
-		return (ENXIO);
-
-	error = usbd_lookup_id_by_uaa(umodem_devs, sizeof(umodem_devs), uaa);
-	if (error)
-		return (error);
-
+	error = usbd_lookup_id_by_uaa(umodem_host_devs,
+	    sizeof(umodem_host_devs), uaa);
+	if (error) {
+		error = usbd_lookup_id_by_uaa(umodem_dual_devs,
+		    sizeof(umodem_dual_devs), uaa);
+		if (error)
+			return (error);
+	}
 	return (BUS_PROBE_GENERIC);
 }
 
@@ -404,18 +426,22 @@
 	    umodem_config, UMODEM_N_TRANSFER,
 	    sc, &sc->sc_mtx);
 	if (error) {
+		device_printf(dev, "Can't setup transfer\n");
 		goto detach;
 	}
 
-	/* clear stall at first run */
-	mtx_lock(&sc->sc_mtx);
-	usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
-	usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
-	mtx_unlock(&sc->sc_mtx);
+	/* clear stall at first run, if USB host mode */
+	if (uaa->usb_mode == USB_MODE_HOST) {
+		mtx_lock(&sc->sc_mtx);
+		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
+		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
+		mtx_unlock(&sc->sc_mtx);
+	}
 
 	error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
 	    &umodem_callback, &sc->sc_mtx);
 	if (error) {
+		device_printf(dev, "Can't attach com\n");
 		goto detach;
 	}
 	ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
@@ -486,6 +512,7 @@
 {
 	struct umodem_softc *sc = ucom->sc_parent;
 
+	usbd_transfer_start(sc->sc_xfer[UMODEM_INTR_WR]);
 	usbd_transfer_start(sc->sc_xfer[UMODEM_BULK_WR]);
 }
 
@@ -494,6 +521,7 @@
 {
 	struct umodem_softc *sc = ucom->sc_parent;
 
+	usbd_transfer_stop(sc->sc_xfer[UMODEM_INTR_WR]);
 	usbd_transfer_stop(sc->sc_xfer[UMODEM_BULK_WR]);
 }
 
@@ -688,8 +716,35 @@
 }
 
 static void
-umodem_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+umodem_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
+	int actlen;
+
+	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+
+		DPRINTF("Transferred %d bytes\n", actlen);
+
+		/* FALLTHROUGH */
+	case USB_ST_SETUP:
+tr_setup:
+		break;
+
+	default:			/* Error */
+		if (error != USB_ERR_CANCELLED) {
+			/* start clear stall */
+			usbd_xfer_set_stall(xfer);
+			goto tr_setup;
+		}
+		break;
+	}
+}
+
+static void
+umodem_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
 	struct usb_cdc_notification pkt;
 	struct umodem_softc *sc = usbd_xfer_softc(xfer);
 	struct usb_page_cache *pc;
@@ -910,3 +965,56 @@
 	struct umodem_softc *sc = ucom->sc_parent;
 	usbd_transfer_poll(sc->sc_xfer, UMODEM_N_TRANSFER);
 }
+
+static int
+umodem_handle_request(device_t dev,
+    const void *preq, void **pptr, uint16_t *plen,
+    uint16_t offset, uint8_t *pstate)
+{
+	struct umodem_softc *sc = device_get_softc(dev);
+	const struct usb_device_request *req = preq;
+	uint8_t is_complete = *pstate;
+
+	DPRINTF("sc=%p\n", sc);
+
+	if (!is_complete) {
+		if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+		    (req->bRequest == UCDC_SET_LINE_CODING) &&
+		    (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+		    (req->wIndex[1] == 0x00) &&
+		    (req->wValue[0] == 0x00) &&
+		    (req->wValue[1] == 0x00)) {
+			if (offset == 0) {
+				*plen = sizeof(sc->sc_line_coding);
+				*pptr = &sc->sc_line_coding;
+			} else {
+				*plen = 0;
+			}
+			return (0);
+		} else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+		    (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+		    (req->wIndex[1] == 0x00) &&
+		    (req->bRequest == UCDC_SET_COMM_FEATURE)) {
+			if (offset == 0) {
+				*plen = sizeof(sc->sc_abstract_state);
+				*pptr = &sc->sc_abstract_state;
+			} else {
+				*plen = 0;
+			}
+			return (0);
+		} else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+		    (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+		    (req->wIndex[1] == 0x00) &&
+		    (req->bRequest == UCDC_SET_CONTROL_LINE_STATE)) {
+			*plen = 0;
+			return (0);
+		} else if ((req->bmRequestType == UT_WRITE_CLASS_INTERFACE) &&
+		    (req->wIndex[0] == sc->sc_ctrl_iface_no) &&
+		    (req->wIndex[1] == 0x00) &&
+		    (req->bRequest == UCDC_SEND_BREAK)) {
+			*plen = 0;
+			return (0);
+		}
+	}
+	return (ENXIO);			/* use builtin handler */
+}

Modified: stable/0.8/sys/dev/usb/serial/umoscom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/umoscom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/umoscom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/serial/umoscom.c 248085 2013-03-09 02:36:32Z marius $ */
 /*	$OpenBSD: umoscom.c,v 1.2 2006/10/26 06:02:43 jsg Exp $	*/
 
 /*

Modified: stable/0.8/sys/dev/usb/serial/uplcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uplcom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uplcom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
 /*	$NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $	*/
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uplcom.c 305557 2016-09-07 19:21:52Z dim $");
 
 /*-
  * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -44,13 +44,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -173,7 +166,7 @@
 /* prototypes */
 
 static usb_error_t uplcom_reset(struct uplcom_softc *, struct usb_device *);
-static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t,
+static usb_error_t uplcom_pl2303_do(struct usb_device *, uint8_t, uint8_t,
 			uint16_t, uint16_t, uint16_t);
 static int	uplcom_pl2303_init(struct usb_device *, uint8_t);
 static void	uplcom_free(struct ucom_softc *);
@@ -520,7 +513,7 @@
 }
 
 static usb_error_t
-uplcom_pl2303_do(struct usb_device *udev, int8_t req_type, uint8_t request,
+uplcom_pl2303_do(struct usb_device *udev, uint8_t req_type, uint8_t request,
     uint16_t value, uint16_t index, uint16_t length)
 {
 	struct usb_device_request req;

Modified: stable/0.8/sys/dev/usb/serial/usb_serial.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/usb_serial.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/usb_serial.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/usb_serial.c 268208 2014-07-03 08:07:37Z hselasky $");
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -46,13 +46,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -210,7 +203,7 @@
 
 	mtx_destroy(&ucom_mtx);
 }
-SYSUNINIT(ucom_uninit, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL);
+SYSUNINIT(ucom_uninit, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_uninit, NULL);
 
 /*
  * Mark a unit number (the X in cuaUX) as in use.
@@ -965,7 +958,7 @@
 	sc->sc_pls_set = 0;
 	sc->sc_pls_clr = 0;
 
-	/* ensure that we don't loose any levels */
+	/* ensure that we don't lose any levels */
 	if (notch_bits & UCOM_LS_DTR)
 		sc->sc_callback->ucom_cfg_set_dtr(sc,
 		    (prev_value & UCOM_LS_DTR) ? 1 : 0);

Modified: stable/0.8/sys/dev/usb/serial/usb_serial.h
===================================================================
--- stable/0.8/sys/dev/usb/serial/usb_serial.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/usb_serial.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/serial/usb_serial.h 268208 2014-07-03 08:07:37Z hselasky $	*/
 
 /*-
  * Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -43,13 +43,6 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -146,7 +139,7 @@
 
 struct ucom_softc {
 	/*
-	 * NOTE: To avoid loosing level change information we use two
+	 * NOTE: To avoid losing level change information we use two
 	 * tasks instead of one for all commands.
 	 *
 	 * Level changes are transitions like:
@@ -202,7 +195,7 @@
 #define	UCOM_MTX_LOCK(sc) mtx_lock((sc)->sc_mtx)
 #define	UCOM_MTX_UNLOCK(sc) mtx_unlock((sc)->sc_mtx)
 #define	UCOM_UNLOAD_DRAIN(x) \
-SYSUNINIT(var, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_drain_all, 0)
+SYSUNINIT(var, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_drain_all, 0)
 
 #define	ucom_cfg_do_request(udev,com,req,ptr,flags,timo) \
     usbd_do_request_proc(udev,&(com)->sc_super->sc_tq,req,ptr,flags,NULL,timo)

Modified: stable/0.8/sys/dev/usb/serial/uslcom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uslcom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uslcom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
 /*	$OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $	*/
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uslcom.c 263166 2014-03-14 10:18:53Z hselasky $");
 
 /*
  * Copyright (c) 2006 Jonathan Gray <jsg at openbsd.org>
@@ -242,15 +242,37 @@
     USLCOM_DEV(JABLOTRON, PC60B),
     USLCOM_DEV(KAMSTRUP, OPTICALEYE),
     USLCOM_DEV(KAMSTRUP, MBUS_250D),
+    USLCOM_DEV(LAKESHORE, 121),
+    USLCOM_DEV(LAKESHORE, 218A),
+    USLCOM_DEV(LAKESHORE, 219),
+    USLCOM_DEV(LAKESHORE, 233),
+    USLCOM_DEV(LAKESHORE, 235),
+    USLCOM_DEV(LAKESHORE, 335),
+    USLCOM_DEV(LAKESHORE, 336),
+    USLCOM_DEV(LAKESHORE, 350),
+    USLCOM_DEV(LAKESHORE, 371),
+    USLCOM_DEV(LAKESHORE, 411),
+    USLCOM_DEV(LAKESHORE, 425),
+    USLCOM_DEV(LAKESHORE, 455A),
+    USLCOM_DEV(LAKESHORE, 465),
+    USLCOM_DEV(LAKESHORE, 475A),
+    USLCOM_DEV(LAKESHORE, 625A),
+    USLCOM_DEV(LAKESHORE, 642A),
+    USLCOM_DEV(LAKESHORE, 648),
+    USLCOM_DEV(LAKESHORE, 737),
+    USLCOM_DEV(LAKESHORE, 776),
     USLCOM_DEV(LINKINSTRUMENTS, MSO19),
     USLCOM_DEV(LINKINSTRUMENTS, MSO28),
     USLCOM_DEV(LINKINSTRUMENTS, MSO28_2),
     USLCOM_DEV(MEI, CASHFLOW_SC),
     USLCOM_DEV(MEI, S2000),
+    USLCOM_DEV(NETGEAR, M4100),
     USLCOM_DEV(OWEN, AC4),
+    USLCOM_DEV(OWL, CM_160),
     USLCOM_DEV(PHILIPS, ACE1001),
     USLCOM_DEV(PLX, CA42),
     USLCOM_DEV(RENESAS, RX610),
+    USLCOM_DEV(SEL, C662),
     USLCOM_DEV(SILABS, AC_SERV_CAN),
     USLCOM_DEV(SILABS, AC_SERV_CIS),
     USLCOM_DEV(SILABS, AC_SERV_IBUS),
@@ -283,6 +305,7 @@
     USLCOM_DEV(SILABS, HELICOM),
     USLCOM_DEV(SILABS, IMS_USB_RS422),
     USLCOM_DEV(SILABS, INFINITY_MIC),
+    USLCOM_DEV(SILABS, INGENI_ZIGBEE),
     USLCOM_DEV(SILABS, INSYS_MODEM),
     USLCOM_DEV(SILABS, IRZ_SG10),
     USLCOM_DEV(SILABS, KYOCERA_GPS),
@@ -290,6 +313,7 @@
     USLCOM_DEV(SILABS, LIPOWSKY_JTAG),
     USLCOM_DEV(SILABS, LIPOWSKY_LIN),
     USLCOM_DEV(SILABS, MC35PU),
+    USLCOM_DEV(SILABS, MMB_ZIGBEE),
     USLCOM_DEV(SILABS, MJS_TOSLINK),
     USLCOM_DEV(SILABS, MSD_DASHHAWK),
     USLCOM_DEV(SILABS, MULTIPLEX_RC),
@@ -306,6 +330,7 @@
     USLCOM_DEV(SILABS, USBPULSE100),
     USLCOM_DEV(SILABS, USBSCOPE50),
     USLCOM_DEV(SILABS, USBWAVE12),
+    USLCOM_DEV(SILABS, V_PREON32),
     USLCOM_DEV(SILABS, VSTABI),
     USLCOM_DEV(SILABS, WAVIT),
     USLCOM_DEV(SILABS, WMRBATT),
@@ -320,6 +345,7 @@
     USLCOM_DEV(VAISALA, CABLE),
     USLCOM_DEV(WAGO, SERVICECABLE),
     USLCOM_DEV(WAVESENSE, JAZZ),
+    USLCOM_DEV(WESTMOUNTAIN, RIGBLASTER_ADVANTAGE),
     USLCOM_DEV(WIENERPLEINBAUS, PL512),
     USLCOM_DEV(WIENERPLEINBAUS, RCM),
     USLCOM_DEV(WIENERPLEINBAUS, MPOD),

Modified: stable/0.8/sys/dev/usb/serial/uvisor.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uvisor.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uvisor.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $	*/
-/*      $MidnightBSD$ */
+/*      $FreeBSD: stable/9/sys/dev/usb/serial/uvisor.c 248085 2013-03-09 02:36:32Z marius $ */
 
 /* Also already merged from NetBSD:
  *	$NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $

Modified: stable/0.8/sys/dev/usb/serial/uvscom.c
===================================================================
--- stable/0.8/sys/dev/usb/serial/uvscom.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/serial/uvscom.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,7 +1,7 @@
 /*	$NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $	*/
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/serial/uvscom.c 248085 2013-03-09 02:36:32Z marius $");
 
 /*-
  * Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.

Modified: stable/0.8/sys/dev/usb/storage/rio500_usb.h
===================================================================
--- stable/0.8/sys/dev/usb/storage/rio500_usb.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/rio500_usb.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -20,7 +20,7 @@
 
     ---------------------------------------------------------------------- */
 
-/*  $MidnightBSD$ */
+/*  $FreeBSD: stable/9/sys/dev/usb/storage/rio500_usb.h 196219 2009-08-14 20:03:53Z jhb $ */
 
 #include <sys/ioccom.h>
 #ifndef USB_VENDOR_DIAMOND

Modified: stable/0.8/sys/dev/usb/storage/umass.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/umass.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/umass.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/storage/umass.c 255663 2013-09-18 06:38:40Z hselasky $");
 
 /*-
  * Copyright (c) 1999 MAEKAWA Masahide <bishop at rr.iij4u.or.jp>,
@@ -27,7 +27,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$MidnightBSD$
+ *	$FreeBSD: stable/9/sys/dev/usb/storage/umass.c 255663 2013-09-18 06:38:40Z hselasky $
  *	$NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $
  */
 
@@ -1320,10 +1320,12 @@
 			}
 			sc->cbw.bCDBLength = sc->sc_transfer.cmd_len;
 
+			/* copy SCSI command data */
 			memcpy(sc->cbw.CBWCDB, sc->sc_transfer.cmd_data,
 			    sc->sc_transfer.cmd_len);
 
-			memset(sc->sc_transfer.cmd_data +
+			/* clear remaining command area */
+			memset(sc->cbw.CBWCDB +
 			    sc->sc_transfer.cmd_len, 0,
 			    sizeof(sc->cbw.CBWCDB) -
 			    sc->sc_transfer.cmd_len);

Modified: stable/0.8/sys/dev/usb/storage/urio.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/urio.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/urio.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/storage/urio.c 248085 2013-03-09 02:36:32Z marius $");
 
 
 /*

Modified: stable/0.8/sys/dev/usb/storage/ustorage_fs.c
===================================================================
--- stable/0.8/sys/dev/usb/storage/ustorage_fs.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/storage/ustorage_fs.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/storage/ustorage_fs.c 260575 2014-01-12 21:21:19Z hselasky $ */
 /*-
  * Copyright (C) 2003-2005 Alan Stern
  * Copyright (C) 2008 Hans Petter Selasky
@@ -74,7 +74,7 @@
 /* Define some limits */
 
 #ifndef USTORAGE_FS_BULK_SIZE 
-#define	USTORAGE_FS_BULK_SIZE (1UL << 17)	/* bytes */
+#define	USTORAGE_FS_BULK_SIZE	(1U << 17)	/* bytes */
 #endif
 
 #ifndef	USTORAGE_FS_MAX_LUN
@@ -85,8 +85,6 @@
 #define	USTORAGE_QDATA_MAX	40	/* bytes */
 #endif
 
-#define sc_cmd_data sc_cbw.CBWCDB
-
 /*
  * The SCSI ID string must be exactly 28 characters long
  * exluding the terminating zero.
@@ -176,8 +174,9 @@
 
 struct ustorage_fs_softc {
 
-	ustorage_fs_bbb_cbw_t sc_cbw;	/* Command Wrapper Block */
-	ustorage_fs_bbb_csw_t sc_csw;	/* Command Status Block */
+	ustorage_fs_bbb_cbw_t *sc_cbw;	/* Command Wrapper Block */
+	ustorage_fs_bbb_csw_t *sc_csw;	/* Command Status Block */
+	void *sc_dma_ptr;		/* Main data buffer */
 
 	struct mtx sc_mtx;
 
@@ -275,7 +274,6 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
-		.flags = {.ext_buffer = 1,},
 		.callback = &ustorage_fs_t_bbb_command_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -295,7 +293,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = USTORAGE_FS_BULK_SIZE,
-		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
+		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
 		.callback = &ustorage_fs_t_bbb_data_read_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -315,7 +313,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
 		.bufsize = sizeof(ustorage_fs_bbb_csw_t),
-		.flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
+		.flags = {.short_xfer_ok = 1},
 		.callback = &ustorage_fs_t_bbb_status_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -409,6 +407,14 @@
 		    "transfers, %s\n", usbd_errstr(err));
 		goto detach;
 	}
+
+	sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_COMMAND], 0);
+	sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_STATUS], 0);
+ 	sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_DATA_READ], 0);
+
 	/* start Mass Storage State Machine */
 
 	mtx_lock(&sc->sc_mtx);
@@ -518,7 +524,7 @@
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 
-		tag = UGETDW(sc->sc_cbw.dCBWSignature);
+		tag = UGETDW(sc->sc_cbw->dCBWSignature);
 
 		if (tag != CBWSIGNATURE) {
 			/* do nothing */
@@ -525,29 +531,29 @@
 			DPRINTF("invalid signature 0x%08x\n", tag);
 			break;
 		}
-		tag = UGETDW(sc->sc_cbw.dCBWTag);
+		tag = UGETDW(sc->sc_cbw->dCBWTag);
 
 		/* echo back tag */
-		USETDW(sc->sc_csw.dCSWTag, tag);
+		USETDW(sc->sc_csw->dCSWTag, tag);
 
 		/* reset status */
-		sc->sc_csw.bCSWStatus = 0;
+		sc->sc_csw->bCSWStatus = 0;
 
 		/* reset data offset, data length and data remainder */
 		sc->sc_transfer.offset = 0;
 		sc->sc_transfer.data_rem =
-		    UGETDW(sc->sc_cbw.dCBWDataTransferLength);
+		    UGETDW(sc->sc_cbw->dCBWDataTransferLength);
 
 		/* reset data flags */
 		sc->sc_transfer.data_short = 0;
 
 		/* extract LUN */
-		sc->sc_transfer.lun = sc->sc_cbw.bCBWLUN;
+		sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
 
 		if (sc->sc_transfer.data_rem == 0) {
 			sc->sc_transfer.cbw_dir = DIR_NONE;
 		} else {
-			if (sc->sc_cbw.bCBWFlags & CBWFLAGS_IN) {
+			if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
 				sc->sc_transfer.cbw_dir = DIR_WRITE;
 			} else {
 				sc->sc_transfer.cbw_dir = DIR_READ;
@@ -554,8 +560,8 @@
 			}
 		}
 
-		sc->sc_transfer.cmd_len = sc->sc_cbw.bCDBLength;
-		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw.CBWCDB)) ||
+		sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
+		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
 		    (sc->sc_transfer.cmd_len == 0)) {
 			/* just halt - this is invalid */
 			DPRINTF("invalid command length %d bytes\n",
@@ -597,9 +603,8 @@
 			usbd_xfer_set_stall(xfer);
 			DPRINTF("stall pipe\n");
 		}
-
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_cbw,
-		    sizeof(sc->sc_cbw));
+		usbd_xfer_set_frame_len(xfer, 0,
+		    sizeof(ustorage_fs_bbb_cbw_t));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -616,9 +621,9 @@
 		goto tr_setup;
 	}
 	if (err) {
-		if (sc->sc_csw.bCSWStatus == 0) {
+		if (sc->sc_csw->bCSWStatus == 0) {
 			/* set some default error code */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 		}
 		if (sc->sc_transfer.cbw_dir == DIR_READ) {
 			/* dump all data */
@@ -699,6 +704,9 @@
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
+		/* XXX copy data from DMA buffer */
+		memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
+
 		sc->sc_transfer.data_rem -= actlen;
 		sc->sc_transfer.data_ptr += actlen;
 		sc->sc_transfer.offset += actlen;
@@ -721,8 +729,7 @@
 			usbd_xfer_set_stall(xfer);
 		}
 
-		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
-		    max_bulk);
+		usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -778,8 +785,10 @@
 			usbd_xfer_set_stall(xfer);
 		}
 
-		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
-		    max_bulk);
+		/* XXX copy data to DMA buffer */
+		memcpy(sc->sc_dma_ptr, sc->sc_transfer.data_ptr, max_bulk);
+
+		usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -813,16 +822,15 @@
 
 	case USB_ST_SETUP:
 tr_setup:
-		USETDW(sc->sc_csw.dCSWSignature, CSWSIGNATURE);
-		USETDW(sc->sc_csw.dCSWDataResidue, sc->sc_transfer.data_rem);
+		USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
+		USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
 
 		if (sc->sc_transfer.data_error) {
 			sc->sc_transfer.data_error = 0;
 			usbd_xfer_set_stall(xfer);
 		}
-
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_csw,
-		    sizeof(sc->sc_csw));
+		usbd_xfer_set_frame_len(xfer, 0,
+		    sizeof(ustorage_fs_bbb_csw_t));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -934,17 +942,17 @@
 	/*
 	 * Get the starting Logical Block Address
 	 */
-	lba = get_be32(&sc->sc_cmd_data[2]);
+	lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 	/*
 	 * We allow DPO (Disable Page Out = don't save data in the cache)
 	 * but we don't implement it.
 	 */
-	if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
+	if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
 	}
-	vlen = get_be16(&sc->sc_cmd_data[7]);
+	vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
 	if (vlen == 0) {
 		goto done;
 	}
@@ -1092,8 +1100,8 @@
 {
 	uint8_t *buf = sc->sc_transfer.data_ptr;
 	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
-	uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
-	uint8_t pmi = sc->sc_cmd_data[8];
+	uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
+	uint8_t pmi = sc->sc_cbw->CBWCDB[8];
 
 	/* Check the PMI and LBA fields */
 	if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
@@ -1126,7 +1134,7 @@
 	uint8_t *buf0;
 	uint16_t len;
 	uint16_t limit;
-	uint8_t mscmnd = sc->sc_cmd_data[0];
+	uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
 	uint8_t pc;
 	uint8_t page_code;
 	uint8_t changeable_values;
@@ -1134,13 +1142,13 @@
 
 	buf0 = buf;
 
-	if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
+	if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
 		/* Mask away DBD */
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
 	}
-	pc = sc->sc_cmd_data[2] >> 6;
-	page_code = sc->sc_cmd_data[2] & 0x3f;
+	pc = sc->sc_cbw->CBWCDB[2] >> 6;
+	page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
 	if (pc == 3) {
 		currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
 		return (1);
@@ -1237,9 +1245,9 @@
 		currlun->sense_data = SS_INVALID_COMMAND;
 		return (1);
 	}
-	immed = sc->sc_cmd_data[1] & 0x01;
-	loej = sc->sc_cmd_data[4] & 0x02;
-	start = sc->sc_cmd_data[4] & 0x01;
+	immed = sc->sc_cbw->CBWCDB[1] & 0x01;
+	loej = sc->sc_cbw->CBWCDB[4] & 0x02;
+	start = sc->sc_cbw->CBWCDB[4] & 0x01;
 
 	if (immed || loej || start) {
 		/* compile fix */
@@ -1264,8 +1272,8 @@
 		currlun->sense_data = SS_INVALID_COMMAND;
 		return (1);
 	}
-	prevent = sc->sc_cmd_data[4] & 0x01;
-	if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
+	prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
+	if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
 		/* Mask away Prevent */
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
@@ -1369,11 +1377,11 @@
 	 * Get the starting Logical Block Address and check that it's not
 	 * too big
 	 */
-	if (sc->sc_cmd_data[0] == SC_READ_6) {
-		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
-		    get_be16(&sc->sc_cmd_data[2]);
+	if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
+		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+		    get_be16(&sc->sc_cbw->CBWCDB[2]);
 	} else {
-		lba = get_be32(&sc->sc_cmd_data[2]);
+		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 		/*
 		 * We allow DPO (Disable Page Out = don't save data in the
@@ -1380,7 +1388,7 @@
 		 * cache) and FUA (Force Unit Access = don't read from the
 		 * cache), but we don't implement them.
 		 */
-		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
 			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return (1);
 		}
@@ -1427,11 +1435,11 @@
 	 * Get the starting Logical Block Address and check that it's not
 	 * too big.
 	 */
-	if (sc->sc_cmd_data[0] == SC_WRITE_6)
-		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
-		    get_be16(&sc->sc_cmd_data[2]);
+	if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
+		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+		    get_be16(&sc->sc_cbw->CBWCDB[2]);
 	else {
-		lba = get_be32(&sc->sc_cmd_data[2]);
+		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 		/*
 		 * We allow DPO (Disable Page Out = don't save data in the
@@ -1439,11 +1447,11 @@
 		 * medium).  We don't implement DPO; we implement FUA by
 		 * performing synchronous output.
 		 */
-		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
 			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return (1);
 		}
-		if (sc->sc_cmd_data[1] & 0x08) {
+		if (sc->sc_cbw->CBWCDB[1] & 0x08) {
 			/* FUA */
 			/* XXX set SYNC flag here */
 		}
@@ -1483,7 +1491,7 @@
 			 * there must be something wrong about this SCSI
 			 * command
 			 */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
 			return (1);
 		}
 		/* compute the minimum length */
@@ -1519,7 +1527,7 @@
     uint16_t mask, uint8_t needs_medium)
 {
 	struct ustorage_fs_lun *currlun;
-	uint8_t lun = (sc->sc_cmd_data[1] >> 5);
+	uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
 	uint8_t i;
 
 	/* Verify the length of the command itself */
@@ -1526,11 +1534,11 @@
 	if (min_cmd_size > sc->sc_transfer.cmd_len) {
 		DPRINTF("%u > %u\n",
 		    min_cmd_size, sc->sc_transfer.cmd_len);
-		sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+		sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
 		return (1);
 	}
 	/* Mask away the LUN */
-	sc->sc_cmd_data[1] &= 0x1f;
+	sc->sc_cbw->CBWCDB[1] &= 0x1f;
 
 	/* Check if LUN is correct */
 	if (lun != sc->sc_transfer.lun) {
@@ -1540,7 +1548,7 @@
 	if (sc->sc_transfer.lun <= sc->sc_last_lun) {
 		sc->sc_transfer.currlun = currlun =
 		    sc->sc_lun + sc->sc_transfer.lun;
-		if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
+		if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
 			currlun->sense_data = SS_NO_SENSE;
 			currlun->sense_data_info = 0;
 			currlun->info_valid = 0;
@@ -1551,8 +1559,8 @@
 		 * else must fail!
 		 */
 		if ((currlun->unit_attention_data != SS_NO_SENSE) &&
-		    (sc->sc_cmd_data[0] != SC_INQUIRY) &&
-		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+		    (sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
 			currlun->sense_data = currlun->unit_attention_data;
 			currlun->unit_attention_data = SS_NO_SENSE;
 			return (1);
@@ -1564,8 +1572,8 @@
 		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not.
 		 */
-		if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
-		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+		if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
 			return (1);
 		}
 	}
@@ -1575,7 +1583,7 @@
 	 * non-zero.
 	 */
 	for (i = 0; i != min_cmd_size; i++) {
-		if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
+		if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
 			if (currlun) {
 				currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			}
@@ -1613,12 +1621,12 @@
 	sc->sc_transfer.data_ptr = sc->sc_qdata;
 
 	DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
-	    sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
+	    sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
 
-	switch (sc->sc_cmd_data[0]) {
+	switch (sc->sc_cbw->CBWCDB[0]) {
 	case SC_INQUIRY:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1633,7 +1641,7 @@
 
 	case SC_MODE_SELECT_6:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1649,7 +1657,7 @@
 	case SC_MODE_SELECT_10:
 		sc->sc_transfer.cmd_dir = DIR_READ;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1664,7 +1672,7 @@
 
 	case SC_MODE_SENSE_6:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1680,7 +1688,7 @@
 	case SC_MODE_SENSE_10:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1708,7 +1716,7 @@
 		break;
 
 	case SC_READ_6:
-		i = sc->sc_cmd_data[4];
+		i = sc->sc_cbw->CBWCDB[4];
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		temp = ((i == 0) ? 256UL : i);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1726,7 +1734,7 @@
 
 	case SC_READ_10:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		temp = get_be16(&sc->sc_cmd_data[7]);
+		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
 		if (error) {
 			break;
@@ -1742,10 +1750,10 @@
 
 	case SC_READ_12:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		temp = get_be32(&sc->sc_cmd_data[6]);
+		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
 		if (temp >= (1UL << (32 - 9))) {
 			/* numerical overflow */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 			error = 1;
 			break;
 		}
@@ -1776,7 +1784,7 @@
 	case SC_READ_FORMAT_CAPACITIES:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1791,7 +1799,7 @@
 
 	case SC_REQUEST_SENSE:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1860,7 +1868,7 @@
 		break;
 
 	case SC_WRITE_6:
-		i = sc->sc_cmd_data[4];
+		i = sc->sc_cbw->CBWCDB[4];
 		sc->sc_transfer.cmd_dir = DIR_READ;
 		temp = ((i == 0) ? 256UL : i);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1878,7 +1886,7 @@
 
 	case SC_WRITE_10:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		temp = get_be16(&sc->sc_cmd_data[7]);
+		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
 		if (error) {
 			break;
@@ -1894,10 +1902,10 @@
 
 	case SC_WRITE_12:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		temp = get_be32(&sc->sc_cmd_data[6]);
+		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
 		if (temp > (mask9 >> 9)) {
 			/* numerical overflow */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 			error = 1;
 			break;
 		}

Modified: stable/0.8/sys/dev/usb/template/usb_template.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/template/usb_template.c 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
  *
@@ -1240,7 +1240,7 @@
 		return (0);
 
 	/* Protect scratch area */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
 	uts = udev->scratch.temp_setup;
 
@@ -1319,7 +1319,7 @@
 	if (error)
 		usb_temp_unsetup(udev);
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 	return (error);
 }
 

Modified: stable/0.8/sys/dev/usb/template/usb_template.h
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/template/usb_template.h 223467 2011-06-23 07:54:03Z hselasky $ */
 /*-
  * Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>
  * All rights reserved.

Modified: stable/0.8/sys/dev/usb/template/usb_template_audio.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_audio.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_audio.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_audio.c 223472 2011-06-23 10:35:45Z hselasky $");
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.

Modified: stable/0.8/sys/dev/usb/template/usb_template_cdce.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_cdce.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_cdce.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_cdce.c 223467 2011-06-23 07:54:03Z hselasky $");
 
 /*-
  * Copyright (c) 2007 Hans Petter Selasky <hselasky at FreeBSD.org>

Modified: stable/0.8/sys/dev/usb/template/usb_template_kbd.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_kbd.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_kbd.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_kbd.c 229103 2011-12-31 14:37:51Z hselasky $");
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.

Modified: stable/0.8/sys/dev/usb/template/usb_template_modem.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_modem.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_modem.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_modem.c 229103 2011-12-31 14:37:51Z hselasky $");
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.

Modified: stable/0.8/sys/dev/usb/template/usb_template_mouse.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_mouse.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_mouse.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_mouse.c 229103 2011-12-31 14:37:51Z hselasky $");
 
 /*-
  * Copyright (c) 2010 Hans Petter Selasky. All rights reserved.

Modified: stable/0.8/sys/dev/usb/template/usb_template_msc.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_msc.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_msc.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_msc.c 223467 2011-06-23 07:54:03Z hselasky $");
 
 /*-
  * Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>

Modified: stable/0.8/sys/dev/usb/template/usb_template_mtp.c
===================================================================
--- stable/0.8/sys/dev/usb/template/usb_template_mtp.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/template/usb_template_mtp.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/template/usb_template_mtp.c 223467 2011-06-23 07:54:03Z hselasky $");
 
 /*-
  * Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>

Modified: stable/0.8/sys/dev/usb/ufm_ioctl.h
===================================================================
--- stable/0.8/sys/dev/usb/ufm_ioctl.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/ufm_ioctl.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -28,7 +28,7 @@
  * its contributors.
  */
 
-/*  $MidnightBSD$ */
+/*  $FreeBSD: stable/9/sys/dev/usb/ufm_ioctl.h 196219 2009-08-14 20:03:53Z jhb $ */
 
 #include <sys/ioccom.h>
 

Added: stable/0.8/sys/dev/usb/uftdiio.h
===================================================================
--- stable/0.8/sys/dev/usb/uftdiio.h	                        (rev 0)
+++ stable/0.8/sys/dev/usb/uftdiio.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -0,0 +1,75 @@
+/*-
+ * Copyright 2008-2012 - Symmetricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *  $FreeBSD: stable/9/sys/dev/usb/uftdiio.h 265050 2014-04-28 13:28:10Z ian $ 
+ */
+
+/*
+ * FTDI USB serial converter chip ioctl commands.
+ */
+
+#ifndef _USB_UFTDIIO_H_
+#define _USB_UFTDIIO_H_
+
+#include <sys/ioccom.h>
+
+enum uftdi_bitmodes
+{
+	UFTDI_BITMODE_ASYNC = 0,
+	UFTDI_BITMODE_MPSSE = 1,
+	UFTDI_BITMODE_SYNC = 2,
+	UFTDI_BITMODE_CPU_EMUL = 3,
+	UFTDI_BITMODE_FAST_SERIAL = 4,
+	UFTDI_BITMODE_CBUS = 5,
+	UFTDI_BITMODE_NONE = 0xff,
+};
+
+/*
+ * For UFTDIIOC_SET_BITMODE:
+ *   mode   = One of the uftdi_bitmodes enum values.
+ *   iomask = Mask of bits enabled for bitbang output.
+ *
+ * For UFTDIIOC_GET_BITMODE:
+ *   mode   = Unused.
+ *   iomask = Returned snapshot of bitbang pin states at time of call.
+ */
+struct uftdi_bitmode
+{
+	uint8_t mode;
+	uint8_t iomask;
+};
+
+#define	UFTDIIOC_RESET_IO	_IO('c', 0)	/* Reset config, flush fifos.*/
+#define	UFTDIIOC_RESET_RX	_IO('c', 1)	/* Flush input fifo. */
+#define	UFTDIIOC_RESET_TX	_IO('c', 2)	/* Flush output fifo. */
+#define	UFTDIIOC_SET_BITMODE	_IOW('c', 3, struct uftdi_bitmode)
+#define	UFTDIIOC_GET_BITMODE	_IOR('c', 4, struct uftdi_bitmode)
+#define	UFTDIIOC_SET_ERROR_CHAR	_IOW('c', 5, int)	/* -1 to disable */
+#define	UFTDIIOC_SET_EVENT_CHAR	_IOW('c', 6, int)	/* -1 to disable */
+#define	UFTDIIOC_SET_LATENCY	_IOW('c', 7, int)	/* 1-255 ms */
+#define	UFTDIIOC_GET_LATENCY	_IOR('c', 8, int)
+#define	UFTDIIOC_GET_HWREV	_IOR('c', 9, int)
+
+#endif


Property changes on: stable/0.8/sys/dev/usb/uftdiio.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Modified: stable/0.8/sys/dev/usb/usb.h
===================================================================
--- stable/0.8/sys/dev/usb/usb.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb.h 282510 2015-05-05 20:00:20Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -493,8 +493,11 @@
 #define	UICLASS_WIRELESS	0xe0
 #define	UISUBCLASS_RF			0x01
 #define	UIPROTO_BLUETOOTH		0x01
+#define	UIPROTO_RNDIS			0x03
 
 #define	UICLASS_IAD		0xEF	/* Interface Association Descriptor */
+#define	UISUBCLASS_SYNC			0x01
+#define	UIPROTO_ACTIVESYNC		0x01
 
 #define	UICLASS_APPL_SPEC	0xfe
 #define	UISUBCLASS_FIRMWARE_DOWNLOAD	1
@@ -533,6 +536,11 @@
 #define	UE_ISO_ADAPT	0x08
 #define	UE_ISO_SYNC	0x0c
 #define	UE_GET_ISO_TYPE(a)	((a) & UE_ISO_TYPE)
+#define	UE_ISO_USAGE	0x30
+#define	UE_ISO_USAGE_DATA	0x00
+#define	UE_ISO_USAGE_FEEDBACK	0x10
+#define	UE_ISO_USAGE_IMPLICT_FB	0x20
+#define	UE_GET_ISO_USAGE(a)	((a) & UE_ISO_USAGE)
 	uWord	wMaxPacketSize;
 #define	UE_ZERO_MPS 0xFFFF		/* for internal use only */
 	uByte	bInterval;

Modified: stable/0.8/sys/dev/usb/usb_bus.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_bus.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_bus.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_bus.h 278291 2015-02-05 21:37:59Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -27,6 +27,8 @@
 #ifndef _USB_BUS_H_
 #define	_USB_BUS_H_
 
+struct usb_fs_privdata;
+
 /*
  * The following structure defines the USB explore message sent to the USB
  * explore process.
@@ -71,7 +73,12 @@
 	struct usb_bus_msg attach_msg[2];
 	struct usb_bus_msg suspend_msg[2];
 	struct usb_bus_msg resume_msg[2];
+	struct usb_bus_msg reset_msg[2];
 	struct usb_bus_msg shutdown_msg[2];
+#if USB_HAVE_UGEN
+	struct usb_bus_msg cleanup_msg[2];
+	LIST_HEAD(,usb_fs_privdata) pd_cleanup_list;
+#endif
 	/*
 	 * This mutex protects the USB hardware:
 	 */
@@ -103,6 +110,7 @@
 	uint8_t	devices_max;		/* maximum number of USB devices */
 	uint8_t	do_probe;		/* set if USB should be re-probed */
 	uint8_t no_explore;		/* don't explore USB ports */
+	uint8_t dma_bits;		/* number of DMA address lines */
 };
 
 #endif					/* _USB_BUS_H_ */

Modified: stable/0.8/sys/dev/usb/usb_busdma.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_busdma.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_busdma.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_busdma.c 291251 2015-11-24 12:19:20Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -130,6 +130,35 @@
 }
 
 /*------------------------------------------------------------------------*
+ *  usb_pc_buffer_is_aligned - verify alignment
+ * 
+ * This function is used to check if a page cache buffer is properly
+ * aligned to reduce the use of bounce buffers in PIO mode.
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_buffer_is_aligned(struct usb_page_cache *pc, usb_frlength_t offset,
+    usb_frlength_t len, usb_frlength_t mask)
+{
+	struct usb_page_search buf_res;
+
+	while (len != 0) {
+
+		usbd_get_page(pc, offset, &buf_res);
+
+		if (buf_res.length > len)
+			buf_res.length = len;
+		if (USB_P2U(buf_res.buffer) & mask)
+			return (0);
+		if (buf_res.length & mask)
+			return (0);
+
+		offset += buf_res.length;
+		len -= buf_res.length;
+	}
+	return (1);
+}
+
+/*------------------------------------------------------------------------*
  *  usbd_copy_in - copy directly to DMA-able memory
  *------------------------------------------------------------------------*/
 void
@@ -211,9 +240,7 @@
     struct mbuf *m, usb_size_t src_offset, usb_frlength_t src_len)
 {
 	struct usb_m_copy_in_arg arg = {cache, dst_offset};
-	int error;
-
-	error = m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
+	(void) m_apply(m, src_offset, src_len, &usbd_m_copy_in_cb, &arg);
 }
 #endif
 
@@ -358,8 +385,7 @@
 	if (bus_dma_tag_create
 	    ( /* parent    */ udt->tag_parent->tag,
 	     /* alignment */ align,
-	     /* boundary  */ (align == 1) ?
-	    USB_PAGE_SIZE : 0,
+	     /* boundary  */ 0,
 	     /* lowaddr   */ (2ULL << (udt->tag_parent->dma_bits - 1)) - 1,
 	     /* highaddr  */ BUS_SPACE_MAXADDR,
 	     /* filter    */ NULL,
@@ -418,6 +444,7 @@
 	struct usb_page_cache *pc;
 	struct usb_page *pg;
 	usb_size_t rem;
+	bus_size_t off;
 	uint8_t owned;
 
 	pc = arg;
@@ -433,16 +460,21 @@
 	if (error) {
 		goto done;
 	}
+
+	off = 0;
 	pg = pc->page_start;
 	pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
 	rem = segs->ds_addr & (USB_PAGE_SIZE - 1);
 	pc->page_offset_buf = rem;
 	pc->page_offset_end += rem;
-	nseg--;
 #ifdef USB_DEBUG
-	if (rem != (USB_P2U(pc->buffer) & (USB_PAGE_SIZE - 1))) {
+	if (nseg > 1 &&
+	    ((segs->ds_addr + segs->ds_len) & (USB_PAGE_SIZE - 1)) !=
+	    ((segs + 1)->ds_addr & (USB_PAGE_SIZE - 1))) {
 		/*
-		 * This check verifies that the physical address is correct:
+		 * This check verifies there is no page offset hole
+		 * between the first and second segment. See the
+		 * BUS_DMA_KEEP_PG_OFFSET flag.
 		 */
 		DPRINTFN(0, "Page offset was not preserved\n");
 		error = 1;
@@ -449,11 +481,19 @@
 		goto done;
 	}
 #endif
-	while (nseg > 0) {
-		nseg--;
-		segs++;
+	while (pc->ismultiseg) {
+		off += USB_PAGE_SIZE;
+		if (off >= (segs->ds_len + rem)) {
+			/* page crossing */
+			nseg--;
+			segs++;
+			off = 0;
+			rem = 0;
+			if (nseg == 0)
+				break;
+		}
 		pg++;
-		pg->physaddr = segs->ds_addr & ~(USB_PAGE_SIZE - 1);
+		pg->physaddr = (segs->ds_addr + off) & ~(USB_PAGE_SIZE - 1);
 	}
 
 done:

Modified: stable/0.8/sys/dev/usb/usb_busdma.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_busdma.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_busdma.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_busdma.h 291063 2015-11-19 09:54:28Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -60,7 +60,7 @@
  */
 struct usb_page {
 #if USB_HAVE_BUSDMA
-	bus_size_t physaddr;
+	bus_addr_t physaddr;
 	void   *buffer;			/* non Kernel Virtual Address */
 #endif
 };
@@ -73,7 +73,7 @@
 struct usb_page_search {
 	void   *buffer;
 #if USB_HAVE_BUSDMA
-	bus_size_t physaddr;
+	bus_addr_t physaddr;
 #endif
 	usb_size_t length;
 };
@@ -157,5 +157,8 @@
 void	usb_pc_cpu_invalidate(struct usb_page_cache *pc);
 void	usb_pc_dmamap_destroy(struct usb_page_cache *pc);
 void	usb_pc_free_mem(struct usb_page_cache *pc);
+uint8_t	usb_pc_buffer_is_aligned(struct usb_page_cache *pc,
+	    usb_frlength_t offset, usb_frlength_t len,
+	    usb_frlength_t mask);
 
 #endif					/* _USB_BUSDMA_H_ */

Modified: stable/0.8/sys/dev/usb/usb_cdc.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_cdc.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_cdc.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$NetBSD: usbcdc.h,v 1.9 2004/10/23 13:24:24 augustss Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/usb_cdc.h 213809 2010-10-13 22:04:55Z hselasky $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.

Modified: stable/0.8/sys/dev/usb/usb_compat_linux.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_compat_linux.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_compat_linux.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_compat_linux.c 254555 2013-08-20 07:28:24Z hselasky $ */
 /*-
  * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved.
  * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.
@@ -45,7 +45,6 @@
 #include <sys/priv.h>
 
 #include <dev/usb/usb.h>
-#include <dev/usb/usb_ioctl.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 

Modified: stable/0.8/sys/dev/usb/usb_compat_linux.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_compat_linux.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_compat_linux.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_compat_linux.h 198776 2009-11-01 21:48:18Z thompsa $ */
 /*-
  * Copyright (c) 2007 Luigi Rizzo - Universita` di Pisa. All rights reserved.
  * Copyright (c) 2007 Hans Petter Selasky. All rights reserved.

Modified: stable/0.8/sys/dev/usb/usb_controller.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_controller.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_controller.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_controller.h 259602 2013-12-19 07:12:40Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -186,6 +186,7 @@
 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);
+void	usb_bus_reset_async_locked(struct usb_bus *bus);
 #if USB_HAVE_TT_SUPPORT
 uint8_t	usbd_fs_isoc_schedule_alloc_slot(struct usb_xfer *isoc_xfer, uint16_t isoc_time);
 #endif

Modified: stable/0.8/sys/dev/usb/usb_core.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_core.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_core.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_core.c 217265 2011-01-11 13:59:06Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_core.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_core.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_core.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_core.h 278508 2015-02-10 13:18:48Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -97,6 +97,7 @@
 					 * sent */
 	uint8_t	control_act:1;		/* set if control transfer is active */
 	uint8_t	control_stall:1;	/* set if control transfer should be stalled */
+	uint8_t control_did_data:1;	/* set if control DATA has been transferred */
 
 	uint8_t	short_frames_ok:1;	/* filtered version */
 	uint8_t	short_xfer_ok:1;	/* filtered version */
@@ -113,6 +114,8 @@
 	uint8_t	can_cancel_immed:1;	/* set if USB transfer can be
 					 * cancelled immediately */
 	uint8_t	doing_callback:1;	/* set if executing the callback */
+	uint8_t maxp_was_clamped:1;	/* set if the max packet size 
+					 * was outside its allowed range */
 };
 
 /*

Modified: stable/0.8/sys/dev/usb/usb_debug.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_debug.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_debug.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_debug.c 242775 2012-11-08 16:13:51Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_debug.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_debug.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_debug.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_debug.h 242775 2012-11-08 16:13:51Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_dev.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_dev.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dev.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dev.c 301254 2016-06-03 08:56:54Z hselasky $ */
 /*-
  * Copyright (c) 2006-2008 Hans Petter Selasky. All rights reserved.
  *
@@ -105,7 +105,7 @@
 static int	usb_fifo_uiomove(struct usb_fifo *, void *, int,
 		    struct uio *);
 static void	usb_fifo_check_methods(struct usb_fifo_methods *);
-static struct	usb_fifo *usb_fifo_alloc(void);
+static struct	usb_fifo *usb_fifo_alloc(struct mtx *);
 static struct	usb_endpoint *usb_dev_get_ep(struct usb_device *, uint8_t,
 		    uint8_t);
 static void	usb_loc_fill(struct usb_fs_privdata *,
@@ -120,6 +120,7 @@
 static d_read_t usb_read;
 static d_write_t usb_write;
 static d_poll_t usb_poll;
+static d_kqfilter_t usb_kqfilter;
 
 static d_ioctl_t usb_static_ioctl;
 
@@ -137,7 +138,8 @@
 	.d_flags = D_TRACKCLOSE,
 	.d_read = usb_read,
 	.d_write = usb_write,
-	.d_poll = usb_poll
+	.d_poll = usb_poll,
+	.d_kqfilter = usb_kqfilter,
 };
 
 static struct cdev* usb_dev = NULL;
@@ -203,12 +205,18 @@
 		DPRINTFN(2, "no device at %u\n", cpd->dev_index);
 		goto error;
 	}
-	if (cpd->udev->refcount == USB_DEV_REF_MAX) {
-		DPRINTFN(2, "no dev ref\n");
+	if (cpd->udev->state == USB_STATE_DETACHED &&
+	    (need_uref != 2)) {
+		DPRINTFN(2, "device is detached\n");
 		goto error;
 	}
 	if (need_uref) {
 		DPRINTFN(2, "ref udev - needed\n");
+
+		if (cpd->udev->refcount == USB_DEV_REF_MAX) {
+			DPRINTFN(2, "no dev ref\n");
+			goto error;
+		}
 		cpd->udev->refcount++;
 
 		mtx_unlock(&usb_ref_lock);
@@ -217,7 +225,7 @@
 		 * We need to grab the enumeration SX-lock before
 		 * grabbing the FIFO refs to avoid deadlock at detach!
 		 */
-		crd->do_unlock = usbd_enum_lock(cpd->udev);
+		crd->do_unlock = usbd_enum_lock_sig(cpd->udev);
 
 		mtx_lock(&usb_ref_lock);
 
@@ -225,6 +233,12 @@
 		 * Set "is_uref" after grabbing the default SX lock
 		 */
 		crd->is_uref = 1;
+
+		/* check for signal */
+		if (crd->do_unlock > 1) {
+			crd->do_unlock = 0;
+			goto error;
+		}
 	}
 
 	/* check if we are doing an open */
@@ -282,12 +296,15 @@
 		usbd_enum_unlock(cpd->udev);
 
 	if (crd->is_uref) {
-		if (--(cpd->udev->refcount) == 0) {
-			cv_signal(&cpd->udev->ref_cv);
-		}
+		if (--(cpd->udev->refcount) == 0)
+			cv_broadcast(&cpd->udev->ref_cv);
 	}
 	mtx_unlock(&usb_ref_lock);
 	DPRINTFN(2, "fail\n");
+
+	/* clear all refs */
+	memset(crd, 0, sizeof(*crd));
+
 	return (USB_ERR_INVAL);
 }
 
@@ -350,24 +367,25 @@
 		crd->is_write = 0;
 	}
 	if (crd->is_uref) {
-		if (--(cpd->udev->refcount) == 0) {
-			cv_signal(&cpd->udev->ref_cv);
-		}
 		crd->is_uref = 0;
+		if (--(cpd->udev->refcount) == 0)
+			cv_broadcast(&cpd->udev->ref_cv);
 	}
 	mtx_unlock(&usb_ref_lock);
 }
 
 static struct usb_fifo *
-usb_fifo_alloc(void)
+usb_fifo_alloc(struct mtx *mtx)
 {
 	struct usb_fifo *f;
 
 	f = malloc(sizeof(*f), M_USBDEV, M_WAITOK | M_ZERO);
-	if (f) {
+	if (f != NULL) {
 		cv_init(&f->cv_io, "FIFO-IO");
 		cv_init(&f->cv_drain, "FIFO-DRAIN");
+		f->priv_mtx = mtx;
 		f->refcount = 1;
+		knlist_init_mtx(&f->selinfo.si_note, mtx);
 	}
 	return (f);
 }
@@ -491,7 +509,7 @@
 			DPRINTFN(5, "dev_get_endpoint returned NULL\n");
 			return (EINVAL);
 		}
-		f = usb_fifo_alloc();
+		f = usb_fifo_alloc(&udev->device_mtx);
 		if (f == NULL) {
 			DPRINTFN(5, "could not alloc tx fifo\n");
 			return (ENOMEM);
@@ -499,7 +517,6 @@
 		/* update some fields */
 		f->fifo_index = n + USB_FIFO_TX;
 		f->dev_ep_index = e;
-		f->priv_mtx = &udev->device_mtx;
 		f->priv_sc0 = ep;
 		f->methods = &usb_ugen_methods;
 		f->iface_index = ep->iface_index;
@@ -518,7 +535,7 @@
 			DPRINTFN(5, "dev_get_endpoint returned NULL\n");
 			return (EINVAL);
 		}
-		f = usb_fifo_alloc();
+		f = usb_fifo_alloc(&udev->device_mtx);
 		if (f == NULL) {
 			DPRINTFN(5, "could not alloc rx fifo\n");
 			return (ENOMEM);
@@ -526,7 +543,6 @@
 		/* update some fields */
 		f->fifo_index = n + USB_FIFO_RX;
 		f->dev_ep_index = e;
-		f->priv_mtx = &udev->device_mtx;
 		f->priv_sc0 = ep;
 		f->methods = &usb_ugen_methods;
 		f->iface_index = ep->iface_index;
@@ -579,12 +595,12 @@
 
 	/* decrease refcount */
 	f->refcount--;
-	/* prevent any write flush */
-	f->flag_iserror = 1;
 	/* need to wait until all callers have exited */
 	while (f->refcount != 0) {
 		mtx_unlock(&usb_ref_lock);	/* avoid LOR */
 		mtx_lock(f->priv_mtx);
+		/* prevent write flush, if any */
+		f->flag_iserror = 1;
 		/* get I/O thread out of any sleep state */
 		if (f->flag_sleeping) {
 			f->flag_sleeping = 0;
@@ -593,6 +609,13 @@
 		mtx_unlock(f->priv_mtx);
 		mtx_lock(&usb_ref_lock);
 
+		/*
+		 * Check if the "f->refcount" variable reached zero
+		 * during the unlocked time before entering wait:
+		 */
+		if (f->refcount == 0)
+			break;
+
 		/* wait for sync */
 		cv_wait(&f->cv_drain, &usb_ref_lock);
 	}
@@ -604,6 +627,10 @@
 	cv_destroy(&f->cv_io);
 	cv_destroy(&f->cv_drain);
 
+	knlist_clear(&f->selinfo.si_note, 0);
+	seldrain(&f->selinfo);
+	knlist_destroy(&f->selinfo.si_note);
+
 	free(f, M_USBDEV);
 }
 
@@ -758,8 +785,13 @@
 	mtx_lock(f->priv_mtx);
 
 	/* clear current cdev private data pointer */
+	mtx_lock(&usb_ref_lock);
 	f->curr_cpd = NULL;
+	mtx_unlock(&usb_ref_lock);
 
+	/* check if we are watched by kevent */
+	KNOTE_LOCKED(&f->selinfo.si_note, 0);
+
 	/* check if we are selected */
 	if (f->flag_isselect) {
 		selwakeup(&f->selinfo);
@@ -801,7 +833,8 @@
 			    (!f->flag_iserror)) {
 				/* wait until all data has been written */
 				f->flag_sleeping = 1;
-				err = cv_wait_sig(&f->cv_io, f->priv_mtx);
+				err = cv_timedwait_sig(&f->cv_io, f->priv_mtx,
+				    USB_MS_TO_TICKS(USB_DEFAULT_TIMEOUT));
 				if (err) {
 					DPRINTF("signal received\n");
 					break;
@@ -911,23 +944,12 @@
 
 	DPRINTFN(2, "cpd=%p\n", cpd);
 
-	err = usb_ref_device(cpd, &refs, 0);
-	if (err)
+	err = usb_ref_device(cpd, &refs,
+	    2 /* uref and allow detached state */);
+	if (err) {
+		DPRINTFN(2, "Cannot grab USB reference when "
+		    "closing USB file handle\n");
 		goto done;
-
-	/*
-	 * If this function is not called directly from the root HUB
-	 * thread, there is usually a need to lock the enumeration
-	 * lock. Check this.
-	 */
-	if (!usbd_enum_is_locked(cpd->udev)) {
-
-		DPRINTFN(2, "Locking enumeration\n");
-
-		/* reference device */
-		err = usb_usb_ref_device(cpd, &refs);
-		if (err)
-			goto done;
 	}
 	if (cpd->fflags & FREAD) {
 		usb_fifo_close(refs.rxfifo, cpd->fflags);
@@ -1079,8 +1101,8 @@
 		goto done;
 
 	if (usb_usb_ref_device(cpd, &refs)) {
-		err = ENXIO;
-		goto done;
+		/* we lost the reference */
+		return (ENXIO);
 	}
 
 	err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
@@ -1095,15 +1117,19 @@
 
 	/* Wait for re-enumeration, if any */
 
-	while (f->udev->re_enumerate_wait != 0) {
+	while (f->udev->re_enumerate_wait != USB_RE_ENUM_DONE) {
 
 		usb_unref_device(cpd, &refs);
 
 		usb_pause_mtx(NULL, hz / 128);
 
-		if (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
-			err = ENXIO;
-			goto done;
+		while (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
+			if (usb_ref_device(cpd, &refs, 0)) {
+				/* device no longer exists */
+				return (ENXIO);
+			}
+			usb_unref_device(cpd, &refs);
+			usb_pause_mtx(NULL, hz / 128);
 		}
 	}
 
@@ -1112,8 +1138,164 @@
 	return (err);
 }
 
+static void
+usb_filter_detach(struct knote *kn)
+{
+	struct usb_fifo *f = kn->kn_hook;
+	knlist_remove(&f->selinfo.si_note, kn, 0);
+}
+
+static int
+usb_filter_write(struct knote *kn, long hint)
+{
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	struct usb_mbuf *m;
+
+	DPRINTFN(2, "\n");
+
+	f = kn->kn_hook;
+
+	mtx_assert(f->priv_mtx, MA_OWNED);
+
+	cpd = f->curr_cpd;
+	if (cpd == NULL) {
+		m = (void *)1;
+	} else if (f->fs_ep_max == 0) {
+		if (f->flag_iserror) {
+			/* we got an error */
+			m = (void *)1;
+		} else {
+			if (f->queue_data == NULL) {
+				/*
+				 * start write transfer, if not
+				 * already started
+				 */
+				(f->methods->f_start_write) (f);
+			}
+			/* check if any packets are available */
+			USB_IF_POLL(&f->free_q, m);
+		}
+	} else {
+		if (f->flag_iscomplete) {
+			m = (void *)1;
+		} else {
+			m = NULL;
+		}
+	}
+	return (m ? 1 : 0);
+}
+
+static int
+usb_filter_read(struct knote *kn, long hint)
+{
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	struct usb_mbuf *m;
+
+	DPRINTFN(2, "\n");
+
+	f = kn->kn_hook;
+
+	mtx_assert(f->priv_mtx, MA_OWNED);
+
+	cpd = f->curr_cpd;
+	if (cpd == NULL) {
+		m = (void *)1;
+	} else if (f->fs_ep_max == 0) {
+		if (f->flag_iserror) {
+			/* we have an error */
+			m = (void *)1;
+		} else {
+			if (f->queue_data == NULL) {
+				/*
+				 * start read transfer, if not
+				 * already started
+				 */
+				(f->methods->f_start_read) (f);
+			}
+			/* check if any packets are available */
+			USB_IF_POLL(&f->used_q, m);
+
+			/* start reading data, if any */
+			if (m == NULL)
+				(f->methods->f_start_read) (f);
+		}
+	} else {
+		if (f->flag_iscomplete) {
+			m = (void *)1;
+		} else {
+			m = NULL;
+		}
+	}
+	return (m ? 1 : 0);
+}
+
+static struct filterops usb_filtops_write = {
+	.f_isfd = 1,
+	.f_detach = usb_filter_detach,
+	.f_event = usb_filter_write,
+};
+
+static struct filterops usb_filtops_read = {
+	.f_isfd = 1,
+	.f_detach = usb_filter_detach,
+	.f_event = usb_filter_read,
+};
+
+
 /* ARGSUSED */
 static int
+usb_kqfilter(struct cdev* dev, struct knote *kn)
+{
+	struct usb_cdev_refdata refs;
+	struct usb_cdev_privdata* cpd;
+	struct usb_fifo *f;
+	int fflags;
+	int err = EINVAL;
+
+	DPRINTFN(2, "\n");
+
+	if (devfs_get_cdevpriv((void **)&cpd) != 0 ||
+	    usb_ref_device(cpd, &refs, 0) != 0)
+		return (ENXIO);
+
+	fflags = cpd->fflags;
+
+	/* Figure out who needs service */
+	switch (kn->kn_filter) {
+	case EVFILT_WRITE:
+		if (fflags & FWRITE) {
+			f = refs.txfifo;
+			kn->kn_fop = &usb_filtops_write;
+			err = 0;
+		}
+		break;
+	case EVFILT_READ:
+		if (fflags & FREAD) {
+			f = refs.rxfifo;
+			kn->kn_fop = &usb_filtops_read;
+			err = 0;
+		}
+		break;
+	default:
+		err = EOPNOTSUPP;
+		break;
+	}
+
+	if (err == 0) {
+		kn->kn_hook = f;
+		mtx_lock(f->priv_mtx);
+		knlist_add(&f->selinfo.si_note, kn, 1);
+		mtx_unlock(f->priv_mtx);
+	}
+
+	usb_unref_device(cpd, &refs);
+	return (err);
+}
+
+/* ARGSUSED */
+static int
 usb_poll(struct cdev* dev, int events, struct thread* td)
 {
 	struct usb_cdev_refdata refs;
@@ -1179,7 +1361,7 @@
 
 		if (!refs.is_usbfs) {
 			if (f->flag_iserror) {
-				/* we have and error */
+				/* we have an error */
 				m = (void *)1;
 			} else {
 				if (f->queue_data == NULL) {
@@ -1236,9 +1418,9 @@
 		return (err);
 
 	err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
-	if (err) {
+	if (err)
 		return (ENXIO);
-	}
+
 	fflags = cpd->fflags;
 
 	f = refs.rxfifo;
@@ -1362,9 +1544,9 @@
 		return (err);
 
 	err = usb_ref_device(cpd, &refs, 0 /* no uref */ );
-	if (err) {
+	if (err)
 		return (ENXIO);
-	}
+
 	fflags = cpd->fflags;
 
 	f = refs.txfifo;
@@ -1576,6 +1758,8 @@
 {
 	usb_fifo_signal(f);
 
+	KNOTE_LOCKED(&f->selinfo.si_note, 0);
+
 	if (f->flag_isselect) {
 		selwakeup(&f->selinfo);
 		f->flag_isselect = 0;
@@ -1691,8 +1875,8 @@
 		break;
 	}
 
-	f_tx = usb_fifo_alloc();
-	f_rx = usb_fifo_alloc();
+	f_tx = usb_fifo_alloc(priv_mtx);
+	f_rx = usb_fifo_alloc(priv_mtx);
 
 	if ((f_tx == NULL) || (f_rx == NULL)) {
 		usb_fifo_free(f_tx);
@@ -1703,7 +1887,6 @@
 
 	f_tx->fifo_index = n + USB_FIFO_TX;
 	f_tx->dev_ep_index = -1;
-	f_tx->priv_mtx = priv_mtx;
 	f_tx->priv_sc0 = priv_sc;
 	f_tx->methods = pm;
 	f_tx->iface_index = iface_index;
@@ -1711,7 +1894,6 @@
 
 	f_rx->fifo_index = n + USB_FIFO_RX;
 	f_rx->dev_ep_index = -1;
-	f_rx->priv_mtx = priv_mtx;
 	f_rx->priv_sc0 = priv_sc;
 	f_rx->methods = pm;
 	f_rx->iface_index = iface_index;

Modified: stable/0.8/sys/dev/usb/usb_dev.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_dev.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dev.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dev.h 247090 2013-02-21 07:48:07Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_device.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_device.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_device.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_device.c 310283 2016-12-19 18:32:26Z trasz $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -94,7 +94,7 @@
 		    struct usb_attach_arg *);
 static void	usb_suspend_resume_sub(struct usb_device *, device_t,
 		    uint8_t);
-static void	usbd_clear_stall_proc(struct usb_proc_msg *_pm);
+static usb_proc_callback_t usbd_clear_stall_proc;
 static usb_error_t usb_config_parse(struct usb_device *, uint8_t, uint8_t);
 static void	usbd_set_device_strings(struct usb_device *);
 #if USB_HAVE_DEVCTL
@@ -431,6 +431,33 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usb_wait_pending_refs
+ *
+ * This function will wait for any USB references to go away before
+ * returning. This function is used before freeing a USB device.
+ *------------------------------------------------------------------------*/
+static void
+usb_wait_pending_refs(struct usb_device *udev)
+{
+#if USB_HAVE_UGEN
+	DPRINTF("Refcount = %d\n", (int)udev->refcount); 
+
+	mtx_lock(&usb_ref_lock);
+	udev->refcount--;
+	while (1) {
+		/* wait for any pending references to go away */
+		if (udev->refcount == 0) {
+			/* prevent further refs being taken, if any */
+			udev->refcount = USB_DEV_REF_MAX;
+			break;
+		}
+		cv_wait(&udev->ref_cv, &usb_ref_lock);
+	}
+	mtx_unlock(&usb_ref_lock);
+#endif
+}
+
+/*------------------------------------------------------------------------*
  *	usb_unconfigure
  *
  * This function will free all USB interfaces and USB endpoints belonging
@@ -779,9 +806,6 @@
 			/* find maximum number of endpoints */
 			if (ep_max < temp)
 				ep_max = temp;
-
-			/* optimalisation */
-			id = (struct usb_interface_descriptor *)ed;
 		}
 	}
 
@@ -1035,10 +1059,12 @@
 		 */
 		*ppdev = NULL;
 
-		device_printf(dev, "at %s, port %d, addr %d "
-		    "(disconnected)\n",
-		    device_get_nameunit(udev->parent_dev),
-		    udev->port_no, udev->address);
+		if (!rebooting) {
+			device_printf(dev, "at %s, port %d, addr %d "
+			    "(disconnected)\n",
+			    device_get_nameunit(udev->parent_dev),
+			    udev->port_no, udev->address);
+		}
 
 		if (device_is_attached(dev)) {
 			if (udev->flags.peer_suspended) {
@@ -1047,10 +1073,8 @@
 					device_printf(dev, "Resume failed\n");
 				}
 			}
-			if (device_detach(dev)) {
-				goto error;
-			}
 		}
+		/* detach and delete child */
 		if (device_delete_child(udev->parent_dev, dev)) {
 			goto error;
 		}
@@ -1287,6 +1311,12 @@
 	 */
 	if (iface_index == USB_IFACE_INDEX_ANY) {
 
+		if (usb_test_quirk(&uaa, UQ_MSC_DYMO_EJECT) != 0 &&
+		    usb_dymo_eject(udev, 0) == 0) {
+			/* success, mark the udev as disappearing */
+			uaa.dev_state = UAA_DEV_EJECTING;
+		}
+
 		EVENTHANDLER_INVOKE(usb_dev_configured, udev, &uaa);
 
 		if (uaa.dev_state != UAA_DEV_READY) {
@@ -1444,7 +1474,7 @@
 static void
 usbd_clear_stall_proc(struct usb_proc_msg *_pm)
 {
-	struct usb_clear_stall_msg *pm = (void *)_pm;
+	struct usb_udev_msg *pm = (void *)_pm;
 	struct usb_device *udev = pm->udev;
 
 	/* Change lock */
@@ -1523,6 +1553,7 @@
 	/* initialise our SX-lock */
 	sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
 	sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
+	sx_init_flags(&udev->ctrl_sx, "USB control transfer SX lock", SX_DUPOK);
 
 	cv_init(&udev->ctrlreq_cv, "WCTRL");
 	cv_init(&udev->ref_cv, "UGONE");
@@ -1673,10 +1704,14 @@
 	err = usbd_setup_device_desc(udev, NULL);
 
 	if (err != 0) {
-		/* XXX try to re-enumerate the device */
+		/* try to enumerate two more times */
 		err = usbd_req_re_enumerate(udev, NULL);
-		if (err)
-			goto done;
+		if (err != 0) {
+			err = usbd_req_re_enumerate(udev, NULL);
+			if (err != 0) {
+				goto done;
+			}
+		}
 	}
 
 	/*
@@ -1704,11 +1739,13 @@
 	 */
 
 	/* Protect scratch area */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
 	scratch_ptr = udev->scratch.data;
 
-	if (udev->ddesc.iManufacturer ||
+	if (udev->flags.no_strings) {
+		err = USB_ERR_INVAL;
+	} else if (udev->ddesc.iManufacturer ||
 	    udev->ddesc.iProduct ||
 	    udev->ddesc.iSerialNumber) {
 		/* read out the language ID string */
@@ -1753,7 +1790,7 @@
 	}
 
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 
 	/* assume 100mA bus powered for now. Changed when configured. */
 	udev->power = USB_MIN_POWER;
@@ -1867,8 +1904,8 @@
 	udev->ugen_symlink = usb_alloc_symlink(udev->ugen_name);
 
 	/* Announce device */
-	printf("%s: <%s> at %s\n", udev->ugen_name,
-	    usb_get_manufacturer(udev),
+	printf("%s: <%s %s> at %s\n", udev->ugen_name,
+	    usb_get_manufacturer(udev), usb_get_product(udev),
 	    device_get_nameunit(udev->bus->bdev));
 #endif
 
@@ -1925,14 +1962,46 @@
 }
 
 void
+usb_destroy_dev_sync(struct usb_fs_privdata *pd)
+{
+	DPRINTFN(1, "Destroying device at ugen%d.%d\n",
+	    pd->bus_index, pd->dev_index);
+
+	/*
+	 * Destroy character device synchronously. After this
+	 * all system calls are returned. Can block.
+	 */
+	destroy_dev(pd->cdev);
+
+	free(pd, M_USBDEV);
+}
+
+void
 usb_destroy_dev(struct usb_fs_privdata *pd)
 {
+	struct usb_bus *bus;
+
 	if (pd == NULL)
 		return;
 
-	destroy_dev(pd->cdev);
+	mtx_lock(&usb_ref_lock);
+	bus = devclass_get_softc(usb_devclass_ptr, pd->bus_index);
+	mtx_unlock(&usb_ref_lock);
 
-	free(pd, M_USBDEV);
+	if (bus == NULL) {
+		usb_destroy_dev_sync(pd);
+		return;
+	}
+
+	/* make sure we can re-use the device name */
+	delist_dev(pd->cdev);
+
+	USB_BUS_LOCK(bus);
+	LIST_INSERT_HEAD(&bus->pd_cleanup_list, pd, pd_next);
+	/* get cleanup going */
+	usb_proc_msignal(&bus->explore_proc,
+	    &bus->cleanup_msg[0], &bus->cleanup_msg[1]);
+	USB_BUS_UNLOCK(bus);
 }
 
 static void
@@ -2032,6 +2101,8 @@
 	DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no);
 
 	bus = udev->bus;
+
+	/* set DETACHED state to prevent any further references */
 	usb_set_device_state(udev, USB_STATE_DETACHED);
 
 #if USB_HAVE_DEVCTL
@@ -2039,8 +2110,11 @@
 #endif
 
 #if USB_HAVE_UGEN
-	printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
-	    usb_get_manufacturer(udev), device_get_nameunit(bus->bdev));
+	if (!rebooting) {
+		printf("%s: <%s %s> at %s (disconnected)\n", udev->ugen_name,
+		    usb_get_manufacturer(udev), usb_get_product(udev),
+		    device_get_nameunit(bus->bdev));
+	}
 
 	/* Destroy UGEN symlink, if any */
 	if (udev->ugen_symlink) {
@@ -2047,24 +2121,7 @@
 		usb_free_symlink(udev->ugen_symlink);
 		udev->ugen_symlink = NULL;
 	}
-#endif
-	/*
-	 * Unregister our device first which will prevent any further
-	 * references:
-	 */
-	usb_bus_port_set_device(bus, udev->parent_hub ?
-	    udev->parent_hub->hub->ports + udev->port_index : NULL,
-	    NULL, USB_ROOT_HUB_ADDR);
 
-#if USB_HAVE_UGEN
-	/* wait for all pending references to go away: */
-	mtx_lock(&usb_ref_lock);
-	udev->refcount--;
-	while (udev->refcount != 0) {
-		cv_wait(&udev->ref_cv, &usb_ref_lock);
-	}
-	mtx_unlock(&usb_ref_lock);
-
 	usb_destroy_dev(udev->ctrl_dev);
 #endif
 
@@ -2076,6 +2133,11 @@
 	/* the following will get the device unconfigured in software */
 	usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_EP0);
 
+	/* final device unregister after all character devices are closed */
+	usb_bus_port_set_device(bus, udev->parent_hub ?
+	    udev->parent_hub->hub->ports + udev->port_index : NULL,
+	    NULL, USB_ROOT_HUB_ADDR);
+
 	/* unsetup any leftover default USB transfers */
 	usbd_transfer_unsetup(udev->ctrl_xfer, USB_CTRL_XFER_MAX);
 
@@ -2091,8 +2153,12 @@
 	    &udev->cs_msg[0], &udev->cs_msg[1]);
 	USB_BUS_UNLOCK(udev->bus);
 
+	/* wait for all references to go away */
+	usb_wait_pending_refs(udev);
+	
 	sx_destroy(&udev->enum_sx);
 	sx_destroy(&udev->sr_sx);
+	sx_destroy(&udev->ctrl_sx);
 
 	cv_destroy(&udev->ctrlreq_cv);
 	cv_destroy(&udev->ref_cv);
@@ -2256,7 +2322,7 @@
 	uint8_t do_unlock;
 
 	/* Protect scratch area */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
 	temp_ptr = (char *)udev->scratch.data;
 	temp_size = sizeof(udev->scratch.data);
@@ -2316,7 +2382,7 @@
 	}
 
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 }
 
 /*
@@ -2609,8 +2675,14 @@
 
 	DPRINTF("udev %p state %s -> %s\n", udev,
 	    usb_statestr(udev->state), usb_statestr(state));
+
+#if USB_HAVE_UGEN
+	mtx_lock(&usb_ref_lock);
+#endif
 	udev->state = state;
-
+#if USB_HAVE_UGEN
+	mtx_unlock(&usb_ref_lock);
+#endif
 	if (udev->bus->methods->device_state_change != NULL)
 		(udev->bus->methods->device_state_change) (udev);
 }
@@ -2632,7 +2704,7 @@
 /*
  * The following function locks enumerating the given USB device. If
  * the lock is already grabbed this function returns zero. Else a
- * non-zero value is returned.
+ * a value of one is returned.
  */
 uint8_t
 usbd_enum_lock(struct usb_device *udev)
@@ -2651,6 +2723,27 @@
 	return (1);
 }
 
+#if USB_HAVE_UGEN
+/*
+ * This function is the same like usbd_enum_lock() except a value of
+ * 255 is returned when a signal is pending:
+ */
+uint8_t
+usbd_enum_lock_sig(struct usb_device *udev)
+{
+	if (sx_xlocked(&udev->enum_sx))
+		return (0);
+	if (sx_xlock_sig(&udev->enum_sx))
+		return (255);
+	if (sx_xlock_sig(&udev->sr_sx)) {
+		sx_xunlock(&udev->enum_sx);
+		return (255);
+	}
+	mtx_lock(&Giant);
+	return (1);
+}
+#endif
+
 /* The following function unlocks enumerating the given USB device. */
 
 void
@@ -2696,6 +2789,40 @@
 }
 
 /*
+ * The following function is used to serialize access to USB control
+ * transfers and the USB scratch area. If the lock is already grabbed
+ * this function returns zero. Else a value of one is returned.
+ */
+uint8_t
+usbd_ctrl_lock(struct usb_device *udev)
+{
+	if (sx_xlocked(&udev->ctrl_sx))
+		return (0);
+	sx_xlock(&udev->ctrl_sx);
+
+	/*
+	 * We need to allow suspend and resume at this point, else the
+	 * control transfer will timeout if the device is suspended!
+	 */
+	if (usbd_enum_is_locked(udev))
+		usbd_sr_unlock(udev);
+	return (1);
+}
+
+void
+usbd_ctrl_unlock(struct usb_device *udev)
+{
+	sx_xunlock(&udev->ctrl_sx);
+
+	/*
+	 * Restore the suspend and resume lock after we have unlocked
+	 * the USB control transfer lock to avoid LOR:
+	 */
+	if (usbd_enum_is_locked(udev))
+		usbd_sr_lock(udev);
+}
+
+/*
  * The following function is used to set the per-interface specific
  * plug and play information. The string referred to by the pnpinfo
  * argument can safely be freed after calling this function. The

Modified: stable/0.8/sys/dev/usb/usb_device.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_device.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_device.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_device.h 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -53,7 +53,7 @@
 #define	USB_UNCFG_FLAG_NONE 0x00
 #define	USB_UNCFG_FLAG_FREE_EP0	0x02		/* endpoint zero is freed */
 
-struct usb_clear_stall_msg {
+struct usb_udev_msg {
 	struct usb_proc_msg hdr;
 	struct usb_device *udev;
 };
@@ -162,7 +162,7 @@
 
 /* 
  * The scratch area for USB devices. Access to this structure is
- * protected by the enumeration SX lock.
+ * protected by the control SX lock.
  */
 union usb_device_scratch {
 	struct usb_hw_ep_scratch hw_ep_scratch[1];
@@ -179,10 +179,11 @@
  * these structures for every USB device.
  */
 struct usb_device {
-	struct usb_clear_stall_msg cs_msg[2];	/* generic clear stall
-						 * messages */
+	/* generic clear stall message */
+	struct usb_udev_msg cs_msg[2];
 	struct sx enum_sx;
 	struct sx sr_sx;
+  	struct sx ctrl_sx;
 	struct mtx device_mtx;
 	struct cv ctrlreq_cv;
 	struct cv ref_cv;
@@ -220,6 +221,7 @@
 	uint8_t	address;		/* device addess */
 	uint8_t	device_index;		/* device index in "bus->devices" */
 	uint8_t	controller_slot_id;	/* controller specific value */
+	uint8_t next_config_index;	/* used by USB_RE_ENUM_SET_CONFIG */
 	uint8_t	curr_config_index;	/* current configuration index */
 	uint8_t	curr_config_no;		/* current configuration number */
 	uint8_t	depth;			/* distance from root HUB */
@@ -230,6 +232,10 @@
 	uint8_t	driver_added_refcount;	/* our driver added generation count */
 	uint8_t	power_mode;		/* see USB_POWER_XXX */
 	uint8_t re_enumerate_wait;	/* set if re-enum. is in progress */
+#define	USB_RE_ENUM_DONE	0
+#define	USB_RE_ENUM_START	1
+#define	USB_RE_ENUM_PWR_OFF	2
+#define	USB_RE_ENUM_SET_CONFIG	3
 	uint8_t ifaces_max;		/* number of interfaces present */
 	uint8_t endpoints_max;		/* number of endpoints present */
 
@@ -276,6 +282,7 @@
 struct usb_fs_privdata *usb_make_dev(struct usb_device *, const char *,
 		    int, int, int, uid_t, gid_t, int);
 void	usb_destroy_dev(struct usb_fs_privdata *);
+void	usb_destroy_dev_sync(struct usb_fs_privdata *);
 #endif
 usb_error_t	usb_probe_and_attach(struct usb_device *udev,
 		    uint8_t iface_index);
@@ -296,9 +303,20 @@
 enum usb_dev_state usb_get_device_state(struct usb_device *);
 
 uint8_t	usbd_enum_lock(struct usb_device *);
+#if USB_HAVE_UGEN
+uint8_t	usbd_enum_lock_sig(struct usb_device *);
+#endif
 void	usbd_enum_unlock(struct usb_device *);
 void	usbd_sr_lock(struct usb_device *);
 void	usbd_sr_unlock(struct usb_device *);
+uint8_t	usbd_ctrl_lock(struct usb_device *);
+void	usbd_ctrl_unlock(struct usb_device *);
 uint8_t usbd_enum_is_locked(struct usb_device *);
 
+#if USB_HAVE_TT_SUPPORT
+void	uhub_tt_buffer_reset_async_locked(struct usb_device *, struct usb_endpoint *);
+#endif
+
+uint8_t uhub_count_active_host_ports(struct usb_device *, enum usb_dev_speed);
+
 #endif					/* _USB_DEVICE_H_ */

Modified: stable/0.8/sys/dev/usb/usb_dynamic.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_dynamic.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dynamic.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dynamic.c 273889 2014-10-31 08:06:21Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -64,7 +64,7 @@
 usb_temp_unsetup_t *usb_temp_unsetup_p = &usb_temp_unsetup_w;
 usb_test_quirk_t *usb_test_quirk_p = &usb_test_quirk_w;
 usb_quirk_ioctl_t *usb_quirk_ioctl_p = &usb_quirk_ioctl_w;
-devclass_t usb_devclass_ptr = NULL;
+devclass_t usb_devclass_ptr;
 
 static usb_error_t
 usb_temp_setup_by_index_w(struct usb_device *udev, uint16_t index)

Modified: stable/0.8/sys/dev/usb/usb_dynamic.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_dynamic.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_dynamic.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_dynamic.h 225469 2011-09-10 15:55:36Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_endian.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_endian.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_endian.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_endian.h 196219 2009-08-14 20:03:53Z jhb $ */
 /*
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_error.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_error.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_error.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_error.c 217265 2011-01-11 13:59:06Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_freebsd.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_freebsd.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_freebsd.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_freebsd.h 277363 2015-01-19 07:03:40Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -43,6 +43,9 @@
 #define	USB_HAVE_MSCTEST 1
 #define	USB_HAVE_PF 1
 
+/* define zero ticks callout value */
+#define	USB_CALLOUT_ZERO_TICKS 1
+
 #define	USB_TD_GET_PROC(td) (td)->td_proc
 #define	USB_PROC_GET_GID(td) (td)->p_pgid
 
@@ -68,7 +71,7 @@
 #define	USB_EP0_BUFSIZE		1024	/* bytes */
 #define	USB_CS_RESET_LIMIT	20	/* failures = 20 * 50 ms = 1sec */
 
-#define	USB_MAX_AUTO_QUIRK	4	/* maximum number of dynamic quirks */
+#define	USB_MAX_AUTO_QUIRK	8	/* maximum number of dynamic quirks */
 
 typedef uint32_t usb_timeout_t;		/* milliseconds */
 typedef uint32_t usb_frlength_t;	/* bytes */

Modified: stable/0.8/sys/dev/usb/usb_generic.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_generic.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_generic.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_generic.c 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -610,10 +610,7 @@
 		/* not possible in device side mode */
 		return (ENOTTY);
 	}
-	if (f->udev->curr_config_index == index) {
-		/* no change needed */
-		return (0);
-	}
+
 	/* make sure all FIFO's are gone */
 	/* else there can be a deadlock */
 	if (ugen_fs_uninit(f)) {
@@ -620,14 +617,10 @@
 		/* ignore any errors */
 		DPRINTFN(6, "no FIFOs\n");
 	}
-	/* change setting - will free generic FIFOs, if any */
-	if (usbd_set_config_index(f->udev, index)) {
+
+	if (usbd_start_set_config(f->udev, index) != 0)
 		return (EIO);
-	}
-	/* probe and attach */
-	if (usb_probe_and_attach(f->udev, USB_IFACE_INDEX_ANY)) {
-		return (EIO);
-	}
+
 	return (0);
 }
 
@@ -713,10 +706,6 @@
 	return (error);
 }
 
-/*
- * This function is called having the enumeration SX locked which
- * protects the scratch area used.
- */
 static int
 ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd)
 {
@@ -723,7 +712,11 @@
 	void *ptr;
 	uint16_t size;
 	int error;
+	uint8_t do_unlock;
 
+	/* Protect scratch area */
+	do_unlock = usbd_ctrl_lock(f->udev);
+
 	ptr = f->udev->scratch.data;
 	size = sizeof(f->udev->scratch.data);
 
@@ -743,6 +736,9 @@
 
 		error = copyout(ptr, ugd->ugd_data, size);
 	}
+	if (do_unlock)
+		usbd_ctrl_unlock(f->udev);
+
 	return (error);
 }
 
@@ -961,11 +957,6 @@
 		DPRINTFN(6, "device mode\n");
 		return (ENOTTY);
 	}
-	if (udev->parent_hub == NULL) {
-		/* the root HUB cannot be re-enumerated */
-		DPRINTFN(6, "cannot reset root HUB\n");
-		return (EINVAL);
-	}
 	/* make sure all FIFO's are gone */
 	/* else there can be a deadlock */
 	if (ugen_fs_uninit(f)) {
@@ -1749,16 +1740,11 @@
 
 	switch (mode) {
 	case USB_POWER_MODE_OFF:
-		/* get the device unconfigured */
-		err = ugen_set_config(f, USB_UNCONFIG_INDEX);
-		if (err) {
-			DPRINTFN(0, "Could not unconfigure "
-			    "device (ignored)\n");
+		if (udev->flags.usb_mode == USB_MODE_HOST &&
+		    udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+			udev->re_enumerate_wait = USB_RE_ENUM_PWR_OFF;
 		}
-
-		/* clear port enable */
-		err = usbd_req_clear_port_feature(udev->parent_hub,
-		    NULL, udev->port_no, UHF_PORT_ENABLE);
+		/* set power mode will wake up the explore thread */
 		break;
 
 	case USB_POWER_MODE_ON:
@@ -1806,9 +1792,9 @@
 
 	/* if we are powered off we need to re-enumerate first */
 	if (old_mode == USB_POWER_MODE_OFF) {
-		if (udev->flags.usb_mode == USB_MODE_HOST) {
-			if (udev->re_enumerate_wait == 0)
-				udev->re_enumerate_wait = 1;
+		if (udev->flags.usb_mode == USB_MODE_HOST &&
+		    udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+			udev->re_enumerate_wait = USB_RE_ENUM_START;
 		}
 		/* set power mode will wake up the explore thread */
 	}
@@ -1831,6 +1817,45 @@
 }
 
 static int
+ugen_get_port_path(struct usb_fifo *f, struct usb_device_port_path *dpp)
+{
+	struct usb_device *udev = f->udev;
+	struct usb_device *next;
+	unsigned int nlevel = 0;
+
+	if (udev == NULL)
+		goto error;
+
+	dpp->udp_bus = device_get_unit(udev->bus->bdev);
+	dpp->udp_index = udev->device_index;
+
+	/* count port levels */
+	next = udev;
+	while (next->parent_hub != NULL) {
+		nlevel++;
+		next = next->parent_hub;
+	}
+
+	/* check if too many levels */
+	if (nlevel > USB_DEVICE_PORT_PATH_MAX)
+		goto error;
+
+	/* store total level of ports */
+	dpp->udp_port_level = nlevel;
+
+	/* store port index array */
+	next = udev;
+	while (next->parent_hub != NULL) {
+		dpp->udp_port_no[--nlevel] = next->port_no;
+		next = next->parent_hub;
+	}
+	return (0);	/* success */
+
+error:
+	return (EINVAL);	/* failure */
+}
+
+static int
 ugen_get_power_usage(struct usb_fifo *f)
 {
 	struct usb_device *udev = f->udev;
@@ -2031,6 +2056,7 @@
 		struct usb_device_stats *stat;
 		struct usb_fs_init *pinit;
 		struct usb_fs_uninit *puninit;
+		struct usb_device_port_path *dpp;
 		uint32_t *ptime;
 		void   *addr;
 		int    *pint;
@@ -2203,6 +2229,10 @@
 		*u.pint = ugen_get_power_mode(f);
 		break;
 
+	case USB_GET_DEV_PORT_PATH:
+		error = ugen_get_port_path(f, u.dpp);
+		break;
+
 	case USB_GET_POWER_USAGE:
 		*u.pint = ugen_get_power_usage(f);
 		break;

Modified: stable/0.8/sys/dev/usb/usb_generic.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_generic.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_generic.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_generic.h 196219 2009-08-14 20:03:53Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_handle_request.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_handle_request.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_handle_request.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_handle_request.c 247090 2013-02-21 07:48:07Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_hid.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_hid.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hid.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -2,7 +2,7 @@
 
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/usb_hid.c 296445 2016-03-07 09:39:35Z hselasky $");
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -353,7 +353,8 @@
 					/* range check usage count */
 					if (c->loc.count > 255) {
 						DPRINTFN(0, "Number of "
-						    "items truncated to 255\n");
+						    "items(%u) truncated to 255\n",
+						    (unsigned)(c->loc.count));
 						s->ncount = 255;
 					} else
 						s->ncount = c->loc.count;

Modified: stable/0.8/sys/dev/usb/usb_hub.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_hub.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hub.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_hub.c 279637 2015-03-05 09:35:15Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -50,7 +50,6 @@
 #include <sys/priv.h>
 
 #include <dev/usb/usb.h>
-#include <dev/usb/usb_ioctl.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 
@@ -71,7 +70,13 @@
 #include <dev/usb/usb_bus.h>
 
 #define	UHUB_INTR_INTERVAL 250		/* ms */
-#define	UHUB_N_TRANSFER 1
+enum {
+	UHUB_INTR_TRANSFER,
+#if USB_HAVE_TT_SUPPORT
+	UHUB_RESET_TT_TRANSFER,
+#endif
+	UHUB_N_TRANSFER,
+};
 
 #ifdef USB_DEBUG
 static int uhub_debug = 0;
@@ -124,6 +129,9 @@
 static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
 
 static usb_callback_t uhub_intr_callback;
+#if USB_HAVE_TT_SUPPORT
+static usb_callback_t uhub_reset_tt_callback;
+#endif
 
 static void usb_dev_resume_peer(struct usb_device *udev);
 static void usb_dev_suspend_peer(struct usb_device *udev);
@@ -131,7 +139,7 @@
 
 static const struct usb_config uhub_config[UHUB_N_TRANSFER] = {
 
-	[0] = {
+	[UHUB_INTR_TRANSFER] = {
 		.type = UE_INTERRUPT,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_ANY,
@@ -141,6 +149,17 @@
 		.callback = &uhub_intr_callback,
 		.interval = UHUB_INTR_INTERVAL,
 	},
+#if USB_HAVE_TT_SUPPORT
+	[UHUB_RESET_TT_TRANSFER] = {
+		.type = UE_CONTROL,
+		.endpoint = 0x00,	/* Control pipe */
+		.direction = UE_DIR_ANY,
+		.bufsize = sizeof(struct usb_device_request),
+		.callback = &uhub_reset_tt_callback,
+		.timeout = 1000,	/* 1 second */
+		.usb_mode = USB_MODE_HOST,
+	},
+#endif
 };
 
 /*
@@ -210,6 +229,279 @@
 }
 
 /*------------------------------------------------------------------------*
+ *      uhub_reset_tt_proc
+ *
+ * This function starts the TT reset USB request
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
+static void
+uhub_reset_tt_proc(struct usb_proc_msg *_pm)
+{
+	struct usb_udev_msg *pm = (void *)_pm;
+	struct usb_device *udev = pm->udev;
+	struct usb_hub *hub;
+	struct uhub_softc *sc;
+
+	hub = udev->hub;
+	if (hub == NULL)
+		return;
+	sc = hub->hubsoftc;
+	if (sc == NULL)
+		return;
+
+	/* Change lock */
+	USB_BUS_UNLOCK(udev->bus);
+	mtx_lock(&sc->sc_mtx);
+	/* Start transfer */
+	usbd_transfer_start(sc->sc_xfer[UHUB_RESET_TT_TRANSFER]);
+	/* Change lock */
+	mtx_unlock(&sc->sc_mtx);
+	USB_BUS_LOCK(udev->bus);
+}
+#endif
+
+/*------------------------------------------------------------------------*
+ *      uhub_tt_buffer_reset_async_locked
+ *
+ * This function queues a TT reset for the given USB device and endpoint.
+ *------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
+void
+uhub_tt_buffer_reset_async_locked(struct usb_device *child, struct usb_endpoint *ep)
+{
+	struct usb_device_request req;
+	struct usb_device *udev;
+	struct usb_hub *hub;
+	struct usb_port *up;
+	uint16_t wValue;
+	uint8_t port;
+
+	if (child == NULL || ep == NULL)
+		return;
+
+	udev = child->parent_hs_hub;
+	port = child->hs_port_no;
+
+	if (udev == NULL)
+		return;
+
+	hub = udev->hub;
+	if ((hub == NULL) ||
+	    (udev->speed != USB_SPEED_HIGH) ||
+	    (child->speed != USB_SPEED_LOW &&
+	     child->speed != USB_SPEED_FULL) ||
+	    (child->flags.usb_mode != USB_MODE_HOST) ||
+	    (port == 0) || (ep->edesc == NULL)) {
+		/* not applicable */
+		return;
+	}
+
+	USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
+
+	up = hub->ports + port - 1;
+
+	if (udev->ddesc.bDeviceClass == UDCLASS_HUB &&
+	    udev->ddesc.bDeviceProtocol == UDPROTO_HSHUBSTT)
+		port = 1;
+
+	/* if we already received a clear buffer request, reset the whole TT */
+	if (up->req_reset_tt.bRequest != 0) {
+		req.bmRequestType = UT_WRITE_CLASS_OTHER;
+		req.bRequest = UR_RESET_TT;
+		USETW(req.wValue, 0);
+		req.wIndex[0] = port;
+		req.wIndex[1] = 0;
+		USETW(req.wLength, 0);
+	} else {
+		wValue = (ep->edesc->bEndpointAddress & 0xF) |
+		      ((child->address & 0x7F) << 4) |
+		      ((ep->edesc->bEndpointAddress & 0x80) << 8) |
+		      ((ep->edesc->bmAttributes & 3) << 12);
+
+		req.bmRequestType = UT_WRITE_CLASS_OTHER;
+		req.bRequest = UR_CLEAR_TT_BUFFER;
+		USETW(req.wValue, wValue);
+		req.wIndex[0] = port;
+		req.wIndex[1] = 0;
+		USETW(req.wLength, 0);
+	}
+	up->req_reset_tt = req;
+	/* get reset transfer started */
+	usb_proc_msignal(&udev->bus->non_giant_callback_proc,
+	    &hub->tt_msg[0], &hub->tt_msg[1]);
+}
+#endif
+
+#if USB_HAVE_TT_SUPPORT
+static void
+uhub_reset_tt_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct uhub_softc *sc;
+	struct usb_device *udev;
+	struct usb_port *up;
+	uint8_t x;
+
+	DPRINTF("TT buffer reset\n");
+
+	sc = usbd_xfer_softc(xfer);
+	udev = sc->sc_udev;
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+	case USB_ST_SETUP:
+tr_setup:
+		USB_BUS_LOCK(udev->bus);
+		/* find first port which needs a TT reset */
+		for (x = 0; x != udev->hub->nports; x++) {
+			up = udev->hub->ports + x;
+
+			if (up->req_reset_tt.bRequest == 0)
+				continue;
+
+			/* copy in the transfer */
+			usbd_copy_in(xfer->frbuffers, 0, &up->req_reset_tt,
+			    sizeof(up->req_reset_tt));
+			/* reset buffer */
+			memset(&up->req_reset_tt, 0, sizeof(up->req_reset_tt));
+
+			/* set length */
+			usbd_xfer_set_frame_len(xfer, 0, sizeof(up->req_reset_tt));
+			xfer->nframes = 1;
+			USB_BUS_UNLOCK(udev->bus);
+
+			usbd_transfer_submit(xfer);
+			return;
+		}
+		USB_BUS_UNLOCK(udev->bus);
+		break;
+
+	default:
+		if (error == USB_ERR_CANCELLED)
+			break;
+
+		DPRINTF("TT buffer reset failed (%s)\n", usbd_errstr(error));
+		goto tr_setup;
+	}
+}
+#endif
+
+/*------------------------------------------------------------------------*
+ *      uhub_count_active_host_ports
+ *
+ * This function counts the number of active ports at the given speed.
+ *------------------------------------------------------------------------*/
+uint8_t
+uhub_count_active_host_ports(struct usb_device *udev, enum usb_dev_speed speed)
+{
+	struct uhub_softc *sc;
+	struct usb_device *child;
+	struct usb_hub *hub;
+	struct usb_port *up;
+	uint8_t retval = 0;
+	uint8_t x;
+
+	if (udev == NULL)
+		goto done;
+	hub = udev->hub;
+	if (hub == NULL)
+		goto done;
+	sc = hub->hubsoftc;
+	if (sc == NULL)
+		goto done;
+
+	for (x = 0; x != hub->nports; x++) {
+		up = hub->ports + x;
+		child = usb_bus_port_get_device(udev->bus, up);
+		if (child != NULL &&
+		    child->flags.usb_mode == USB_MODE_HOST &&
+		    child->speed == speed)
+			retval++;
+	}
+done:
+	return (retval);
+}
+
+void
+uhub_explore_handle_re_enumerate(struct usb_device *child)
+{
+	uint8_t do_unlock;
+	usb_error_t err;
+
+	/* check if device should be re-enumerated */
+	if (child->flags.usb_mode != USB_MODE_HOST)
+		return;
+
+	do_unlock = usbd_enum_lock(child);
+	switch (child->re_enumerate_wait) {
+	case USB_RE_ENUM_START:
+		err = usbd_set_config_index(child,
+		    USB_UNCONFIG_INDEX);
+		if (err != 0) {
+			DPRINTF("Unconfigure failed: %s: Ignored.\n",
+			    usbd_errstr(err));
+		}
+		if (child->parent_hub == NULL) {
+			/* the root HUB cannot be re-enumerated */
+			DPRINTFN(6, "cannot reset root HUB\n");
+			err = 0;
+		} else {
+			err = usbd_req_re_enumerate(child, NULL);
+		}
+		if (err == 0)
+			err = usbd_set_config_index(child, 0);
+		if (err == 0) {
+			err = usb_probe_and_attach(child,
+			    USB_IFACE_INDEX_ANY);
+		}
+		child->re_enumerate_wait = USB_RE_ENUM_DONE;
+		break;
+
+	case USB_RE_ENUM_PWR_OFF:
+		/* get the device unconfigured */
+		err = usbd_set_config_index(child,
+		    USB_UNCONFIG_INDEX);
+		if (err) {
+			DPRINTFN(0, "Could not unconfigure "
+			    "device (ignored)\n");
+		}
+		if (child->parent_hub == NULL) {
+			/* the root HUB cannot be re-enumerated */
+			DPRINTFN(6, "cannot set port feature\n");
+			err = 0;
+		} else {
+			/* clear port enable */
+			err = usbd_req_clear_port_feature(child->parent_hub,
+			    NULL, child->port_no, UHF_PORT_ENABLE);
+			if (err) {
+				DPRINTFN(0, "Could not disable port "
+				    "(ignored)\n");
+			}
+		}
+		child->re_enumerate_wait = USB_RE_ENUM_DONE;
+		break;
+
+	case USB_RE_ENUM_SET_CONFIG:
+		err = usbd_set_config_index(child,
+		    child->next_config_index);
+		if (err != 0) {
+			DPRINTF("Configure failed: %s: Ignored.\n",
+			    usbd_errstr(err));
+		} else {
+			err = usb_probe_and_attach(child,
+			    USB_IFACE_INDEX_ANY);
+		}
+		child->re_enumerate_wait = USB_RE_ENUM_DONE;
+		break;
+
+	default:
+		child->re_enumerate_wait = USB_RE_ENUM_DONE;
+		break;
+	}
+	if (do_unlock)
+		usbd_enum_unlock(child);
+}
+
+/*------------------------------------------------------------------------*
  *	uhub_explore_sub - subroutine
  *
  * Return values:
@@ -237,34 +529,8 @@
 		goto done;
 	}
 
-	/* check if device should be re-enumerated */
+	uhub_explore_handle_re_enumerate(child);
 
-	if (child->flags.usb_mode == USB_MODE_HOST) {
-		uint8_t do_unlock;
-		
-		do_unlock = usbd_enum_lock(child);
-		if (child->re_enumerate_wait) {
-			err = usbd_set_config_index(child,
-			    USB_UNCONFIG_INDEX);
-			if (err != 0) {
-				DPRINTF("Unconfigure failed: "
-				    "%s: Ignored.\n",
-				    usbd_errstr(err));
-			}
-			err = usbd_req_re_enumerate(child, NULL);
-			if (err == 0)
-				err = usbd_set_config_index(child, 0);
-			if (err == 0) {
-				err = usb_probe_and_attach(child,
-				    USB_IFACE_INDEX_ANY);
-			}
-			child->re_enumerate_wait = 0;
-			err = 0;
-		}
-		if (do_unlock)
-			usbd_enum_unlock(child);
-	}
-
 	/* check if probe and attach should be done */
 
 	if (child->driver_added_refcount != refcount) {
@@ -335,7 +601,6 @@
 
 	DPRINTF("reattaching port %d\n", portno);
 
-	err = 0;
 	timeout = 0;
 	udev = sc->sc_udev;
 	child = usb_bus_port_get_device(udev->bus,
@@ -520,7 +785,10 @@
 	 *
 	 * NOTE: This part is currently FreeBSD specific.
 	 */
-	if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
+	if (udev->parent_hub != NULL) {
+		/* inherit mode from the parent HUB */
+		mode = udev->parent_hub->flags.usb_mode;
+	} else if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
 		mode = USB_MODE_DEVICE;
 	else
 		mode = USB_MODE_HOST;
@@ -1077,7 +1345,12 @@
 	hub->explore = &uhub_explore;
 	hub->nports = nports;
 	hub->hubudev = udev;
-
+#if USB_HAVE_TT_SUPPORT
+	hub->tt_msg[0].hdr.pm_callback = &uhub_reset_tt_proc;
+	hub->tt_msg[0].udev = udev;
+	hub->tt_msg[1].hdr.pm_callback = &uhub_reset_tt_proc;
+	hub->tt_msg[1].udev = udev;
+#endif
 	/* if self powered hub, give ports maximum current */
 	if (udev->flags.self_powered) {
 		hub->portpower = USB_MAX_POWER;
@@ -1179,11 +1452,9 @@
 
 	/* Start the interrupt endpoint, if any */
 
-	if (sc->sc_xfer[0] != NULL) {
-		mtx_lock(&sc->sc_mtx);
-		usbd_transfer_start(sc->sc_xfer[0]);
-		mtx_unlock(&sc->sc_mtx);
-	}
+	mtx_lock(&sc->sc_mtx);
+	usbd_transfer_start(sc->sc_xfer[UHUB_INTR_TRANSFER]);
+	mtx_unlock(&sc->sc_mtx);
 
 	/* Enable automatic power save on all USB HUBs */
 
@@ -1213,6 +1484,7 @@
 {
 	struct uhub_softc *sc = device_get_softc(dev);
 	struct usb_hub *hub = sc->sc_udev->hub;
+	struct usb_bus *bus = sc->sc_udev->bus;
 	struct usb_device *child;
 	uint8_t x;
 
@@ -1225,7 +1497,7 @@
 	/* Detach all ports */
 	for (x = 0; x != hub->nports; x++) {
 
-		child = usb_bus_port_get_device(sc->sc_udev->bus, hub->ports + x);
+		child = usb_bus_port_get_device(bus, hub->ports + x);
 
 		if (child == NULL) {
 			continue;
@@ -1237,6 +1509,13 @@
 		usb_free_device(child, 0);
 	}
 
+#if USB_HAVE_TT_SUPPORT
+	/* Make sure our TT messages are not queued anywhere */
+	USB_BUS_LOCK(bus);
+	usb_proc_mwait(&bus->non_giant_callback_proc,
+	    &hub->tt_msg[0], &hub->tt_msg[1]);
+	USB_BUS_UNLOCK(bus);
+#endif
 	free(hub, M_USBDEV);
 	sc->sc_udev->hub = NULL;
 
@@ -1332,10 +1611,11 @@
 		}
 		goto done;
 	}
-	snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u",
+	snprintf(buf, buflen, "bus=%u hubaddr=%u port=%u devaddr=%u interface=%u"
+	    " ugen=%s",
 	    (res.udev->parent_hub != NULL) ? res.udev->parent_hub->device_index : 0,
 	    res.portno, device_get_unit(res.udev->bus->bdev),
-	    res.udev->device_index, res.iface_index);
+	    res.udev->device_index, res.iface_index, res.udev->ugen_name);
 done:
 	mtx_unlock(&Giant);
 
@@ -1377,7 +1657,7 @@
 		    "release=0x%04x "
 		    "mode=%s "
 		    "intclass=0x%02x intsubclass=0x%02x "
-		    "intprotocol=0x%02x " "%s%s",
+		    "intprotocol=0x%02x" "%s%s",
 		    UGETW(res.udev->ddesc.idVendor),
 		    UGETW(res.udev->ddesc.idProduct),
 		    res.udev->ddesc.bDeviceClass,
@@ -2068,9 +2348,10 @@
 static uint8_t
 usb_peer_should_wakeup(struct usb_device *udev)
 {
-	return ((udev->power_mode == USB_POWER_MODE_ON) ||
+	return (((udev->power_mode == USB_POWER_MODE_ON) &&
+	    (udev->flags.usb_mode == USB_MODE_HOST)) ||
 	    (udev->driver_added_refcount != udev->bus->driver_added_refcount) ||
-	    (udev->re_enumerate_wait != 0) ||
+	    (udev->re_enumerate_wait != USB_RE_ENUM_DONE) ||
 	    (udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
 	    (udev->pwr_save.write_refs != 0) ||
 	    ((udev->pwr_save.read_refs != 0) &&
@@ -2486,6 +2767,8 @@
 
 #if USB_HAVE_POWERD
 	usb_bus_power_update(udev->bus);
+#else
+	usb_needs_explore(udev->bus, 0 /* no probe */ );
 #endif
 }
 
@@ -2524,8 +2807,36 @@
 void
 usbd_start_re_enumerate(struct usb_device *udev)
 {
-	if (udev->re_enumerate_wait == 0) {
-		udev->re_enumerate_wait = 1;
+	if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+		udev->re_enumerate_wait = USB_RE_ENUM_START;
 		usb_needs_explore(udev->bus, 0);
 	}
 }
+
+/*-----------------------------------------------------------------------*
+ *	usbd_start_set_config
+ *
+ * This function starts setting a USB configuration. This function
+ * does not need to be called BUS-locked. This function does not wait
+ * until the set USB configuratino is completed.
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_start_set_config(struct usb_device *udev, uint8_t index)
+{
+	if (udev->re_enumerate_wait == USB_RE_ENUM_DONE) {
+		if (udev->curr_config_index == index) {
+			/* no change needed */
+			return (0);
+		}
+		udev->next_config_index = index;
+		udev->re_enumerate_wait = USB_RE_ENUM_SET_CONFIG;
+		usb_needs_explore(udev->bus, 0);
+		return (0);
+	} else if (udev->re_enumerate_wait == USB_RE_ENUM_SET_CONFIG) {
+		if (udev->next_config_index == index) {
+			/* no change needed */
+			return (0);
+		}
+	}
+	return (USB_ERR_PENDING_REQUESTS);
+}

Modified: stable/0.8/sys/dev/usb/usb_hub.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_hub.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_hub.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_hub.h 267350 2014-06-11 06:45:52Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -35,6 +35,9 @@
 #define	USB_RESTART_MAX 5
 	uint8_t	device_index;		/* zero means not valid */
 	enum usb_hc_mode usb_mode;	/* host or device mode */
+#if USB_HAVE_TT_SUPPORT
+	struct usb_device_request req_reset_tt __aligned(4);
+#endif
 };
 
 /*
@@ -44,6 +47,9 @@
 	struct usb_device *hubudev;	/* the HUB device */
 	usb_error_t (*explore) (struct usb_device *hub);
 	void   *hubsoftc;
+#if USB_HAVE_TT_SUPPORT
+	struct usb_udev_msg tt_msg[2];
+#endif
 	usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
 	uint16_t portpower;		/* mA per USB port */
 	uint8_t	isoc_last_time;
@@ -65,5 +71,6 @@
 void	usb_bus_powerd(struct usb_bus *bus);
 void	uhub_root_intr(struct usb_bus *, const uint8_t *, uint8_t);
 usb_error_t uhub_query_info(struct usb_device *, uint8_t *, uint8_t *);
+void	uhub_explore_handle_re_enumerate(struct usb_device *);
 
 #endif					/* _USB_HUB_H_ */

Modified: stable/0.8/sys/dev/usb/usb_if.m
===================================================================
--- stable/0.8/sys/dev/usb/usb_if.m	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_if.m	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-# $MidnightBSD$
+# $FreeBSD: stable/9/sys/dev/usb/usb_if.m 229096 2011-12-31 14:22:02Z hselasky $
 #
 
 # USB interface description

Modified: stable/0.8/sys/dev/usb/usb_ioctl.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_ioctl.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_ioctl.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_ioctl.h 254566 2013-08-20 14:19:00Z emaste $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -30,6 +30,7 @@
 #define	_USB_IOCTL_H_
 
 #include <sys/ioccom.h>
+#include <sys/cdefs.h>
 
 /* Building "kdump" depends on these includes */
 
@@ -41,6 +42,16 @@
 #define	USB_GENERIC_NAME "ugen"
 #define	USB_TEMPLATE_SYSCTL "hw.usb.template"	/* integer type */
 
+/*
+ * Align IOCTL structures to hide differences when running 32-bit
+ * programs under 64-bit kernels:
+ */
+#ifdef COMPAT_32BIT
+#define	USB_IOCTL_STRUCT_ALIGN(n) __aligned(n)
+#else
+#define	USB_IOCTL_STRUCT_ALIGN(n)
+#endif
+
 /* Definition of valid template sysctl values */
 
 enum {
@@ -62,7 +73,7 @@
 #endif
 	uint32_t urd_startentry;
 	uint32_t urd_maxlen;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
 
 struct usb_ctl_request {
 #ifdef COMPAT_32BIT
@@ -74,12 +85,12 @@
 	uint16_t ucr_actlen;		/* actual length transferred */
 	uint8_t	ucr_addr;		/* zero - currently not used */
 	struct usb_device_request ucr_request;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
 
 struct usb_alt_interface {
 	uint8_t	uai_interface_index;
 	uint8_t	uai_alt_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_gen_descriptor {
 #ifdef COMPAT_32BIT
@@ -98,7 +109,7 @@
 	uint8_t	ugd_endpt_index;
 	uint8_t	ugd_report_type;
 	uint8_t	reserved[8];
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
 
 struct usb_device_info {
 	uint16_t udi_productNo;
@@ -127,24 +138,33 @@
 	char	udi_vendor[128];
 	char	udi_serial[64];
 	char	udi_release[8];
-};
+} USB_IOCTL_STRUCT_ALIGN(2);
 
+#define	USB_DEVICE_PORT_PATH_MAX 32
+
+struct usb_device_port_path {
+	uint8_t udp_bus;		/* which bus we are on */
+	uint8_t udp_index;		/* which device index */
+	uint8_t udp_port_level;		/* how many levels: 0, 1, 2 ... */
+	uint8_t udp_port_no[USB_DEVICE_PORT_PATH_MAX];
+} USB_IOCTL_STRUCT_ALIGN(1);
+
 struct usb_device_stats {
 	uint32_t uds_requests_ok[4];	/* Indexed by transfer type UE_XXX */
 	uint32_t uds_requests_fail[4];	/* Indexed by transfer type UE_XXX */
-};
+} USB_IOCTL_STRUCT_ALIGN(4);
 
 struct usb_fs_start {
 	uint8_t	ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_fs_stop {
 	uint8_t	ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_fs_complete {
 	uint8_t	ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 /* This structure is used for all endpoint types */
 struct usb_fs_endpoint {
@@ -177,7 +197,7 @@
 	/* timeout value for no timeout */
 #define	USB_FS_TIMEOUT_NONE 0
 	int	status;			/* see USB_ERR_XXX */
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
 
 struct usb_fs_init {
 	/* userland pointer to endpoints structure */
@@ -188,11 +208,11 @@
 #endif
 	/* maximum number of endpoints */
 	uint8_t	ep_index_max;
-};
+} USB_IOCTL_STRUCT_ALIGN(8);
 
 struct usb_fs_uninit {
 	uint8_t	dummy;			/* zero */
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_fs_open {
 #define	USB_FS_MAX_BUFSIZE (1 << 18)
@@ -204,15 +224,20 @@
 	uint8_t	dev_index;		/* currently unused */
 	uint8_t	ep_index;
 	uint8_t	ep_no;			/* bEndpointNumber */
-};
+} USB_IOCTL_STRUCT_ALIGN(4);
 
+struct usb_fs_open_stream {
+	struct usb_fs_open fs_open;
+	uint16_t stream_id;		/* stream ID */
+} USB_IOCTL_STRUCT_ALIGN(4);
+
 struct usb_fs_close {
 	uint8_t	ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_fs_clear_stall_sync {
 	uint8_t	ep_index;
-};
+} USB_IOCTL_STRUCT_ALIGN(1);
 
 struct usb_gen_quirk {
 	uint16_t index;			/* Quirk Index */
@@ -222,11 +247,11 @@
 	uint16_t bcdDeviceHigh;		/* High Device Revision */
 	uint16_t reserved[2];
 	/*
-	 * String version of quirk including terminating zero. See UQ_XXX in
-	 * "usb_quirk.h".
+	 * String version of quirk including terminating zero. See
+	 * UQ_XXX in "usb_quirk.h".
 	 */
 	char	quirkname[64 - 14];
-};
+} USB_IOCTL_STRUCT_ALIGN(2);
 
 /* USB controller */
 #define	USB_REQUEST		_IOWR('U', 1, struct usb_ctl_request)
@@ -270,7 +295,8 @@
 #define	USB_IFACE_DRIVER_DETACH	_IOW ('U', 125, int)
 #define	USB_GET_PLUGTIME	_IOR ('U', 126, uint32_t)
 #define	USB_READ_DIR		_IOW ('U', 127, struct usb_read_dir)
-/* 128 - 134 unused */
+/* 128 - 133 unused */
+#define	USB_GET_DEV_PORT_PATH	_IOR ('U', 134, struct usb_device_port_path)
 #define	USB_GET_POWER_USAGE	_IOR ('U', 135, int)
 #define	USB_SET_TX_FORCE_SHORT	_IOW ('U', 136, int)
 #define	USB_SET_TX_TIMEOUT	_IOW ('U', 137, int)

Modified: stable/0.8/sys/dev/usb/usb_lookup.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_lookup.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_lookup.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_lookup.c 223538 2011-06-25 15:51:44Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_mbuf.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_mbuf.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_mbuf.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_mbuf.c 217265 2011-01-11 13:59:06Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_mbuf.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_mbuf.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_mbuf.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_mbuf.h 196219 2009-08-14 20:03:53Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_msctest.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_msctest.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_msctest.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_msctest.c 283174 2015-05-21 06:53:55Z hselasky $ */
 /*-
  * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
  *
@@ -83,7 +83,7 @@
 	DIR_NONE,
 };
 
-#define	SCSI_MAX_LEN	0x100
+#define	SCSI_MAX_LEN	MAX(0x100, BULK_SIZE)
 #define	SCSI_INQ_LEN	0x24
 #define	SCSI_SENSE_LEN	0xFF
 
@@ -98,6 +98,9 @@
 static uint8_t scsi_huawei_eject[] =	{ 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 					  0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_huawei_eject2[] =	{ 0x11, 0x06, 0x20, 0x00, 0x00, 0x01,
+					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+					  0x00, 0x00, 0x00, 0x00 };
 static uint8_t scsi_tct_eject[] =	{ 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
 static uint8_t scsi_sync_cache[] =	{ 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
 					  0x00, 0x00, 0x00, 0x00 };
@@ -105,6 +108,8 @@
 					  0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 static uint8_t scsi_read_capacity[] =	{ 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
 					  0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_prevent_removal[] =	{ 0x1e, 0, 0, 0, 1, 0 };
+static uint8_t scsi_allow_removal[] =	{ 0x1e, 0, 0, 0, 0, 0 };
 
 #define	BULK_SIZE		64	/* dummy */
 #define	ERR_CSW_FAILED		-1
@@ -139,8 +144,8 @@
 struct bbb_transfer {
 	struct mtx mtx;
 	struct cv cv;
-	struct bbb_cbw cbw;
-	struct bbb_csw csw;
+	struct bbb_cbw *cbw;
+	struct bbb_csw *csw;
 
 	struct usb_xfer *xfer[ST_MAX];
 
@@ -150,6 +155,7 @@
 	usb_size_t data_rem;		/* bytes */
 	usb_timeout_t data_timeout;	/* ms */
 	usb_frlength_t actlen;		/* bytes */
+	usb_frlength_t buffer_size;    	/* bytes */
 
 	uint8_t	cmd_len;		/* bytes */
 	uint8_t	dir;
@@ -158,7 +164,7 @@
 	uint8_t	status_try;
 	int	error;
 
-	uint8_t	buffer[SCSI_MAX_LEN] __aligned(4);
+	uint8_t	*buffer;
 };
 
 static usb_callback_t bbb_command_callback;
@@ -167,6 +173,7 @@
 static usb_callback_t bbb_data_write_callback;
 static usb_callback_t bbb_data_wr_cs_callback;
 static usb_callback_t bbb_status_callback;
+static usb_callback_t bbb_raw_write_callback;
 
 static void	bbb_done(struct bbb_transfer *, int);
 static void	bbb_transfer_start(struct bbb_transfer *, uint8_t);
@@ -174,7 +181,7 @@
 		    uint8_t);
 static int	bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
 		    void *, size_t, void *, size_t, usb_timeout_t);
-static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
+static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t, uint8_t);
 static void	bbb_detach(struct bbb_transfer *);
 
 static const struct usb_config bbb_config[ST_MAX] = {
@@ -184,7 +191,6 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = sizeof(struct bbb_cbw),
-		.flags = {.ext_buffer = 1,},
 		.callback = &bbb_command_callback,
 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
 	},
@@ -193,8 +199,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = BULK_SIZE,
-		.flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
+		.bufsize = SCSI_MAX_LEN,
+		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
 		.callback = &bbb_data_read_callback,
 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
 	},
@@ -212,7 +218,7 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = BULK_SIZE,
+		.bufsize = SCSI_MAX_LEN,
 		.flags = {.ext_buffer = 1,.proxy_buffer = 1,},
 		.callback = &bbb_data_write_callback,
 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
@@ -232,16 +238,28 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
 		.bufsize = sizeof(struct bbb_csw),
-		.flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
+		.flags = {.short_xfer_ok = 1,},
 		.callback = &bbb_status_callback,
 		.timeout = 1 * USB_MS_HZ,	/* 1 second  */
 	},
 };
 
+static const struct usb_config bbb_raw_config[1] = {
+
+	[0] = {
+		.type = UE_BULK_INTR,
+		.endpoint = UE_ADDR_ANY,
+		.direction = UE_DIR_OUT,
+		.bufsize = SCSI_MAX_LEN,
+		.flags = {.ext_buffer = 1,.proxy_buffer = 1,},
+		.callback = &bbb_raw_write_callback,
+		.timeout = 1 * USB_MS_HZ,	/* 1 second */
+	},
+};
+
 static void
 bbb_done(struct bbb_transfer *sc, int error)
 {
-
 	sc->error = error;
 	sc->state = ST_COMMAND;
 	sc->status_try = 1;
@@ -290,18 +308,19 @@
 
 	case USB_ST_SETUP:
 		sc->status_try = 0;
-		tag = UGETDW(sc->cbw.dCBWTag) + 1;
-		USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
-		USETDW(sc->cbw.dCBWTag, tag);
-		USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
-		sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
-		sc->cbw.bCBWLUN = sc->lun;
-		sc->cbw.bCDBLength = sc->cmd_len;
-		if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) {
-			sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB);
+		tag = UGETDW(sc->cbw->dCBWTag) + 1;
+		USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
+		USETDW(sc->cbw->dCBWTag, tag);
+		USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
+		sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
+		sc->cbw->bCBWLUN = sc->lun;
+		sc->cbw->bCDBLength = sc->cmd_len;
+		if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
+			sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
 			DPRINTFN(0, "Truncating long command\n");
 		}
-		usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw));
+		usbd_xfer_set_frame_len(xfer, 0,
+		    sizeof(struct bbb_cbw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -388,7 +407,7 @@
 
 		if (sc->data_rem == 0) {
 			bbb_transfer_start(sc, ST_STATUS);
-			return;
+			break;
 		}
 		if (max_bulk > sc->data_rem) {
 			max_bulk = sc->data_rem;
@@ -396,7 +415,7 @@
 		usbd_xfer_set_timeout(xfer, sc->data_timeout);
 		usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
 		usbd_transfer_submit(xfer);
-		return;
+		break;
 
 	default:			/* Error */
 		if (error == USB_ERR_CANCELLED) {
@@ -404,8 +423,7 @@
 		} else {
 			bbb_transfer_start(sc, ST_DATA_WR_CS);
 		}
-		return;
-
+		break;
 	}
 }
 
@@ -430,9 +448,9 @@
 
 		/* very simple status check */
 
-		if (actlen < (int)sizeof(sc->csw)) {
+		if (actlen < (int)sizeof(struct bbb_csw)) {
 			bbb_done(sc, USB_ERR_SHORT_XFER);
-		} else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
+		} else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
 			bbb_done(sc, 0);	/* success */
 		} else {
 			bbb_done(sc, ERR_CSW_FAILED);	/* error */
@@ -440,7 +458,8 @@
 		break;
 
 	case USB_ST_SETUP:
-		usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw));
+		usbd_xfer_set_frame_len(xfer, 0,
+		    sizeof(struct bbb_csw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -458,6 +477,47 @@
 	}
 }
 
+static void
+bbb_raw_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+	struct bbb_transfer *sc = usbd_xfer_softc(xfer);
+	usb_frlength_t max_bulk = usbd_xfer_max_len(xfer);
+	int actlen, sumlen;
+
+	usbd_xfer_status(xfer, &actlen, &sumlen, NULL, NULL);
+
+	switch (USB_GET_STATE(xfer)) {
+	case USB_ST_TRANSFERRED:
+		sc->data_rem -= actlen;
+		sc->data_ptr += actlen;
+		sc->actlen += actlen;
+
+		if (actlen < sumlen) {
+			/* short transfer */
+			sc->data_rem = 0;
+		}
+	case USB_ST_SETUP:
+		DPRINTF("max_bulk=%d, data_rem=%d\n",
+		    max_bulk, sc->data_rem);
+
+		if (sc->data_rem == 0) {
+			bbb_done(sc, 0);
+			break;
+		}
+		if (max_bulk > sc->data_rem) {
+			max_bulk = sc->data_rem;
+		}
+		usbd_xfer_set_timeout(xfer, sc->data_timeout);
+		usbd_xfer_set_frame_data(xfer, 0, sc->data_ptr, max_bulk);
+		usbd_transfer_submit(xfer);
+		break;
+
+	default:			/* Error */
+		bbb_done(sc, error);
+		break;
+	}
+}
+
 /*------------------------------------------------------------------------*
  *	bbb_command_start - execute a SCSI command synchronously
  *
@@ -477,10 +537,11 @@
 	sc->data_rem = data_len;
 	sc->data_timeout = (data_timeout + USB_MS_HZ);
 	sc->actlen = 0;
+	sc->error = 0;
 	sc->cmd_len = cmd_len;
-	memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
-	memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
-	DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
+	memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
+	memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
+	DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
 
 	mtx_lock(&sc->mtx);
 	usbd_transfer_start(sc->xfer[sc->state]);
@@ -492,13 +553,45 @@
 	return (sc->error);
 }
 
+/*------------------------------------------------------------------------*
+ *	bbb_raw_write - write a raw BULK message synchronously
+ *
+ * Return values
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+static int
+bbb_raw_write(struct bbb_transfer *sc, const void *data_ptr, size_t data_len,
+    usb_timeout_t data_timeout)
+{
+	sc->data_ptr = __DECONST(void *, data_ptr);
+	sc->data_len = data_len;
+	sc->data_rem = data_len;
+	sc->data_timeout = (data_timeout + USB_MS_HZ);
+	sc->actlen = 0;
+	sc->error = 0;
+
+	DPRINTFN(1, "BULK DATA = %*D\n", (int)data_len,
+	    (const char *)data_ptr, ":");
+
+	mtx_lock(&sc->mtx);
+	usbd_transfer_start(sc->xfer[0]);
+	while (usbd_transfer_pending(sc->xfer[0]))
+		cv_wait(&sc->cv, &sc->mtx);
+	mtx_unlock(&sc->mtx);
+	return (sc->error);
+}
+
 static struct bbb_transfer *
-bbb_attach(struct usb_device *udev, uint8_t iface_index)
+bbb_attach(struct usb_device *udev, uint8_t iface_index,
+    uint8_t bInterfaceClass)
 {
 	struct usb_interface *iface;
 	struct usb_interface_descriptor *id;
+	const struct usb_config *pconfig;
 	struct bbb_transfer *sc;
 	usb_error_t err;
+	int nconfig;
 	uint8_t do_unlock;
 
 	/* Prevent re-enumeration */
@@ -518,22 +611,39 @@
 		return (NULL);
 
 	id = iface->idesc;
-	if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+	if (id == NULL || id->bInterfaceClass != bInterfaceClass)
 		return (NULL);
 
-	switch (id->bInterfaceSubClass) {
-	case UISUBCLASS_SCSI:
-	case UISUBCLASS_UFI:
-	case UISUBCLASS_SFF8020I:
-	case UISUBCLASS_SFF8070I:
+	switch (id->bInterfaceClass) {
+	case UICLASS_MASS:
+		switch (id->bInterfaceSubClass) {
+		case UISUBCLASS_SCSI:
+		case UISUBCLASS_UFI:
+		case UISUBCLASS_SFF8020I:
+		case UISUBCLASS_SFF8070I:
+			break;
+		default:
+			return (NULL);
+		}
+		switch (id->bInterfaceProtocol) {
+		case UIPROTO_MASS_BBB_OLD:
+		case UIPROTO_MASS_BBB:
+			break;
+		default:
+			return (NULL);
+		}
+		pconfig = bbb_config;
+		nconfig = ST_MAX;
 		break;
-	default:
-		return (NULL);
-	}
-
-	switch (id->bInterfaceProtocol) {
-	case UIPROTO_MASS_BBB_OLD:
-	case UIPROTO_MASS_BBB:
+	case UICLASS_HID:
+		switch (id->bInterfaceSubClass) {
+		case 0:
+			break;
+		default:
+			return (NULL);
+		}
+		pconfig = bbb_raw_config;
+		nconfig = 1;
 		break;
 	default:
 		return (NULL);
@@ -543,12 +653,27 @@
 	mtx_init(&sc->mtx, "USB autoinstall", NULL, MTX_DEF);
 	cv_init(&sc->cv, "WBBB");
 
-	err = usbd_transfer_setup(udev, &iface_index, sc->xfer, bbb_config,
-	    ST_MAX, sc, &sc->mtx);
+	err = usbd_transfer_setup(udev, &iface_index, sc->xfer, pconfig,
+	    nconfig, sc, &sc->mtx);
 	if (err) {
 		bbb_detach(sc);
 		return (NULL);
 	}
+	switch (id->bInterfaceClass) {
+	case UICLASS_MASS:
+		/* store pointer to DMA buffers */
+		sc->buffer = usbd_xfer_get_frame_buffer(
+		    sc->xfer[ST_DATA_RD], 0);
+		sc->buffer_size =
+		    usbd_xfer_max_len(sc->xfer[ST_DATA_RD]);
+		sc->cbw = usbd_xfer_get_frame_buffer(
+		    sc->xfer[ST_COMMAND], 0);
+		sc->csw = usbd_xfer_get_frame_buffer(
+		    sc->xfer[ST_STATUS], 0);
+		break;
+	default:
+		break;
+	}
 	return (sc);
 }
 
@@ -577,7 +702,7 @@
 	uint8_t sid_type;
 	int err;
 
-	sc = bbb_attach(udev, iface_index);
+	sc = bbb_attach(udev, iface_index, UICLASS_MASS);
 	if (sc == NULL)
 		return (0);
 
@@ -633,7 +758,7 @@
 	uint8_t sid_type;
 	int err;
 
-	sc = bbb_attach(udev, iface_index);
+	sc = bbb_attach(udev, iface_index, UICLASS_MASS);
 	if (sc == NULL)
 		return (0);
 
@@ -677,10 +802,28 @@
 	    USB_MS_HZ);
 
 	if (err != 0) {
+		if (err != ERR_CSW_FAILED)
+			goto error;
+		DPRINTF("Test unit ready failed\n");
+	}
 
+	err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
+	    &scsi_prevent_removal, sizeof(scsi_prevent_removal),
+	    USB_MS_HZ);
+
+	if (err == 0) {
+		err = bbb_command_start(sc, DIR_OUT, 0, NULL, 0,
+		    &scsi_allow_removal, sizeof(scsi_allow_removal),
+		    USB_MS_HZ);
+	}
+
+	if (err != 0) {
 		if (err != ERR_CSW_FAILED)
 			goto error;
+		DPRINTF("Device doesn't handle prevent and allow removal\n");
+		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
 	}
+
 	timeout = 1;
 
 retry_sync_cache:
@@ -696,7 +839,6 @@
 		DPRINTF("Device doesn't handle synchronize cache\n");
 
 		usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
-
 	} else {
 
 		/*
@@ -770,6 +912,7 @@
 	DPRINTF("Device did not respond, enabling all quirks\n");
 
 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_PREVENT_ALLOW);
 	usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
 
 	/* Need to re-enumerate the device */
@@ -784,11 +927,10 @@
 	struct bbb_transfer *sc;
 	usb_error_t err;
 
-	sc = bbb_attach(udev, iface_index);
+	sc = bbb_attach(udev, iface_index, UICLASS_MASS);
 	if (sc == NULL)
 		return (USB_ERR_INVAL);
 
-	err = 0;
 	switch (method) {
 	case MSC_EJECT_STOPUNIT:
 		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
@@ -819,21 +961,44 @@
 		    &scsi_huawei_eject, sizeof(scsi_huawei_eject),
 		    USB_MS_HZ);
 		break;
+	case MSC_EJECT_HUAWEI2:
+		err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+		    &scsi_huawei_eject2, sizeof(scsi_huawei_eject2),
+		    USB_MS_HZ);
+		break;
 	case MSC_EJECT_TCT:
 		/*
 		 * TCTMobile needs DIR_IN flag. To get it, we
 		 * supply a dummy data with the command.
 		 */
-		err = bbb_command_start(sc, DIR_IN, 0, &sc->buffer,
-		    sizeof(sc->buffer), &scsi_tct_eject,
+		err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+		    sc->buffer_size, &scsi_tct_eject,
 		    sizeof(scsi_tct_eject), USB_MS_HZ);
 		break;
 	default:
-		printf("usb_msc_eject: unknown eject method (%d)\n", method);
-		break;
+		DPRINTF("Unknown eject method (%d)\n", method);
+		bbb_detach(sc);
+		return (USB_ERR_INVAL);
 	}
+
 	DPRINTF("Eject CD command status: %s\n", usbd_errstr(err));
 
 	bbb_detach(sc);
 	return (0);
 }
+
+usb_error_t
+usb_dymo_eject(struct usb_device *udev, uint8_t iface_index)
+{
+	static const uint8_t data[3] = { 0x1b, 0x5a, 0x01 };
+	struct bbb_transfer *sc;
+	usb_error_t err;
+
+	sc = bbb_attach(udev, iface_index, UICLASS_HID);
+	if (sc == NULL)
+		return (USB_ERR_INVAL);
+	err = bbb_raw_write(sc, data, sizeof(data), USB_MS_HZ);
+	bbb_detach(sc);
+	return (err);
+}
+

Modified: stable/0.8/sys/dev/usb/usb_msctest.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_msctest.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_msctest.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_msctest.h 283174 2015-05-21 06:53:55Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -33,6 +33,7 @@
 	MSC_EJECT_ZTESTOR,
 	MSC_EJECT_CMOTECH,
 	MSC_EJECT_HUAWEI,
+	MSC_EJECT_HUAWEI2,
 	MSC_EJECT_TCT,
 };
 
@@ -42,5 +43,7 @@
 	    uint8_t iface_index, int method);
 usb_error_t usb_msc_auto_quirk(struct usb_device *udev,
 	    uint8_t iface_index);
+usb_error_t usb_dymo_eject(struct usb_device *udev,
+	    uint8_t iface_index);
 
 #endif					/* _USB_MSCTEST_H_ */

Modified: stable/0.8/sys/dev/usb/usb_parse.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_parse.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_parse.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_parse.c 217265 2011-01-11 13:59:06Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_pci.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_pci.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pci.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_pci.h 196219 2009-08-14 20:03:53Z jhb $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_pf.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_pf.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pf.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/usb_pf.c 287273 2015-08-29 06:17:39Z hselasky $");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/bus.h>
@@ -103,6 +103,10 @@
 {
 	struct ifnet *ifp = ubus->ifp;
 
+	USB_BUS_LOCK(ubus);
+	ubus->ifp = NULL;
+	USB_BUS_UNLOCK(ubus);
+
 	if (ifp != NULL) {
 		bpfdetach(ifp);
 		if_down(ifp);
@@ -109,7 +113,6 @@
 		if_detach(ifp);
 		if_free(ifp);
 	}
-	ubus->ifp = NULL;
 }
 
 static uint32_t
@@ -261,7 +264,7 @@
 	/* sanity checks */
 	if (usb_no_pf != 0)
 		return;
-	if (bus->ifp == NULL)
+	if (bus->ifp == NULL || bus->ifp->if_bpf == NULL)
 		return;
 	if (!bpf_peers_present(bus->ifp->if_bpf))
 		return;

Modified: stable/0.8/sys/dev/usb/usb_pf.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_pf.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_pf.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usb_pf.h 220301 2011-04-03 20:03:45Z hselasky $
  */
 
 #ifndef _DEV_USB_PF_H

Modified: stable/0.8/sys/dev/usb/usb_process.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_process.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_process.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_process.c 273889 2014-10-31 08:06:21Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -24,8 +24,6 @@
  * SUCH DAMAGE.
  */
 
-#define	USB_DEBUG_VAR usb_proc_debug
-
 #include <sys/stdint.h>
 #include <sys/stddef.h>
 #include <sys/param.h>
@@ -49,6 +47,8 @@
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 #include <dev/usb/usb_process.h>
+
+#define	USB_DEBUG_VAR usb_proc_debug
 #include <dev/usb/usb_debug.h>
 #include <dev/usb/usb_util.h>
 
@@ -493,3 +493,15 @@
 		cv_signal(&up->up_cv);
 	}
 }
+
+/*------------------------------------------------------------------------*
+ *	usb_proc_is_called_from
+ *
+ * This function will return non-zero if called from inside the USB
+ * process passed as first argument. Else this function returns zero.
+ *------------------------------------------------------------------------*/
+int
+usb_proc_is_called_from(struct usb_process *up)
+{
+	return (up->up_curtd == curthread);
+}

Modified: stable/0.8/sys/dev/usb/usb_process.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_process.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_process.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_process.h 263800 2014-03-27 07:03:50Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -79,6 +79,7 @@
 void	usb_proc_free(struct usb_process *up);
 void   *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1);
 void	usb_proc_rewakeup(struct usb_process *up);
+int	usb_proc_is_called_from(struct usb_process *up);
 
 void	usb_proc_explore_mwait(struct usb_device *, void *, void *);
 void   *usb_proc_explore_msignal(struct usb_device *, void *, void *);

Modified: stable/0.8/sys/dev/usb/usb_request.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_request.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_request.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_request.c 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -48,7 +48,6 @@
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
-#include <dev/usb/usb_ioctl.h>
 #include <dev/usb/usbhid.h>
 
 #define	USB_DEBUG_VAR usb_debug
@@ -72,6 +71,11 @@
 SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
     &usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
 
+static int usb_full_ddesc;
+
+SYSCTL_INT(_hw_usb, OID_AUTO, full_ddesc, CTLFLAG_RW,
+    &usb_full_ddesc, 0, "USB always read complete device descriptor, if set");
+
 #ifdef USB_DEBUG
 #ifdef USB_REQ_DEBUG
 /* The following structures are used in connection to fault injection. */
@@ -449,17 +453,10 @@
 	}
 
 	/*
-	 * Grab the USB device enumeration SX-lock serialization is
-	 * achieved when multiple threads are involved:
+	 * Serialize access to this function:
 	 */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
-	/*
-	 * We need to allow suspend and resume at this point, else the
-	 * control transfer will timeout if the device is suspended!
-	 */
-	usbd_sr_unlock(udev);
-
 	hr_func = usbd_get_hr_func(udev);
 
 	if (hr_func != NULL) {
@@ -702,14 +699,23 @@
 	USB_XFER_UNLOCK(xfer);
 
 done:
-	usbd_sr_lock(udev);
-
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 
 	if ((mtx != NULL) && (mtx != &Giant))
 		mtx_lock(mtx);
 
+	switch (err) {
+	case USB_ERR_NORMAL_COMPLETION:
+	case USB_ERR_SHORT_XFER:
+	case USB_ERR_STALLED:
+	case USB_ERR_CANCELLED:
+		break;
+	default:
+		DPRINTF("I/O error - waiting a bit for TT cleanup\n");
+		usb_pause_mtx(mtx, hz / 16);
+		break;
+	}
 	return ((usb_error_t)err);
 }
 
@@ -789,8 +795,6 @@
 	/* check for errors */
 	if (err)
 		goto done;
-#ifdef USB_DEBUG
-#endif
 	n = 0;
 	while (1) {
 		/* wait for the device to recover from reset */
@@ -997,7 +1001,7 @@
 		USETW(req.wLength, min_len);
 
 		err = usbd_do_request_flags(udev, mtx, &req,
-		    desc, 0, NULL, 1000);
+		    desc, 0, NULL, 500 /* ms */);
 
 		if (err) {
 			if (!retries) {
@@ -1882,32 +1886,41 @@
 	 */
 	switch (udev->speed) {
 	case USB_SPEED_FULL:
-	case USB_SPEED_LOW:
+		if (usb_full_ddesc != 0) {
+			/* get full device descriptor */
+			err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+			if (err == 0)
+				break;
+		}
+
+		/* get partial device descriptor, some devices crash on this */
 		err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
 		    USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
-		if (err != 0) {
-			DPRINTFN(0, "getting device descriptor "
-			    "at addr %d failed, %s\n", udev->address,
-			    usbd_errstr(err));
-			return (err);
-		}
+		if (err != 0)
+			break;
+
+		/* get the full device descriptor */
+		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
 		break;
+
 	default:
 		DPRINTF("Minimum MaxPacketSize is large enough "
-		    "to hold the complete device descriptor\n");
+		    "to hold the complete device descriptor or "
+		    "only once MaxPacketSize choice\n");
+
+		/* get the full device descriptor */
+		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+		/* try one more time, if error */
+		if (err != 0)
+			err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
 		break;
 	}
 
-	/* get the full device descriptor */
-	err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-
-	/* try one more time, if error */
-	if (err)
-		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-
-	if (err) {
-		DPRINTF("addr=%d, getting full desc failed\n",
-		    udev->address);
+	if (err != 0) {
+		DPRINTFN(0, "getting device descriptor "
+		    "at addr %d failed, %s\n", udev->address,
+		    usbd_errstr(err));
 		return (err);
 	}
 
@@ -1952,6 +1965,7 @@
 		return (USB_ERR_INVAL);
 	}
 retry:
+#if USB_HAVE_TT_SUPPORT
 	/*
 	 * Try to reset the High Speed parent HUB of a LOW- or FULL-
 	 * speed device, if any.
@@ -1959,8 +1973,17 @@
 	if (udev->parent_hs_hub != NULL &&
 	    udev->speed != USB_SPEED_HIGH) {
 		DPRINTF("Trying to reset parent High Speed TT.\n");
-		err = usbd_req_reset_tt(udev->parent_hs_hub, NULL,
-		    udev->hs_port_no);
+		if (udev->parent_hs_hub == parent_hub &&
+		    (uhub_count_active_host_ports(parent_hub, USB_SPEED_LOW) +
+		     uhub_count_active_host_ports(parent_hub, USB_SPEED_FULL)) == 1) {
+			/* we can reset the whole TT */
+			err = usbd_req_reset_tt(parent_hub, NULL,
+			    udev->hs_port_no);
+		} else {
+			/* only reset a particular device and endpoint */
+			err = usbd_req_clear_tt_buffer(udev->parent_hs_hub, NULL,
+			    udev->hs_port_no, old_addr, UE_CONTROL, 0);
+		}
 		if (err) {
 			DPRINTF("Resetting parent High "
 			    "Speed TT failed (%s).\n",
@@ -1967,7 +1990,7 @@
 			    usbd_errstr(err));
 		}
 	}
-
+#endif
 	/* Try to warm reset first */
 	if (parent_hub->speed == USB_SPEED_SUPER)
 		usbd_req_warm_reset_port(parent_hub, mtx, udev->port_no);

Modified: stable/0.8/sys/dev/usb/usb_request.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_request.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_request.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_request.h 236898 2012-06-11 17:27:53Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_transfer.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_transfer.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_transfer.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_transfer.c 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -322,6 +322,7 @@
 	usb_frcount_t n_frlengths;
 	usb_frcount_t n_frbuffers;
 	usb_frcount_t x;
+	uint16_t maxp_old;
 	uint8_t type;
 	uint8_t zmps;
 
@@ -407,6 +408,11 @@
 	if (xfer->max_packet_count > parm->hc_max_packet_count) {
 		xfer->max_packet_count = parm->hc_max_packet_count;
 	}
+
+	/* store max packet size value before filtering */
+
+	maxp_old = xfer->max_packet_size;
+
 	/* filter "wMaxPacketSize" according to HC capabilities */
 
 	if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
@@ -439,6 +445,13 @@
 		}
 	}
 
+	/*
+	 * Check if the max packet size was outside its allowed range
+	 * and clamped to a valid value:
+	 */
+	if (maxp_old != xfer->max_packet_size)
+		xfer->flags_int.maxp_was_clamped = 1;
+	
 	/* compute "max_frame_size" */
 
 	usbd_update_max_frame_size(xfer);
@@ -859,7 +872,7 @@
 		return (error);
 
 	/* Protect scratch area */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
 	refcount = 0;
 	info = NULL;
@@ -902,7 +915,8 @@
 #if USB_HAVE_BUSDMA
 			usb_dma_tag_setup(&info->dma_parent_tag,
 			    parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag,
-			    xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max);
+			    xfer_mtx, &usb_bdma_done_event, udev->bus->dma_bits,
+			    parm->dma_tag_max);
 #endif
 
 			info->bus = udev->bus;
@@ -1157,7 +1171,7 @@
 	error = parm->err;
 
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 
 	return (error);
 }
@@ -1331,6 +1345,29 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_control_transfer_did_data
+ *
+ * This function returns non-zero if a control endpoint has
+ * transferred the first DATA packet after the SETUP packet.
+ * Else it returns zero.
+ *------------------------------------------------------------------------*/
+static uint8_t
+usbd_control_transfer_did_data(struct usb_xfer *xfer)
+{
+	struct usb_device_request req;
+
+	/* SETUP packet is not yet sent */
+	if (xfer->flags_int.control_hdr != 0)
+		return (0);
+
+	/* copy out the USB request header */
+	usbd_copy_out(xfer->frbuffers, 0, &req, sizeof(req));
+
+	/* compare remainder to the initial value */
+	return (xfer->flags_int.control_rem != UGETW(req.wLength));
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_setup_ctrl_transfer
  *
  * This function handles initialisation of control transfers. Control
@@ -1435,6 +1472,11 @@
 		len = (xfer->sumlen - sizeof(struct usb_device_request));
 	}
 
+	/* update did data flag */
+
+	xfer->flags_int.control_did_data =
+	    usbd_control_transfer_did_data(xfer);
+
 	/* check if there is a length mismatch */
 
 	if (len > xfer->flags_int.control_rem) {
@@ -2250,8 +2292,11 @@
 	}
 
 #if USB_HAVE_PF
-	if (xfer->usb_state != USB_ST_SETUP)
+	if (xfer->usb_state != USB_ST_SETUP) {
+		USB_BUS_LOCK(info->bus);
 		usbpf_xfertap(xfer, USBPF_XFERTAP_DONE);
+		USB_BUS_UNLOCK(info->bus);
+	}
 #endif
 	/* call processing routine */
 	(xfer->callback) (xfer, xfer->error);
@@ -2366,8 +2411,10 @@
 void
 usbd_transfer_done(struct usb_xfer *xfer, usb_error_t error)
 {
-	USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
+	struct usb_xfer_root *info = xfer->xroot;
 
+	USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
+
 	DPRINTF("err=%s\n", usbd_errstr(error));
 
 	/*
@@ -2380,10 +2427,10 @@
 		xfer->flags_int.control_act = 0;
 		return;
 	}
-	/* only set transfer error if not already set */
-	if (!xfer->error) {
+	/* only set transfer error, if not already set */
+	if (xfer->error == USB_ERR_NORMAL_COMPLETION)
 		xfer->error = error;
-	}
+
 	/* stop any callouts */
 	usb_callout_stop(&xfer->timeout_handle);
 
@@ -2395,7 +2442,7 @@
 	usbd_transfer_dequeue(xfer);
 
 #if USB_HAVE_BUSDMA
-	if (mtx_owned(xfer->xroot->xfer_mtx)) {
+	if (mtx_owned(info->xfer_mtx)) {
 		struct usb_xfer_queue *pq;
 
 		/*
@@ -2402,7 +2449,7 @@
 		 * If the private USB lock is not locked, then we assume
 		 * that the BUS-DMA load stage has been passed:
 		 */
-		pq = &xfer->xroot->dma_q;
+		pq = &info->dma_q;
 
 		if (pq->curr == xfer) {
 			/* start the next BUS-DMA load, if any */
@@ -2412,10 +2459,10 @@
 #endif
 	/* keep some statistics */
 	if (xfer->error) {
-		xfer->xroot->bus->stats_err.uds_requests
+		info->bus->stats_err.uds_requests
 		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
 	} else {
-		xfer->xroot->bus->stats_ok.uds_requests
+		info->bus->stats_ok.uds_requests
 		    [xfer->endpoint->edesc->bmAttributes & UE_XFERTYPE]++;
 	}
 
@@ -2655,7 +2702,7 @@
 
 	/* defer delay */
 	usb_callout_reset(&xfer->timeout_handle,
-	    USB_MS_TO_TICKS(ms), cb, xfer);
+	    USB_MS_TO_TICKS(ms) + USB_CALLOUT_ZERO_TICKS, cb, xfer);
 }
 
 /*------------------------------------------------------------------------*
@@ -2781,6 +2828,22 @@
 		/* end of control transfer, if any */
 		xfer->flags_int.control_act = 0;
 
+#if USB_HAVE_TT_SUPPORT
+		switch (xfer->error) {
+		case USB_ERR_NORMAL_COMPLETION:
+		case USB_ERR_SHORT_XFER:
+		case USB_ERR_STALLED:
+		case USB_ERR_CANCELLED:
+			/* nothing to do */
+			break;
+		default:
+			/* try to reset the TT, if any */
+			USB_BUS_LOCK(bus);
+			uhub_tt_buffer_reset_async_locked(xfer->xroot->udev, xfer->endpoint);
+			USB_BUS_UNLOCK(bus);
+			break;
+		}
+#endif
 		/* check if we should block the execution queue */
 		if ((xfer->error != USB_ERR_CANCELLED) &&
 		    (xfer->flags.pipe_bof)) {
@@ -3347,3 +3410,13 @@
 {
 	return (xfer->isoc_time_complete);
 }
+
+/*
+ * The following function returns non-zero if the max packet size
+ * field was clamped to a valid value. Else it returns zero.
+ */
+uint8_t
+usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
+{
+	return (xfer->flags_int.maxp_was_clamped);
+}

Modified: stable/0.8/sys/dev/usb/usb_transfer.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_transfer.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_transfer.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_transfer.h 213435 2010-10-04 23:18:05Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usb_util.c
===================================================================
--- stable/0.8/sys/dev/usb/usb_util.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_util.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_util.c 305735 2016-09-12 10:20:44Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *
@@ -94,7 +94,7 @@
 	}
 
 	/* Protect scratch area */
-	do_unlock = usbd_enum_lock(udev);
+	do_unlock = usbd_ctrl_lock(udev);
 
 	temp_p = (char *)udev->scratch.data;
 
@@ -111,7 +111,7 @@
 	}
 
 	if (do_unlock)
-		usbd_enum_unlock(udev);
+		usbd_ctrl_unlock(udev);
 
 	device_set_desc_copy(dev, temp_p);
 	device_printf(dev, "<%s> on %s\n", temp_p,

Modified: stable/0.8/sys/dev/usb/usb_util.h
===================================================================
--- stable/0.8/sys/dev/usb/usb_util.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usb_util.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usb_util.h 229118 2011-12-31 15:31:34Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  *

Modified: stable/0.8/sys/dev/usb/usbdevs
===================================================================
--- stable/0.8/sys/dev/usb/usbdevs	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdevs	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-$MidnightBSD$
+$FreeBSD: stable/9/sys/dev/usb/usbdevs 315250 2017-03-14 15:25:49Z hselasky $
 /* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
 
 /*-
@@ -525,7 +525,7 @@
 vendor CANYON		0x0c10	Canyon
 vendor ICOM		0x0c26	Icom Inc.
 vendor GNOTOMETRICS	0x0c33	GN Otometrics
-vendor CHICONY2		0x0c45	Chicony
+vendor CHICONY2		0x0c45	Chicony / Microdia / Sonix Technology Co., Ltd.
 vendor REINERSCT	0x0c4b	Reiner-SCT
 vendor SEALEVEL		0x0c52	Sealevel System
 vendor JETI		0x0c6c	Jeti
@@ -687,6 +687,7 @@
 vendor SWEEX2		0x177f	Sweex
 vendor METAGEEK		0x1781	MetaGeek
 vendor KAMSTRUP		0x17a8	Kamstrup A/S
+vendor DISPLAYLINK	0x17e9	DisplayLink
 vendor LENOVO		0x17ef	Lenovo
 vendor WAVESENSE	0x17f4	WaveSense
 vendor VAISALA		0x1843	Vaisala
@@ -775,6 +776,7 @@
 vendor NETGEAR4		0x9846  Netgear
 vendor MARVELL		0x9e88	Marvell Technology Group Ltd.
 vendor 3COM3		0xa727	3Com
+vendor CACE		0xcace	CACE Technologies
 vendor EVOLUTION	0xdeee	Evolution Robotics products
 vendor DATAAPEX		0xdaae	DataApex
 vendor HP2		0xf003	Hewlett Packard
@@ -862,6 +864,7 @@
 product	ACCTON RT3070_5		0xd522	RT3070
 product ACCTON RTL8192SU        0xc512  RTL8192SU
 product ACCTON ZD1211B		0xe501	ZD1211B
+product ACCTON WN7512		0xf522	WN7512
 
 /* Aceeca products */
 product ACEECA MEZ1000		0x0001	MEZ1000 RDA
@@ -1128,6 +1131,10 @@
 product APPLE WELLSPRING8_ANSI	0x0290	Apple Internal Keyboard/Trackpad
 product APPLE WELLSPRING8_ISO	0x0291	Apple Internal Keyboard/Trackpad
 product APPLE WELLSPRING8_JIS	0x0292	Apple Internal Keyboard/Trackpad
+/* MacbookPro12,1 */
+product APPLE WELLSPRING9_ANSI	0x0272	Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_ISO	0x0273	Apple Internal Keyboard/Trackpad
+product APPLE WELLSPRING9_JIS	0x0274	Apple Internal Keyboard/Trackpad
 product APPLE MOUSE		0x0301	Mouse M4848
 product APPLE OPTMOUSE		0x0302	Optical mouse
 product APPLE MIGHTYMOUSE	0x0304	Mighty Mouse
@@ -1222,6 +1229,11 @@
 product ATHEROS2 AR5523_2_NF	0x0004	AR5523 (no firmware)
 product ATHEROS2 AR5523_3	0x0005	AR5523
 product ATHEROS2 AR5523_3_NF	0x0006	AR5523 (no firmware)
+product ATHEROS2 TG121N		0x1001	TG121N
+product ATHEROS2 WN821NV2	0x1002	WN821NV2
+product ATHEROS2 3CRUSBN275	0x1010	3CRUSBN275
+product ATHEROS2 WN612		0x1011	WN612
+product ATHEROS2 AR9170		0x9170	AR9170
 
 /* Atmel Comp. products */
 product ATMEL STK541		0x2109	Zigbee Controller
@@ -1237,6 +1249,9 @@
 /* Avision products */
 product AVISION 1200U		0x0268	1200U scanner
 
+/* AVM products */
+product AVM FRITZWLAN		0x8401	FRITZ!WLAN N
+
 /* Axesstel products */
 product AXESSTEL DATAMODEM	0x1000  Data Modem
 
@@ -1339,6 +1354,9 @@
 product BTC BTC6100		0x5550	6100C Keyboard
 product BTC BTC7932		0x6782	Keyboard with mouse port
 
+/* CACE Technologies products */
+product CACE AIRPCAPNX		0x0300	AirPcap NX
+
 /* Canon, Inc. products */
 product CANON N656U		0x2206	CanoScan N656U
 product CANON N1220U		0x2207	CanoScan N1220U
@@ -1407,6 +1425,7 @@
 product CISCOLINKSYS WUSB54GR	0x0023	WUSB54GR
 product CISCOLINKSYS WUSBF54G	0x0024	WUSBF54G
 product CISCOLINKSYS AE1000	0x002f	AE1000
+product CISCOLINKSYS USB3GIGV1	0x0041  USB3GIGV1 USB Ethernet Adapter
 product CISCOLINKSYS2 RT3070	0x4001	RT3070
 product CISCOLINKSYS3 RT3070	0x0101	RT3070
 
@@ -1419,6 +1438,9 @@
 product CLIPSAL C5000CT2	0x0305	C5000CT2 C-Bus Touch Screen
 product CLIPSAL L51xx		0x0401	L51xx C-Bus Dimmer
 
+/* C-Media products */
+product CMEDIA CM6206		0x0102	CM106 compatible sound device
+
 /* CMOTECH products */
 product CMOTECH CNU510		0x5141	CDMA Technologies USB modem
 product CMOTECH CNU550		0x5543	CDMA 2000 1xRTT/1xEVDO USB modem
@@ -1490,6 +1512,7 @@
 /* Corsair products */
 product CORSAIR K60		0x0a60	Corsair Vengeance K60 keyboard
 product CORSAIR K70		0x1b09	Corsair Vengeance K70 keyboard
+product CORSAIR STRAFE		0x1b15	Cossair STRAFE Gaming keyboard
 
 /* Creative products */
 product CREATIVE NOMAD_II	0x1002	Nomad II MP3 player
@@ -1598,6 +1621,7 @@
 product DLINK DSB650TX4		0x200c	10/100 Ethernet
 product DLINK DWL120E		0x3200	DWL-120 rev E
 product DLINK DWA125D1		0x330f	DWA-125 rev D1
+product DLINK DWA123D1		0x3310	DWA-123 rev D1
 product DLINK DWL122		0x3700	DWL-122
 product DLINK DWLG120		0x3701	DWL-G120
 product DLINK DWL120F		0x3702	DWL-120 rev F
@@ -1637,8 +1661,10 @@
 product DLINK2 RTL8192SU_1	0x3300	RTL8192SU
 product DLINK2 RTL8192SU_2	0x3302	RTL8192SU
 product DLINK2 DWA131A1		0x3303	DWA-131 A1
+product DLINK2 DWA160A2		0x3a09	DWA-160 A2
 product DLINK2 DWA120		0x3a0c	DWA-120
 product DLINK2 DWA120_NF	0x3a0d	DWA-120 (no firmware)
+product DLINK2 DWA130D1		0x3a0f	DWA-130 D1
 product DLINK2 DWLG122C1	0x3c03	DWL-G122 c1
 product DLINK2 WUA1340		0x3c04	WUA-1340
 product DLINK2 DWA111		0x3c06	DWA-111
@@ -1649,6 +1675,7 @@
 product DLINK2 RT3070_1		0x3c0d	RT3070
 product DLINK2 RT3070_2		0x3c0e	RT3070
 product DLINK2 RT3070_3		0x3c0f	RT3070
+product DLINK2 DWA160A1		0x3c10	DWA-160 A1
 product DLINK2 RT2870_2		0x3c11	RT2870
 product DLINK2 DWA130		0x3c13	DWA-130
 product DLINK2 RT3070_4		0x3c15	RT3070
@@ -1655,6 +1682,28 @@
 product DLINK2 RT3070_5		0x3c16	RT3070
 product DLINK3 DWM652		0x3e04	DWM-652
 
+/* DisplayLink products */
+product DISPLAYLINK LCD4300U	0x01ba	LCD-4300U
+product DISPLAYLINK LCD8000U	0x01bb	LCD-8000U
+product DISPLAYLINK LD220	0x0100	Samsung LD220
+product DISPLAYLINK GUC2020	0x0059	IOGEAR DVI GUC2020
+product DISPLAYLINK VCUD60	0x0136	Rextron DVI
+product DISPLAYLINK CONV	0x0138	StarTech CONV-USB2DVI
+product DISPLAYLINK DLDVI	0x0141	DisplayLink DVI
+product DISPLAYLINK VGA10	0x015a	CMP-USBVGA10
+product DISPLAYLINK WSDVI	0x0198	WS Tech DVI
+product DISPLAYLINK EC008	0x019b	EasyCAP008 DVI
+product DISPLAYLINK HPDOCK	0x01d4	HP USB Docking
+product DISPLAYLINK NL571	0x01d7	HP USB DVI
+product DISPLAYLINK M01061	0x01e2	Lenovo DVI
+product DISPLAYLINK SWDVI	0x024c	SUNWEIT DVI
+product DISPLAYLINK NBDOCK	0x0215	VideoHome NBdock1920
+product DISPLAYLINK LUM70	0x02a9	Lilliput UM-70
+product DISPLAYLINK UM7X0	0x401a	nanovision MiMo
+product DISPLAYLINK LT1421	0x03e0	Lenovo ThinkVision LT1421
+product DISPLAYLINK POLARIS2	0x0117	Polaris2 USB dock
+product DISPLAYLINK PLUGABLE	0x0377	Plugable docking station
+
 /* DMI products */
 product DMI CFSM_RW		0xa109	CF/SM Reader/Writer
 product DMI DISK		0x2bcf	Generic Disk
@@ -1715,6 +1764,7 @@
 product ELECOM LDUSBTX0		0x200c	LD-USB/TX
 product ELECOM LDUSBTX1		0x4002	LD-USB/TX
 product ELECOM LDUSBLTX		0x4005	LD-USBL/TX
+product ELECOM WDC150SU2M	0x4008	WDC-150SU2M
 product ELECOM LDUSBTX2		0x400b	LD-USB/TX
 product ELECOM LDUSB20		0x4010	LD-USB20
 product ELECOM UCSGT		0x5003	UC-SGT
@@ -2220,6 +2270,9 @@
 product HITACHI DVDCAM_DZ_MV100A	0x0004	DVD-CAM DZ-MV100A Camcorder
 product HITACHI DVDCAM_USB	0x001e	DVDCAM USB HS Interface
 
+/* Holtek products */
+product HOLTEK F85		0xa030	Holtek USB gaming keyboard
+
 /* HP products */
 product HP 895C			0x0004	DeskJet 895C
 product HP 4100C		0x0101	Scanjet 4100C
@@ -2364,6 +2417,7 @@
 product HUAWEI K4505_INIT	0x1521	K4505 Initial
 product HUAWEI K3772_INIT	0x1526	K3772 Initial
 product HUAWEI E3272_INIT	0x155b	LTE modem initial
+product HUAWEI ME909U		0x1573  LTE modem
 product HUAWEI R215_INIT	0x1582	LTE modem initial
 product HUAWEI R215		0x1588	LTE modem
 product HUAWEI ETS2055		0x1803	CDMA modem
@@ -2442,6 +2496,7 @@
 product IODATA USBWNB11A	0x0919	USB WN-B11
 product IODATA USBWNB11		0x0922	USB Airport WN-B11
 product IODATA ETGUS2		0x0930	ETG-US2
+product IODATA WNGDNUS2		0x093f	WN-GDN/US2
 product IODATA RT3072_1		0x0944	RT3072
 product IODATA RT3072_2		0x0945	RT3072
 product IODATA RT3072_3		0x0947	RT3072
@@ -2607,6 +2662,7 @@
 product LEADTEK 9531		0x2101	9531 GPS
 
 /* Lenovo products */
+product LENOVO GIGALAN		0x304b	USB 3.0 Ethernet
 product LENOVO ETHERNET		0x7203	USB 2.0 Ethernet
 
 /* Lexar products */
@@ -2673,6 +2729,7 @@
 product LOGITECH RK53		0xc501	Cordless mouse
 product LOGITECH RB6		0xc503	Cordless keyboard
 product LOGITECH MX700		0xc506	Cordless optical mouse
+product LOGITECH UNIFYING	0xc52b  Logitech Unifying Receiver
 product LOGITECH QUICKCAMPRO2	0xd001	QuickCam Pro
 
 /* Logitec Corp. products */
@@ -2996,11 +3053,12 @@
 product MELCO WLRUCGAOSS	0x0119	WLR-UC-G-AOSS
 product MELCO WLIUCAG300N	0x012e	WLI-UC-AG300N
 product MELCO WLIUCG		0x0137	WLI-UC-G
-product MELCO RT2870_1		0x0148	RT2870
+product MELCO WLIUCG300HP	0x0148	WLI-UC-G300HP
 product MELCO RT2870_2		0x0150	RT2870
 product MELCO WLIUCGN		0x015d	WLI-UC-GN
 product MELCO WLIUCG301N	0x016f	WLI-UC-G301N
 product MELCO WLIUCGNM		0x01a2	WLI-UC-GNM
+product MELCO WLIUCG300HPV1	0x01a8	WLI-UC-G300HP-V1
 product MELCO WLIUCGNM2		0x01ee	WLI-UC-GNM2
 
 /* Merlin products */
@@ -3023,6 +3081,11 @@
 product MEI CASHFLOW_SC		0x1100	Cashflow-SC Cash Acceptor
 product MEI S2000		0x1101	Series 2000 Combo Acceptor
 
+/* Microdia / Sonix Techonology Co., Ltd. products */
+product CHICONY2 YUREX		0x1010	YUREX
+product CHICONY2 CAM_1		0x62c0	CAM_1
+product CHICONY2 TEMPER		0x7401	TEMPer sensor
+
 /* Micro Star International products */
 product MSI BT_DONGLE		0x1967	Bluetooth USB dongle
 product MSI RT3070_1		0x3820	RT3070
@@ -3175,6 +3238,7 @@
 /* NEC products */
 product NEC HUB_0050		0x0050	USB 2.0 7-Port Hub
 product NEC HUB_005A		0x005a	USB 2.0 4-Port Hub
+product NEC WL300NUG		0x0249	WL300NU-G
 product NEC HUB			0x55aa	hub
 product NEC HUB_B		0x55ab	hub
 
@@ -3202,12 +3266,17 @@
 product NETGEAR FA101		0x1020	Ethernet 10/100, USB1.1
 product NETGEAR FA120		0x1040	USB 2.0 Ethernet
 product NETGEAR M4100		0x1100	M4100/M5300/M7100 series switch
-product NETGEAR WG111V2_2	0x4240	PrismGT USB 2.0 WLAN
+product NETGEAR WG111V1_2	0x4240	PrismGT USB 2.0 WLAN
 product NETGEAR WG111V3		0x4260	WG111v3
 product NETGEAR WG111U		0x4300	WG111U
 product NETGEAR WG111U_NF	0x4301	WG111U (no firmware)
 product NETGEAR WG111V2		0x6a00	WG111V2
+product NETGEAR WN111V2		0x9001	WN111V2
+product NETGEAR WNDA3100	0x9010	WNDA3100
+product NETGEAR WNDA4100	0x9012	WNDA4100
+product NETGEAR WNDA3200	0x9018	WNDA3200
 product NETGEAR RTL8192CU	0x9021	RTL8192CU
+product NETGEAR WNA1000		0x9040	WNA1000
 product NETGEAR WNA1000M	0x9041	WNA1000M
 product NETGEAR2 MA101		0x4100	MA101
 product NETGEAR2 MA101B		0x4102	MA101 Rev B
@@ -3471,6 +3540,7 @@
 product PLANEX2 RTL8188CUS	0x1201	RTL8188CUS
 product PLANEX2 GW_US11S	0x3220	GW-US11S WLAN
 product PLANEX2 GW_US54GXS	0x5303	GW-US54GXS WLAN
+product PLANEX2 GW_US300	0x5304	GW-US300
 product PLANEX2 RTL8188CU_1	0xab2a	RTL8188CU
 product PLANEX2 RTL8188CU_2	0xed17	RTL8188CU
 product PLANEX2 RTL8188CU_3	0x4902	RTL8188CU
@@ -3651,6 +3721,7 @@
 product QUALCOMMINC E0078	0x0078	3G modem
 product QUALCOMMINC E0082	0x0082	3G modem
 product QUALCOMMINC E0086	0x0086	3G modem
+product QUALCOMMINC MF112	0x0103	3G modem
 product QUALCOMMINC SURFSTICK	0x0117	1&1 Surf Stick
 product QUALCOMMINC K3772_Z_INIT	0x1179	K3772-Z Initial
 product QUALCOMMINC K3772_Z	0x1181	K3772-Z
@@ -3734,6 +3805,7 @@
 product REALTEK RTL8188CU_2	0x817b	RTL8188CU
 product REALTEK RTL8187		0x8187	RTL8187 Wireless Adapter
 product REALTEK RTL8187B_0	0x8189	RTL8187B Wireless Adapter
+product REALTEK RTL8188CU_3	0x8191	RTL8188CU
 product REALTEK RTL8196EU	0x8196	RTL8196EU
 product REALTEK RTL8187B_1	0x8197	RTL8187B Wireless Adapter
 product REALTEK RTL8187B_2	0x8198	RTL8187B Wireless Adapter
@@ -4007,7 +4079,9 @@
 product SIERRA E6892		0x6892	E6892
 product SIERRA E6893		0x6893	E6893
 product SIERRA MC8700		0x68A3	MC8700
-product SIERRA AIRCARD875	0x6820	Aircard 875 HSDPA
+product SIERRA MC7354		0x68C0	MC7354
+product SIERRA MC7355		0x9041	MC7355
+product SIERRA MC7430		0x9071	Sierra Wireless MC7430 Qualcomm Snapdragon X7 LTE-A
 product SIERRA AC313U		0x68aa	Sierra Wireless AirCard 313U
 product SIERRA TRUINSTALL	0x0fff	Aircard Tru Installer
 
@@ -4386,6 +4460,7 @@
 
 /* TRENDnet products */
 product TRENDNET RTL8192CU	0x624d	RTL8192CU
+product TRENDNET TEW646UBH	0x646b	TEW-646UBH
 product TRENDNET RTL8188CU	0x648b	RTL8188CU
 
 /* Tripp-Lite products */
@@ -4539,8 +4614,10 @@
 product WINMAXGROUP FLASH64MC	0x6660	USB Flash Disk 64M-C
 
 /* Wistron NeWeb products */
+product WISTRONNEWEB WNC0600	0x0326	WNC-0600USB
 product WISTRONNEWEB UR045G	0x0427	PrismGT USB 2.0 WLAN
 product WISTRONNEWEB UR055G	0x0711	UR055G
+product WISTRONNEWEB O8494	0x0804	ORiNOCO 802.11n
 product WISTRONNEWEB AR5523_1	0x0826	AR5523
 product WISTRONNEWEB AR5523_1_NF	0x0827	AR5523 (no firmware)
 product WISTRONNEWEB AR5523_2	0x082a	AR5523
@@ -4589,7 +4666,9 @@
 product ZCOM XM142		0x0015	XM-142
 product ZCOM ZD1211B		0x001a	ZD1211B
 product ZCOM RT2870_1		0x0022	RT2870
+product ZCOM UB81		0x0023	UB81
 product ZCOM RT2870_2		0x0025	RT2870
+product ZCOM UB82		0x0026	UB82
 
 /* Zinwell products */
 product ZINWELL RT2570		0x0260	RT2570
@@ -4608,6 +4687,7 @@
 /* Zydas Technology Corporation products */
 product ZYDAS ZD1211		0x1211	ZD1211 WLAN abg
 product ZYDAS ZD1211B		0x1215	ZD1211B
+product ZYDAS ZD1221		0x1221	ZD1221
 
 /* ZyXEL Communication Co. products */
 product ZYXEL OMNI56K		0x1500	Omni 56K Plus
@@ -4619,6 +4699,8 @@
 product ZYXEL G220V2		0x340f	G-220 v2
 product ZYXEL G202		0x3410	G-202
 product ZYXEL RT2870_1		0x3416	RT2870
+product ZYXEL NWD271N		0x3417	NWD-271N
+product ZYXEL NWD211AN		0x3418	NWD-211AN
 product ZYXEL RT2870_2		0x341a	RT2870
 product ZYXEL RT3070		0x341e	NWD2105
 product ZYXEL RTL8192CU		0x341f	RTL8192CU

Modified: stable/0.8/sys/dev/usb/usbdi.h
===================================================================
--- stable/0.8/sys/dev/usb/usbdi.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdi.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -21,7 +21,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usbdi.h 267350 2014-06-11 06:45:52Z hselasky $
  */
 #ifndef _USB_USBDI_H_
 #define _USB_USBDI_H_
@@ -549,6 +549,7 @@
 void	usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
 void	usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
 uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
+uint8_t usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer);
 
 void	usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
 	    const void *ptr, usb_frlength_t len);
@@ -565,6 +566,8 @@
 void	usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
 	    usb_frlength_t len);
 void	usbd_start_re_enumerate(struct usb_device *udev);
+usb_error_t
+	usbd_start_set_config(struct usb_device *, uint8_t);
 
 int	usb_fifo_attach(struct usb_device *udev, void *priv_sc,
 	    struct mtx *priv_mtx, struct usb_fifo_methods *pm,

Modified: stable/0.8/sys/dev/usb/usbdi_util.h
===================================================================
--- stable/0.8/sys/dev/usb/usbdi_util.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbdi_util.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -21,7 +21,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/usbdi_util.h 213435 2010-10-04 23:18:05Z hselasky $
  */
 #ifndef _USB_USBDI_UTIL_H_
 #define _USB_USBDI_UTIL_H_

Modified: stable/0.8/sys/dev/usb/usbhid.h
===================================================================
--- stable/0.8/sys/dev/usb/usbhid.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/usbhid.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/* $MidnightBSD$ */
+/* $FreeBSD: stable/9/sys/dev/usb/usbhid.h 245733 2013-01-21 07:28:46Z hselasky $ */
 /*-
  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.

Modified: stable/0.8/sys/dev/usb/wlan/if_rum.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rum.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rum.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_rum.c 269267 2014-07-29 22:00:54Z hselasky $	*/
 
 /*-
  * Copyright (c) 2005-2007 Damien Bergamini <damien.bergamini at free.fr>
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_rum.c 269267 2014-07-29 22:00:54Z hselasky $");
 
 /*-
  * Ralink Technology RT2501USB/RT2601USB chipset driver
@@ -543,6 +543,11 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
 
+	/* Prevent further ioctls */
+	RUM_LOCK(sc);
+	sc->sc_detached = 1;
+	RUM_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
 
@@ -557,7 +562,6 @@
 		if_free(ifp);
 	}
 	mtx_destroy(&sc->sc_mtx);
-
 	return (0);
 }
 
@@ -600,9 +604,14 @@
 		return NULL;
 	vap = &rvp->vap;
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(rvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	/* override state transition machine */
 	rvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = rum_newstate;
@@ -1025,6 +1034,8 @@
 		desc->plcp_length_hi = plcp_length >> 6;
 		desc->plcp_length_lo = plcp_length & 0x3f;
 	} else {
+		if (rate == 0)
+			rate = 2;	/* avoid division by zero */
 		plcp_length = (16 * len + rate - 1) / rate;
 		if (rate == 22) {
 			remainder = (16 * len) % 22;
@@ -1127,7 +1138,7 @@
 
 		dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate, 
 		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 
 		/* tell hardware to add timestamp for probe responses */
 		if ((wh->i_fc[0] &
@@ -1271,7 +1282,7 @@
 
 		dur = ieee80211_ack_duration(ic->ic_rt, rate, 
 		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 	}
 
 	rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
@@ -1322,8 +1333,15 @@
 	struct rum_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
 
+	RUM_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RUM_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		RUM_LOCK(sc);
@@ -2366,8 +2384,7 @@
 	DEVMETHOD(device_probe,		rum_match),
 	DEVMETHOD(device_attach,	rum_attach),
 	DEVMETHOD(device_detach,	rum_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t rum_driver = {

Modified: stable/0.8/sys/dev/usb/wlan/if_rumfw.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumfw.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumfw.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_rumfw.h 196219 2009-08-14 20:03:53Z jhb $	*/
 
 /*-
  * Copyright (c) 2005-2006, Ralink Technology, Corp.

Modified: stable/0.8/sys/dev/usb/wlan/if_rumreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_rumreg.h 196970 2009-09-08 13:19:05Z phk $	*/
 
 /*-
  * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>

Modified: stable/0.8/sys/dev/usb/wlan/if_rumvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_rumvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_rumvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_rumvar.h 259460 2013-12-16 09:34:01Z hselasky $	*/
 
 /*-
  * Copyright (c) 2005, 2006 Damien Bergamini <damien.bergamini at free.fr>
@@ -29,7 +29,7 @@
 	int8_t		wr_antsignal;
 	int8_t		wr_antnoise;
 	uint8_t		wr_antenna;
-};
+} __packed __aligned(8);
 
 #define RT2573_RX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -47,7 +47,7 @@
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
 	uint8_t		wt_antenna;
-};
+} __packed __aligned(8);
 
 #define RT2573_TX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -106,6 +106,7 @@
 	uint32_t			rf_regs[4];
 	uint8_t				txpow[44];
 	uint8_t				sc_bssid[6];
+	uint8_t				sc_detached;
 
 	struct {
 		uint8_t	val;

Modified: stable/0.8/sys/dev/usb/wlan/if_run.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_run.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_run.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -2,6 +2,7 @@
  * Copyright (c) 2008,2010 Damien Bergamini <damien.bergamini at free.fr>
  * ported to FreeBSD by Akinori Furukoshi <moonlightakkiy at yahoo.ca>
  * USB Consulting, Hans Petter Selasky <hselasky at freebsd.org>
+ * Copyright (c) 2013-2014 Kevin Lo
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,10 +18,10 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_run.c 294903 2016-01-27 07:34:23Z delphij $");
 
 /*-
- * Ralink Technology RT2700U/RT2800U/RT3000U chipset driver.
+ * Ralink Technology RT2700U/RT2800U/RT3000U/RT3900E chipset driver.
  * http://www.ralinktech.com/
  */
 
@@ -68,16 +69,15 @@
 #include <dev/usb/usbdi.h>
 #include "usbdevs.h"
 
-#define USB_DEBUG_VAR run_debug
+#define	USB_DEBUG_VAR	run_debug
 #include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_msctest.h>
 
 #include <dev/usb/wlan/if_runreg.h>
 #include <dev/usb/wlan/if_runvar.h>
 
-#define	N(_a) ((int)(sizeof((_a)) / sizeof((_a)[0])))
-
 #ifdef	USB_DEBUG
-#define RUN_DEBUG
+#define	RUN_DEBUG
 #endif
 
 #ifdef	RUN_DEBUG
@@ -87,7 +87,7 @@
     "run debug level");
 #endif
 
-#define IEEE80211_HAS_ADDR4(wh) \
+#define	IEEE80211_HAS_ADDR4(wh)	\
 	(((wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
 
 /*
@@ -94,10 +94,13 @@
  * Because of LOR in run_key_delete(), use atomic instead.
  * '& RUN_CMDQ_MASQ' is to loop cmdq[].
  */
-#define RUN_CMDQ_GET(c)	(atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
+#define	RUN_CMDQ_GET(c)	(atomic_fetchadd_32((c), 1) & RUN_CMDQ_MASQ)
 
 static const STRUCT_USB_HOST_ID run_devs[] = {
-#define RUN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+#define	RUN_DEV(v,p)	{ USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+#define	RUN_DEV_EJECT(v,p)	\
+	{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RUN_EJECT) }
+#define	RUN_EJECT	1
     RUN_DEV(ABOCOM,		RT2770),
     RUN_DEV(ABOCOM,		RT2870),
     RUN_DEV(ABOCOM,		RT3070),
@@ -136,6 +139,7 @@
     RUN_DEV(ASUS,		RT2870_5),
     RUN_DEV(ASUS,		USBN13),
     RUN_DEV(ASUS,		RT3070_1),
+    RUN_DEV(ASUS,		USBN66),
     RUN_DEV(ASUS,		USB_N53),
     RUN_DEV(ASUS2,		USBN11),
     RUN_DEV(AZUREWAVE,		RT2870_1),
@@ -143,10 +147,12 @@
     RUN_DEV(AZUREWAVE,		RT3070_1),
     RUN_DEV(AZUREWAVE,		RT3070_2),
     RUN_DEV(AZUREWAVE,		RT3070_3),
+    RUN_DEV(BELKIN,		F9L1103),
     RUN_DEV(BELKIN,		F5D8053V3),
     RUN_DEV(BELKIN,		F5D8055),
     RUN_DEV(BELKIN,		F5D8055V2),
     RUN_DEV(BELKIN,		F6D4050V1),
+    RUN_DEV(BELKIN,		F6D4050V2),
     RUN_DEV(BELKIN,		RT2870_1),
     RUN_DEV(BELKIN,		RT2870_2),
     RUN_DEV(CISCOLINKSYS,	AE1000),
@@ -171,6 +177,10 @@
     RUN_DEV(CYBERTAN,		RT2870),
     RUN_DEV(DLINK,		RT2870),
     RUN_DEV(DLINK,		RT3072),
+    RUN_DEV(DLINK,		DWA127),
+    RUN_DEV(DLINK,		DWA140B3),
+    RUN_DEV(DLINK,		DWA160B2),
+    RUN_DEV(DLINK,		DWA162),
     RUN_DEV(DLINK2,		DWA130),
     RUN_DEV(DLINK2,		RT2870_1),
     RUN_DEV(DLINK2,		RT2870_2),
@@ -183,6 +193,7 @@
     RUN_DEV(DLINK2,		RT3072_1),
     RUN_DEV(EDIMAX,		EW7717),
     RUN_DEV(EDIMAX,		EW7718),
+    RUN_DEV(EDIMAX,		EW7733UND),
     RUN_DEV(EDIMAX,		RT2870_1),
     RUN_DEV(ENCORE,		RT3070_1),
     RUN_DEV(ENCORE,		RT3070_2),
@@ -212,7 +223,7 @@
     RUN_DEV(LOGITEC,		LANW300NU2),
     RUN_DEV(LOGITEC,		LANW150NU2),
     RUN_DEV(LOGITEC,		LANW300NU2S),
-    RUN_DEV(MELCO,		RT2870_1),
+    RUN_DEV(MELCO,		WLIUCG300HP),
     RUN_DEV(MELCO,		RT2870_2),
     RUN_DEV(MELCO,		WLIUCAG300N),
     RUN_DEV(MELCO,		WLIUCG300N),
@@ -219,6 +230,7 @@
     RUN_DEV(MELCO,		WLIUCG301N),
     RUN_DEV(MELCO,		WLIUCGN),
     RUN_DEV(MELCO,		WLIUCGNM),
+    RUN_DEV(MELCO,		WLIUCG300HPV1),
     RUN_DEV(MELCO,		WLIUCGNM2),
     RUN_DEV(MOTOROLA4,		RT2770),
     RUN_DEV(MOTOROLA4,		RT3070),
@@ -233,6 +245,7 @@
     RUN_DEV(MSI,		RT3070_9),
     RUN_DEV(MSI,		RT3070_10),
     RUN_DEV(MSI,		RT3070_11),
+    RUN_DEV(NETGEAR,		WNDA4100),
     RUN_DEV(OVISLINK,		RT3072),
     RUN_DEV(PARA,		RT3070),
     RUN_DEV(PEGATRON,		RT2870),
@@ -254,6 +267,9 @@
     RUN_DEV(RALINK,		RT3072),
     RUN_DEV(RALINK,		RT3370),
     RUN_DEV(RALINK,		RT3572),
+    RUN_DEV(RALINK,		RT3573),
+    RUN_DEV(RALINK,		RT5370),
+    RUN_DEV(RALINK,		RT5572),
     RUN_DEV(RALINK,		RT8070),
     RUN_DEV(SAMSUNG,		WIS09ABGN),
     RUN_DEV(SAMSUNG2,		RT2870_1),
@@ -301,6 +317,10 @@
     RUN_DEV(ZINWELL,		RT3072_2),
     RUN_DEV(ZYXEL,		RT2870_1),
     RUN_DEV(ZYXEL,		RT2870_2),
+    RUN_DEV(ZYXEL,		RT3070),
+    RUN_DEV_EJECT(ZYXEL,	NWD2705),
+    RUN_DEV_EJECT(RALINK,	RT_STOR),
+#undef RUN_DEV_EJECT
 #undef RUN_DEV
 };
 
@@ -316,8 +336,11 @@
 static usb_callback_t	run_bulk_tx_callback4;
 static usb_callback_t	run_bulk_tx_callback5;
 
+static void	run_autoinst(void *, struct usb_device *,
+		    struct usb_attach_arg *);
+static int	run_driver_loaded(struct module *, int, void *);
 static void	run_bulk_tx_callbackN(struct usb_xfer *xfer,
-		    usb_error_t error, unsigned int index);
+		    usb_error_t error, u_int index);
 static struct ieee80211vap *run_vap_create(struct ieee80211com *,
 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
 		    const uint8_t [IEEE80211_ADDR_LEN],
@@ -339,15 +362,18 @@
 static int	run_write_region_1(struct run_softc *, uint16_t,
 		    const uint8_t *, int);
 static int	run_set_region_4(struct run_softc *, uint16_t, uint32_t, int);
+static int	run_efuse_read(struct run_softc *, uint16_t, uint16_t *, int);
 static int	run_efuse_read_2(struct run_softc *, uint16_t, uint16_t *);
 static int	run_eeprom_read_2(struct run_softc *, uint16_t, uint16_t *);
-static int	run_rt2870_rf_write(struct run_softc *, uint8_t, uint32_t);
+static int	run_rt2870_rf_write(struct run_softc *, uint32_t);
 static int	run_rt3070_rf_read(struct run_softc *, uint8_t, uint8_t *);
 static int	run_rt3070_rf_write(struct run_softc *, uint8_t, uint8_t);
 static int	run_bbp_read(struct run_softc *, uint8_t, uint8_t *);
 static int	run_bbp_write(struct run_softc *, uint8_t, uint8_t);
 static int	run_mcu_cmd(struct run_softc *, uint8_t, uint16_t);
-static const char *run_get_rf(int);
+static const char *run_get_rf(uint16_t);
+static void	run_rt3593_get_txpower(struct run_softc *);
+static void	run_get_txpower(struct run_softc *);
 static int	run_read_eeprom(struct run_softc *);
 static struct ieee80211_node *run_node_alloc(struct ieee80211vap *,
 			    const uint8_t mac[IEEE80211_ADDR_LEN]);
@@ -359,7 +385,7 @@
 static void	run_key_update_end(struct ieee80211vap *);
 static void	run_key_set_cb(void *);
 static int	run_key_set(struct ieee80211vap *, struct ieee80211_key *,
-			    const uint8_t mac[IEEE80211_ADDR_LEN]);
+		    const uint8_t mac[IEEE80211_ADDR_LEN]);
 static void	run_key_delete_cb(void *);
 static int	run_key_delete(struct ieee80211vap *, struct ieee80211_key *);
 static void	run_ratectl_to(void *);
@@ -385,6 +411,7 @@
 		    const struct ieee80211_bpf_params *);
 static void	run_start(struct ifnet *);
 static int	run_ioctl(struct ifnet *, u_long, caddr_t);
+static void	run_iq_calib(struct run_softc *, u_int);
 static void	run_set_agc(struct run_softc *, uint8_t);
 static void	run_select_chan_group(struct run_softc *, int);
 static void	run_set_rx_antenna(struct run_softc *, int);
@@ -391,6 +418,9 @@
 static void	run_rt2870_set_chan(struct run_softc *, u_int);
 static void	run_rt3070_set_chan(struct run_softc *, u_int);
 static void	run_rt3572_set_chan(struct run_softc *, u_int);
+static void	run_rt3593_set_chan(struct run_softc *, u_int);
+static void	run_rt5390_set_chan(struct run_softc *, u_int);
+static void	run_rt5592_set_chan(struct run_softc *, u_int);
 static int	run_set_chan(struct run_softc *, struct ieee80211_channel *);
 static void	run_set_channel(struct ieee80211com *);
 static void	run_scan_start(struct ieee80211com *);
@@ -414,17 +444,47 @@
 static int8_t	run_rssi2dbm(struct run_softc *, uint8_t, uint8_t);
 static void	run_update_promisc_locked(struct ifnet *);
 static void	run_update_promisc(struct ifnet *);
+static void	run_rt5390_bbp_init(struct run_softc *);
 static int	run_bbp_init(struct run_softc *);
 static int	run_rt3070_rf_init(struct run_softc *);
+static void	run_rt3593_rf_init(struct run_softc *);
+static void	run_rt5390_rf_init(struct run_softc *);
 static int	run_rt3070_filter_calib(struct run_softc *, uint8_t, uint8_t,
 		    uint8_t *);
 static void	run_rt3070_rf_setup(struct run_softc *);
+static void	run_rt3593_rf_setup(struct run_softc *);
+static void	run_rt5390_rf_setup(struct run_softc *);
 static int	run_txrx_enable(struct run_softc *);
+static void	run_adjust_freq_offset(struct run_softc *);
 static void	run_init(void *);
 static void	run_init_locked(struct run_softc *);
 static void	run_stop(void *);
-static void	run_delay(struct run_softc *, unsigned int);
+static void	run_delay(struct run_softc *, u_int);
 
+static eventhandler_tag run_etag;
+
+static const struct rt2860_rate {
+	uint8_t		rate;
+	uint8_t		mcs;
+	enum		ieee80211_phytype phy;
+	uint8_t		ctl_ridx;
+	uint16_t	sp_ack_dur;
+	uint16_t	lp_ack_dur;
+} rt2860_rates[] = {
+	{   2, 0, IEEE80211_T_DS,   0, 314, 314 },
+	{   4, 1, IEEE80211_T_DS,   1, 258, 162 },
+	{  11, 2, IEEE80211_T_DS,   2, 223, 127 },
+	{  22, 3, IEEE80211_T_DS,   3, 213, 117 },
+	{  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
+	{  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
+	{  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
+	{  36, 3, IEEE80211_T_OFDM, 6,  44,  44 },
+	{  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
+	{  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
+	{  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
+	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
+};
+
 static const struct {
 	uint16_t	reg;
 	uint32_t	val;
@@ -437,8 +497,27 @@
 	uint8_t	val;
 } rt2860_def_bbp[] = {
 	RT2860_DEF_BBP
+},rt5390_def_bbp[] = {
+	RT5390_DEF_BBP
+},rt5592_def_bbp[] = {
+	RT5592_DEF_BBP
 };
 
+/* 
+ * Default values for BBP register R196 for RT5592.
+ */
+static const uint8_t rt5592_bbp_r196[] = {
+	0xe0, 0x1f, 0x38, 0x32, 0x08, 0x28, 0x19, 0x0a, 0xff, 0x00,
+	0x16, 0x10, 0x10, 0x0b, 0x36, 0x2c, 0x26, 0x24, 0x42, 0x36,
+	0x30, 0x2d, 0x4c, 0x46, 0x3d, 0x40, 0x3e, 0x42, 0x3d, 0x40,
+	0x3c, 0x34, 0x2c, 0x2f, 0x3c, 0x35, 0x2e, 0x2a, 0x49, 0x41,
+	0x36, 0x31, 0x30, 0x30, 0x0e, 0x0d, 0x28, 0x21, 0x1c, 0x16,
+	0x50, 0x4a, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x7d, 0x14, 0x32, 0x2c, 0x36, 0x4c, 0x43, 0x2c,
+	0x2e, 0x36, 0x30, 0x6e
+};
+
 static const struct rfprog {
 	uint8_t		chan;
 	uint32_t	r1, r2, r3, r4;
@@ -452,6 +531,15 @@
 	RT3070_RF3052
 };
 
+static const struct rt5592_freqs {
+	uint16_t	n;
+	uint8_t		k, m, r;
+} rt5592_freqs_20mhz[] = {
+	RT5592_RF5592_20MHZ
+},rt5592_freqs_40mhz[] = {
+	RT5592_RF5592_40MHZ
+};
+
 static const struct {
 	uint8_t	reg;
 	uint8_t	val;
@@ -459,8 +547,29 @@
 	RT3070_DEF_RF
 },rt3572_def_rf[] = {
 	RT3572_DEF_RF
+},rt3593_def_rf[] = {
+	RT3593_DEF_RF
+},rt5390_def_rf[] = {
+	RT5390_DEF_RF
+},rt5392_def_rf[] = {
+	RT5392_DEF_RF
+},rt5592_def_rf[] = {
+	RT5592_DEF_RF
+},rt5592_2ghz_def_rf[] = {
+	RT5592_2GHZ_DEF_RF
+},rt5592_5ghz_def_rf[] = {
+	RT5592_5GHZ_DEF_RF
 };
 
+static const struct {
+	u_int	firstchan;
+	u_int	lastchan;
+	uint8_t	reg;
+	uint8_t	val;
+} rt5592_chan_5ghz[] = {
+	RT5592_CHAN_5GHZ
+};
+
 static const struct usb_config run_config[RUN_N_XFER] = {
     [RUN_BULK_TX_BE] = {
 	.type = UE_BULK,
@@ -532,7 +641,47 @@
     }
 };
 
+static void
+run_autoinst(void *arg, struct usb_device *udev,
+    struct usb_attach_arg *uaa)
+{
+	struct usb_interface *iface;
+	struct usb_interface_descriptor *id;
+
+	if (uaa->dev_state != UAA_DEV_READY)
+		return;
+
+	iface = usbd_get_iface(udev, 0);
+	if (iface == NULL)
+		return;
+	id = iface->idesc;
+	if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
+		return;
+	if (usbd_lookup_id_by_uaa(run_devs, sizeof(run_devs), uaa))
+		return;
+
+	if (usb_msc_eject(udev, 0, MSC_EJECT_STOPUNIT) == 0)
+		uaa->dev_state = UAA_DEV_EJECTING;
+}
+
 static int
+run_driver_loaded(struct module *mod, int what, void *arg)
+{
+	switch (what) {
+	case MOD_LOAD:
+		run_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
+		    run_autoinst, NULL, EVENTHANDLER_PRI_ANY);
+		break;
+	case MOD_UNLOAD:
+		EVENTHANDLER_DEREGISTER(usb_dev_configured, run_etag);
+		break;
+	default:
+		return (EOPNOTSUPP);
+	}
+	return (0);
+}
+
+static int
 run_match(device_t self)
 {
 	struct usb_attach_arg *uaa = device_get_ivars(self);
@@ -555,12 +704,14 @@
 	struct ieee80211com *ic;
 	struct ifnet *ifp;
 	uint32_t ver;
-	int i, ntries, error;
+	int ntries, error;
 	uint8_t iface_index, bands;
 
 	device_set_usb_desc(self);
 	sc->sc_udev = uaa->device;
 	sc->sc_dev = self;
+	if (USB_GET_DRIVER_INFO(uaa) != RUN_EJECT)
+		sc->sc_flags |= RUN_FLAG_FWLOAD_NEEDED;
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
 	    MTX_NETWORK_LOCK, MTX_DEF);
@@ -652,27 +803,12 @@
 	bands = 0;
 	setbit(&bands, IEEE80211_MODE_11B);
 	setbit(&bands, IEEE80211_MODE_11G);
+	if (sc->rf_rev == RT2860_RF_2750 || sc->rf_rev == RT2860_RF_2850 ||
+	    sc->rf_rev == RT3070_RF_3052 || sc->rf_rev == RT3593_RF_3053 ||
+	    sc->rf_rev == RT5592_RF_5592)
+		setbit(&bands, IEEE80211_MODE_11A);
 	ieee80211_init_channels(ic, NULL, &bands);
 
-	/*
-	 * Do this by own because h/w supports
-	 * more channels than ieee80211_init_channels()
-	 */
-	if (sc->rf_rev == RT2860_RF_2750 ||
-	    sc->rf_rev == RT2860_RF_2850 ||
-	    sc->rf_rev == RT3070_RF_3052) {
-		/* set supported .11a rates */
-		for (i = 14; i < N(rt2860_rf2850); i++) {
-			uint8_t chan = rt2860_rf2850[i].chan;
-			ic->ic_channels[ic->ic_nchans].ic_freq =
-			    ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A);
-			ic->ic_channels[ic->ic_nchans].ic_ieee = chan;
-			ic->ic_channels[ic->ic_nchans].ic_flags = IEEE80211_CHAN_A;
-			ic->ic_channels[ic->ic_nchans].ic_extieee = 0;
-			ic->ic_nchans++;
-		}
-	}
-
 	ieee80211_ifattach(ic, sc->sc_bssid);
 
 	ic->ic_scan_start = run_scan_start;
@@ -697,7 +833,7 @@
 
 	TASK_INIT(&sc->cmdq_task, 0, run_cmdq_cb, sc);
 	TASK_INIT(&sc->ratectl_task, 0, run_ratectl_cb, sc);
-	callout_init((struct callout *)&sc->ratectl_ch, 1);
+	usb_callout_init_mtx(&sc->ratectl_ch, &sc->sc_mtx, 0);
 
 	if (bootverbose)
 		ieee80211_announce(ic);
@@ -717,11 +853,14 @@
 	struct ieee80211com *ic;
 	int i;
 
+	RUN_LOCK(sc);
+	sc->sc_detached = 1;
+	RUN_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, RUN_N_XFER);
 
 	RUN_LOCK(sc);
-
 	sc->ratectl_run = RUN_RATECTL_OFF;
 	sc->cmdq_run = sc->cmdq_key_set = RUN_CMDQ_ABORT;
 
@@ -798,8 +937,14 @@
 	if (rvp == NULL)
 		return (NULL);
 	vap = &rvp->vap;
-	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit,
+	    opmode, flags, bssid, mac) != 0) {
+		/* out of memory */
+		free(rvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	vap->iv_key_update_begin = run_key_update_begin;
 	vap->iv_key_update_end = run_key_update_end;
 	vap->iv_update_beacon = run_update_beacon;
@@ -1004,17 +1149,18 @@
 	/* cheap sanity check */
 	temp = fw->data;
 	bytes = *temp;
-	if (bytes != be64toh(0xffffff0210280210)) {
+	if (bytes != be64toh(0xffffff0210280210ULL)) {
 		device_printf(sc->sc_dev, "firmware checksum failed\n");
 		error = EINVAL;
 		goto fail;
 	}
 
-	run_read(sc, RT2860_ASIC_VER_ID, &tmp);
 	/* write microcode image */
-	run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
-	run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
-	run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+	if (sc->sc_flags & RUN_FLAG_FWLOAD_NEEDED) {
+		run_write_region_1(sc, RT2870_FW_BASE, base, 4096);
+		run_write(sc, RT2860_H2M_MAILBOX_CID, 0xffffffff);
+		run_write(sc, RT2860_H2M_MAILBOX_STATUS, 0xffffffff);
+	}
 
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = RT2870_RESET;
@@ -1029,15 +1175,16 @@
 
 	run_delay(sc, 10);
 
+	run_write(sc, RT2860_H2M_BBPAGENT, 0);
 	run_write(sc, RT2860_H2M_MAILBOX, 0);
+	run_write(sc, RT2860_H2M_INTSRC, 0);
 	if ((error = run_mcu_cmd(sc, RT2860_MCU_CMD_RFRESET, 0)) != 0)
 		goto fail;
 
 	/* wait until microcontroller is ready */
 	for (ntries = 0; ntries < 1000; ntries++) {
-		if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0) {
+		if ((error = run_read(sc, RT2860_SYS_CTRL, &tmp)) != 0)
 			goto fail;
-		}
 		if (tmp & RT2860_MCU_READY)
 			break;
 		run_delay(sc, 10);
@@ -1057,7 +1204,7 @@
 	return (error);
 }
 
-int
+static int
 run_reset(struct run_softc *sc)
 {
 	usb_device_request_t req;
@@ -1159,13 +1306,32 @@
 	return (error);
 #else
 	usb_device_request_t req;
+	int error = 0;
 
-	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
-	req.bRequest = RT2870_WRITE_REGION_1;
-	USETW(req.wValue, 0);
-	USETW(req.wIndex, reg);
-	USETW(req.wLength, len);
-	return (run_do_request(sc, &req, buf));
+	/*
+	 * NOTE: It appears the WRITE_REGION_1 command cannot be
+	 * passed a huge amount of data, which will crash the
+	 * firmware. Limit amount of data passed to 64-bytes at a
+	 * time.
+	 */
+	while (len > 0) {
+		int delta = 64;
+		if (delta > len)
+			delta = len;
+
+		req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+		req.bRequest = RT2870_WRITE_REGION_1;
+		USETW(req.wValue, 0);
+		USETW(req.wIndex, reg);
+		USETW(req.wLength, delta);
+		error = run_do_request(sc, &req, __DECONST(uint8_t *, buf));
+		if (error != 0)
+			break;
+		reg += delta;
+		buf += delta;
+		len -= delta;
+	}
+	return (error);
 #endif
 }
 
@@ -1180,9 +1346,8 @@
 	return (error);
 }
 
-/* Read 16-bit from eFUSE ROM (RT3070 only.) */
 static int
-run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+run_efuse_read(struct run_softc *sc, uint16_t addr, uint16_t *val, int count)
 {
 	uint32_t tmp;
 	uint16_t reg;
@@ -1191,7 +1356,8 @@
 	if ((error = run_read(sc, RT3070_EFUSE_CTRL, &tmp)) != 0)
 		return (error);
 
-	addr *= 2;
+	if (count == 2)
+		addr *= 2;
 	/*-
 	 * Read one 16-byte block into registers EFUSE_DATA[0-3]:
 	 * DATA0: F E D C
@@ -1221,11 +1387,20 @@
 	if ((error = run_read(sc, reg, &tmp)) != 0)
 		return (error);
 
-	*val = (addr & 2) ? tmp >> 16 : tmp & 0xffff;
+	tmp >>= (8 * (addr & 0x3));
+	*val = (addr & 1) ? tmp >> 16 : tmp & 0xffff;
+
 	return (0);
 }
 
+/* Read 16-bit from eFUSE ROM for RT3xxx. */
 static int
+run_efuse_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
+{
+	return (run_efuse_read(sc, addr, val, 2));
+}
+
+static int
 run_eeprom_read_2(struct run_softc *sc, uint16_t addr, uint16_t *val)
 {
 	usb_device_request_t req;
@@ -1237,7 +1412,7 @@
 	req.bRequest = RT2870_EEPROM_READ;
 	USETW(req.wValue, 0);
 	USETW(req.wIndex, addr);
-	USETW(req.wLength, sizeof tmp);
+	USETW(req.wLength, sizeof(tmp));
 
 	error = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, &tmp);
 	if (error == 0)
@@ -1255,7 +1430,7 @@
 }
 
 static int
-run_rt2870_rf_write(struct run_softc *sc, uint8_t reg, uint32_t val)
+run_rt2870_rf_write(struct run_softc *sc, uint32_t val)
 {
 	uint32_t tmp;
 	int error, ntries;
@@ -1269,10 +1444,7 @@
 	if (ntries == 10)
 		return (ETIMEDOUT);
 
-	/* RF registers are 24-bit on the RT2860 */
-	tmp = RT2860_RF_REG_CTRL | 24 << RT2860_RF_REG_WIDTH_SHIFT |
-	    (val & 0x3fffff) << 2 | (reg & 3);
-	return (run_write(sc, RT2860_RF_CSR_CFG0, tmp));
+	return (run_write(sc, RT2860_RF_CSR_CFG0, val));
 }
 
 static int
@@ -1423,7 +1595,7 @@
 }
 
 static const char *
-run_get_rf(int rev)
+run_get_rf(uint16_t rev)
 {
 	switch (rev) {
 	case RT2860_RF_2820:	return "RT2820";
@@ -1435,11 +1607,134 @@
 	case RT3070_RF_3021:	return "RT3021";
 	case RT3070_RF_3022:	return "RT3022";
 	case RT3070_RF_3052:	return "RT3052";
+	case RT3593_RF_3053:	return "RT3053";
+	case RT5592_RF_5592:	return "RT5592";
+	case RT5390_RF_5370:	return "RT5370";
+	case RT5390_RF_5372:	return "RT5372";
 	}
 	return ("unknown");
 }
 
-int
+static void
+run_rt3593_get_txpower(struct run_softc *sc)
+{
+	uint16_t addr, val;
+	int i;
+
+	/* Read power settings for 2GHz channels. */
+	for (i = 0; i < 14; i += 2) {
+		addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE1 :
+		    RT2860_EEPROM_PWR2GHZ_BASE1;
+		run_srom_read(sc, addr + i / 2, &val);
+		sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+		sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+		addr = (sc->ntxchains == 3) ? RT3593_EEPROM_PWR2GHZ_BASE2 :
+		    RT2860_EEPROM_PWR2GHZ_BASE2;
+		run_srom_read(sc, addr + i / 2, &val);
+		sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+		sc->txpow2[i + 1] = (int8_t)(val >> 8);
+
+		if (sc->ntxchains == 3) {
+			run_srom_read(sc, RT3593_EEPROM_PWR2GHZ_BASE3 + i / 2,
+			    &val);
+			sc->txpow3[i + 0] = (int8_t)(val & 0xff);
+			sc->txpow3[i + 1] = (int8_t)(val >> 8);
+		}
+	}
+	/* Fix broken Tx power entries. */
+	for (i = 0; i < 14; i++) {
+		if (sc->txpow1[i] > 31)
+			sc->txpow1[i] = 5;
+		if (sc->txpow2[i] > 31)
+			sc->txpow2[i] = 5;
+		if (sc->ntxchains == 3) {
+			if (sc->txpow3[i] > 31)
+				sc->txpow3[i] = 5;
+		}
+	}
+	/* Read power settings for 5GHz channels. */
+	for (i = 0; i < 40; i += 2) {
+		run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+		sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+		sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+		run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+		sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+		sc->txpow2[i + 15] = (int8_t)(val >> 8);
+
+		if (sc->ntxchains == 3) {
+			run_srom_read(sc, RT3593_EEPROM_PWR5GHZ_BASE3 + i / 2,
+			    &val);
+			sc->txpow3[i + 14] = (int8_t)(val & 0xff);
+			sc->txpow3[i + 15] = (int8_t)(val >> 8);
+		}
+	}
+}
+
+static void
+run_get_txpower(struct run_softc *sc)
+{
+	uint16_t val;
+	int i;
+
+	/* Read power settings for 2GHz channels. */
+	for (i = 0; i < 14; i += 2) {
+		run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
+		sc->txpow1[i + 0] = (int8_t)(val & 0xff);
+		sc->txpow1[i + 1] = (int8_t)(val >> 8);
+
+		if (sc->mac_ver != 0x5390) {
+			run_srom_read(sc,
+			    RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
+			sc->txpow2[i + 0] = (int8_t)(val & 0xff);
+			sc->txpow2[i + 1] = (int8_t)(val >> 8);
+		}
+	}
+	/* Fix broken Tx power entries. */
+	for (i = 0; i < 14; i++) {
+		if (sc->mac_ver >= 0x5390) {
+			if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
+				sc->txpow1[i] = 5;
+		} else {
+			if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
+				sc->txpow1[i] = 5;
+		}
+		if (sc->mac_ver > 0x5390) {
+			if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
+				sc->txpow2[i] = 5;
+		} else if (sc->mac_ver < 0x5390) {
+			if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
+				sc->txpow2[i] = 5;
+		}
+		DPRINTF("chan %d: power1=%d, power2=%d\n",
+		    rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
+	}
+	/* Read power settings for 5GHz channels. */
+	for (i = 0; i < 40; i += 2) {
+		run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
+		sc->txpow1[i + 14] = (int8_t)(val & 0xff);
+		sc->txpow1[i + 15] = (int8_t)(val >> 8);
+
+		run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
+		sc->txpow2[i + 14] = (int8_t)(val & 0xff);
+		sc->txpow2[i + 15] = (int8_t)(val >> 8);
+	}
+	/* Fix broken Tx power entries. */
+	for (i = 0; i < 40; i++ ) {
+		if (sc->mac_ver != 0x5592) {
+			if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
+				sc->txpow1[14 + i] = 5;
+			if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
+				sc->txpow2[14 + i] = 5;
+		}
+		DPRINTF("chan %d: power1=%d, power2=%d\n",
+		    rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
+		    sc->txpow2[14 + i]);
+	}
+}
+
+static int
 run_read_eeprom(struct run_softc *sc)
 {
 	int8_t delta_2ghz, delta_5ghz;
@@ -1452,7 +1747,7 @@
 	if (sc->mac_ver >= 0x3070) {
 		run_read(sc, RT3070_EFUSE_CTRL, &tmp);
 		DPRINTF("EFUSE_CTRL=0x%08x\n", tmp);
-		if (tmp & RT3070_SEL_EFUSE)
+		if ((tmp & RT3070_SEL_EFUSE) || sc->mac_ver == 0x3593)
 			sc->sc_srom_read = run_efuse_read_2;
 	}
 
@@ -1471,35 +1766,45 @@
 	sc->sc_bssid[4] = val & 0xff;
 	sc->sc_bssid[5] = val >> 8;
 
-	/* read vender BBP settings */
-	for (i = 0; i < 10; i++) {
-		run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
-		sc->bbp[i].val = val & 0xff;
-		sc->bbp[i].reg = val >> 8;
-		DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg, sc->bbp[i].val);
-	}
-	if (sc->mac_ver >= 0x3071) {
-		/* read vendor RF settings */
+	if (sc->mac_ver < 0x3593) {
+		/* read vender BBP settings */
 		for (i = 0; i < 10; i++) {
-			run_srom_read(sc, RT3071_EEPROM_RF_BASE + i, &val);
-			sc->rf[i].val = val & 0xff;
-			sc->rf[i].reg = val >> 8;
-			DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
-			    sc->rf[i].val);
+			run_srom_read(sc, RT2860_EEPROM_BBP_BASE + i, &val);
+			sc->bbp[i].val = val & 0xff;
+			sc->bbp[i].reg = val >> 8;
+			DPRINTF("BBP%d=0x%02x\n", sc->bbp[i].reg,
+			    sc->bbp[i].val);
 		}
+		if (sc->mac_ver >= 0x3071) {
+			/* read vendor RF settings */
+			for (i = 0; i < 10; i++) {
+				run_srom_read(sc, RT3071_EEPROM_RF_BASE + i,
+				   &val);
+				sc->rf[i].val = val & 0xff;
+				sc->rf[i].reg = val >> 8;
+				DPRINTF("RF%d=0x%02x\n", sc->rf[i].reg,
+				    sc->rf[i].val);
+			}
+		}
 	}
 
 	/* read RF frequency offset from EEPROM */
-	run_srom_read(sc, RT2860_EEPROM_FREQ_LEDS, &val);
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+	    RT3593_EEPROM_FREQ, &val);
 	sc->freq = ((val & 0xff) != 0xff) ? val & 0xff : 0;
 	DPRINTF("EEPROM freq offset %d\n", sc->freq & 0xff);
 
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_FREQ_LEDS :
+	    RT3593_EEPROM_FREQ_LEDS, &val);
 	if (val >> 8 != 0xff) {
 		/* read LEDs operating mode */
 		sc->leds = val >> 8;
-		run_srom_read(sc, RT2860_EEPROM_LED1, &sc->led[0]);
-		run_srom_read(sc, RT2860_EEPROM_LED2, &sc->led[1]);
-		run_srom_read(sc, RT2860_EEPROM_LED3, &sc->led[2]);
+		run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED1 :
+		    RT3593_EEPROM_LED1, &sc->led[0]);
+		run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED2 :
+		    RT3593_EEPROM_LED2, &sc->led[1]);
+		run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LED3 :
+		    RT3593_EEPROM_LED3, &sc->led[2]);
 	} else {
 		/* broken EEPROM, use default settings */
 		sc->leds = 0x01;
@@ -1511,8 +1816,14 @@
 	    sc->leds, sc->led[0], sc->led[1], sc->led[2]);
 
 	/* read RF information */
-	run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+	if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392)
+		run_srom_read(sc, 0x00, &val);
+	else
+		run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+
 	if (val == 0xffff) {
+		device_printf(sc->sc_dev,
+		    "invalid EEPROM antenna info, using default\n");
 		DPRINTF("invalid EEPROM antenna info, using default\n");
 		if (sc->mac_ver == 0x3572) {
 			/* default to RF3052 2T2R */
@@ -1531,11 +1842,15 @@
 			sc->nrxchains = 2;
 		}
 	} else {
-		sc->rf_rev = (val >> 8) & 0xf;
+		if (sc->mac_ver == 0x5390 || sc->mac_ver ==0x5392) {
+			sc->rf_rev = val;
+			run_srom_read(sc, RT2860_EEPROM_ANTENNA, &val);
+		} else
+			sc->rf_rev = (val >> 8) & 0xf;
 		sc->ntxchains = (val >> 4) & 0xf;
 		sc->nrxchains = val & 0xf;
 	}
-	DPRINTF("EEPROM RF rev=0x%02x chains=%dT%dR\n",
+	DPRINTF("EEPROM RF rev=0x%04x chains=%dT%dR\n",
 	    sc->rf_rev, sc->ntxchains, sc->nrxchains);
 
 	/* check if RF supports automatic Tx access gain control */
@@ -1553,46 +1868,12 @@
 		sc->rfswitch = val & 1;
 	}
 
-	/* read power settings for 2GHz channels */
-	for (i = 0; i < 14; i += 2) {
-		run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE1 + i / 2, &val);
-		sc->txpow1[i + 0] = (int8_t)(val & 0xff);
-		sc->txpow1[i + 1] = (int8_t)(val >> 8);
+	/* Read Tx power settings. */
+	if (sc->mac_ver == 0x3593)
+		run_rt3593_get_txpower(sc);
+	else
+		run_get_txpower(sc);
 
-		run_srom_read(sc, RT2860_EEPROM_PWR2GHZ_BASE2 + i / 2, &val);
-		sc->txpow2[i + 0] = (int8_t)(val & 0xff);
-		sc->txpow2[i + 1] = (int8_t)(val >> 8);
-	}
-	/* fix broken Tx power entries */
-	for (i = 0; i < 14; i++) {
-		if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
-			sc->txpow1[i] = 5;
-		if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
-			sc->txpow2[i] = 5;
-		DPRINTF("chan %d: power1=%d, power2=%d\n",
-		    rt2860_rf2850[i].chan, sc->txpow1[i], sc->txpow2[i]);
-	}
-	/* read power settings for 5GHz channels */
-	for (i = 0; i < 40; i += 2) {
-		run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE1 + i / 2, &val);
-		sc->txpow1[i + 14] = (int8_t)(val & 0xff);
-		sc->txpow1[i + 15] = (int8_t)(val >> 8);
-
-		run_srom_read(sc, RT2860_EEPROM_PWR5GHZ_BASE2 + i / 2, &val);
-		sc->txpow2[i + 14] = (int8_t)(val & 0xff);
-		sc->txpow2[i + 15] = (int8_t)(val >> 8);
-	}
-	/* fix broken Tx power entries */
-	for (i = 0; i < 40; i++) {
-		if (sc->txpow1[14 + i] < -7 || sc->txpow1[14 + i] > 15)
-			sc->txpow1[14 + i] = 5;
-		if (sc->txpow2[14 + i] < -7 || sc->txpow2[14 + i] > 15)
-			sc->txpow2[14 + i] = 5;
-		DPRINTF("chan %d: power1=%d, power2=%d\n",
-		    rt2860_rf2850[14 + i].chan, sc->txpow1[14 + i],
-		    sc->txpow2[14 + i]);
-	}
-
 	/* read Tx power compensation for each Tx rate */
 	run_srom_read(sc, RT2860_EEPROM_DELTAPWR, &val);
 	delta_2ghz = delta_5ghz = 0;
@@ -1627,27 +1908,38 @@
 		    sc->txpow40mhz_2ghz[ridx], sc->txpow40mhz_5ghz[ridx]);
 	}
 
-	/* read RSSI offsets and LNA gains from EEPROM */
-	run_srom_read(sc, RT2860_EEPROM_RSSI1_2GHZ, &val);
+	/* Read RSSI offsets and LNA gains from EEPROM. */
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_2GHZ :
+	    RT3593_EEPROM_RSSI1_2GHZ, &val);
 	sc->rssi_2ghz[0] = val & 0xff;	/* Ant A */
 	sc->rssi_2ghz[1] = val >> 8;	/* Ant B */
-	run_srom_read(sc, RT2860_EEPROM_RSSI2_2GHZ, &val);
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_2GHZ :
+	    RT3593_EEPROM_RSSI2_2GHZ, &val);
 	if (sc->mac_ver >= 0x3070) {
-		/*
-		 * On RT3070 chips (limited to 2 Rx chains), this ROM
-		 * field contains the Tx mixer gain for the 2GHz band.
-		 */
-		if ((val & 0xff) != 0xff)
-			sc->txmixgain_2ghz = val & 0x7;
+		if (sc->mac_ver == 0x3593) {
+			sc->txmixgain_2ghz = 0;
+			sc->rssi_2ghz[2] = val & 0xff;	/* Ant C */
+		} else {
+			/*
+			 * On RT3070 chips (limited to 2 Rx chains), this ROM
+			 * field contains the Tx mixer gain for the 2GHz band.
+			 */
+			if ((val & 0xff) != 0xff)
+				sc->txmixgain_2ghz = val & 0x7;
+		}
 		DPRINTF("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz);
 	} else
 		sc->rssi_2ghz[2] = val & 0xff;	/* Ant C */
+	if (sc->mac_ver == 0x3593)
+		run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
 	sc->lna[2] = val >> 8;		/* channel group 2 */
 
-	run_srom_read(sc, RT2860_EEPROM_RSSI1_5GHZ, &val);
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI1_5GHZ :
+	    RT3593_EEPROM_RSSI1_5GHZ, &val);
 	sc->rssi_5ghz[0] = val & 0xff;	/* Ant A */
 	sc->rssi_5ghz[1] = val >> 8;	/* Ant B */
-	run_srom_read(sc, RT2860_EEPROM_RSSI2_5GHZ, &val);
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_RSSI2_5GHZ :
+	    RT3593_EEPROM_RSSI2_5GHZ, &val);
 	if (sc->mac_ver == 0x3572) {
 		/*
 		 * On RT3572 chips (limited to 2 Rx chains), this ROM
@@ -1658,9 +1950,14 @@
 		DPRINTF("tx mixer gain=%u (5GHz)\n", sc->txmixgain_5ghz);
 	} else
 		sc->rssi_5ghz[2] = val & 0xff;	/* Ant C */
+	if (sc->mac_ver == 0x3593) {
+		sc->txmixgain_5ghz = 0;
+		run_srom_read(sc, RT3593_EEPROM_LNA_5GHZ, &val);
+	}
 	sc->lna[3] = val >> 8;		/* channel group 3 */
 
-	run_srom_read(sc, RT2860_EEPROM_LNA, &val);
+	run_srom_read(sc, (sc->mac_ver != 0x3593) ? RT2860_EEPROM_LNA :
+	    RT3593_EEPROM_LNA, &val);
 	sc->lna[0] = val & 0xff;	/* channel group 0 */
 	sc->lna[1] = val >> 8;		/* channel group 1 */
 
@@ -2213,9 +2510,7 @@
 	if (vap == NULL)
 		return;
 
-	if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA)
-		run_iter_func(sc, vap->iv_bss);
-	else {
+	if (sc->rvp_cnt > 1 || vap->iv_opmode != IEEE80211_M_STA) {
 		/*
 		 * run_reset_livelock() doesn't do anything with AMRR,
 		 * but Ralink wants us to call it every 1 sec. So, we
@@ -2228,11 +2523,14 @@
 		/* just in case, there are some stats to drain */
 		run_drain_fifo(sc);
 		RUN_UNLOCK(sc);
-		ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc);
 	}
 
+	ieee80211_iterate_nodes(&ic->ic_sta, run_iter_func, sc);
+
+	RUN_LOCK(sc);
 	if(sc->ratectl_run != RUN_RATECTL_OFF)
 		usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+	RUN_UNLOCK(sc);
 }
 
 static void
@@ -2308,6 +2606,11 @@
 
 	RUN_LOCK(sc);
 
+	/* Check for special case */
+	if (sc->rvp_cnt <= 1 && vap->iv_opmode == IEEE80211_M_STA &&
+	    ni != vap->iv_bss)
+		goto fail;
+
 	if (sc->rvp_cnt <= 1 && (vap->iv_opmode == IEEE80211_M_IBSS ||
 	    vap->iv_opmode == IEEE80211_M_STA)) {
 		/* read statistic counters (clear on read) and update AMRR state */
@@ -2436,7 +2739,10 @@
 	rn->mgt_ridx = ridx;
 	DPRINTF("rate=%d, mgmt_ridx=%d\n", rate, rn->mgt_ridx);
 
-	usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+	RUN_LOCK(sc);
+	if(sc->ratectl_run != RUN_RATECTL_OFF)
+		usb_callout_reset(&sc->ratectl_ch, hz, run_ratectl_to, sc);
+	RUN_UNLOCK(sc);
 }
 
 /*
@@ -2467,12 +2773,17 @@
 	struct rt2870_rxd *rxd;
 	struct rt2860_rxwi *rxwi;
 	uint32_t flags;
-	uint16_t len, phy;
+	uint16_t len, rxwisize;
 	uint8_t ant, rssi;
 	int8_t nf;
 
 	rxwi = mtod(m, struct rt2860_rxwi *);
 	len = le16toh(rxwi->len) & 0xfff;
+	rxwisize = sizeof(struct rt2860_rxwi);
+	if (sc->mac_ver == 0x5592)
+		rxwisize += sizeof(uint64_t);
+	else if (sc->mac_ver == 0x3593)
+		rxwisize += sizeof(uint32_t);
 	if (__predict_false(len > dmalen)) {
 		m_freem(m);
 		ifp->if_ierrors++;
@@ -2490,8 +2801,8 @@
 		return;
 	}
 
-	m->m_data += sizeof(struct rt2860_rxwi);
-	m->m_pkthdr.len = m->m_len -= sizeof(struct rt2860_rxwi);
+	m->m_data += rxwisize;
+	m->m_pkthdr.len = m->m_len -= rxwisize;
 
 	wh = mtod(m, struct ieee80211_frame *);
 
@@ -2511,7 +2822,8 @@
 	if (__predict_false(flags & RT2860_RX_MICERR)) {
 		/* report MIC failures to net80211 for TKIP */
 		if (ni != NULL)
-			ieee80211_notify_michael_failure(ni->ni_vap, wh, rxwi->keyidx);
+			ieee80211_notify_michael_failure(ni->ni_vap, wh,
+			    rxwi->keyidx);
 		m_freem(m);
 		ifp->if_ierrors++;
 		DPRINTF("MIC error. Someone is lying.\n");
@@ -2534,6 +2846,7 @@
 
 	if (__predict_false(ieee80211_radiotap_active(ic))) {
 		struct run_rx_radiotap_header *tap = &sc->sc_rxtap;
+		uint16_t phy;
 
 		tap->wr_flags = 0;
 		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
@@ -2578,8 +2891,15 @@
 	struct mbuf *m = NULL;
 	struct mbuf *m0;
 	uint32_t dmalen;
+	uint16_t rxwisize;
 	int xferlen;
 
+	rxwisize = sizeof(struct rt2860_rxwi);
+	if (sc->mac_ver == 0x5592)
+		rxwisize += sizeof(uint64_t);
+	else if (sc->mac_ver == 0x3593)
+		rxwisize += sizeof(uint32_t);
+
 	usbd_xfer_status(xfer, &xferlen, NULL, NULL, NULL);
 
 	switch (USB_GET_STATE(xfer)) {
@@ -2587,8 +2907,8 @@
 
 		DPRINTFN(15, "rx done, actlen=%d\n", xferlen);
 
-		if (xferlen < (int)(sizeof(uint32_t) +
-		    sizeof(struct rt2860_rxwi) + sizeof(struct rt2870_rxd))) {
+		if (xferlen < (int)(sizeof(uint32_t) + rxwisize +
+		    sizeof(struct rt2870_rxd))) {
 			DPRINTF("xfer too short %d\n", xferlen);
 			goto tr_setup;
 		}
@@ -2670,6 +2990,7 @@
 			m->m_data += 4;
 			m->m_pkthdr.len = m->m_len -= 4;
 			run_rx_frame(sc, m, dmalen);
+			m = NULL;	/* don't free source buffer */
 			break;
 		}
 
@@ -2691,6 +3012,9 @@
 		m->m_pkthdr.len = m->m_len -= dmalen + 8;
 	}
 
+	/* make sure we free the source buffer, if any */
+	m_freem(m);
+
 	RUN_LOCK(sc);
 }
 
@@ -2718,7 +3042,7 @@
 }
 
 static void
-run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, unsigned int index)
+run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
 {
 	struct run_softc *sc = usbd_xfer_softc(xfer);
 	struct ifnet *ifp = sc->sc_ifp;
@@ -2758,8 +3082,10 @@
 		STAILQ_REMOVE_HEAD(&pq->tx_qh, next);
 
 		m = data->m;
+		size = (sc->mac_ver == 0x5592) ?
+		    sizeof(data->desc) + sizeof(uint32_t) : sizeof(data->desc);
 		if ((m->m_pkthdr.len +
-		    sizeof(data->desc) + 3 + 8) > RUN_MAX_TXSZ) {
+		    size + 3 + 8) > RUN_MAX_TXSZ) {
 			DPRINTF("data overflow, %u bytes\n",
 			    m->m_pkthdr.len);
 
@@ -2771,7 +3097,6 @@
 		}
 
 		pc = usbd_xfer_get_frame(xfer, 0);
-		size = sizeof(data->desc);
 		usbd_copy_in(pc, 0, &data->desc, size);
 		usbd_m_copy_in(pc, size, m, 0, m->m_pkthdr.len);
 		size += m->m_pkthdr.len;
@@ -2786,9 +3111,8 @@
 		vap = data->ni->ni_vap;
 		if (ieee80211_radiotap_active_vap(vap)) {
 			struct run_tx_radiotap_header *tap = &sc->sc_txtap;
-			struct rt2860_txwi *txwi =
+			struct rt2860_txwi *txwi = 
 			    (struct rt2860_txwi *)(&data->desc + sizeof(struct rt2870_txd));
-
 			tap->wt_flags = 0;
 			tap->wt_rate = rt2860_rates[data->ridx].rate;
 			tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
@@ -2898,7 +3222,7 @@
 	struct ieee80211_frame *wh;
 	struct rt2870_txd *txd;
 	struct rt2860_txwi *txwi;
-	uint16_t xferlen;
+	uint16_t xferlen, txwisize;
 	uint16_t mcs;
 	uint8_t ridx = data->ridx;
 	uint8_t pad;
@@ -2906,7 +3230,9 @@
 	/* get MCS code from rate index */
 	mcs = rt2860_rates[ridx].mcs;
 
-	xferlen = sizeof(*txwi) + m->m_pkthdr.len;
+	txwisize = (sc->mac_ver == 0x5592) ?
+	    sizeof(*txwi) + sizeof(uint32_t) : sizeof(*txwi);
+	xferlen = txwisize + m->m_pkthdr.len;
 
 	/* roundup to 32-bit alignment */
 	xferlen = (xferlen + 3) & ~3;
@@ -3032,7 +3358,7 @@
 			dur = rt2860_rates[ctl_ridx].sp_ack_dur;
 		else
 			dur = rt2860_rates[ctl_ridx].lp_ack_dur;
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 	}
 
 	/* reserve slots for mgmt packets, just in case */
@@ -3049,12 +3375,12 @@
 	txd->flags = qflags;
 	txwi = (struct rt2860_txwi *)(txd + 1);
 	txwi->xflags = xflags;
-	if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
+	if (IEEE80211_IS_MULTICAST(wh->i_addr1))
 		txwi->wcid = 0;
-	} else {
+	else
 		txwi->wcid = (vap->iv_opmode == IEEE80211_M_STA) ?
 		    1 : RUN_AID2WCID(ni->ni_associd);
-	}
+
 	/* clear leftover garbage bits */
 	txwi->flags = 0;
 	txwi->txop = 0;
@@ -3112,9 +3438,9 @@
 
 	usbd_transfer_start(sc->sc_xfer[qid]);
 
-	DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n", m->m_pkthdr.len +
-	    (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
-	    rt2860_rates[ridx].rate, qid);
+	DPRINTFN(8, "sending data frame len=%d rate=%d qid=%d\n",
+	    m->m_pkthdr.len + (int)(sizeof(struct rt2870_txd) +
+	    sizeof(struct rt2860_txwi)), rt2860_rates[ridx].rate, qid);
 
 	return (0);
 }
@@ -3151,7 +3477,7 @@
 
 		dur = ieee80211_ack_duration(ic->ic_rt, rt2860_rates[ridx].rate, 
 		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 	}
 
 	if (sc->sc_epq[0].tx_nfree == 0) {
@@ -3178,7 +3504,7 @@
 	run_set_tx_desc(sc, data);
 
 	DPRINTFN(10, "sending mgt frame len=%d rate=%d\n", m->m_pkthdr.len +
-	    (int)(sizeof (struct rt2870_txd) + sizeof (struct rt2860_rxwi)),
+	    (int)(sizeof(struct rt2870_txd) + sizeof(struct rt2860_txwi)),
 	    rt2860_rates[ridx].rate);
 
 	STAILQ_INSERT_TAIL(&sc->sc_epq[0].tx_qh, data, next);
@@ -3442,8 +3768,14 @@
 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
 	int startall = 0;
-	int error = 0;
+	int error;
 
+	RUN_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RUN_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		RUN_LOCK(sc);
@@ -3478,6 +3810,107 @@
 }
 
 static void
+run_iq_calib(struct run_softc *sc, u_int chan)
+{
+	uint16_t val;
+
+	/* Tx0 IQ gain. */
+	run_bbp_write(sc, 158, 0x2c);
+	if (chan <= 14)
+		run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ, &val, 1);
+	else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+	    RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val);
+
+	/* Tx0 IQ phase. */
+	run_bbp_write(sc, 158, 0x2d);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val);
+
+	/* Tx1 IQ gain. */
+	run_bbp_write(sc, 158, 0x4a);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val);
+
+	/* Tx1 IQ phase. */
+	run_bbp_write(sc, 158, 0x4b);
+	if (chan <= 14) {
+		run_efuse_read(sc, RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ,
+		    &val, 1);
+	} else if (chan <= 64) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ,
+		    &val, 1);
+	} else if (chan <= 138) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ,
+		    &val, 1);
+	} else if (chan <= 165) {
+		run_efuse_read(sc,
+		    RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ,
+		    &val, 1);
+	} else
+		val = 0;
+	run_bbp_write(sc, 159, val);
+
+	/* RF IQ compensation control. */
+	run_bbp_write(sc, 158, 0x04);
+	run_efuse_read(sc, RT5390_EEPROM_RF_IQ_COMPENSATION_CTL,
+	    &val, 1);
+	run_bbp_write(sc, 159, val);
+
+	/* RF IQ imbalance compensation control. */
+	run_bbp_write(sc, 158, 0x03);
+	run_efuse_read(sc,
+	    RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL, &val, 1);
+	run_bbp_write(sc, 159, val);
+}
+
+static void
 run_set_agc(struct run_softc *sc, uint8_t agc)
 {
 	uint8_t bbp;
@@ -3502,21 +3935,73 @@
 	run_bbp_write(sc, 62, 0x37 - sc->lna[group]);
 	run_bbp_write(sc, 63, 0x37 - sc->lna[group]);
 	run_bbp_write(sc, 64, 0x37 - sc->lna[group]);
-	run_bbp_write(sc, 86, 0x00);
+	if (sc->mac_ver < 0x3572)
+		run_bbp_write(sc, 86, 0x00);
 
+	if (sc->mac_ver == 0x3593) {
+		run_bbp_write(sc, 77, 0x98);
+		run_bbp_write(sc, 83, (group == 0) ? 0x8a : 0x9a);
+	}
+
 	if (group == 0) {
 		if (sc->ext_2ghz_lna) {
-			run_bbp_write(sc, 82, 0x62);
-			run_bbp_write(sc, 75, 0x46);
+			if (sc->mac_ver >= 0x5390)
+				run_bbp_write(sc, 75, 0x52);
+			else {
+				run_bbp_write(sc, 82, 0x62);
+				run_bbp_write(sc, 75, 0x46);
+			}
 		} else {
-			run_bbp_write(sc, 82, 0x84);
-			run_bbp_write(sc, 75, 0x50);
+			if (sc->mac_ver == 0x5592) {
+				run_bbp_write(sc, 79, 0x1c);
+				run_bbp_write(sc, 80, 0x0e);
+				run_bbp_write(sc, 81, 0x3a);
+				run_bbp_write(sc, 82, 0x62);
+
+				run_bbp_write(sc, 195, 0x80);
+				run_bbp_write(sc, 196, 0xe0);
+				run_bbp_write(sc, 195, 0x81);
+				run_bbp_write(sc, 196, 0x1f);
+				run_bbp_write(sc, 195, 0x82);
+				run_bbp_write(sc, 196, 0x38);
+				run_bbp_write(sc, 195, 0x83);
+				run_bbp_write(sc, 196, 0x32);
+				run_bbp_write(sc, 195, 0x85);
+				run_bbp_write(sc, 196, 0x28);
+				run_bbp_write(sc, 195, 0x86);
+				run_bbp_write(sc, 196, 0x19);
+			} else if (sc->mac_ver >= 0x5390)
+				run_bbp_write(sc, 75, 0x50);
+			else {
+				run_bbp_write(sc, 82,
+				    (sc->mac_ver == 0x3593) ? 0x62 : 0x84);
+				run_bbp_write(sc, 75, 0x50);
+			}
 		}
 	} else {
-		if (sc->mac_ver == 0x3572)
+		if (sc->mac_ver == 0x5592) {
+			run_bbp_write(sc, 79, 0x18);
+			run_bbp_write(sc, 80, 0x08);
+			run_bbp_write(sc, 81, 0x38);
+			run_bbp_write(sc, 82, 0x92);
+
+			run_bbp_write(sc, 195, 0x80);
+			run_bbp_write(sc, 196, 0xf0);
+			run_bbp_write(sc, 195, 0x81);
+			run_bbp_write(sc, 196, 0x1e);
+			run_bbp_write(sc, 195, 0x82);
+			run_bbp_write(sc, 196, 0x28);
+			run_bbp_write(sc, 195, 0x83);
+			run_bbp_write(sc, 196, 0x20);
+			run_bbp_write(sc, 195, 0x85);
+			run_bbp_write(sc, 196, 0x7f);
+			run_bbp_write(sc, 195, 0x86);
+			run_bbp_write(sc, 196, 0x7f);
+		} else if (sc->mac_ver == 0x3572)
 			run_bbp_write(sc, 82, 0x94);
 		else
-			run_bbp_write(sc, 82, 0xf2);
+			run_bbp_write(sc, 82,
+			    (sc->mac_ver == 0x3593) ? 0x82 : 0xf2);
 		if (sc->ext_5ghz_lna)
 			run_bbp_write(sc, 75, 0x46);
 		else 
@@ -3530,6 +4015,8 @@
 
 	/* enable appropriate Power Amplifiers and Low Noise Amplifiers */
 	tmp = RT2860_RFTR_EN | RT2860_TRSW_EN | RT2860_LNA_PE0_EN;
+	if (sc->mac_ver == 0x3593)
+		tmp |= 1 << 29 | 1 << 28;
 	if (sc->nrxchains > 1)
 		tmp |= RT2860_LNA_PE1_EN;
 	if (group == 0) {	/* 2GHz */
@@ -3536,6 +4023,10 @@
 		tmp |= RT2860_PA_PE_G0_EN;
 		if (sc->ntxchains > 1)
 			tmp |= RT2860_PA_PE_G1_EN;
+		if (sc->mac_ver == 0x3593) {
+			if (sc->ntxchains > 2)
+				tmp |= 1 << 25;
+		}
 	} else {		/* 5GHz */
 		tmp |= RT2860_PA_PE_A0_EN;
 		if (sc->ntxchains > 1)
@@ -3548,6 +4039,20 @@
 	} else
 		run_write(sc, RT2860_TX_PIN_CFG, tmp);
 
+	if (sc->mac_ver == 0x5592) {
+		run_bbp_write(sc, 195, 0x8d);
+		run_bbp_write(sc, 196, 0x1a);
+	}
+
+	if (sc->mac_ver == 0x3593) {
+		run_read(sc, RT2860_GPIO_CTRL, &tmp);
+		tmp &= ~0x01010000;
+		if (group == 0)
+			tmp |= 0x00010000;
+		tmp = (tmp & ~0x00009090) | 0x00000090;
+		run_write(sc, RT2860_GPIO_CTRL, tmp);
+	}
+
 	/* set initial AGC value */
 	if (group == 0) {	/* 2GHz band */
 		if (sc->mac_ver >= 0x3070)
@@ -3555,7 +4060,9 @@
 		else
 			agc = 0x2e + sc->lna[0];
 	} else {		/* 5GHz band */
-		if (sc->mac_ver == 0x3572)
+		if (sc->mac_ver == 0x5592)
+			agc = 0x24 + sc->lna[group] * 2;
+		else if (sc->mac_ver == 0x3572 || sc->mac_ver == 0x3593)
 			agc = 0x22 + (sc->lna[group] * 5) / 3;
 		else
 			agc = 0x32 + (sc->lna[group] * 5) / 3;
@@ -3564,7 +4071,7 @@
 }
 
 static void
-run_rt2870_set_chan(struct run_softc *sc, uint32_t chan)
+run_rt2870_set_chan(struct run_softc *sc, u_int chan)
 {
 	const struct rfprog *rfprog = rt2860_rf2850;
 	uint32_t r2, r3, r4;
@@ -3576,58 +4083,71 @@
 
 	r2 = rfprog[i].r2;
 	if (sc->ntxchains == 1)
-		r2 |= 1 << 12;		/* 1T: disable Tx chain 2 */
+		r2 |= 1 << 14;		/* 1T: disable Tx chain 2 */
 	if (sc->nrxchains == 1)
-		r2 |= 1 << 15 | 1 << 4;	/* 1R: disable Rx chains 2 & 3 */
+		r2 |= 1 << 17 | 1 << 6;	/* 1R: disable Rx chains 2 & 3 */
 	else if (sc->nrxchains == 2)
-		r2 |= 1 << 4;		/* 2R: disable Rx chain 3 */
+		r2 |= 1 << 6;		/* 2R: disable Rx chain 3 */
 
 	/* use Tx power values from EEPROM */
 	txpow1 = sc->txpow1[i];
 	txpow2 = sc->txpow2[i];
+
+	/* Initialize RF R3 and R4. */
+	r3 = rfprog[i].r3 & 0xffffc1ff;
+	r4 = (rfprog[i].r4 & ~(0x001f87c0)) | (sc->freq << 15);
 	if (chan > 14) {
-		if (txpow1 >= 0)
-			txpow1 = txpow1 << 1 | 1;
-		else
-			txpow1 = (7 + txpow1) << 1;
-		if (txpow2 >= 0)
-			txpow2 = txpow2 << 1 | 1;
-		else
-			txpow2 = (7 + txpow2) << 1;
+		if (txpow1 >= 0) {
+			txpow1 = (txpow1 > 0xf) ? (0xf) : (txpow1);
+			r3 |= (txpow1 << 10) | (1 << 9);
+		} else {
+			txpow1 += 7;
+
+			/* txpow1 is not possible larger than 15. */
+			r3 |= (txpow1 << 10);
+		}
+		if (txpow2 >= 0) {
+			txpow2 = (txpow2 > 0xf) ? (0xf) : (txpow2);
+			r4 |= (txpow2 << 7) | (1 << 6);
+		} else {
+			txpow2 += 7;
+			r4 |= (txpow2 << 7);
+		}
+	} else {
+		/* Set Tx0 power. */
+		r3 |= (txpow1 << 9);
+
+		/* Set frequency offset and Tx1 power. */
+		r4 |= (txpow2 << 6);
 	}
-	r3 = rfprog[i].r3 | txpow1 << 7;
-	r4 = rfprog[i].r4 | sc->freq << 13 | txpow2 << 4;
 
-	run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
-	run_rt2870_rf_write(sc, RT2860_RF2, r2);
-	run_rt2870_rf_write(sc, RT2860_RF3, r3);
-	run_rt2870_rf_write(sc, RT2860_RF4, r4);
+	run_rt2870_rf_write(sc, rfprog[i].r1);
+	run_rt2870_rf_write(sc, r2);
+	run_rt2870_rf_write(sc, r3 & ~(1 << 2));
+	run_rt2870_rf_write(sc, r4);
 
 	run_delay(sc, 10);
 
-	run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
-	run_rt2870_rf_write(sc, RT2860_RF2, r2);
-	run_rt2870_rf_write(sc, RT2860_RF3, r3 | 1);
-	run_rt2870_rf_write(sc, RT2860_RF4, r4);
+	run_rt2870_rf_write(sc, rfprog[i].r1);
+	run_rt2870_rf_write(sc, r2);
+	run_rt2870_rf_write(sc, r3 | (1 << 2));
+	run_rt2870_rf_write(sc, r4);
 
 	run_delay(sc, 10);
 
-	run_rt2870_rf_write(sc, RT2860_RF1, rfprog[i].r1);
-	run_rt2870_rf_write(sc, RT2860_RF2, r2);
-	run_rt2870_rf_write(sc, RT2860_RF3, r3);
-	run_rt2870_rf_write(sc, RT2860_RF4, r4);
+	run_rt2870_rf_write(sc, rfprog[i].r1);
+	run_rt2870_rf_write(sc, r2);
+	run_rt2870_rf_write(sc, r3 & ~(1 << 2));
+	run_rt2870_rf_write(sc, r4);
 }
 
 static void
-run_rt3070_set_chan(struct run_softc *sc, uint32_t chan)
+run_rt3070_set_chan(struct run_softc *sc, u_int chan)
 {
 	int8_t txpow1, txpow2;
 	uint8_t rf;
 	int i;
 
-	/* RT3070 is 2GHz only */
-	KASSERT(chan >= 1 && chan <= 14, ("wrong channel selected\n"));
-
 	/* find the settings for this channel (we know it exists) */
 	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
 
@@ -3636,7 +4156,12 @@
 	txpow2 = sc->txpow2[i];
 
 	run_rt3070_rf_write(sc, 2, rt3070_freqs[i].n);
-	run_rt3070_rf_write(sc, 3, rt3070_freqs[i].k);
+
+	/* RT3370/RT3390: RF R3 [7:4] is not reserved bits. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf = (rf & ~0x0f) | rt3070_freqs[i].k;
+	run_rt3070_rf_write(sc, 3, rf);
+
 	run_rt3070_rf_read(sc, 6, &rf);
 	rf = (rf & ~0x03) | rt3070_freqs[i].r;
 	run_rt3070_rf_write(sc, 6, rf);
@@ -3832,18 +4357,436 @@
 }
 
 static void
+run_rt3593_set_chan(struct run_softc *sc, u_int chan)
+{
+	int8_t txpow1, txpow2, txpow3;
+	uint8_t h20mhz, rf;
+	int i;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+	txpow3 = (sc->ntxchains == 3) ? sc->txpow3[i] : 0;
+
+	if (chan <= 14) {
+		run_bbp_write(sc, 25, sc->bbp25);
+		run_bbp_write(sc, 26, sc->bbp26);
+	} else {
+		/* Enable IQ phase correction. */
+		run_bbp_write(sc, 25, 0x09);
+		run_bbp_write(sc, 26, 0xff);
+	}
+
+	run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+	run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	/* Set pll_idoh. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x4c;
+	rf |= (chan <= 14) ? 0x44 : 0x48;
+	run_rt3070_rf_write(sc, 11, rf);
+
+	if (chan <= 14)
+		rf = txpow1 & 0x1f;
+	else
+		rf = 0x40 | ((txpow1 & 0x18) << 1) | (txpow1 & 0x07);
+	run_rt3070_rf_write(sc, 53, rf);
+
+	if (chan <= 14)
+		rf = txpow2 & 0x1f;
+	else
+		rf = 0x40 | ((txpow2 & 0x18) << 1) | (txpow2 & 0x07);
+	run_rt3070_rf_write(sc, 55, rf);
+
+	if (chan <= 14)
+		rf = txpow3 & 0x1f;
+	else
+		rf = 0x40 | ((txpow3 & 0x18) << 1) | (txpow3 & 0x07);
+	run_rt3070_rf_write(sc, 54, rf);
+
+	rf = RT3070_RF_BLOCK | RT3070_PLL_PD;
+	if (sc->ntxchains == 3)
+		rf |= RT3070_TX0_PD | RT3070_TX1_PD | RT3070_TX2_PD;
+	else
+		rf |= RT3070_TX0_PD | RT3070_TX1_PD;
+	rf |= RT3070_RX0_PD | RT3070_RX1_PD | RT3070_RX2_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	run_adjust_freq_offset(sc);
+
+	run_rt3070_rf_write(sc, 31, (chan <= 14) ? 0xa0 : 0x80);
+
+	h20mhz = (sc->rf24_20mhz & 0x20) >> 5; 
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x06) | (h20mhz << 1) | (h20mhz << 2);
+	run_rt3070_rf_write(sc, 30, rf);
+
+	run_rt3070_rf_read(sc, 36, &rf);
+	if (chan <= 14)
+		rf |= 0x80;
+	else
+		rf &= ~0x80;
+	run_rt3070_rf_write(sc, 36, rf);
+
+	/* Set vcolo_bs. */
+	run_rt3070_rf_write(sc, 34, (chan <= 14) ? 0x3c : 0x20);
+	/* Set pfd_delay. */
+	run_rt3070_rf_write(sc, 12, (chan <= 14) ? 0x1a : 0x12);
+
+	/* Set vco bias current control. */
+	run_rt3070_rf_read(sc, 6, &rf);
+	rf &= ~0xc0;
+	if (chan <= 14)
+		rf |= 0x40;
+	else if (chan <= 128)
+		rf |= 0x80;
+	else
+		rf |= 0x40;
+	run_rt3070_rf_write(sc, 6, rf);
+		
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	run_rt3070_rf_write(sc, 10, (chan <= 14) ? 0xd3 : 0xd8);
+	run_rt3070_rf_write(sc, 13, (chan <= 14) ? 0x12 : 0x23);
+
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf = (rf & ~0x03) | 0x01;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_mx1_cc. */
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf &= ~0x1c;
+	rf |= (chan <= 14) ? 0x14 : 0x10;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_mx1_ic. */
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf &= ~0xe0;
+	rf |= (chan <= 14) ? 0x60 : 0x40;
+	run_rt3070_rf_write(sc, 51, rf);
+	/* Set tx_lo1_ic. */
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf &= ~0x1c;
+	rf |= (chan <= 14) ? 0x0c : 0x08;
+	run_rt3070_rf_write(sc, 49, rf);
+	/* Set tx_lo1_en. */
+	run_rt3070_rf_read(sc, 50, &rf);
+	run_rt3070_rf_write(sc, 50, rf & ~0x20);
+	/* Set drv_cc. */
+	run_rt3070_rf_read(sc, 57, &rf);
+	rf &= ~0xfc;
+	rf |= (chan <= 14) ?  0x6c : 0x3c;
+	run_rt3070_rf_write(sc, 57, rf);
+	/* Set rx_mix1_ic, rxa_lnactr, lna_vc, lna_inbias_en and lna_en. */
+	run_rt3070_rf_write(sc, 44, (chan <= 14) ? 0x93 : 0x9b);
+	/* Set drv_gnd_a, tx_vga_cc_a and tx_mx2_gain. */
+	run_rt3070_rf_write(sc, 52, (chan <= 14) ? 0x45 : 0x05);
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf &= ~RT5390_VCOCAL;
+	rf |= (chan <= 14) ? RT5390_VCOCAL : 0xbe;
+	run_rt3070_rf_write(sc, 3, rf);
+
+	if (chan <= 14)
+		rf = 0x23;
+	else if (chan <= 64)
+		rf = 0x36;
+	else if (chan <= 128)
+		rf = 0x32;
+	else
+		rf = 0x30;
+	run_rt3070_rf_write(sc, 39, rf);
+	if (chan <= 14)
+		rf = 0xbb;
+	else if (chan <= 64)
+		rf = 0xeb;
+	else if (chan <= 128)
+		rf = 0xb3;
+	else
+		rf = 0x9b;
+	run_rt3070_rf_write(sc, 45, rf);
+
+	/* Set FEQ/AEQ control. */
+	run_bbp_write(sc, 105, 0x34);
+}
+
+static void
+run_rt5390_set_chan(struct run_softc *sc, u_int chan)
+{
+	int8_t txpow1, txpow2;
+	uint8_t rf;
+	int i;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+
+	run_rt3070_rf_write(sc, 8, rt3070_freqs[i].n);
+	run_rt3070_rf_write(sc, 9, rt3070_freqs[i].k & 0x0f);
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf = (rf & ~0x03) | (rt3070_freqs[i].r & 0x03);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	/* The valid range of the RF R49 is 0x00 to 0x27. */
+	if ((rf & 0x3f) > 0x27)
+		rf = (rf & ~0x3f) | 0x27;
+	run_rt3070_rf_write(sc, 49, rf);
+
+	if (sc->mac_ver == 0x5392) {
+		run_rt3070_rf_read(sc, 50, &rf);
+		rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+		/* The valid range of the RF R50 is 0x00 to 0x27. */
+		if ((rf & 0x3f) > 0x27)
+			rf = (rf & ~0x3f) | 0x27;
+		run_rt3070_rf_write(sc, 50, rf);
+	}
+
+	run_rt3070_rf_read(sc, 1, &rf);
+	rf |= RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD;
+	if (sc->mac_ver == 0x5392)
+		rf |= RT3070_RX1_PD | RT3070_TX1_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	if (sc->mac_ver != 0x5392) {
+		run_rt3070_rf_read(sc, 2, &rf);
+		rf |= 0x80;
+		run_rt3070_rf_write(sc, 2, rf);
+		run_delay(sc, 10);
+		rf &= 0x7f;
+		run_rt3070_rf_write(sc, 2, rf);
+	}
+
+	run_adjust_freq_offset(sc);
+
+	if (sc->mac_ver == 0x5392) {
+		/* Fix for RT5392C. */
+		if (sc->mac_rev >= 0x0223) {
+			if (chan <= 4)
+				rf = 0x0f;
+			else if (chan >= 5 && chan <= 7)
+				rf = 0x0e;
+			else
+				rf = 0x0d;
+			run_rt3070_rf_write(sc, 23, rf);
+
+			if (chan <= 4)
+				rf = 0x0c;
+			else if (chan == 5)
+				rf = 0x0b;
+			else if (chan >= 6 && chan <= 7)
+				rf = 0x0a;
+			else if (chan >= 8 && chan <= 10)
+				rf = 0x09;
+			else
+				rf = 0x08;
+			run_rt3070_rf_write(sc, 59, rf);
+		} else {
+			if (chan <= 11)
+				rf = 0x0f;
+			else
+				rf = 0x0b;
+			run_rt3070_rf_write(sc, 59, rf);
+		}
+	} else {
+		/* Fix for RT5390F. */
+		if (sc->mac_rev >= 0x0502) {
+			if (chan <= 11)
+				rf = 0x43;
+			else
+				rf = 0x23;
+			run_rt3070_rf_write(sc, 55, rf);
+
+			if (chan <= 11)
+				rf = 0x0f;
+			else if (chan == 12)
+				rf = 0x0d;
+			else
+				rf = 0x0b;
+			run_rt3070_rf_write(sc, 59, rf);
+		} else {
+			run_rt3070_rf_write(sc, 55, 0x44);
+			run_rt3070_rf_write(sc, 59, 0x8f);
+		}
+	}
+
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf |= RT5390_VCOCAL;
+	run_rt3070_rf_write(sc, 3, rf);
+}
+
+static void
+run_rt5592_set_chan(struct run_softc *sc, u_int chan)
+{
+	const struct rt5592_freqs *freqs;
+	uint32_t tmp;
+	uint8_t reg, rf, txpow_bound;
+	int8_t txpow1, txpow2;
+	int i;
+
+	run_read(sc, RT5592_DEBUG_INDEX, &tmp);
+	freqs = (tmp & RT5592_SEL_XTAL) ?
+	    rt5592_freqs_40mhz : rt5592_freqs_20mhz;
+
+	/* find the settings for this channel (we know it exists) */
+	for (i = 0; rt2860_rf2850[i].chan != chan; i++, freqs++);
+
+	/* use Tx power values from EEPROM */
+	txpow1 = sc->txpow1[i];
+	txpow2 = sc->txpow2[i];
+
+	run_read(sc, RT3070_LDO_CFG0, &tmp);
+	tmp &= ~0x1c000000;
+	if (chan > 14)
+		tmp |= 0x14000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+
+	/* N setting. */
+	run_rt3070_rf_write(sc, 8, freqs->n & 0xff);
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~(1 << 4);
+	rf |= ((freqs->n & 0x0100) >> 8) << 4;
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* K setting. */
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~0x0f;
+	rf |= (freqs->k & 0x0f);
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* Mode setting. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x0c;
+	rf |= ((freqs->m - 0x8) & 0x3) << 2;
+	run_rt3070_rf_write(sc, 11, rf);
+	run_rt3070_rf_read(sc, 9, &rf);
+	rf &= ~(1 << 7);
+	rf |= (((freqs->m - 0x8) & 0x4) >> 2) << 7;
+	run_rt3070_rf_write(sc, 9, rf);
+
+	/* R setting. */
+	run_rt3070_rf_read(sc, 11, &rf);
+	rf &= ~0x03;
+	rf |= (freqs->r - 0x1);
+	run_rt3070_rf_write(sc, 11, rf);
+
+	if (chan <= 14) {
+		/* Initialize RF registers for 2GHZ. */
+		for (i = 0; i < nitems(rt5592_2ghz_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_2ghz_def_rf[i].reg,
+			    rt5592_2ghz_def_rf[i].val);
+		}
+
+		rf = (chan <= 10) ? 0x07 : 0x06;
+		run_rt3070_rf_write(sc, 23, rf);
+		run_rt3070_rf_write(sc, 59, rf);
+
+		run_rt3070_rf_write(sc, 55, 0x43);
+
+		/* 
+		 * RF R49/R50 Tx power ALC code.
+		 * G-band bit<7:6>=1:0, bit<5:0> range from 0x0 ~ 0x27.
+		 */
+		reg = 2;
+		txpow_bound = 0x27;
+	} else {
+		/* Initialize RF registers for 5GHZ. */
+		for (i = 0; i < nitems(rt5592_5ghz_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_5ghz_def_rf[i].reg,
+			    rt5592_5ghz_def_rf[i].val);
+		}
+		for (i = 0; i < nitems(rt5592_chan_5ghz); i++) {
+			if (chan >= rt5592_chan_5ghz[i].firstchan &&
+			    chan <= rt5592_chan_5ghz[i].lastchan) {
+				run_rt3070_rf_write(sc, rt5592_chan_5ghz[i].reg,
+				    rt5592_chan_5ghz[i].val);
+			}
+		}
+
+		/* 
+		 * RF R49/R50 Tx power ALC code.
+		 * A-band bit<7:6>=1:1, bit<5:0> range from 0x0 ~ 0x2b.
+		 */
+		reg = 3;
+		txpow_bound = 0x2b;
+	}
+
+	/* RF R49 ch0 Tx power ALC code. */
+	run_rt3070_rf_read(sc, 49, &rf);
+	rf &= ~0xc0;
+	rf |= (reg << 6);
+	rf = (rf & ~0x3f) | (txpow1 & 0x3f);
+	if ((rf & 0x3f) > txpow_bound)
+		rf = (rf & ~0x3f) | txpow_bound;
+	run_rt3070_rf_write(sc, 49, rf);
+
+	/* RF R50 ch1 Tx power ALC code. */
+	run_rt3070_rf_read(sc, 50, &rf);
+	rf &= ~(1 << 7 | 1 << 6);
+	rf |= (reg << 6);
+	rf = (rf & ~0x3f) | (txpow2 & 0x3f);
+	if ((rf & 0x3f) > txpow_bound)
+		rf = (rf & ~0x3f) | txpow_bound;
+	run_rt3070_rf_write(sc, 50, rf);
+
+	/* Enable RF_BLOCK, PLL_PD, RX0_PD, and TX0_PD. */
+	run_rt3070_rf_read(sc, 1, &rf);
+	rf |= (RT3070_RF_BLOCK | RT3070_PLL_PD | RT3070_RX0_PD | RT3070_TX0_PD);
+	if (sc->ntxchains > 1)
+		rf |= RT3070_TX1_PD;
+	if (sc->nrxchains > 1)
+		rf |= RT3070_RX1_PD;
+	run_rt3070_rf_write(sc, 1, rf);
+
+	run_rt3070_rf_write(sc, 6, 0xe4);
+
+	run_rt3070_rf_write(sc, 30, 0x10);
+	run_rt3070_rf_write(sc, 31, 0x80);
+	run_rt3070_rf_write(sc, 32, 0x80);
+
+	run_adjust_freq_offset(sc);
+
+	/* Enable VCO calibration. */
+	run_rt3070_rf_read(sc, 3, &rf);
+	rf |= RT5390_VCOCAL;
+	run_rt3070_rf_write(sc, 3, rf);
+}
+
+static void
 run_set_rx_antenna(struct run_softc *sc, int aux)
 {
 	uint32_t tmp;
+	uint8_t bbp152;
 
 	if (aux) {
-		run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0);
-		run_read(sc, RT2860_GPIO_CTRL, &tmp);
-		run_write(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+		if (sc->rf_rev == RT5390_RF_5370) {
+			run_bbp_read(sc, 152, &bbp152);
+			run_bbp_write(sc, 152, bbp152 & ~0x80);
+		} else {
+			run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 0);
+			run_read(sc, RT2860_GPIO_CTRL, &tmp);
+			run_write(sc, RT2860_GPIO_CTRL, (tmp & ~0x0808) | 0x08);
+		}
 	} else {
-		run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 1);
-		run_read(sc, RT2860_GPIO_CTRL, &tmp);
-		run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+		if (sc->rf_rev == RT5390_RF_5370) {
+			run_bbp_read(sc, 152, &bbp152);
+			run_bbp_write(sc, 152, bbp152 | 0x80);
+		} else {
+			run_mcu_cmd(sc, RT2860_MCU_CMD_ANTSEL, 1);
+			run_read(sc, RT2860_GPIO_CTRL, &tmp);
+			run_write(sc, RT2860_GPIO_CTRL, tmp & ~0x0808);
+		}
 	}
 }
 
@@ -3851,13 +4794,19 @@
 run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
 {
 	struct ieee80211com *ic = sc->sc_ifp->if_l2com;
-	uint32_t chan, group;
+	u_int chan, group;
 
 	chan = ieee80211_chan2ieee(ic, c);
 	if (chan == 0 || chan == IEEE80211_CHAN_ANY)
 		return (EINVAL);
 
-	if (sc->mac_ver == 0x3572)
+	if (sc->mac_ver == 0x5592)
+		run_rt5592_set_chan(sc, chan);
+	else if (sc->mac_ver >= 0x5390)
+		run_rt5390_set_chan(sc, chan);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_set_chan(sc, chan);
+	else if (sc->mac_ver == 0x3572)
 		run_rt3572_set_chan(sc, chan);
 	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_set_chan(sc, chan);
@@ -3879,6 +4828,10 @@
 
 	run_delay(sc, 10);
 
+	/* Perform IQ calibration. */
+	if (sc->mac_ver >= 0x5392)
+		run_iq_calib(sc, chan);
+
 	return (0);
 }
 
@@ -3960,6 +4913,12 @@
 	}
 
 	setbit(rvp->bo.bo_flags, item);
+	if (rvp->beacon_mbuf == NULL) {
+		rvp->beacon_mbuf = ieee80211_beacon_alloc(vap->iv_bss,
+		    &rvp->bo);
+		if (rvp->beacon_mbuf == NULL)
+			return;
+	}
 	ieee80211_beacon_update(vap->iv_bss, &rvp->bo, rvp->beacon_mbuf, mcast);
 
 	i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -3980,6 +4939,7 @@
 	struct run_softc *sc = ic->ic_ifp->if_softc;
 	struct rt2860_txwi txwi;
 	struct mbuf *m;
+	uint16_t txwisize;
 	uint8_t ridx;
 
 	if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC)
@@ -3999,25 +4959,26 @@
 	}
 	m = rvp->beacon_mbuf;
 
-	memset(&txwi, 0, sizeof txwi);
+	memset(&txwi, 0, sizeof(txwi));
 	txwi.wcid = 0xff;
 	txwi.len = htole16(m->m_pkthdr.len);
+
 	/* send beacons at the lowest available rate */
 	ridx = (ic->ic_curmode == IEEE80211_MODE_11A) ?
 	    RT2860_RIDX_OFDM6 : RT2860_RIDX_CCK1;
 	txwi.phy = htole16(rt2860_rates[ridx].mcs);
 	if (rt2860_rates[ridx].phy == IEEE80211_T_OFDM)
-	        txwi.phy |= htole16(RT2860_PHY_OFDM);
+		txwi.phy |= htole16(RT2860_PHY_OFDM);
 	txwi.txop = RT2860_TX_TXOP_HT;
 	txwi.flags = RT2860_TX_TS;
 	txwi.xflags = RT2860_TX_NSEQ;
 
-	run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id),
-	    (uint8_t *)&txwi, sizeof txwi);
-	run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + sizeof txwi,
-	    mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1);	/* roundup len */
-
-	return;
+	txwisize = (sc->mac_ver == 0x5592) ?
+	    sizeof(txwi) + sizeof(uint32_t) : sizeof(txwi);
+	run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id), (uint8_t *)&txwi,
+	    txwisize);
+	run_write_region_1(sc, RT2860_BCN_BASE(rvp->rvp_id) + txwisize,
+	    mtod(m, uint8_t *), (m->m_pkthdr.len + 1) & ~1);
 }
 
 static void
@@ -4137,7 +5098,8 @@
 	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
 	uint32_t tmp;
 
-	DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id, ic->ic_opmode);
+	DPRINTF("rvp_id=%d ic_opmode=%d\n", RUN_VAP(vap)->rvp_id,
+	    ic->ic_opmode);
 
 	run_read(sc, RT2860_BCN_TIME_CFG, &tmp);
 	tmp &= ~0x1fffff;
@@ -4173,8 +5135,8 @@
 static void
 run_enable_mrr(struct run_softc *sc)
 {
-#define CCK(mcs)	(mcs)
-#define OFDM(mcs)	(1 << 3 | (mcs))
+#define	CCK(mcs)	(mcs)
+#define	OFDM(mcs)	(1 << 3 | (mcs))
 	run_write(sc, RT2860_LG_FBK_CFG0,
 	    OFDM(6) << 28 |	/* 54->48 */
 	    OFDM(5) << 24 |	/* 48->36 */
@@ -4293,7 +5255,7 @@
 	int delta;
 
 	if (IEEE80211_IS_CHAN_5GHZ(c)) {
-		uint32_t chan = ieee80211_chan2ieee(ic, c);
+		u_int chan = ieee80211_chan2ieee(ic, c);
 		delta = sc->rssi_5ghz[rxchain];
 
 		/* determine channel group */
@@ -4309,6 +5271,64 @@
 	return (-12 - delta - rssi);
 }
 
+static void
+run_rt5390_bbp_init(struct run_softc *sc)
+{
+	int i;
+	uint8_t bbp;
+
+	/* Apply maximum likelihood detection for 2 stream case. */
+	run_bbp_read(sc, 105, &bbp);
+	if (sc->nrxchains > 1)
+		run_bbp_write(sc, 105, bbp | RT5390_MLD);
+
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	if (sc->mac_ver == 0x5592) {
+		for (i = 0; i < nitems(rt5592_def_bbp); i++) {
+			run_bbp_write(sc, rt5592_def_bbp[i].reg,
+			    rt5592_def_bbp[i].val);
+		}
+		for (i = 0; i < nitems(rt5592_bbp_r196); i++) {
+			run_bbp_write(sc, 195, i + 0x80);
+			run_bbp_write(sc, 196, rt5592_bbp_r196[i]);
+		}
+	} else {
+		for (i = 0; i < nitems(rt5390_def_bbp); i++) {
+			run_bbp_write(sc, rt5390_def_bbp[i].reg,
+			    rt5390_def_bbp[i].val);
+		}
+	}
+	if (sc->mac_ver == 0x5392) {
+		run_bbp_write(sc, 88, 0x90);
+		run_bbp_write(sc, 95, 0x9a);
+		run_bbp_write(sc, 98, 0x12);
+		run_bbp_write(sc, 106, 0x12);
+		run_bbp_write(sc, 134, 0xd0);
+		run_bbp_write(sc, 135, 0xf6);
+		run_bbp_write(sc, 148, 0x84);
+	}
+
+	run_bbp_read(sc, 152, &bbp);
+	run_bbp_write(sc, 152, bbp | 0x80);
+
+	/* Fix BBP254 for RT5592C. */
+	if (sc->mac_ver == 0x5592 && sc->mac_rev >= 0x0221) {
+		run_bbp_read(sc, 254, &bbp);
+		run_bbp_write(sc, 254, bbp | 0x80);
+	}
+
+	/* Disable hardware antenna diversity. */
+	if (sc->mac_ver == 0x5390)
+		run_bbp_write(sc, 154, 0);
+
+	/* Initialize Rx CCK/OFDM frequency offset report. */
+	run_bbp_write(sc, 142, 1);
+	run_bbp_write(sc, 143, 57);
+}
+
 static int
 run_bbp_init(struct run_softc *sc)
 {
@@ -4326,16 +5346,29 @@
 		return (ETIMEDOUT);
 
 	/* initialize BBP registers to default values */
-	for (i = 0; i < N(rt2860_def_bbp); i++) {
-		run_bbp_write(sc, rt2860_def_bbp[i].reg,
-		    rt2860_def_bbp[i].val);
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_bbp_init(sc);
+	else {
+		for (i = 0; i < nitems(rt2860_def_bbp); i++) {
+			run_bbp_write(sc, rt2860_def_bbp[i].reg,
+			    rt2860_def_bbp[i].val);
+		}
 	}
 
+	if (sc->mac_ver == 0x3593) {
+		run_bbp_write(sc, 79, 0x13);
+		run_bbp_write(sc, 80, 0x05);
+		run_bbp_write(sc, 81, 0x33);
+		run_bbp_write(sc, 86, 0x46);
+		run_bbp_write(sc, 137, 0x0f);
+	}
+		
 	/* fix BBP84 for RT2860E */
 	if (sc->mac_ver == 0x2860 && sc->mac_rev != 0x0101)
 		run_bbp_write(sc, 84, 0x19);
 
-	if (sc->mac_ver >= 0x3070) {
+	if (sc->mac_ver >= 0x3070 && (sc->mac_ver != 0x3593 &&
+	    sc->mac_ver != 0x5592)) {
 		run_bbp_write(sc, 79, 0x13);
 		run_bbp_write(sc, 80, 0x05);
 		run_bbp_write(sc, 81, 0x33);
@@ -4350,7 +5383,7 @@
 run_rt3070_rf_init(struct run_softc *sc)
 {
 	uint32_t tmp;
-	uint8_t rf, target, bbp4;
+	uint8_t bbp4, mingain, rf, target;
 	int i;
 
 	run_rt3070_rf_read(sc, 30, &rf);
@@ -4361,19 +5394,23 @@
 
 	/* initialize RF registers to default value */
 	if (sc->mac_ver == 0x3572) {
-		for (i = 0; i < N(rt3572_def_rf); i++) {
+		for (i = 0; i < nitems(rt3572_def_rf); i++) {
 			run_rt3070_rf_write(sc, rt3572_def_rf[i].reg,
 			    rt3572_def_rf[i].val);
 		}
 	} else {
-		for (i = 0; i < N(rt3070_def_rf); i++) {
+		for (i = 0; i < nitems(rt3070_def_rf); i++) {
 			run_rt3070_rf_write(sc, rt3070_def_rf[i].reg,
 			    rt3070_def_rf[i].val);
 		}
 	}
 
-	if (sc->mac_ver == 0x3070) {
-		/* change voltage from 1.2V to 1.35V for RT3070 */
+	if (sc->mac_ver == 0x3070 && sc->mac_rev < 0x0201) {
+		/* 
+		 * Change voltage from 1.2V to 1.35V for RT3070.
+		 * The DAC issue (RT3070_LDO_CFG0) has been fixed
+		 * in RT3070(F).
+		 */
 		run_read(sc, RT3070_LDO_CFG0, &tmp);
 		tmp = (tmp & ~0x0f000000) | 0x0d000000;
 		run_write(sc, RT3070_LDO_CFG0, tmp);
@@ -4423,7 +5460,7 @@
 
 	/* select 40MHz bandwidth */
 	run_bbp_read(sc, 4, &bbp4);
-	run_bbp_write(sc, 4, (bbp4 & ~0x08) | 0x10);
+	run_bbp_write(sc, 4, (bbp4 & ~0x18) | 0x10);
 	run_rt3070_rf_read(sc, 31, &rf);
 	run_rt3070_rf_write(sc, 31, rf | 0x20);
 
@@ -4440,7 +5477,7 @@
 		/* save default BBP registers 25 and 26 values */
 		run_bbp_read(sc, 25, &sc->bbp25);
 		run_bbp_read(sc, 26, &sc->bbp26);
-	} else if (sc->mac_rev < 0x0211)
+	} else if (sc->mac_rev < 0x0201 || sc->mac_rev < 0x0211)
 		run_rt3070_rf_write(sc, 27, 0x03);
 
 	run_read(sc, RT3070_OPT_14, &tmp);
@@ -4453,12 +5490,13 @@
 		     (sc->mac_ver == 0x3071 && sc->mac_rev >= 0x0211)) &&
 		    !sc->ext_2ghz_lna)
 			rf |= 0x20;	/* fix for long range Rx issue */
-		if (sc->txmixgain_2ghz >= 1)
+		mingain = (sc->mac_ver == 0x3070) ? 1 : 2;
+		if (sc->txmixgain_2ghz >= mingain)
 			rf = (rf & ~0x7) | sc->txmixgain_2ghz;
 		run_rt3070_rf_write(sc, 17, rf);
 	}
 
-	if (sc->mac_rev == 0x3071) {
+	if (sc->mac_ver == 0x3071) {
 		run_rt3070_rf_read(sc, 1, &rf);
 		rf &= ~(RT3070_RX0_PD | RT3070_TX0_PD);
 		rf |= RT3070_RF_BLOCK | RT3070_RX1_PD | RT3070_TX1_PD;
@@ -4485,6 +5523,119 @@
 	return (0);
 }
 
+static void
+run_rt3593_rf_init(struct run_softc *sc)
+{
+	uint32_t tmp;
+	uint8_t rf;
+	int i;
+
+	/* Disable the GPIO bits 4 and 7 for LNA PE control. */
+	run_read(sc, RT3070_GPIO_SWITCH, &tmp);
+	tmp &= ~(1 << 4 | 1 << 7);
+	run_write(sc, RT3070_GPIO_SWITCH, tmp);
+
+	/* Initialize RF registers to default value. */
+	for (i = 0; i < nitems(rt3593_def_rf); i++) {
+		run_rt3070_rf_write(sc, rt3593_def_rf[i].reg,
+		    rt3593_def_rf[i].val);
+	}
+
+	/* Toggle RF R2 to initiate calibration. */
+	run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+
+	/* Initialize RF frequency offset. */
+	run_adjust_freq_offset(sc);
+
+	run_rt3070_rf_read(sc, 18, &rf);
+	run_rt3070_rf_write(sc, 18, rf | RT3593_AUTOTUNE_BYPASS);
+
+	/*
+	 * Increase voltage from 1.2V to 1.35V, wait for 1 msec to
+	 * decrease voltage back to 1.2V.
+	 */
+	run_read(sc, RT3070_LDO_CFG0, &tmp);
+	tmp = (tmp & ~0x1f000000) | 0x0d000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+	run_delay(sc, 1);
+	tmp = (tmp & ~0x1f000000) | 0x01000000;
+	run_write(sc, RT3070_LDO_CFG0, tmp);
+
+	sc->rf24_20mhz = 0x1f;
+	sc->rf24_40mhz = 0x2f;
+
+	/* Save default BBP registers 25 and 26 values. */
+	run_bbp_read(sc, 25, &sc->bbp25);
+	run_bbp_read(sc, 26, &sc->bbp26);
+
+	run_read(sc, RT3070_OPT_14, &tmp);
+	run_write(sc, RT3070_OPT_14, tmp | 1);
+}
+
+static void
+run_rt5390_rf_init(struct run_softc *sc)
+{
+	uint32_t tmp;
+	uint8_t rf;
+	int i;
+
+	/* Toggle RF R2 to initiate calibration. */
+	if (sc->mac_ver == 0x5390) {
+		run_rt3070_rf_read(sc, 2, &rf);
+		run_rt3070_rf_write(sc, 2, rf | RT5390_RESCAL);
+		run_delay(sc, 10);
+		run_rt3070_rf_write(sc, 2, rf & ~RT5390_RESCAL);
+	} else {
+		run_rt3070_rf_write(sc, 2, RT5390_RESCAL);
+		run_delay(sc, 10);
+	}
+
+	/* Initialize RF registers to default value. */
+	if (sc->mac_ver == 0x5592) {
+		for (i = 0; i < nitems(rt5592_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5592_def_rf[i].reg,
+			    rt5592_def_rf[i].val);
+		}
+		/* Initialize RF frequency offset. */
+		run_adjust_freq_offset(sc);
+	} else if (sc->mac_ver == 0x5392) {
+		for (i = 0; i < nitems(rt5392_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5392_def_rf[i].reg,
+			    rt5392_def_rf[i].val);
+		}
+		if (sc->mac_rev >= 0x0223) {
+			run_rt3070_rf_write(sc, 23, 0x0f);
+			run_rt3070_rf_write(sc, 24, 0x3e);
+			run_rt3070_rf_write(sc, 51, 0x32);
+			run_rt3070_rf_write(sc, 53, 0x22);
+			run_rt3070_rf_write(sc, 56, 0xc1);
+			run_rt3070_rf_write(sc, 59, 0x0f);
+		}
+	} else {
+		for (i = 0; i < nitems(rt5390_def_rf); i++) {
+			run_rt3070_rf_write(sc, rt5390_def_rf[i].reg,
+			    rt5390_def_rf[i].val);
+		}
+		if (sc->mac_rev >= 0x0502) {
+			run_rt3070_rf_write(sc, 6, 0xe0);
+			run_rt3070_rf_write(sc, 25, 0x80);
+			run_rt3070_rf_write(sc, 46, 0x73);
+			run_rt3070_rf_write(sc, 53, 0x00);
+			run_rt3070_rf_write(sc, 56, 0x42);
+			run_rt3070_rf_write(sc, 61, 0xd1);
+		}
+	}
+
+	sc->rf24_20mhz = 0x1f;	/* default value */
+	sc->rf24_40mhz = (sc->mac_ver == 0x5592) ? 0 : 0x2f;
+
+	if (sc->mac_rev < 0x0211)
+		run_rt3070_rf_write(sc, 27, 0x3);
+
+	run_read(sc, RT3070_OPT_14, &tmp);
+	run_write(sc, RT3070_OPT_14, tmp | 1);
+}
+
 static int
 run_rt3070_filter_calib(struct run_softc *sc, uint8_t init, uint8_t target,
     uint8_t *val)
@@ -4514,7 +5665,7 @@
 			break;
 	}
 	if (ntries == 100)
-		return ETIMEDOUT;
+		return (ETIMEDOUT);
 
 	/* set power and frequency of stopband test tone */
 	run_bbp_write(sc, 24, 0x06);
@@ -4579,10 +5730,15 @@
 		run_rt3070_rf_write(sc, 16, rf);
 
 	} else if (sc->mac_ver == 0x3071) {
-		/* enable DC filter */
-		if (sc->mac_rev >= 0x0201)
+		if (sc->mac_rev >= 0x0211) {
+			/* enable DC filter */
 			run_bbp_write(sc, 103, 0xc0);
 
+			/* improve power consumption */
+			run_bbp_read(sc, 31, &bbp);
+			run_bbp_write(sc, 31, bbp & ~0x03);
+		}
+
 		run_bbp_read(sc, 138, &bbp);
 		if (sc->ntxchains == 1)
 			bbp |= 0x20;	/* turn off DAC1 */
@@ -4590,12 +5746,6 @@
 			bbp &= ~0x02;	/* turn off ADC1 */
 		run_bbp_write(sc, 138, bbp);
 
-		if (sc->mac_rev >= 0x0211) {
-			/* improve power consumption */
-			run_bbp_read(sc, 31, &bbp);
-			run_bbp_write(sc, 31, bbp & ~0x03);
-		}
-
 		run_write(sc, RT2860_TX_SW_CFG1, 0);
 		if (sc->mac_rev < 0x0211) {
 			run_write(sc, RT2860_TX_SW_CFG2,
@@ -4613,7 +5763,7 @@
 			run_bbp_write(sc, 31, bbp & ~0x03);
 		}
 
-		if (sc->mac_rev < 0x0211) {
+		if (sc->mac_rev < 0x0201) {
 			run_write(sc, RT2860_TX_SW_CFG1, 0);
 			run_write(sc, RT2860_TX_SW_CFG2, 0x2c);
 		} else
@@ -4630,6 +5780,123 @@
 	}
 }
 
+static void
+run_rt3593_rf_setup(struct run_softc *sc)
+{
+	uint8_t bbp, rf;
+
+	if (sc->mac_rev >= 0x0211) {
+		/* Enable DC filter. */
+		run_bbp_write(sc, 103, 0xc0);
+	}
+	run_write(sc, RT2860_TX_SW_CFG1, 0);
+	if (sc->mac_rev < 0x0211) {
+		run_write(sc, RT2860_TX_SW_CFG2,
+		    sc->patch_dac ? 0x2c : 0x0f);
+	} else
+		run_write(sc, RT2860_TX_SW_CFG2, 0);
+
+	run_rt3070_rf_read(sc, 50, &rf);
+	run_rt3070_rf_write(sc, 50, rf & ~RT3593_TX_LO2);
+
+	run_rt3070_rf_read(sc, 51, &rf);
+	rf = (rf & ~(RT3593_TX_LO1 | 0x0c)) |
+	    ((sc->txmixgain_2ghz & 0x07) << 2);
+	run_rt3070_rf_write(sc, 51, rf);
+
+	run_rt3070_rf_read(sc, 38, &rf);
+	run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+
+	run_rt3070_rf_read(sc, 39, &rf);
+	run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+	run_rt3070_rf_read(sc, 1, &rf);
+	run_rt3070_rf_write(sc, 1, rf & ~(RT3070_RF_BLOCK | RT3070_PLL_PD));
+
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	/* Apply maximum likelihood detection for 2 stream case. */
+	run_bbp_read(sc, 105, &bbp);
+	if (sc->nrxchains > 1)
+		run_bbp_write(sc, 105, bbp | RT5390_MLD);
+
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	run_bbp_write(sc, 92, 0x02);
+	run_bbp_write(sc, 82, 0x82);
+	run_bbp_write(sc, 106, 0x05);
+	run_bbp_write(sc, 104, 0x92);
+	run_bbp_write(sc, 88, 0x90);
+	run_bbp_write(sc, 148, 0xc8);
+	run_bbp_write(sc, 47, 0x48);
+	run_bbp_write(sc, 120, 0x50);
+
+	run_bbp_write(sc, 163, 0x9d);
+
+	/* SNR mapping. */
+	run_bbp_write(sc, 142, 0x06);
+	run_bbp_write(sc, 143, 0xa0);
+	run_bbp_write(sc, 142, 0x07);
+	run_bbp_write(sc, 143, 0xa1);
+	run_bbp_write(sc, 142, 0x08);
+	run_bbp_write(sc, 143, 0xa2);
+
+	run_bbp_write(sc, 31, 0x08);
+	run_bbp_write(sc, 68, 0x0b);
+	run_bbp_write(sc, 105, 0x04);
+}
+
+static void
+run_rt5390_rf_setup(struct run_softc *sc)
+{
+	uint8_t bbp, rf;
+
+	if (sc->mac_rev >= 0x0211) {
+		/* Enable DC filter. */
+		run_bbp_write(sc, 103, 0xc0);
+
+		if (sc->mac_ver != 0x5592) {
+			/* Improve power consumption. */
+			run_bbp_read(sc, 31, &bbp);
+			run_bbp_write(sc, 31, bbp & ~0x03);
+		}
+	}
+
+	run_bbp_read(sc, 138, &bbp);
+	if (sc->ntxchains == 1)
+		bbp |= 0x20;	/* turn off DAC1 */
+	if (sc->nrxchains == 1)
+		bbp &= ~0x02;	/* turn off ADC1 */
+	run_bbp_write(sc, 138, bbp);
+
+	run_rt3070_rf_read(sc, 38, &rf);
+	run_rt3070_rf_write(sc, 38, rf & ~RT5390_RX_LO1);
+
+	run_rt3070_rf_read(sc, 39, &rf);
+	run_rt3070_rf_write(sc, 39, rf & ~RT5390_RX_LO2);
+
+	/* Avoid data lost and CRC error. */
+	run_bbp_read(sc, 4, &bbp);
+	run_bbp_write(sc, 4, bbp | RT5390_MAC_IF_CTRL);
+
+	run_rt3070_rf_read(sc, 30, &rf);
+	rf = (rf & ~0x18) | 0x10;
+	run_rt3070_rf_write(sc, 30, rf);
+
+	if (sc->mac_ver != 0x5592) {
+		run_write(sc, RT2860_TX_SW_CFG1, 0);
+		if (sc->mac_rev < 0x0211) {
+			run_write(sc, RT2860_TX_SW_CFG2,
+			    sc->patch_dac ? 0x2c : 0x0f);
+		} else
+			run_write(sc, RT2860_TX_SW_CFG2, 0);
+	}
+}
+
 static int
 run_txrx_enable(struct run_softc *sc)
 {
@@ -4640,13 +5907,13 @@
 	run_write(sc, RT2860_MAC_SYS_CTRL, RT2860_MAC_TX_EN);
 	for (ntries = 0; ntries < 200; ntries++) {
 		if ((error = run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp)) != 0)
-			return error;
+			return (error);
 		if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
 			break;
 		run_delay(sc, 50);
 	}
 	if (ntries == 200)
-		return ETIMEDOUT;
+		return (ETIMEDOUT);
 
 	run_delay(sc, 50);
 
@@ -4677,6 +5944,20 @@
 }
 
 static void
+run_adjust_freq_offset(struct run_softc *sc)
+{
+	uint8_t rf, tmp;
+
+	run_rt3070_rf_read(sc, 17, &rf);
+	tmp = rf;
+	rf = (rf & ~0x7f) | (sc->freq & 0x7f);
+	rf = MIN(rf, 0x5f);
+
+	if (tmp != rf)
+		run_mcu_cmd(sc, 0x74, (tmp << 8 ) | rf);
+}
+
+static void
 run_init_locked(struct run_softc *sc)
 {
 	struct ifnet *ifp = sc->sc_ifp;
@@ -4749,13 +6030,29 @@
 		run_write(sc, RT2860_TX_PWR_CFG(ridx), sc->txpow20mhz[ridx]);
 	}
 
-	for (i = 0; i < N(rt2870_def_mac); i++)
+	for (i = 0; i < nitems(rt2870_def_mac); i++)
 		run_write(sc, rt2870_def_mac[i].reg, rt2870_def_mac[i].val);
 	run_write(sc, RT2860_WMM_AIFSN_CFG, 0x00002273);
 	run_write(sc, RT2860_WMM_CWMIN_CFG, 0x00002344);
 	run_write(sc, RT2860_WMM_CWMAX_CFG, 0x000034aa);
 
-	if (sc->mac_ver >= 0x3070) {
+	if (sc->mac_ver >= 0x5390) {
+		run_write(sc, RT2860_TX_SW_CFG0,
+		    4 << RT2860_DLY_PAPE_EN_SHIFT | 4);
+		if (sc->mac_ver >= 0x5392) {
+			run_write(sc, RT2860_MAX_LEN_CFG, 0x00002fff);
+			if (sc->mac_ver == 0x5592) {
+				run_write(sc, RT2860_HT_FBK_CFG1, 0xedcba980);
+				run_write(sc, RT2860_TXOP_HLDR_ET, 0x00000082);
+			} else {
+				run_write(sc, RT2860_HT_FBK_CFG1, 0xedcb4980);
+				run_write(sc, RT2860_LG_FBK_CFG0, 0xedcba322);
+			}
+		}
+	} else if (sc->mac_ver == 0x3593) {
+		run_write(sc, RT2860_TX_SW_CFG0,
+		    4 << RT2860_DLY_PAPE_EN_SHIFT | 2);
+	} else if (sc->mac_ver >= 0x3070) {
 		/* set delay of PA_PE assertion to 1us (unit of 0.25us) */
 		run_write(sc, RT2860_TX_SW_CFG0,
 		    4 << RT2860_DLY_PAPE_EN_SHIFT);
@@ -4812,14 +6109,16 @@
 	run_write(sc, RT2860_WMM_TXOP1_CFG, 48 << 16 | 96);
 
 	/* write vendor-specific BBP values (from EEPROM) */
-	for (i = 0; i < 10; i++) {
-		if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
-			continue;
-		run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+	if (sc->mac_ver < 0x3593) {
+		for (i = 0; i < 10; i++) {
+			if (sc->bbp[i].reg == 0 || sc->bbp[i].reg == 0xff)
+				continue;
+			run_bbp_write(sc, sc->bbp[i].reg, sc->bbp[i].val);
+		}
 	}
 
 	/* select Main antenna for 1T1R devices */
-	if (sc->rf_rev == RT3070_RF_3020)
+	if (sc->rf_rev == RT3070_RF_3020 || sc->rf_rev == RT5390_RF_5370)
 		run_set_rx_antenna(sc, 0);
 
 	/* send LEDs operating mode to microcontroller */
@@ -4827,7 +6126,11 @@
 	(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED2, sc->led[1]);
 	(void)run_mcu_cmd(sc, RT2860_MCU_CMD_LED3, sc->led[2]);
 
-	if (sc->mac_ver >= 0x3070)
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_rf_init(sc);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_rf_init(sc);
+	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_rf_init(sc);
 
 	/* disable non-existing Rx chains */
@@ -4845,7 +6148,11 @@
 		bbp1 &= ~(1 << 3 | 1 << 4);
 	run_bbp_write(sc, 1, bbp1);
 
-	if (sc->mac_ver >= 0x3070)
+	if (sc->mac_ver >= 0x5390)
+		run_rt5390_rf_setup(sc);
+	else if (sc->mac_ver == 0x3593)
+		run_rt3593_rf_setup(sc);
+	else if (sc->mac_ver >= 0x3070)
 		run_rt3070_rf_setup(sc);
 
 	/* select default channel */
@@ -4921,6 +6228,24 @@
 		sc->rx_m = NULL;
 	}
 
+	/* Disable Tx/Rx DMA. */
+	if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
+		return;
+	tmp &= ~(RT2860_RX_DMA_EN | RT2860_TX_DMA_EN);
+	run_write(sc, RT2860_WPDMA_GLO_CFG, tmp);
+
+	for (ntries = 0; ntries < 100; ntries++) {
+		if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
+			return;
+		if ((tmp & (RT2860_TX_DMA_BUSY | RT2860_RX_DMA_BUSY)) == 0)
+				break;
+		run_delay(sc, 10);
+	}
+	if (ntries == 100) {
+		device_printf(sc->sc_dev, "timeout waiting for DMA engine\n");
+		return;
+	}
+
 	/* disable Tx/Rx */
 	run_read(sc, RT2860_MAC_SYS_CTRL, &tmp);
 	tmp &= ~(RT2860_MAC_RX_EN | RT2860_MAC_TX_EN);
@@ -4948,12 +6273,10 @@
 
 	for (i = 0; i != RUN_EP_QUEUES; i++)
 		run_unsetup_tx_list(sc, &sc->sc_epq[i]);
-
-	return;
 }
 
 static void
-run_delay(struct run_softc *sc, unsigned int ms)
+run_delay(struct run_softc *sc, u_int ms)
 {
 	usb_pause_mtx(mtx_owned(&sc->sc_mtx) ? 
 	    &sc->sc_mtx : NULL, USB_MS_TO_TICKS(ms));
@@ -4964,8 +6287,7 @@
 	DEVMETHOD(device_probe,		run_match),
 	DEVMETHOD(device_attach,	run_attach),
 	DEVMETHOD(device_detach,	run_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t run_driver = {
@@ -4976,7 +6298,7 @@
 
 static devclass_t run_devclass;
 
-DRIVER_MODULE(run, uhub, run_driver, run_devclass, NULL, 0);
+DRIVER_MODULE(run, uhub, run_driver, run_devclass, run_driver_loaded, NULL);
 MODULE_DEPEND(run, wlan, 1, 1, 1);
 MODULE_DEPEND(run, usb, 1, 1, 1);
 MODULE_DEPEND(run, firmware, 1, 1, 1);

Modified: stable/0.8/sys/dev/usb/wlan/if_runreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_runreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_runreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -16,715 +16,743 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/wlan/if_runreg.h 294903 2016-01-27 07:34:23Z delphij $
  */
 
 #ifndef _IF_RUNREG_H_
 #define	_IF_RUNREG_H_
 
-/* PCI registers */
-#define RT2860_PCI_CFG			0x0000
-#define RT2860_PCI_EECTRL		0x0004
-#define RT2860_PCI_MCUCTRL		0x0008
-#define RT2860_PCI_SYSCTRL		0x000c
-#define RT2860_PCIE_JTAG		0x0010
+#define	RT2860_CONFIG_NO		1
+#define	RT2860_IFACE_INDEX		0
 
-#define RT2860_CONFIG_NO		1
-#define RT2860_IFACE_INDEX		0
+#define	RT3070_OPT_14			0x0114
 
-#define RT3070_OPT_14			0x0114
-
 /* SCH/DMA registers */
-#define RT2860_INT_STATUS		0x0200
-#define RT2860_INT_MASK			0x0204
-#define RT2860_WPDMA_GLO_CFG		0x0208
-#define RT2860_WPDMA_RST_IDX		0x020c
-#define RT2860_DELAY_INT_CFG		0x0210
-#define RT2860_WMM_AIFSN_CFG		0x0214
-#define RT2860_WMM_CWMIN_CFG		0x0218
-#define RT2860_WMM_CWMAX_CFG		0x021c
-#define RT2860_WMM_TXOP0_CFG		0x0220
-#define RT2860_WMM_TXOP1_CFG		0x0224
-#define RT2860_GPIO_CTRL		0x0228
-#define RT2860_MCU_CMD_REG		0x022c
-#define RT2860_TX_BASE_PTR(qid)		(0x0230 + (qid) * 16)
-#define RT2860_TX_MAX_CNT(qid)		(0x0234 + (qid) * 16)
-#define RT2860_TX_CTX_IDX(qid)		(0x0238 + (qid) * 16)
-#define RT2860_TX_DTX_IDX(qid)		(0x023c + (qid) * 16)
-#define RT2860_RX_BASE_PTR		0x0290
-#define RT2860_RX_MAX_CNT		0x0294
-#define RT2860_RX_CALC_IDX		0x0298
-#define RT2860_FS_DRX_IDX		0x029c
-#define RT2860_USB_DMA_CFG		0x02a0	/* RT2870 only */
-#define RT2860_US_CYC_CNT		0x02a4
+#define	RT2860_INT_STATUS		0x0200
+#define	RT2860_INT_MASK			0x0204
+#define	RT2860_WPDMA_GLO_CFG		0x0208
+#define	RT2860_WPDMA_RST_IDX		0x020c
+#define	RT2860_DELAY_INT_CFG		0x0210
+#define	RT2860_WMM_AIFSN_CFG		0x0214
+#define	RT2860_WMM_CWMIN_CFG		0x0218
+#define	RT2860_WMM_CWMAX_CFG		0x021c
+#define	RT2860_WMM_TXOP0_CFG		0x0220
+#define	RT2860_WMM_TXOP1_CFG		0x0224
+#define	RT2860_GPIO_CTRL		0x0228
+#define	RT2860_MCU_CMD_REG		0x022c
+#define	RT2860_TX_BASE_PTR(qid)		(0x0230 + (qid) * 16)
+#define	RT2860_TX_MAX_CNT(qid)		(0x0234 + (qid) * 16)
+#define	RT2860_TX_CTX_IDX(qid)		(0x0238 + (qid) * 16)
+#define	RT2860_TX_DTX_IDX(qid)		(0x023c + (qid) * 16)
+#define	RT2860_RX_BASE_PTR		0x0290
+#define	RT2860_RX_MAX_CNT		0x0294
+#define	RT2860_RX_CALC_IDX		0x0298
+#define	RT2860_FS_DRX_IDX		0x029c
+#define	RT2860_USB_DMA_CFG		0x02a0	/* RT2870 only */
+#define	RT2860_US_CYC_CNT		0x02a4
 
 /* PBF registers */
-#define RT2860_SYS_CTRL			0x0400
-#define RT2860_HOST_CMD			0x0404
-#define RT2860_PBF_CFG			0x0408
-#define RT2860_MAX_PCNT			0x040c
-#define RT2860_BUF_CTRL			0x0410
-#define RT2860_MCU_INT_STA		0x0414
-#define RT2860_MCU_INT_ENA		0x0418
-#define RT2860_TXQ_IO(qid)		(0x041c + (qid) * 4)
-#define RT2860_RX0Q_IO			0x0424
-#define RT2860_BCN_OFFSET0		0x042c
-#define RT2860_BCN_OFFSET1		0x0430
-#define RT2860_TXRXQ_STA		0x0434
-#define RT2860_TXRXQ_PCNT		0x0438
-#define RT2860_PBF_DBG			0x043c
-#define RT2860_CAP_CTRL			0x0440
+#define	RT2860_SYS_CTRL			0x0400
+#define	RT2860_HOST_CMD			0x0404
+#define	RT2860_PBF_CFG			0x0408
+#define	RT2860_MAX_PCNT			0x040c
+#define	RT2860_BUF_CTRL			0x0410
+#define	RT2860_MCU_INT_STA		0x0414
+#define	RT2860_MCU_INT_ENA		0x0418
+#define	RT2860_TXQ_IO(qid)		(0x041c + (qid) * 4)
+#define	RT2860_RX0Q_IO			0x0424
+#define	RT2860_BCN_OFFSET0		0x042c
+#define	RT2860_BCN_OFFSET1		0x0430
+#define	RT2860_TXRXQ_STA		0x0434
+#define	RT2860_TXRXQ_PCNT		0x0438
+#define	RT2860_PBF_DBG			0x043c
+#define	RT2860_CAP_CTRL			0x0440
 
 /* RT3070 registers */
-#define RT3070_RF_CSR_CFG		0x0500
-#define RT3070_EFUSE_CTRL		0x0580
-#define RT3070_EFUSE_DATA0		0x0590
-#define RT3070_EFUSE_DATA1		0x0594
-#define RT3070_EFUSE_DATA2		0x0598
-#define RT3070_EFUSE_DATA3		0x059c
-#define RT3070_LDO_CFG0			0x05d4
-#define RT3070_GPIO_SWITCH		0x05dc
+#define	RT3070_RF_CSR_CFG		0x0500
+#define	RT3070_EFUSE_CTRL		0x0580
+#define	RT3070_EFUSE_DATA0		0x0590
+#define	RT3070_EFUSE_DATA1		0x0594
+#define	RT3070_EFUSE_DATA2		0x0598
+#define	RT3070_EFUSE_DATA3		0x059c
+#define	RT3070_LDO_CFG0			0x05d4
+#define	RT3070_GPIO_SWITCH		0x05dc
 
+/* RT5592 registers */
+#define	RT5592_DEBUG_INDEX		0x05e8
+
 /* MAC registers */
-#define RT2860_ASIC_VER_ID		0x1000
-#define RT2860_MAC_SYS_CTRL		0x1004
-#define RT2860_MAC_ADDR_DW0		0x1008
-#define RT2860_MAC_ADDR_DW1		0x100c
-#define RT2860_MAC_BSSID_DW0		0x1010
-#define RT2860_MAC_BSSID_DW1		0x1014
-#define RT2860_MAX_LEN_CFG		0x1018
-#define RT2860_BBP_CSR_CFG		0x101c
-#define RT2860_RF_CSR_CFG0		0x1020
-#define RT2860_RF_CSR_CFG1		0x1024
-#define RT2860_RF_CSR_CFG2		0x1028
-#define RT2860_LED_CFG			0x102c
+#define	RT2860_ASIC_VER_ID		0x1000
+#define	RT2860_MAC_SYS_CTRL		0x1004
+#define	RT2860_MAC_ADDR_DW0		0x1008
+#define	RT2860_MAC_ADDR_DW1		0x100c
+#define	RT2860_MAC_BSSID_DW0		0x1010
+#define	RT2860_MAC_BSSID_DW1		0x1014
+#define	RT2860_MAX_LEN_CFG		0x1018
+#define	RT2860_BBP_CSR_CFG		0x101c
+#define	RT2860_RF_CSR_CFG0		0x1020
+#define	RT2860_RF_CSR_CFG1		0x1024
+#define	RT2860_RF_CSR_CFG2		0x1028
+#define	RT2860_LED_CFG			0x102c
 
 /* undocumented registers */
-#define RT2860_DEBUG			0x10f4
+#define	RT2860_DEBUG			0x10f4
 
 /* MAC Timing control registers */
-#define RT2860_XIFS_TIME_CFG		0x1100
-#define RT2860_BKOFF_SLOT_CFG		0x1104
-#define RT2860_NAV_TIME_CFG		0x1108
-#define RT2860_CH_TIME_CFG		0x110c
-#define RT2860_PBF_LIFE_TIMER		0x1110
-#define RT2860_BCN_TIME_CFG		0x1114
-#define RT2860_TBTT_SYNC_CFG		0x1118
-#define RT2860_TSF_TIMER_DW0		0x111c
-#define RT2860_TSF_TIMER_DW1		0x1120
-#define RT2860_TBTT_TIMER		0x1124
-#define RT2860_INT_TIMER_CFG		0x1128
-#define RT2860_INT_TIMER_EN		0x112c
-#define RT2860_CH_IDLE_TIME		0x1130
+#define	RT2860_XIFS_TIME_CFG		0x1100
+#define	RT2860_BKOFF_SLOT_CFG		0x1104
+#define	RT2860_NAV_TIME_CFG		0x1108
+#define	RT2860_CH_TIME_CFG		0x110c
+#define	RT2860_PBF_LIFE_TIMER		0x1110
+#define	RT2860_BCN_TIME_CFG		0x1114
+#define	RT2860_TBTT_SYNC_CFG		0x1118
+#define	RT2860_TSF_TIMER_DW0		0x111c
+#define	RT2860_TSF_TIMER_DW1		0x1120
+#define	RT2860_TBTT_TIMER		0x1124
+#define	RT2860_INT_TIMER_CFG		0x1128
+#define	RT2860_INT_TIMER_EN		0x112c
+#define	RT2860_CH_IDLE_TIME		0x1130
 
 /* MAC Power Save configuration registers */
-#define RT2860_MAC_STATUS_REG		0x1200
-#define RT2860_PWR_PIN_CFG		0x1204
-#define RT2860_AUTO_WAKEUP_CFG		0x1208
+#define	RT2860_MAC_STATUS_REG		0x1200
+#define	RT2860_PWR_PIN_CFG		0x1204
+#define	RT2860_AUTO_WAKEUP_CFG		0x1208
 
 /* MAC TX configuration registers */
-#define RT2860_EDCA_AC_CFG(aci)		(0x1300 + (aci) * 4)
-#define RT2860_EDCA_TID_AC_MAP		0x1310
-#define RT2860_TX_PWR_CFG(ridx)		(0x1314 + (ridx) * 4)
-#define RT2860_TX_PIN_CFG		0x1328
-#define RT2860_TX_BAND_CFG		0x132c
-#define RT2860_TX_SW_CFG0		0x1330
-#define RT2860_TX_SW_CFG1		0x1334
-#define RT2860_TX_SW_CFG2		0x1338
-#define RT2860_TXOP_THRES_CFG		0x133c
-#define RT2860_TXOP_CTRL_CFG		0x1340
-#define RT2860_TX_RTS_CFG		0x1344
-#define RT2860_TX_TIMEOUT_CFG		0x1348
-#define RT2860_TX_RTY_CFG		0x134c
-#define RT2860_TX_LINK_CFG		0x1350
-#define RT2860_HT_FBK_CFG0		0x1354
-#define RT2860_HT_FBK_CFG1		0x1358
-#define RT2860_LG_FBK_CFG0		0x135c
-#define RT2860_LG_FBK_CFG1		0x1360
-#define RT2860_CCK_PROT_CFG		0x1364
-#define RT2860_OFDM_PROT_CFG		0x1368
-#define RT2860_MM20_PROT_CFG		0x136c
-#define RT2860_MM40_PROT_CFG		0x1370
-#define RT2860_GF20_PROT_CFG		0x1374
-#define RT2860_GF40_PROT_CFG		0x1378
-#define RT2860_EXP_CTS_TIME		0x137c
-#define RT2860_EXP_ACK_TIME		0x1380
+#define	RT2860_EDCA_AC_CFG(aci)		(0x1300 + (aci) * 4)
+#define	RT2860_EDCA_TID_AC_MAP		0x1310
+#define	RT2860_TX_PWR_CFG(ridx)		(0x1314 + (ridx) * 4)
+#define	RT2860_TX_PIN_CFG		0x1328
+#define	RT2860_TX_BAND_CFG		0x132c
+#define	RT2860_TX_SW_CFG0		0x1330
+#define	RT2860_TX_SW_CFG1		0x1334
+#define	RT2860_TX_SW_CFG2		0x1338
+#define	RT2860_TXOP_THRES_CFG		0x133c
+#define	RT2860_TXOP_CTRL_CFG		0x1340
+#define	RT2860_TX_RTS_CFG		0x1344
+#define	RT2860_TX_TIMEOUT_CFG		0x1348
+#define	RT2860_TX_RTY_CFG		0x134c
+#define	RT2860_TX_LINK_CFG		0x1350
+#define	RT2860_HT_FBK_CFG0		0x1354
+#define	RT2860_HT_FBK_CFG1		0x1358
+#define	RT2860_LG_FBK_CFG0		0x135c
+#define	RT2860_LG_FBK_CFG1		0x1360
+#define	RT2860_CCK_PROT_CFG		0x1364
+#define	RT2860_OFDM_PROT_CFG		0x1368
+#define	RT2860_MM20_PROT_CFG		0x136c
+#define	RT2860_MM40_PROT_CFG		0x1370
+#define	RT2860_GF20_PROT_CFG		0x1374
+#define	RT2860_GF40_PROT_CFG		0x1378
+#define	RT2860_EXP_CTS_TIME		0x137c
+#define	RT2860_EXP_ACK_TIME		0x1380
 
 /* MAC RX configuration registers */
-#define RT2860_RX_FILTR_CFG		0x1400
-#define RT2860_AUTO_RSP_CFG		0x1404
-#define RT2860_LEGACY_BASIC_RATE	0x1408
-#define RT2860_HT_BASIC_RATE		0x140c
-#define RT2860_HT_CTRL_CFG		0x1410
-#define RT2860_SIFS_COST_CFG		0x1414
-#define RT2860_RX_PARSER_CFG		0x1418
+#define	RT2860_RX_FILTR_CFG		0x1400
+#define	RT2860_AUTO_RSP_CFG		0x1404
+#define	RT2860_LEGACY_BASIC_RATE	0x1408
+#define	RT2860_HT_BASIC_RATE		0x140c
+#define	RT2860_HT_CTRL_CFG		0x1410
+#define	RT2860_SIFS_COST_CFG		0x1414
+#define	RT2860_RX_PARSER_CFG		0x1418
 
 /* MAC Security configuration registers */
-#define RT2860_TX_SEC_CNT0		0x1500
-#define RT2860_RX_SEC_CNT0		0x1504
-#define RT2860_CCMP_FC_MUTE		0x1508
+#define	RT2860_TX_SEC_CNT0		0x1500
+#define	RT2860_RX_SEC_CNT0		0x1504
+#define	RT2860_CCMP_FC_MUTE		0x1508
 
 /* MAC HCCA/PSMP configuration registers */
-#define RT2860_TXOP_HLDR_ADDR0		0x1600
-#define RT2860_TXOP_HLDR_ADDR1		0x1604
-#define RT2860_TXOP_HLDR_ET		0x1608
-#define RT2860_QOS_CFPOLL_RA_DW0	0x160c
-#define RT2860_QOS_CFPOLL_A1_DW1	0x1610
-#define RT2860_QOS_CFPOLL_QC		0x1614
+#define	RT2860_TXOP_HLDR_ADDR0		0x1600
+#define	RT2860_TXOP_HLDR_ADDR1		0x1604
+#define	RT2860_TXOP_HLDR_ET		0x1608
+#define	RT2860_QOS_CFPOLL_RA_DW0	0x160c
+#define	RT2860_QOS_CFPOLL_A1_DW1	0x1610
+#define	RT2860_QOS_CFPOLL_QC		0x1614
 
 /* MAC Statistics Counters */
-#define RT2860_RX_STA_CNT0		0x1700
-#define RT2860_RX_STA_CNT1		0x1704
-#define RT2860_RX_STA_CNT2		0x1708
-#define RT2860_TX_STA_CNT0		0x170c
-#define RT2860_TX_STA_CNT1		0x1710
-#define RT2860_TX_STA_CNT2		0x1714
-#define RT2860_TX_STAT_FIFO		0x1718
+#define	RT2860_RX_STA_CNT0		0x1700
+#define	RT2860_RX_STA_CNT1		0x1704
+#define	RT2860_RX_STA_CNT2		0x1708
+#define	RT2860_TX_STA_CNT0		0x170c
+#define	RT2860_TX_STA_CNT1		0x1710
+#define	RT2860_TX_STA_CNT2		0x1714
+#define	RT2860_TX_STAT_FIFO		0x1718
 
 /* RX WCID search table */
-#define RT2860_WCID_ENTRY(wcid)		(0x1800 + (wcid) * 8)
+#define	RT2860_WCID_ENTRY(wcid)		(0x1800 + (wcid) * 8)
 
-#define RT2860_FW_BASE			0x2000
-#define RT2870_FW_BASE			0x3000
+#define	RT2860_FW_BASE			0x2000
+#define	RT2870_FW_BASE			0x3000
 
 /* Pair-wise key table */
-#define RT2860_PKEY(wcid)		(0x4000 + (wcid) * 32)
+#define	RT2860_PKEY(wcid)		(0x4000 + (wcid) * 32)
 
 /* IV/EIV table */
-#define RT2860_IVEIV(wcid)		(0x6000 + (wcid) * 8)
+#define	RT2860_IVEIV(wcid)		(0x6000 + (wcid) * 8)
 
 /* WCID attribute table */
-#define RT2860_WCID_ATTR(wcid)		(0x6800 + (wcid) * 4)
+#define	RT2860_WCID_ATTR(wcid)		(0x6800 + (wcid) * 4)
 
 /* Shared Key Table */
-#define RT2860_SKEY(vap, kidx)		(0x6c00 + (vap) * 128 + (kidx) * 32)
+#define	RT2860_SKEY(vap, kidx)		(0x6c00 + (vap) * 128 + (kidx) * 32)
 
 /* Shared Key Mode */
-#define RT2860_SKEY_MODE_0_7		0x7000
-#define RT2860_SKEY_MODE_8_15		0x7004
-#define RT2860_SKEY_MODE_16_23		0x7008
-#define RT2860_SKEY_MODE_24_31		0x700c
+#define	RT2860_SKEY_MODE_0_7		0x7000
+#define	RT2860_SKEY_MODE_8_15		0x7004
+#define	RT2860_SKEY_MODE_16_23		0x7008
+#define	RT2860_SKEY_MODE_24_31		0x700c
 
 /* Shared Memory between MCU and host */
-#define RT2860_H2M_MAILBOX		0x7010
-#define RT2860_H2M_MAILBOX_CID		0x7014
-#define RT2860_H2M_MAILBOX_STATUS	0x701c
-#define RT2860_H2M_BBPAGENT		0x7028
-#define RT2860_BCN_BASE(vap)		(0x7800 + (vap) * 512)
+#define	RT2860_H2M_MAILBOX		0x7010
+#define	RT2860_H2M_MAILBOX_CID		0x7014
+#define	RT2860_H2M_MAILBOX_STATUS	0x701c
+#define	RT2860_H2M_INTSRC		0x7024
+#define	RT2860_H2M_BBPAGENT		0x7028
+#define	RT2860_BCN_BASE(vap)		(0x7800 + (vap) * 512)
 
 
 /* possible flags for register RT2860_PCI_EECTRL */
-#define RT2860_C	(1 << 0)
-#define RT2860_S	(1 << 1)
-#define RT2860_D	(1 << 2)
-#define RT2860_SHIFT_D	2
-#define RT2860_Q	(1 << 3)
-#define RT2860_SHIFT_Q	3
+#define	RT2860_C	(1 << 0)
+#define	RT2860_S	(1 << 1)
+#define	RT2860_D	(1 << 2)
+#define	RT2860_SHIFT_D	2
+#define	RT2860_Q	(1 << 3)
+#define	RT2860_SHIFT_Q	3
 
 /* possible flags for registers INT_STATUS/INT_MASK */
-#define RT2860_TX_COHERENT	(1 << 17)
-#define RT2860_RX_COHERENT	(1 << 16)
-#define RT2860_MAC_INT_4	(1 << 15)
-#define RT2860_MAC_INT_3	(1 << 14)
-#define RT2860_MAC_INT_2	(1 << 13)
-#define RT2860_MAC_INT_1	(1 << 12)
-#define RT2860_MAC_INT_0	(1 << 11)
-#define RT2860_TX_RX_COHERENT	(1 << 10)
-#define RT2860_MCU_CMD_INT	(1 <<  9)
-#define RT2860_TX_DONE_INT5	(1 <<  8)
-#define RT2860_TX_DONE_INT4	(1 <<  7)
-#define RT2860_TX_DONE_INT3	(1 <<  6)
-#define RT2860_TX_DONE_INT2	(1 <<  5)
-#define RT2860_TX_DONE_INT1	(1 <<  4)
-#define RT2860_TX_DONE_INT0	(1 <<  3)
-#define RT2860_RX_DONE_INT	(1 <<  2)
-#define RT2860_TX_DLY_INT	(1 <<  1)
-#define RT2860_RX_DLY_INT	(1 <<  0)
+#define	RT2860_TX_COHERENT	(1 << 17)
+#define	RT2860_RX_COHERENT	(1 << 16)
+#define	RT2860_MAC_INT_4	(1 << 15)
+#define	RT2860_MAC_INT_3	(1 << 14)
+#define	RT2860_MAC_INT_2	(1 << 13)
+#define	RT2860_MAC_INT_1	(1 << 12)
+#define	RT2860_MAC_INT_0	(1 << 11)
+#define	RT2860_TX_RX_COHERENT	(1 << 10)
+#define	RT2860_MCU_CMD_INT	(1 <<  9)
+#define	RT2860_TX_DONE_INT5	(1 <<  8)
+#define	RT2860_TX_DONE_INT4	(1 <<  7)
+#define	RT2860_TX_DONE_INT3	(1 <<  6)
+#define	RT2860_TX_DONE_INT2	(1 <<  5)
+#define	RT2860_TX_DONE_INT1	(1 <<  4)
+#define	RT2860_TX_DONE_INT0	(1 <<  3)
+#define	RT2860_RX_DONE_INT	(1 <<  2)
+#define	RT2860_TX_DLY_INT	(1 <<  1)
+#define	RT2860_RX_DLY_INT	(1 <<  0)
 
 /* possible flags for register WPDMA_GLO_CFG */
-#define RT2860_HDR_SEG_LEN_SHIFT	8
-#define RT2860_BIG_ENDIAN		(1 << 7)
-#define RT2860_TX_WB_DDONE		(1 << 6)
-#define RT2860_WPDMA_BT_SIZE_SHIFT	4
-#define RT2860_WPDMA_BT_SIZE16		0
-#define RT2860_WPDMA_BT_SIZE32		1
-#define RT2860_WPDMA_BT_SIZE64		2
-#define RT2860_WPDMA_BT_SIZE128		3
-#define RT2860_RX_DMA_BUSY		(1 << 3)
-#define RT2860_RX_DMA_EN		(1 << 2)
-#define RT2860_TX_DMA_BUSY		(1 << 1)
-#define RT2860_TX_DMA_EN		(1 << 0)
+#define	RT2860_HDR_SEG_LEN_SHIFT	8
+#define	RT2860_BIG_ENDIAN		(1 << 7)
+#define	RT2860_TX_WB_DDONE		(1 << 6)
+#define	RT2860_WPDMA_BT_SIZE_SHIFT	4
+#define	RT2860_WPDMA_BT_SIZE16		0
+#define	RT2860_WPDMA_BT_SIZE32		1
+#define	RT2860_WPDMA_BT_SIZE64		2
+#define	RT2860_WPDMA_BT_SIZE128		3
+#define	RT2860_RX_DMA_BUSY		(1 << 3)
+#define	RT2860_RX_DMA_EN		(1 << 2)
+#define	RT2860_TX_DMA_BUSY		(1 << 1)
+#define	RT2860_TX_DMA_EN		(1 << 0)
 
 /* possible flags for register DELAY_INT_CFG */
-#define RT2860_TXDLY_INT_EN		(1 << 31)
-#define RT2860_TXMAX_PINT_SHIFT		24
-#define RT2860_TXMAX_PTIME_SHIFT	16
-#define RT2860_RXDLY_INT_EN		(1 << 15)
-#define RT2860_RXMAX_PINT_SHIFT		8
-#define RT2860_RXMAX_PTIME_SHIFT	0
+#define	RT2860_TXDLY_INT_EN		(1U << 31)
+#define	RT2860_TXMAX_PINT_SHIFT		24
+#define	RT2860_TXMAX_PTIME_SHIFT	16
+#define	RT2860_RXDLY_INT_EN		(1 << 15)
+#define	RT2860_RXMAX_PINT_SHIFT		8
+#define	RT2860_RXMAX_PTIME_SHIFT	0
 
 /* possible flags for register GPIO_CTRL */
-#define RT2860_GPIO_D_SHIFT	8
-#define RT2860_GPIO_O_SHIFT	0
+#define	RT2860_GPIO_D_SHIFT	8
+#define	RT2860_GPIO_O_SHIFT	0
 
 /* possible flags for register USB_DMA_CFG */
-#define RT2860_USB_TX_BUSY		(1 << 31)
-#define RT2860_USB_RX_BUSY		(1 << 30)
-#define RT2860_USB_EPOUT_VLD_SHIFT	24
-#define RT2860_USB_TX_EN		(1 << 23)
-#define RT2860_USB_RX_EN		(1 << 22)
-#define RT2860_USB_RX_AGG_EN		(1 << 21)
-#define RT2860_USB_TXOP_HALT		(1 << 20)
-#define RT2860_USB_TX_CLEAR		(1 << 19)
-#define RT2860_USB_PHY_WD_EN		(1 << 16)
-#define RT2860_USB_PHY_MAN_RST		(1 << 15)
-#define RT2860_USB_RX_AGG_LMT(x)	((x) << 8)	/* in unit of 1KB */
-#define RT2860_USB_RX_AGG_TO(x)		((x) & 0xff)	/* in unit of 33ns */
+#define	RT2860_USB_TX_BUSY		(1U << 31)
+#define	RT2860_USB_RX_BUSY		(1 << 30)
+#define	RT2860_USB_EPOUT_VLD_SHIFT	24
+#define	RT2860_USB_TX_EN		(1 << 23)
+#define	RT2860_USB_RX_EN		(1 << 22)
+#define	RT2860_USB_RX_AGG_EN		(1 << 21)
+#define	RT2860_USB_TXOP_HALT		(1 << 20)
+#define	RT2860_USB_TX_CLEAR		(1 << 19)
+#define	RT2860_USB_PHY_WD_EN		(1 << 16)
+#define	RT2860_USB_PHY_MAN_RST		(1 << 15)
+#define	RT2860_USB_RX_AGG_LMT(x)	((x) << 8)	/* in unit of 1KB */
+#define	RT2860_USB_RX_AGG_TO(x)		((x) & 0xff)	/* in unit of 33ns */
 
 /* possible flags for register US_CYC_CNT */
-#define RT2860_TEST_EN		(1 << 24)
-#define RT2860_TEST_SEL_SHIFT	16
-#define RT2860_BT_MODE_EN	(1 <<  8)
-#define RT2860_US_CYC_CNT_SHIFT	0
+#define	RT2860_TEST_EN		(1 << 24)
+#define	RT2860_TEST_SEL_SHIFT	16
+#define	RT2860_BT_MODE_EN	(1 <<  8)
+#define	RT2860_US_CYC_CNT_SHIFT	0
 
 /* possible flags for register SYS_CTRL */
-#define RT2860_HST_PM_SEL	(1 << 16)
-#define RT2860_CAP_MODE		(1 << 14)
-#define RT2860_PME_OEN		(1 << 13)
-#define RT2860_CLKSELECT	(1 << 12)
-#define RT2860_PBF_CLK_EN	(1 << 11)
-#define RT2860_MAC_CLK_EN	(1 << 10)
-#define RT2860_DMA_CLK_EN	(1 <<  9)
-#define RT2860_MCU_READY	(1 <<  7)
-#define RT2860_ASY_RESET	(1 <<  4)
-#define RT2860_PBF_RESET	(1 <<  3)
-#define RT2860_MAC_RESET	(1 <<  2)
-#define RT2860_DMA_RESET	(1 <<  1)
-#define RT2860_MCU_RESET	(1 <<  0)
+#define	RT2860_HST_PM_SEL	(1 << 16)
+#define	RT2860_CAP_MODE		(1 << 14)
+#define	RT2860_PME_OEN		(1 << 13)
+#define	RT2860_CLKSELECT	(1 << 12)
+#define	RT2860_PBF_CLK_EN	(1 << 11)
+#define	RT2860_MAC_CLK_EN	(1 << 10)
+#define	RT2860_DMA_CLK_EN	(1 <<  9)
+#define	RT2860_MCU_READY	(1 <<  7)
+#define	RT2860_ASY_RESET	(1 <<  4)
+#define	RT2860_PBF_RESET	(1 <<  3)
+#define	RT2860_MAC_RESET	(1 <<  2)
+#define	RT2860_DMA_RESET	(1 <<  1)
+#define	RT2860_MCU_RESET	(1 <<  0)
 
 /* possible values for register HOST_CMD */
-#define RT2860_MCU_CMD_SLEEP	0x30
-#define RT2860_MCU_CMD_WAKEUP	0x31
-#define RT2860_MCU_CMD_LEDS	0x50
-#define RT2860_MCU_CMD_LED_RSSI	0x51
-#define RT2860_MCU_CMD_LED1	0x52
-#define RT2860_MCU_CMD_LED2	0x53
-#define RT2860_MCU_CMD_LED3	0x54
-#define RT2860_MCU_CMD_RFRESET	0x72
-#define RT2860_MCU_CMD_ANTSEL	0x73
-#define RT2860_MCU_CMD_BBP	0x80
-#define RT2860_MCU_CMD_PSLEVEL	0x83
+#define	RT2860_MCU_CMD_SLEEP	0x30
+#define	RT2860_MCU_CMD_WAKEUP	0x31
+#define	RT2860_MCU_CMD_LEDS	0x50
+#define	RT2860_MCU_CMD_LED_RSSI	0x51
+#define	RT2860_MCU_CMD_LED1	0x52
+#define	RT2860_MCU_CMD_LED2	0x53
+#define	RT2860_MCU_CMD_LED3	0x54
+#define	RT2860_MCU_CMD_RFRESET	0x72
+#define	RT2860_MCU_CMD_ANTSEL	0x73
+#define	RT2860_MCU_CMD_BBP	0x80
+#define	RT2860_MCU_CMD_PSLEVEL	0x83
 
 /* possible flags for register PBF_CFG */
-#define RT2860_TX1Q_NUM_SHIFT	21
-#define RT2860_TX2Q_NUM_SHIFT	16
-#define RT2860_NULL0_MODE	(1 << 15)
-#define RT2860_NULL1_MODE	(1 << 14)
-#define RT2860_RX_DROP_MODE	(1 << 13)
-#define RT2860_TX0Q_MANUAL	(1 << 12)
-#define RT2860_TX1Q_MANUAL	(1 << 11)
-#define RT2860_TX2Q_MANUAL	(1 << 10)
-#define RT2860_RX0Q_MANUAL	(1 <<  9)
-#define RT2860_HCCA_EN		(1 <<  8)
-#define RT2860_TX0Q_EN		(1 <<  4)
-#define RT2860_TX1Q_EN		(1 <<  3)
-#define RT2860_TX2Q_EN		(1 <<  2)
-#define RT2860_RX0Q_EN		(1 <<  1)
+#define	RT2860_TX1Q_NUM_SHIFT	21
+#define	RT2860_TX2Q_NUM_SHIFT	16
+#define	RT2860_NULL0_MODE	(1 << 15)
+#define	RT2860_NULL1_MODE	(1 << 14)
+#define	RT2860_RX_DROP_MODE	(1 << 13)
+#define	RT2860_TX0Q_MANUAL	(1 << 12)
+#define	RT2860_TX1Q_MANUAL	(1 << 11)
+#define	RT2860_TX2Q_MANUAL	(1 << 10)
+#define	RT2860_RX0Q_MANUAL	(1 <<  9)
+#define	RT2860_HCCA_EN		(1 <<  8)
+#define	RT2860_TX0Q_EN		(1 <<  4)
+#define	RT2860_TX1Q_EN		(1 <<  3)
+#define	RT2860_TX2Q_EN		(1 <<  2)
+#define	RT2860_RX0Q_EN		(1 <<  1)
 
 /* possible flags for register BUF_CTRL */
-#define RT2860_WRITE_TXQ(qid)	(1 << (11 - (qid)))
-#define RT2860_NULL0_KICK	(1 << 7)
-#define RT2860_NULL1_KICK	(1 << 6)
-#define RT2860_BUF_RESET	(1 << 5)
-#define RT2860_READ_TXQ(qid)	(1 << (3 - (qid))
-#define RT2860_READ_RX0Q	(1 << 0)
+#define	RT2860_WRITE_TXQ(qid)	(1 << (11 - (qid)))
+#define	RT2860_NULL0_KICK	(1 << 7)
+#define	RT2860_NULL1_KICK	(1 << 6)
+#define	RT2860_BUF_RESET	(1 << 5)
+#define	RT2860_READ_TXQ(qid)	(1 << (3 - (qid))
+#define	RT2860_READ_RX0Q	(1 << 0)
 
 /* possible flags for registers MCU_INT_STA/MCU_INT_ENA */
-#define RT2860_MCU_MAC_INT_8	(1 << 24)
-#define RT2860_MCU_MAC_INT_7	(1 << 23)
-#define RT2860_MCU_MAC_INT_6	(1 << 22)
-#define RT2860_MCU_MAC_INT_4	(1 << 20)
-#define RT2860_MCU_MAC_INT_3	(1 << 19)
-#define RT2860_MCU_MAC_INT_2	(1 << 18)
-#define RT2860_MCU_MAC_INT_1	(1 << 17)
-#define RT2860_MCU_MAC_INT_0	(1 << 16)
-#define RT2860_DTX0_INT		(1 << 11)
-#define RT2860_DTX1_INT		(1 << 10)
-#define RT2860_DTX2_INT		(1 <<  9)
-#define RT2860_DRX0_INT		(1 <<  8)
-#define RT2860_HCMD_INT		(1 <<  7)
-#define RT2860_N0TX_INT		(1 <<  6)
-#define RT2860_N1TX_INT		(1 <<  5)
-#define RT2860_BCNTX_INT	(1 <<  4)
-#define RT2860_MTX0_INT		(1 <<  3)
-#define RT2860_MTX1_INT		(1 <<  2)
-#define RT2860_MTX2_INT		(1 <<  1)
-#define RT2860_MRX0_INT		(1 <<  0)
+#define	RT2860_MCU_MAC_INT_8	(1 << 24)
+#define	RT2860_MCU_MAC_INT_7	(1 << 23)
+#define	RT2860_MCU_MAC_INT_6	(1 << 22)
+#define	RT2860_MCU_MAC_INT_4	(1 << 20)
+#define	RT2860_MCU_MAC_INT_3	(1 << 19)
+#define	RT2860_MCU_MAC_INT_2	(1 << 18)
+#define	RT2860_MCU_MAC_INT_1	(1 << 17)
+#define	RT2860_MCU_MAC_INT_0	(1 << 16)
+#define	RT2860_DTX0_INT		(1 << 11)
+#define	RT2860_DTX1_INT		(1 << 10)
+#define	RT2860_DTX2_INT		(1 <<  9)
+#define	RT2860_DRX0_INT		(1 <<  8)
+#define	RT2860_HCMD_INT		(1 <<  7)
+#define	RT2860_N0TX_INT		(1 <<  6)
+#define	RT2860_N1TX_INT		(1 <<  5)
+#define	RT2860_BCNTX_INT	(1 <<  4)
+#define	RT2860_MTX0_INT		(1 <<  3)
+#define	RT2860_MTX1_INT		(1 <<  2)
+#define	RT2860_MTX2_INT		(1 <<  1)
+#define	RT2860_MRX0_INT		(1 <<  0)
 
 /* possible flags for register TXRXQ_PCNT */
-#define RT2860_RX0Q_PCNT_MASK	0xff000000
-#define RT2860_TX2Q_PCNT_MASK	0x00ff0000
-#define RT2860_TX1Q_PCNT_MASK	0x0000ff00
-#define RT2860_TX0Q_PCNT_MASK	0x000000ff
+#define	RT2860_RX0Q_PCNT_MASK	0xff000000
+#define	RT2860_TX2Q_PCNT_MASK	0x00ff0000
+#define	RT2860_TX1Q_PCNT_MASK	0x0000ff00
+#define	RT2860_TX0Q_PCNT_MASK	0x000000ff
 
 /* possible flags for register CAP_CTRL */
-#define RT2860_CAP_ADC_FEQ		(1 << 31)
-#define RT2860_CAP_START		(1 << 30)
-#define RT2860_MAN_TRIG			(1 << 29)
-#define RT2860_TRIG_OFFSET_SHIFT	16
-#define RT2860_START_ADDR_SHIFT		0
+#define	RT2860_CAP_ADC_FEQ		(1U << 31)
+#define	RT2860_CAP_START		(1 << 30)
+#define	RT2860_MAN_TRIG			(1 << 29)
+#define	RT2860_TRIG_OFFSET_SHIFT	16
+#define	RT2860_START_ADDR_SHIFT		0
 
 /* possible flags for register RF_CSR_CFG */
-#define RT3070_RF_KICK		(1 << 17)
-#define RT3070_RF_WRITE		(1 << 16)
+#define	RT3070_RF_KICK		(1 << 17)
+#define	RT3070_RF_WRITE		(1 << 16)
 
 /* possible flags for register EFUSE_CTRL */
-#define RT3070_SEL_EFUSE	(1 << 31)
-#define RT3070_EFSROM_KICK	(1 << 30)
-#define RT3070_EFSROM_AIN_MASK	0x03ff0000
-#define RT3070_EFSROM_AIN_SHIFT	16
-#define RT3070_EFSROM_MODE_MASK	0x000000c0
-#define RT3070_EFUSE_AOUT_MASK	0x0000003f
+#define	RT3070_SEL_EFUSE	(1U << 31)
+#define	RT3070_EFSROM_KICK	(1 << 30)
+#define	RT3070_EFSROM_AIN_MASK	0x03ff0000
+#define	RT3070_EFSROM_AIN_SHIFT	16
+#define	RT3070_EFSROM_MODE_MASK	0x000000c0
+#define	RT3070_EFUSE_AOUT_MASK	0x0000003f
 
+/* possible flag for register DEBUG_INDEX */
+#define	RT5592_SEL_XTAL		(1U << 31)
+
 /* possible flags for register MAC_SYS_CTRL */
-#define RT2860_RX_TS_EN		(1 << 7)
-#define RT2860_WLAN_HALT_EN	(1 << 6)
-#define RT2860_PBF_LOOP_EN	(1 << 5)
-#define RT2860_CONT_TX_TEST	(1 << 4)
-#define RT2860_MAC_RX_EN	(1 << 3)
-#define RT2860_MAC_TX_EN	(1 << 2)
-#define RT2860_BBP_HRST		(1 << 1)
-#define RT2860_MAC_SRST		(1 << 0)
+#define	RT2860_RX_TS_EN		(1 << 7)
+#define	RT2860_WLAN_HALT_EN	(1 << 6)
+#define	RT2860_PBF_LOOP_EN	(1 << 5)
+#define	RT2860_CONT_TX_TEST	(1 << 4)
+#define	RT2860_MAC_RX_EN	(1 << 3)
+#define	RT2860_MAC_TX_EN	(1 << 2)
+#define	RT2860_BBP_HRST		(1 << 1)
+#define	RT2860_MAC_SRST		(1 << 0)
 
 /* possible flags for register MAC_BSSID_DW1 */
-#define RT2860_MULTI_BCN_NUM_SHIFT	18
-#define RT2860_MULTI_BSSID_MODE_SHIFT	16
+#define	RT2860_MULTI_BCN_NUM_SHIFT	18
+#define	RT2860_MULTI_BSSID_MODE_SHIFT	16
 
 /* possible flags for register MAX_LEN_CFG */
-#define RT2860_MIN_MPDU_LEN_SHIFT	16
-#define RT2860_MAX_PSDU_LEN_SHIFT	12
-#define RT2860_MAX_PSDU_LEN8K		0
-#define RT2860_MAX_PSDU_LEN16K		1
-#define RT2860_MAX_PSDU_LEN32K		2
-#define RT2860_MAX_PSDU_LEN64K		3
-#define RT2860_MAX_MPDU_LEN_SHIFT	0
+#define	RT2860_MIN_MPDU_LEN_SHIFT	16
+#define	RT2860_MAX_PSDU_LEN_SHIFT	12
+#define	RT2860_MAX_PSDU_LEN8K		0
+#define	RT2860_MAX_PSDU_LEN16K		1
+#define	RT2860_MAX_PSDU_LEN32K		2
+#define	RT2860_MAX_PSDU_LEN64K		3
+#define	RT2860_MAX_MPDU_LEN_SHIFT	0
 
 /* possible flags for registers BBP_CSR_CFG/H2M_BBPAGENT */
-#define RT2860_BBP_RW_PARALLEL		(1 << 19)
-#define RT2860_BBP_PAR_DUR_112_5	(1 << 18)
-#define RT2860_BBP_CSR_KICK		(1 << 17)
-#define RT2860_BBP_CSR_READ		(1 << 16)
-#define RT2860_BBP_ADDR_SHIFT		8
-#define RT2860_BBP_DATA_SHIFT		0
+#define	RT2860_BBP_RW_PARALLEL		(1 << 19)
+#define	RT2860_BBP_PAR_DUR_112_5	(1 << 18)
+#define	RT2860_BBP_CSR_KICK		(1 << 17)
+#define	RT2860_BBP_CSR_READ		(1 << 16)
+#define	RT2860_BBP_ADDR_SHIFT		8
+#define	RT2860_BBP_DATA_SHIFT		0
 
 /* possible flags for register RF_CSR_CFG0 */
-#define RT2860_RF_REG_CTRL		(1 << 31)
-#define RT2860_RF_LE_SEL1		(1 << 30)
-#define RT2860_RF_LE_STBY		(1 << 29)
-#define RT2860_RF_REG_WIDTH_SHIFT	24
-#define RT2860_RF_REG_0_SHIFT		0
+#define	RT2860_RF_REG_CTRL		(1U << 31)
+#define	RT2860_RF_LE_SEL1		(1 << 30)
+#define	RT2860_RF_LE_STBY		(1 << 29)
+#define	RT2860_RF_REG_WIDTH_SHIFT	24
+#define	RT2860_RF_REG_0_SHIFT		0
 
 /* possible flags for register RF_CSR_CFG1 */
-#define RT2860_RF_DUR_5		(1 << 24)
-#define RT2860_RF_REG_1_SHIFT	0
+#define	RT2860_RF_DUR_5		(1 << 24)
+#define	RT2860_RF_REG_1_SHIFT	0
 
 /* possible flags for register LED_CFG */
-#define RT2860_LED_POL			(1 << 30)
-#define RT2860_Y_LED_MODE_SHIFT		28
-#define RT2860_G_LED_MODE_SHIFT		26
-#define RT2860_R_LED_MODE_SHIFT		24
-#define RT2860_LED_MODE_OFF		0
-#define RT2860_LED_MODE_BLINK_TX	1
-#define RT2860_LED_MODE_SLOW_BLINK	2
-#define RT2860_LED_MODE_ON		3
-#define RT2860_SLOW_BLK_TIME_SHIFT	16
-#define RT2860_LED_OFF_TIME_SHIFT	8
-#define RT2860_LED_ON_TIME_SHIFT	0
+#define	RT2860_LED_POL			(1 << 30)
+#define	RT2860_Y_LED_MODE_SHIFT		28
+#define	RT2860_G_LED_MODE_SHIFT		26
+#define	RT2860_R_LED_MODE_SHIFT		24
+#define	RT2860_LED_MODE_OFF		0
+#define	RT2860_LED_MODE_BLINK_TX	1
+#define	RT2860_LED_MODE_SLOW_BLINK	2
+#define	RT2860_LED_MODE_ON		3
+#define	RT2860_SLOW_BLK_TIME_SHIFT	16
+#define	RT2860_LED_OFF_TIME_SHIFT	8
+#define	RT2860_LED_ON_TIME_SHIFT	0
 
 /* possible flags for register XIFS_TIME_CFG */
-#define RT2860_BB_RXEND_EN		(1 << 29)
-#define RT2860_EIFS_TIME_SHIFT		20
-#define RT2860_OFDM_XIFS_TIME_SHIFT	16
-#define RT2860_OFDM_SIFS_TIME_SHIFT	8
-#define RT2860_CCK_SIFS_TIME_SHIFT	0
+#define	RT2860_BB_RXEND_EN		(1 << 29)
+#define	RT2860_EIFS_TIME_SHIFT		20
+#define	RT2860_OFDM_XIFS_TIME_SHIFT	16
+#define	RT2860_OFDM_SIFS_TIME_SHIFT	8
+#define	RT2860_CCK_SIFS_TIME_SHIFT	0
 
 /* possible flags for register BKOFF_SLOT_CFG */
-#define RT2860_CC_DELAY_TIME_SHIFT	8
-#define RT2860_SLOT_TIME		0
+#define	RT2860_CC_DELAY_TIME_SHIFT	8
+#define	RT2860_SLOT_TIME		0
 
 /* possible flags for register NAV_TIME_CFG */
-#define RT2860_NAV_UPD			(1 << 31)
-#define RT2860_NAV_UPD_VAL_SHIFT	16
-#define RT2860_NAV_CLR_EN		(1 << 15)
-#define RT2860_NAV_TIMER_SHIFT		0
+#define	RT2860_NAV_UPD			(1U << 31)
+#define	RT2860_NAV_UPD_VAL_SHIFT	16
+#define	RT2860_NAV_CLR_EN		(1 << 15)
+#define	RT2860_NAV_TIMER_SHIFT		0
 
 /* possible flags for register CH_TIME_CFG */
-#define RT2860_EIFS_AS_CH_BUSY	(1 << 4)
-#define RT2860_NAV_AS_CH_BUSY	(1 << 3)
-#define RT2860_RX_AS_CH_BUSY	(1 << 2)
-#define RT2860_TX_AS_CH_BUSY	(1 << 1)
-#define RT2860_CH_STA_TIMER_EN	(1 << 0)
+#define	RT2860_EIFS_AS_CH_BUSY	(1 << 4)
+#define	RT2860_NAV_AS_CH_BUSY	(1 << 3)
+#define	RT2860_RX_AS_CH_BUSY	(1 << 2)
+#define	RT2860_TX_AS_CH_BUSY	(1 << 1)
+#define	RT2860_CH_STA_TIMER_EN	(1 << 0)
 
 /* possible values for register BCN_TIME_CFG */
-#define RT2860_TSF_INS_COMP_SHIFT	24
-#define RT2860_BCN_TX_EN		(1 << 20)
-#define RT2860_TBTT_TIMER_EN		(1 << 19)
-#define RT2860_TSF_SYNC_MODE_SHIFT	17
-#define RT2860_TSF_SYNC_MODE_DIS	0
-#define RT2860_TSF_SYNC_MODE_STA	1
-#define RT2860_TSF_SYNC_MODE_IBSS	2
-#define RT2860_TSF_SYNC_MODE_HOSTAP	3
-#define RT2860_TSF_TIMER_EN		(1 << 16)
-#define RT2860_BCN_INTVAL_SHIFT		0
+#define	RT2860_TSF_INS_COMP_SHIFT	24
+#define	RT2860_BCN_TX_EN		(1 << 20)
+#define	RT2860_TBTT_TIMER_EN		(1 << 19)
+#define	RT2860_TSF_SYNC_MODE_SHIFT	17
+#define	RT2860_TSF_SYNC_MODE_DIS	0
+#define	RT2860_TSF_SYNC_MODE_STA	1
+#define	RT2860_TSF_SYNC_MODE_IBSS	2
+#define	RT2860_TSF_SYNC_MODE_HOSTAP	3
+#define	RT2860_TSF_TIMER_EN		(1 << 16)
+#define	RT2860_BCN_INTVAL_SHIFT		0
 
 /* possible flags for register TBTT_SYNC_CFG */
-#define RT2860_BCN_CWMIN_SHIFT		20
-#define RT2860_BCN_AIFSN_SHIFT		16
-#define RT2860_BCN_EXP_WIN_SHIFT	8
-#define RT2860_TBTT_ADJUST_SHIFT	0
+#define	RT2860_BCN_CWMIN_SHIFT		20
+#define	RT2860_BCN_AIFSN_SHIFT		16
+#define	RT2860_BCN_EXP_WIN_SHIFT	8
+#define	RT2860_TBTT_ADJUST_SHIFT	0
 
 /* possible flags for register INT_TIMER_CFG */
-#define RT2860_GP_TIMER_SHIFT		16
-#define RT2860_PRE_TBTT_TIMER_SHIFT	0
+#define	RT2860_GP_TIMER_SHIFT		16
+#define	RT2860_PRE_TBTT_TIMER_SHIFT	0
 
 /* possible flags for register INT_TIMER_EN */
-#define RT2860_GP_TIMER_EN	(1 << 1)
-#define RT2860_PRE_TBTT_INT_EN	(1 << 0)
+#define	RT2860_GP_TIMER_EN	(1 << 1)
+#define	RT2860_PRE_TBTT_INT_EN	(1 << 0)
 
 /* possible flags for register MAC_STATUS_REG */
-#define RT2860_RX_STATUS_BUSY	(1 << 1)
-#define RT2860_TX_STATUS_BUSY	(1 << 0)
+#define	RT2860_RX_STATUS_BUSY	(1 << 1)
+#define	RT2860_TX_STATUS_BUSY	(1 << 0)
 
 /* possible flags for register PWR_PIN_CFG */
-#define RT2860_IO_ADDA_PD	(1 << 3)
-#define RT2860_IO_PLL_PD	(1 << 2)
-#define RT2860_IO_RA_PE		(1 << 1)
-#define RT2860_IO_RF_PE		(1 << 0)
+#define	RT2860_IO_ADDA_PD	(1 << 3)
+#define	RT2860_IO_PLL_PD	(1 << 2)
+#define	RT2860_IO_RA_PE		(1 << 1)
+#define	RT2860_IO_RF_PE		(1 << 0)
 
 /* possible flags for register AUTO_WAKEUP_CFG */
-#define RT2860_AUTO_WAKEUP_EN		(1 << 15)
-#define RT2860_SLEEP_TBTT_NUM_SHIFT	8
-#define RT2860_WAKEUP_LEAD_TIME_SHIFT	0
+#define	RT2860_AUTO_WAKEUP_EN		(1 << 15)
+#define	RT2860_SLEEP_TBTT_NUM_SHIFT	8
+#define	RT2860_WAKEUP_LEAD_TIME_SHIFT	0
 
 /* possible flags for register TX_PIN_CFG */
-#define RT2860_TRSW_POL		(1 << 19)
-#define RT2860_TRSW_EN		(1 << 18)
-#define RT2860_RFTR_POL		(1 << 17)
-#define RT2860_RFTR_EN		(1 << 16)
-#define RT2860_LNA_PE_G1_POL	(1 << 15)
-#define RT2860_LNA_PE_A1_POL	(1 << 14)
-#define RT2860_LNA_PE_G0_POL	(1 << 13)
-#define RT2860_LNA_PE_A0_POL	(1 << 12)
-#define RT2860_LNA_PE_G1_EN	(1 << 11)
-#define RT2860_LNA_PE_A1_EN	(1 << 10)
-#define RT2860_LNA_PE1_EN	(RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN)
-#define RT2860_LNA_PE_G0_EN	(1 <<  9)
-#define RT2860_LNA_PE_A0_EN	(1 <<  8)
-#define RT2860_LNA_PE0_EN	(RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN)
-#define RT2860_PA_PE_G1_POL	(1 <<  7)
-#define RT2860_PA_PE_A1_POL	(1 <<  6)
-#define RT2860_PA_PE_G0_POL	(1 <<  5)
-#define RT2860_PA_PE_A0_POL	(1 <<  4)
-#define RT2860_PA_PE_G1_EN	(1 <<  3)
-#define RT2860_PA_PE_A1_EN	(1 <<  2)
-#define RT2860_PA_PE_G0_EN	(1 <<  1)
-#define RT2860_PA_PE_A0_EN	(1 <<  0)
+#define	RT2860_TRSW_POL		(1 << 19)
+#define	RT2860_TRSW_EN		(1 << 18)
+#define	RT2860_RFTR_POL		(1 << 17)
+#define	RT2860_RFTR_EN		(1 << 16)
+#define	RT2860_LNA_PE_G1_POL	(1 << 15)
+#define	RT2860_LNA_PE_A1_POL	(1 << 14)
+#define	RT2860_LNA_PE_G0_POL	(1 << 13)
+#define	RT2860_LNA_PE_A0_POL	(1 << 12)
+#define	RT2860_LNA_PE_G1_EN	(1 << 11)
+#define	RT2860_LNA_PE_A1_EN	(1 << 10)
+#define	RT2860_LNA_PE1_EN	(RT2860_LNA_PE_A1_EN | RT2860_LNA_PE_G1_EN)
+#define	RT2860_LNA_PE_G0_EN	(1 <<  9)
+#define	RT2860_LNA_PE_A0_EN	(1 <<  8)
+#define	RT2860_LNA_PE0_EN	(RT2860_LNA_PE_A0_EN | RT2860_LNA_PE_G0_EN)
+#define	RT2860_PA_PE_G1_POL	(1 <<  7)
+#define	RT2860_PA_PE_A1_POL	(1 <<  6)
+#define	RT2860_PA_PE_G0_POL	(1 <<  5)
+#define	RT2860_PA_PE_A0_POL	(1 <<  4)
+#define	RT2860_PA_PE_G1_EN	(1 <<  3)
+#define	RT2860_PA_PE_A1_EN	(1 <<  2)
+#define	RT2860_PA_PE_G0_EN	(1 <<  1)
+#define	RT2860_PA_PE_A0_EN	(1 <<  0)
 
 /* possible flags for register TX_BAND_CFG */
-#define RT2860_5G_BAND_SEL_N	(1 << 2)
-#define RT2860_5G_BAND_SEL_P	(1 << 1)
-#define RT2860_TX_BAND_SEL	(1 << 0)
+#define	RT2860_5G_BAND_SEL_N	(1 << 2)
+#define	RT2860_5G_BAND_SEL_P	(1 << 1)
+#define	RT2860_TX_BAND_SEL	(1 << 0)
 
 /* possible flags for register TX_SW_CFG0 */
-#define RT2860_DLY_RFTR_EN_SHIFT	24
-#define RT2860_DLY_TRSW_EN_SHIFT	16
-#define RT2860_DLY_PAPE_EN_SHIFT	8
-#define RT2860_DLY_TXPE_EN_SHIFT	0
+#define	RT2860_DLY_RFTR_EN_SHIFT	24
+#define	RT2860_DLY_TRSW_EN_SHIFT	16
+#define	RT2860_DLY_PAPE_EN_SHIFT	8
+#define	RT2860_DLY_TXPE_EN_SHIFT	0
 
 /* possible flags for register TX_SW_CFG1 */
-#define RT2860_DLY_RFTR_DIS_SHIFT	16
-#define RT2860_DLY_TRSW_DIS_SHIFT	8
-#define RT2860_DLY_PAPE_DIS SHIFT	0
+#define	RT2860_DLY_RFTR_DIS_SHIFT	16
+#define	RT2860_DLY_TRSW_DIS_SHIFT	8
+#define	RT2860_DLY_PAPE_DIS SHIFT	0
 
 /* possible flags for register TX_SW_CFG2 */
-#define RT2860_DLY_LNA_EN_SHIFT		24
-#define RT2860_DLY_LNA_DIS_SHIFT	16
-#define RT2860_DLY_DAC_EN_SHIFT		8
-#define RT2860_DLY_DAC_DIS_SHIFT	0
+#define	RT2860_DLY_LNA_EN_SHIFT		24
+#define	RT2860_DLY_LNA_DIS_SHIFT	16
+#define	RT2860_DLY_DAC_EN_SHIFT		8
+#define	RT2860_DLY_DAC_DIS_SHIFT	0
 
 /* possible flags for register TXOP_THRES_CFG */
-#define RT2860_TXOP_REM_THRES_SHIFT	24
-#define RT2860_CF_END_THRES_SHIFT	16
-#define RT2860_RDG_IN_THRES		8
-#define RT2860_RDG_OUT_THRES		0
+#define	RT2860_TXOP_REM_THRES_SHIFT	24
+#define	RT2860_CF_END_THRES_SHIFT	16
+#define	RT2860_RDG_IN_THRES		8
+#define	RT2860_RDG_OUT_THRES		0
 
 /* possible flags for register TXOP_CTRL_CFG */
-#define RT2860_EXT_CW_MIN_SHIFT		16
-#define RT2860_EXT_CCA_DLY_SHIFT	8
-#define RT2860_EXT_CCA_EN		(1 << 7)
-#define RT2860_LSIG_TXOP_EN		(1 << 6)
-#define RT2860_TXOP_TRUN_EN_MIMOPS	(1 << 4)
-#define RT2860_TXOP_TRUN_EN_TXOP	(1 << 3)
-#define RT2860_TXOP_TRUN_EN_RATE	(1 << 2)
-#define RT2860_TXOP_TRUN_EN_AC		(1 << 1)
-#define RT2860_TXOP_TRUN_EN_TIMEOUT	(1 << 0)
+#define	RT2860_EXT_CW_MIN_SHIFT		16
+#define	RT2860_EXT_CCA_DLY_SHIFT	8
+#define	RT2860_EXT_CCA_EN		(1 << 7)
+#define	RT2860_LSIG_TXOP_EN		(1 << 6)
+#define	RT2860_TXOP_TRUN_EN_MIMOPS	(1 << 4)
+#define	RT2860_TXOP_TRUN_EN_TXOP	(1 << 3)
+#define	RT2860_TXOP_TRUN_EN_RATE	(1 << 2)
+#define	RT2860_TXOP_TRUN_EN_AC		(1 << 1)
+#define	RT2860_TXOP_TRUN_EN_TIMEOUT	(1 << 0)
 
 /* possible flags for register TX_RTS_CFG */
-#define RT2860_RTS_FBK_EN		(1 << 24)
-#define RT2860_RTS_THRES_SHIFT		8
-#define RT2860_RTS_RTY_LIMIT_SHIFT	0
+#define	RT2860_RTS_FBK_EN		(1 << 24)
+#define	RT2860_RTS_THRES_SHIFT		8
+#define	RT2860_RTS_RTY_LIMIT_SHIFT	0
 
 /* possible flags for register TX_TIMEOUT_CFG */
-#define RT2860_TXOP_TIMEOUT_SHIFT	16
-#define RT2860_RX_ACK_TIMEOUT_SHIFT	8
-#define RT2860_MPDU_LIFE_TIME_SHIFT	4
+#define	RT2860_TXOP_TIMEOUT_SHIFT	16
+#define	RT2860_RX_ACK_TIMEOUT_SHIFT	8
+#define	RT2860_MPDU_LIFE_TIME_SHIFT	4
 
 /* possible flags for register TX_RTY_CFG */
-#define RT2860_TX_AUTOFB_EN		(1 << 30)
-#define RT2860_AGG_RTY_MODE_TIMER	(1 << 29)
-#define RT2860_NAG_RTY_MODE_TIMER	(1 << 28)
-#define RT2860_LONG_RTY_THRES_SHIFT	16
-#define RT2860_LONG_RTY_LIMIT_SHIFT	8
-#define RT2860_SHORT_RTY_LIMIT_SHIFT	0
+#define	RT2860_TX_AUTOFB_EN		(1 << 30)
+#define	RT2860_AGG_RTY_MODE_TIMER	(1 << 29)
+#define	RT2860_NAG_RTY_MODE_TIMER	(1 << 28)
+#define	RT2860_LONG_RTY_THRES_SHIFT	16
+#define	RT2860_LONG_RTY_LIMIT_SHIFT	8
+#define	RT2860_SHORT_RTY_LIMIT_SHIFT	0
 
 /* possible flags for register TX_LINK_CFG */
-#define RT2860_REMOTE_MFS_SHIFT		24
-#define RT2860_REMOTE_MFB_SHIFT		16
-#define RT2860_TX_CFACK_EN		(1 << 12)
-#define RT2860_TX_RDG_EN		(1 << 11)
-#define RT2860_TX_MRQ_EN		(1 << 10)
-#define RT2860_REMOTE_UMFS_EN		(1 <<  9)
-#define RT2860_TX_MFB_EN		(1 <<  8)
-#define RT2860_REMOTE_MFB_LT_SHIFT	0
+#define	RT2860_REMOTE_MFS_SHIFT		24
+#define	RT2860_REMOTE_MFB_SHIFT		16
+#define	RT2860_TX_CFACK_EN		(1 << 12)
+#define	RT2860_TX_RDG_EN		(1 << 11)
+#define	RT2860_TX_MRQ_EN		(1 << 10)
+#define	RT2860_REMOTE_UMFS_EN		(1 <<  9)
+#define	RT2860_TX_MFB_EN		(1 <<  8)
+#define	RT2860_REMOTE_MFB_LT_SHIFT	0
 
 /* possible flags for registers *_PROT_CFG */
-#define RT2860_RTSTH_EN			(1 << 26)
-#define RT2860_TXOP_ALLOW_GF40		(1 << 25)
-#define RT2860_TXOP_ALLOW_GF20		(1 << 24)
-#define RT2860_TXOP_ALLOW_MM40		(1 << 23)
-#define RT2860_TXOP_ALLOW_MM20		(1 << 22)
-#define RT2860_TXOP_ALLOW_OFDM		(1 << 21)
-#define RT2860_TXOP_ALLOW_CCK		(1 << 20)
-#define RT2860_TXOP_ALLOW_ALL		(0x3f << 20)
-#define RT2860_PROT_NAV_SHORT		(1 << 18)
-#define RT2860_PROT_NAV_LONG		(2 << 18)
-#define RT2860_PROT_CTRL_RTS_CTS	(1 << 16)
-#define RT2860_PROT_CTRL_CTS		(2 << 16)
+#define	RT2860_RTSTH_EN			(1 << 26)
+#define	RT2860_TXOP_ALLOW_GF40		(1 << 25)
+#define	RT2860_TXOP_ALLOW_GF20		(1 << 24)
+#define	RT2860_TXOP_ALLOW_MM40		(1 << 23)
+#define	RT2860_TXOP_ALLOW_MM20		(1 << 22)
+#define	RT2860_TXOP_ALLOW_OFDM		(1 << 21)
+#define	RT2860_TXOP_ALLOW_CCK		(1 << 20)
+#define	RT2860_TXOP_ALLOW_ALL		(0x3f << 20)
+#define	RT2860_PROT_NAV_SHORT		(1 << 18)
+#define	RT2860_PROT_NAV_LONG		(2 << 18)
+#define	RT2860_PROT_CTRL_RTS_CTS	(1 << 16)
+#define	RT2860_PROT_CTRL_CTS		(2 << 16)
 
 /* possible flags for registers EXP_{CTS,ACK}_TIME */
-#define RT2860_EXP_OFDM_TIME_SHIFT	16
-#define RT2860_EXP_CCK_TIME_SHIFT	0
+#define	RT2860_EXP_OFDM_TIME_SHIFT	16
+#define	RT2860_EXP_CCK_TIME_SHIFT	0
 
 /* possible flags for register RX_FILTR_CFG */
-#define RT2860_DROP_CTRL_RSV	(1 << 16)
-#define RT2860_DROP_BAR		(1 << 15)
-#define RT2860_DROP_BA		(1 << 14)
-#define RT2860_DROP_PSPOLL	(1 << 13)
-#define RT2860_DROP_RTS		(1 << 12)
-#define RT2860_DROP_CTS		(1 << 11)
-#define RT2860_DROP_ACK		(1 << 10)
-#define RT2860_DROP_CFEND	(1 <<  9)
-#define RT2860_DROP_CFACK	(1 <<  8)
-#define RT2860_DROP_DUPL	(1 <<  7)
-#define RT2860_DROP_BC		(1 <<  6)
-#define RT2860_DROP_MC		(1 <<  5)
-#define RT2860_DROP_VER_ERR	(1 <<  4)
-#define RT2860_DROP_NOT_MYBSS	(1 <<  3)
-#define RT2860_DROP_UC_NOME	(1 <<  2)
-#define RT2860_DROP_PHY_ERR	(1 <<  1)
-#define RT2860_DROP_CRC_ERR	(1 <<  0)
+#define	RT2860_DROP_CTRL_RSV	(1 << 16)
+#define	RT2860_DROP_BAR		(1 << 15)
+#define	RT2860_DROP_BA		(1 << 14)
+#define	RT2860_DROP_PSPOLL	(1 << 13)
+#define	RT2860_DROP_RTS		(1 << 12)
+#define	RT2860_DROP_CTS		(1 << 11)
+#define	RT2860_DROP_ACK		(1 << 10)
+#define	RT2860_DROP_CFEND	(1 <<  9)
+#define	RT2860_DROP_CFACK	(1 <<  8)
+#define	RT2860_DROP_DUPL	(1 <<  7)
+#define	RT2860_DROP_BC		(1 <<  6)
+#define	RT2860_DROP_MC		(1 <<  5)
+#define	RT2860_DROP_VER_ERR	(1 <<  4)
+#define	RT2860_DROP_NOT_MYBSS	(1 <<  3)
+#define	RT2860_DROP_UC_NOME	(1 <<  2)
+#define	RT2860_DROP_PHY_ERR	(1 <<  1)
+#define	RT2860_DROP_CRC_ERR	(1 <<  0)
 
 /* possible flags for register AUTO_RSP_CFG */
-#define RT2860_CTRL_PWR_BIT	(1 << 7)
-#define RT2860_BAC_ACK_POLICY	(1 << 6)
-#define RT2860_CCK_SHORT_EN	(1 << 4)
-#define RT2860_CTS_40M_REF_EN	(1 << 3)
-#define RT2860_CTS_40M_MODE_EN	(1 << 2)
-#define RT2860_BAC_ACKPOLICY_EN	(1 << 1)
-#define RT2860_AUTO_RSP_EN	(1 << 0)
+#define	RT2860_CTRL_PWR_BIT	(1 << 7)
+#define	RT2860_BAC_ACK_POLICY	(1 << 6)
+#define	RT2860_CCK_SHORT_EN	(1 << 4)
+#define	RT2860_CTS_40M_REF_EN	(1 << 3)
+#define	RT2860_CTS_40M_MODE_EN	(1 << 2)
+#define	RT2860_BAC_ACKPOLICY_EN	(1 << 1)
+#define	RT2860_AUTO_RSP_EN	(1 << 0)
 
 /* possible flags for register SIFS_COST_CFG */
-#define RT2860_OFDM_SIFS_COST_SHIFT	8
-#define RT2860_CCK_SIFS_COST_SHIFT	0
+#define	RT2860_OFDM_SIFS_COST_SHIFT	8
+#define	RT2860_CCK_SIFS_COST_SHIFT	0
 
 /* possible flags for register TXOP_HLDR_ET */
-#define RT2860_TXOP_ETM1_EN		(1 << 25)
-#define RT2860_TXOP_ETM0_EN		(1 << 24)
-#define RT2860_TXOP_ETM_THRES_SHIFT	16
-#define RT2860_TXOP_ETO_EN		(1 <<  8)
-#define RT2860_TXOP_ETO_THRES_SHIFT	1
-#define RT2860_PER_RX_RST_EN		(1 <<  0)
+#define	RT2860_TXOP_ETM1_EN		(1 << 25)
+#define	RT2860_TXOP_ETM0_EN		(1 << 24)
+#define	RT2860_TXOP_ETM_THRES_SHIFT	16
+#define	RT2860_TXOP_ETO_EN		(1 <<  8)
+#define	RT2860_TXOP_ETO_THRES_SHIFT	1
+#define	RT2860_PER_RX_RST_EN		(1 <<  0)
 
 /* possible flags for register TX_STAT_FIFO */
-#define RT2860_TXQ_MCS_SHIFT	16
-#define RT2860_TXQ_WCID_SHIFT	8
-#define RT2860_TXQ_ACKREQ	(1 << 7)
-#define RT2860_TXQ_AGG		(1 << 6)
-#define RT2860_TXQ_OK		(1 << 5)
-#define RT2860_TXQ_PID_SHIFT	1
-#define RT2860_TXQ_VLD		(1 << 0)
+#define	RT2860_TXQ_MCS_SHIFT	16
+#define	RT2860_TXQ_WCID_SHIFT	8
+#define	RT2860_TXQ_ACKREQ	(1 << 7)
+#define	RT2860_TXQ_AGG		(1 << 6)
+#define	RT2860_TXQ_OK		(1 << 5)
+#define	RT2860_TXQ_PID_SHIFT	1
+#define	RT2860_TXQ_VLD		(1 << 0)
 
 /* possible flags for register WCID_ATTR */
-#define RT2860_MODE_NOSEC	0
-#define RT2860_MODE_WEP40	1
-#define RT2860_MODE_WEP104	2
-#define RT2860_MODE_TKIP	3
-#define RT2860_MODE_AES_CCMP	4
-#define RT2860_MODE_CKIP40	5
-#define RT2860_MODE_CKIP104	6
-#define RT2860_MODE_CKIP128	7
-#define RT2860_RX_PKEY_EN	(1 << 0)
+#define	RT2860_MODE_NOSEC	0
+#define	RT2860_MODE_WEP40	1
+#define	RT2860_MODE_WEP104	2
+#define	RT2860_MODE_TKIP	3
+#define	RT2860_MODE_AES_CCMP	4
+#define	RT2860_MODE_CKIP40	5
+#define	RT2860_MODE_CKIP104	6
+#define	RT2860_MODE_CKIP128	7
+#define	RT2860_RX_PKEY_EN	(1 << 0)
 
 /* possible flags for register H2M_MAILBOX */
-#define RT2860_H2M_BUSY		(1 << 24)
-#define RT2860_TOKEN_NO_INTR	0xff
+#define	RT2860_H2M_BUSY		(1 << 24)
+#define	RT2860_TOKEN_NO_INTR	0xff
 
-
 /* possible flags for MCU command RT2860_MCU_CMD_LEDS */
-#define RT2860_LED_RADIO	(1 << 13)
-#define RT2860_LED_LINK_2GHZ	(1 << 14)
-#define RT2860_LED_LINK_5GHZ	(1 << 15)
+#define	RT2860_LED_RADIO	(1 << 13)
+#define	RT2860_LED_LINK_2GHZ	(1 << 14)
+#define	RT2860_LED_LINK_5GHZ	(1 << 15)
 
-
 /* possible flags for RT3020 RF register 1 */
-#define RT3070_RF_BLOCK	(1 << 0)
-#define RT3070_RX0_PD	(1 << 2)
-#define RT3070_TX0_PD	(1 << 3)
-#define RT3070_RX1_PD	(1 << 4)
-#define RT3070_TX1_PD	(1 << 5)
+#define	RT3070_RF_BLOCK	(1 << 0)
+#define	RT3070_PLL_PD	(1 << 1)
+#define	RT3070_RX0_PD	(1 << 2)
+#define	RT3070_TX0_PD	(1 << 3)
+#define	RT3070_RX1_PD	(1 << 4)
+#define	RT3070_TX1_PD	(1 << 5)
+#define	RT3070_RX2_PD	(1 << 6)
+#define	RT3070_TX2_PD	(1 << 7)
 
 /* possible flags for RT3020 RF register 15 */
-#define RT3070_TX_LO2	(1 << 3)
+#define	RT3070_TX_LO2	(1 << 3)
 
 /* possible flags for RT3020 RF register 17 */
-#define RT3070_TX_LO1	(1 << 3)
+#define	RT3070_TX_LO1	(1 << 3)
 
 /* possible flags for RT3020 RF register 20 */
-#define RT3070_RX_LO1	(1 << 3)
+#define	RT3070_RX_LO1	(1 << 3)
 
 /* possible flags for RT3020 RF register 21 */
-#define RT3070_RX_LO2	(1 << 3)
+#define	RT3070_RX_LO2	(1 << 3)
 
+/* possible flags for RT3053 RF register 18 */
+#define	RT3593_AUTOTUNE_BYPASS	(1 << 6)
 
+/* possible flags for RT3053 RF register 50 */
+#define	RT3593_TX_LO2	(1 << 4)
+
+/* possible flags for RT3053 RF register 51 */
+#define	RT3593_TX_LO1	(1 << 4)
+
+/* Possible flags for RT5390 RF register 2. */
+#define	RT5390_RESCAL	(1 << 7)
+
+/* Possible flags for RT5390 RF register 3. */
+#define	RT5390_VCOCAL	(1 << 7)
+
+/* Possible flags for RT5390 RF register 38. */
+#define	RT5390_RX_LO1	(1 << 5)
+
+/* Possible flags for RT5390 RF register 39. */
+#define	RT5390_RX_LO2	(1 << 7)
+
+/* Possible flags for RT5390 BBP register 4. */
+#define	RT5390_MAC_IF_CTRL	(1 << 6)
+
+/* Possible flags for RT5390 BBP register 105. */
+#define	RT5390_MLD			(1 << 2)
+#define	RT5390_EN_SIG_MODULATION	(1 << 3)
+
 /* RT2860 TX descriptor */
 struct rt2860_txd {
 	uint32_t	sdp0;		/* Segment Data Pointer 0 */
 	uint16_t	sdl1;		/* Segment Data Length 1 */
-#define RT2860_TX_BURST	(1 << 15)
-#define RT2860_TX_LS1	(1 << 14)	/* SDP1 is the last segment */
+#define	RT2860_TX_BURST	(1 << 15)
+#define	RT2860_TX_LS1	(1 << 14)	/* SDP1 is the last segment */
 
 	uint16_t	sdl0;		/* Segment Data Length 0 */
-#define RT2860_TX_DDONE	(1 << 15)
-#define RT2860_TX_LS0	(1 << 14)	/* SDP0 is the last segment */
+#define	RT2860_TX_DDONE	(1 << 15)
+#define	RT2860_TX_LS0	(1 << 14)	/* SDP0 is the last segment */
 
 	uint32_t	sdp1;		/* Segment Data Pointer 1 */
 	uint8_t		reserved[3];
 	uint8_t		flags;
-#define RT2860_TX_QSEL_SHIFT	1
-#define RT2860_TX_QSEL_MGMT	(0 << 1)
-#define RT2860_TX_QSEL_HCCA	(1 << 1)
-#define RT2860_TX_QSEL_EDCA	(2 << 1)
-#define RT2860_TX_WIV		(1 << 0)
+#define	RT2860_TX_QSEL_SHIFT	1
+#define	RT2860_TX_QSEL_MGMT	(0 << 1)
+#define	RT2860_TX_QSEL_HCCA	(1 << 1)
+#define	RT2860_TX_QSEL_EDCA	(2 << 1)
+#define	RT2860_TX_WIV		(1 << 0)
 } __packed;
 
 /* RT2870 TX descriptor */
@@ -737,38 +765,38 @@
 /* TX Wireless Information */
 struct rt2860_txwi {
 	uint8_t		flags;
-#define RT2860_TX_MPDU_DSITY_SHIFT	5
-#define RT2860_TX_AMPDU			(1 << 4)
-#define RT2860_TX_TS			(1 << 3)
-#define RT2860_TX_CFACK			(1 << 2)
-#define RT2860_TX_MMPS			(1 << 1)
-#define RT2860_TX_FRAG			(1 << 0)
+#define	RT2860_TX_MPDU_DSITY_SHIFT	5
+#define	RT2860_TX_AMPDU			(1 << 4)
+#define	RT2860_TX_TS			(1 << 3)
+#define	RT2860_TX_CFACK			(1 << 2)
+#define	RT2860_TX_MMPS			(1 << 1)
+#define	RT2860_TX_FRAG			(1 << 0)
 
 	uint8_t		txop;
-#define RT2860_TX_TXOP_HT	0
-#define RT2860_TX_TXOP_PIFS	1
-#define RT2860_TX_TXOP_SIFS	2
-#define RT2860_TX_TXOP_BACKOFF	3
+#define	RT2860_TX_TXOP_HT	0
+#define	RT2860_TX_TXOP_PIFS	1
+#define	RT2860_TX_TXOP_SIFS	2
+#define	RT2860_TX_TXOP_BACKOFF	3
 
 	uint16_t	phy;
-#define RT2860_PHY_MODE		0xc000
-#define RT2860_PHY_CCK		(0 << 14)
-#define RT2860_PHY_OFDM		(1 << 14)
-#define RT2860_PHY_HT		(2 << 14)
-#define RT2860_PHY_HT_GF	(3 << 14)
-#define RT2860_PHY_SGI		(1 << 8)
-#define RT2860_PHY_BW40		(1 << 7)
-#define RT2860_PHY_MCS		0x7f
-#define RT2860_PHY_SHPRE	(1 << 3)
+#define	RT2860_PHY_MODE		0xc000
+#define	RT2860_PHY_CCK		(0 << 14)
+#define	RT2860_PHY_OFDM		(1 << 14)
+#define	RT2860_PHY_HT		(2 << 14)
+#define	RT2860_PHY_HT_GF	(3 << 14)
+#define	RT2860_PHY_SGI		(1 << 8)
+#define	RT2860_PHY_BW40		(1 << 7)
+#define	RT2860_PHY_MCS		0x7f
+#define	RT2860_PHY_SHPRE	(1 << 3)
 
 	uint8_t		xflags;
-#define RT2860_TX_BAWINSIZE_SHIFT	2
-#define RT2860_TX_NSEQ			(1 << 1)
-#define RT2860_TX_ACK			(1 << 0)
+#define	RT2860_TX_BAWINSIZE_SHIFT	2
+#define	RT2860_TX_NSEQ			(1 << 1)
+#define	RT2860_TX_ACK			(1 << 0)
 
 	uint8_t		wcid;	/* Wireless Client ID */
 	uint16_t	len;
-#define RT2860_TX_PID_SHIFT	12
+#define	RT2860_TX_PID_SHIFT	12
 
 	uint32_t	iv;
 	uint32_t	eiv;
@@ -779,28 +807,28 @@
 	uint32_t	sdp0;
 	uint16_t	sdl1;	/* unused */
 	uint16_t	sdl0;
-#define RT2860_RX_DDONE	(1 << 15)
-#define RT2860_RX_LS0	(1 << 14)
+#define	RT2860_RX_DDONE	(1 << 15)
+#define	RT2860_RX_LS0	(1 << 14)
 
 	uint32_t	sdp1;	/* unused */
 	uint32_t	flags;
-#define RT2860_RX_DEC		(1 << 16)
-#define RT2860_RX_AMPDU		(1 << 15)
-#define RT2860_RX_L2PAD		(1 << 14)
-#define RT2860_RX_RSSI		(1 << 13)
-#define RT2860_RX_HTC		(1 << 12)
-#define RT2860_RX_AMSDU		(1 << 11)
-#define RT2860_RX_MICERR	(1 << 10)
-#define RT2860_RX_ICVERR	(1 <<  9)
-#define RT2860_RX_CRCERR	(1 <<  8)
-#define RT2860_RX_MYBSS		(1 <<  7)
-#define RT2860_RX_BC		(1 <<  6)
-#define RT2860_RX_MC		(1 <<  5)
-#define RT2860_RX_UC2ME		(1 <<  4)
-#define RT2860_RX_FRAG		(1 <<  3)
-#define RT2860_RX_NULL		(1 <<  2)
-#define RT2860_RX_DATA		(1 <<  1)
-#define RT2860_RX_BA		(1 <<  0)
+#define	RT2860_RX_DEC		(1 << 16)
+#define	RT2860_RX_AMPDU		(1 << 15)
+#define	RT2860_RX_L2PAD		(1 << 14)
+#define	RT2860_RX_RSSI		(1 << 13)
+#define	RT2860_RX_HTC		(1 << 12)
+#define	RT2860_RX_AMSDU		(1 << 11)
+#define	RT2860_RX_MICERR	(1 << 10)
+#define	RT2860_RX_ICVERR	(1 <<  9)
+#define	RT2860_RX_CRCERR	(1 <<  8)
+#define	RT2860_RX_MYBSS		(1 <<  7)
+#define	RT2860_RX_BC		(1 <<  6)
+#define	RT2860_RX_MC		(1 <<  5)
+#define	RT2860_RX_UC2ME		(1 <<  4)
+#define	RT2860_RX_FRAG		(1 <<  3)
+#define	RT2860_RX_NULL		(1 <<  2)
+#define	RT2860_RX_DATA		(1 <<  1)
+#define	RT2860_RX_BA		(1 <<  0)
 } __packed;
 
 /* RT2870 RX descriptor */
@@ -813,11 +841,11 @@
 struct rt2860_rxwi {
 	uint8_t		wcid;
 	uint8_t		keyidx;
-#define RT2860_RX_UDF_SHIFT	5
-#define RT2860_RX_BSS_IDX_SHIFT	2
+#define	RT2860_RX_UDF_SHIFT	5
+#define	RT2860_RX_BSS_IDX_SHIFT	2
 
 	uint16_t	len;
-#define RT2860_RX_TID_SHIFT	12
+#define	RT2860_RX_TID_SHIFT	12
 
 	uint16_t	seq;
 	uint16_t	phy;
@@ -827,125 +855,112 @@
 	uint16_t	reserved2;
 } __packed;
 
+#define	RT2860_RF_2820	0x0001	/* 2T3R */
+#define	RT2860_RF_2850	0x0002	/* dual-band 2T3R */
+#define	RT2860_RF_2720	0x0003	/* 1T2R */
+#define	RT2860_RF_2750	0x0004	/* dual-band 1T2R */
+#define	RT3070_RF_3020	0x0005	/* 1T1R */
+#define	RT3070_RF_2020	0x0006	/* b/g */
+#define	RT3070_RF_3021	0x0007	/* 1T2R */
+#define	RT3070_RF_3022	0x0008	/* 2T2R */
+#define	RT3070_RF_3052	0x0009	/* dual-band 2T2R */
+#define	RT3593_RF_3053	0x000d	/* dual-band 3T3R */
+#define	RT5592_RF_5592	0x000f	/* dual-band 2T2R */
+#define	RT5390_RF_5370	0x5370	/* 1T1R */
+#define	RT5390_RF_5372	0x5372	/* 2T2R */
 
-/* first DMA segment contains TXWI + 802.11 header + 32-bit padding */
-#define RT2860_TXWI_DMASZ			\
-	(sizeof (struct rt2860_txwi) +		\
-	 sizeof (struct ieee80211_htframe) +	\
-	 sizeof (uint16_t))
-
-#define RT2860_RF1	0
-#define RT2860_RF2	2
-#define RT2860_RF3	1
-#define RT2860_RF4	3
-
-#define RT2860_RF_2820	1	/* 2T3R */
-#define RT2860_RF_2850	2	/* dual-band 2T3R */
-#define RT2860_RF_2720	3	/* 1T2R */
-#define RT2860_RF_2750	4	/* dual-band 1T2R */
-#define RT3070_RF_3020	5	/* 1T1R */
-#define RT3070_RF_2020	6	/* b/g */
-#define RT3070_RF_3021	7	/* 1T2R */
-#define RT3070_RF_3022	8	/* 2T2R */
-#define RT3070_RF_3052	9	/* dual-band 2T2R */
-
 /* USB commands for RT2870 only */
-#define RT2870_RESET		1
-#define RT2870_WRITE_2		2
-#define RT2870_WRITE_REGION_1	6
-#define RT2870_READ_REGION_1	7
-#define RT2870_EEPROM_READ	9
+#define	RT2870_RESET		1
+#define	RT2870_WRITE_2		2
+#define	RT2870_WRITE_REGION_1	6
+#define	RT2870_READ_REGION_1	7
+#define	RT2870_EEPROM_READ	9
 
-#define RT2860_EEPROM_DELAY	1	/* minimum hold time (microsecond) */
+#define	RT2860_EEPROM_DELAY	1	/* minimum hold time (microsecond) */
 
-#define RT2860_EEPROM_VERSION		0x01
-#define RT2860_EEPROM_MAC01		0x02
-#define RT2860_EEPROM_MAC23		0x03
-#define RT2860_EEPROM_MAC45		0x04
-#define RT2860_EEPROM_PCIE_PSLEVEL	0x11
-#define RT2860_EEPROM_REV		0x12
-#define RT2860_EEPROM_ANTENNA		0x1a
-#define RT2860_EEPROM_CONFIG		0x1b
-#define RT2860_EEPROM_COUNTRY		0x1c
-#define RT2860_EEPROM_FREQ_LEDS		0x1d
-#define RT2860_EEPROM_LED1		0x1e
-#define RT2860_EEPROM_LED2		0x1f
-#define RT2860_EEPROM_LED3		0x20
-#define RT2860_EEPROM_LNA		0x22
-#define RT2860_EEPROM_RSSI1_2GHZ	0x23
-#define RT2860_EEPROM_RSSI2_2GHZ	0x24
-#define RT2860_EEPROM_RSSI1_5GHZ	0x25
-#define RT2860_EEPROM_RSSI2_5GHZ	0x26
-#define RT2860_EEPROM_DELTAPWR		0x28
-#define RT2860_EEPROM_PWR2GHZ_BASE1	0x29
-#define RT2860_EEPROM_PWR2GHZ_BASE2	0x30
-#define RT2860_EEPROM_TSSI1_2GHZ	0x37
-#define RT2860_EEPROM_TSSI2_2GHZ	0x38
-#define RT2860_EEPROM_TSSI3_2GHZ	0x39
-#define RT2860_EEPROM_TSSI4_2GHZ	0x3a
-#define RT2860_EEPROM_TSSI5_2GHZ	0x3b
-#define RT2860_EEPROM_PWR5GHZ_BASE1	0x3c
-#define RT2860_EEPROM_PWR5GHZ_BASE2	0x53
-#define RT2860_EEPROM_TSSI1_5GHZ	0x6a
-#define RT2860_EEPROM_TSSI2_5GHZ	0x6b
-#define RT2860_EEPROM_TSSI3_5GHZ	0x6c
-#define RT2860_EEPROM_TSSI4_5GHZ	0x6d
-#define RT2860_EEPROM_TSSI5_5GHZ	0x6e
-#define RT2860_EEPROM_RPWR		0x6f
-#define RT2860_EEPROM_BBP_BASE		0x78
-#define RT3071_EEPROM_RF_BASE		0x82
+#define	RT2860_EEPROM_VERSION		0x01
+#define	RT2860_EEPROM_MAC01		0x02
+#define	RT2860_EEPROM_MAC23		0x03
+#define	RT2860_EEPROM_MAC45		0x04
+#define	RT2860_EEPROM_PCIE_PSLEVEL	0x11
+#define	RT2860_EEPROM_REV		0x12
+#define	RT2860_EEPROM_ANTENNA		0x1a
+#define	RT2860_EEPROM_CONFIG		0x1b
+#define	RT2860_EEPROM_COUNTRY		0x1c
+#define	RT2860_EEPROM_FREQ_LEDS		0x1d
+#define	RT2860_EEPROM_LED1		0x1e
+#define	RT2860_EEPROM_LED2		0x1f
+#define	RT2860_EEPROM_LED3		0x20
+#define	RT2860_EEPROM_LNA		0x22
+#define	RT2860_EEPROM_RSSI1_2GHZ	0x23
+#define	RT2860_EEPROM_RSSI2_2GHZ	0x24
+#define	RT2860_EEPROM_RSSI1_5GHZ	0x25
+#define	RT2860_EEPROM_RSSI2_5GHZ	0x26
+#define	RT2860_EEPROM_DELTAPWR		0x28
+#define	RT2860_EEPROM_PWR2GHZ_BASE1	0x29
+#define	RT2860_EEPROM_PWR2GHZ_BASE2	0x30
+#define	RT2860_EEPROM_TSSI1_2GHZ	0x37
+#define	RT2860_EEPROM_TSSI2_2GHZ	0x38
+#define	RT2860_EEPROM_TSSI3_2GHZ	0x39
+#define	RT2860_EEPROM_TSSI4_2GHZ	0x3a
+#define	RT2860_EEPROM_TSSI5_2GHZ	0x3b
+#define	RT2860_EEPROM_PWR5GHZ_BASE1	0x3c
+#define	RT2860_EEPROM_PWR5GHZ_BASE2	0x53
+#define	RT2860_EEPROM_TSSI1_5GHZ	0x6a
+#define	RT2860_EEPROM_TSSI2_5GHZ	0x6b
+#define	RT2860_EEPROM_TSSI3_5GHZ	0x6c
+#define	RT2860_EEPROM_TSSI4_5GHZ	0x6d
+#define	RT2860_EEPROM_TSSI5_5GHZ	0x6e
+#define	RT2860_EEPROM_RPWR		0x6f
+#define	RT2860_EEPROM_BBP_BASE		0x78
+#define	RT3071_EEPROM_RF_BASE		0x82
 
-#define RT2860_RIDX_CCK1	 0
-#define RT2860_RIDX_CCK11	 3
-#define RT2860_RIDX_OFDM6	 4
-#define RT2860_RIDX_MAX		12
-static const struct rt2860_rate {
-	uint8_t		rate;
-	uint8_t		mcs;
-	enum		ieee80211_phytype phy;
-	uint8_t		ctl_ridx;
-	uint16_t	sp_ack_dur;
-	uint16_t	lp_ack_dur;
-} rt2860_rates[] = {
-	{   2, 0, IEEE80211_T_DS,   0, 314, 314 },
-	{   4, 1, IEEE80211_T_DS,   1, 258, 162 },
-	{  11, 2, IEEE80211_T_DS,   2, 223, 127 },
-	{  22, 3, IEEE80211_T_DS,   3, 213, 117 },
-	{  12, 0, IEEE80211_T_OFDM, 4,  60,  60 },
-	{  18, 1, IEEE80211_T_OFDM, 4,  52,  52 },
-	{  24, 2, IEEE80211_T_OFDM, 6,  48,  48 },
-	{  36, 3, IEEE80211_T_OFDM, 6,  44,  44 },
-	{  48, 4, IEEE80211_T_OFDM, 8,  44,  44 },
-	{  72, 5, IEEE80211_T_OFDM, 8,  40,  40 },
-	{  96, 6, IEEE80211_T_OFDM, 8,  40,  40 },
-	{ 108, 7, IEEE80211_T_OFDM, 8,  40,  40 }
-};
+/* EEPROM registers for RT3593. */
+#define	RT3593_EEPROM_FREQ_LEDS		0x21
+#define	RT3593_EEPROM_FREQ		0x22
+#define	RT3593_EEPROM_LED1		0x22
+#define	RT3593_EEPROM_LED2		0x23
+#define	RT3593_EEPROM_LED3		0x24
+#define	RT3593_EEPROM_LNA		0x26
+#define	RT3593_EEPROM_LNA_5GHZ		0x27
+#define	RT3593_EEPROM_RSSI1_2GHZ	0x28
+#define	RT3593_EEPROM_RSSI2_2GHZ	0x29
+#define	RT3593_EEPROM_RSSI1_5GHZ	0x2a
+#define	RT3593_EEPROM_RSSI2_5GHZ	0x2b
+#define	RT3593_EEPROM_PWR2GHZ_BASE1	0x30
+#define	RT3593_EEPROM_PWR2GHZ_BASE2	0x37
+#define	RT3593_EEPROM_PWR2GHZ_BASE3	0x3e
+#define	RT3593_EEPROM_PWR5GHZ_BASE1	0x4b
+#define	RT3593_EEPROM_PWR5GHZ_BASE2	0x65
+#define	RT3593_EEPROM_PWR5GHZ_BASE3	0x7f
 
 /*
- * Control and status registers access macros.
+ * EEPROM IQ calibration.
  */
-#define RAL_READ(sc, reg)						\
-	bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg))
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX0_2GHZ			0x130
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX0_2GHZ			0x131
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_2GHZ			0x133
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_2GHZ			0x134
+#define	RT5390_EEPROM_RF_IQ_COMPENSATION_CTL			0x13c
+#define	RT5390_EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CTL		0x13d
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5GHZ		0x144
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5GHZ	0x145
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5GHZ	0x146
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5GHZ	0x147
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5GHZ	0x148
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5GHZ	0x149
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5GHZ		0x14a
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5GHZ	0x14b
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5GHZ	0x14c
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5GHZ	0x14d
+#define	RT5390_EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5GHZ	0x14e
+#define	RT5390_EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5GHZ	0x14f
 
-#define RAL_WRITE(sc, reg, val)						\
-	bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val))
+#define	RT2860_RIDX_CCK1	 0
+#define	RT2860_RIDX_CCK11	 3
+#define	RT2860_RIDX_OFDM6	 4
+#define	RT2860_RIDX_MAX		12
 
-#define RAL_BARRIER_WRITE(sc)						\
-	bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800,		\
-	    BUS_SPACE_BARRIER_WRITE)
-
-#define RAL_BARRIER_READ_WRITE(sc)					\
-	bus_space_barrier((sc)->sc_st, (sc)->sc_sh, 0, 0x1800,		\
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
-
-#define RAL_WRITE_REGION_1(sc, offset, datap, count)			\
-	bus_space_write_region_1((sc)->sc_st, (sc)->sc_sh, (offset),	\
-	    (datap), (count))
-
-#define RAL_SET_REGION_4(sc, offset, val, count)			\
-	bus_space_set_region_4((sc)->sc_st, (sc)->sc_sh, (offset),	\
-	    (val), (count))
-
 /*
  * EEPROM access macro.
  */
@@ -958,8 +973,9 @@
 /*
  * Default values for MAC registers; values taken from the reference driver.
  */
-#define RT2860_DEF_MAC					\
+#define	RT2870_DEF_MAC					\
 	{ RT2860_BCN_OFFSET0,		0xf8f0e8e0 },	\
+	{ RT2860_BCN_OFFSET1,		0x6f77d0c8 },	\
 	{ RT2860_LEGACY_BASIC_RATE,	0x0000013f },	\
 	{ RT2860_HT_BASIC_RATE,		0x00008003 },	\
 	{ RT2860_MAC_SYS_CTRL,		0x00000000 },	\
@@ -968,6 +984,7 @@
 	{ RT2860_TX_SW_CFG1,		0x00080606 },	\
 	{ RT2860_TX_LINK_CFG,		0x00001020 },	\
 	{ RT2860_TX_TIMEOUT_CFG,	0x000a2090 },	\
+	{ RT2860_MAX_LEN_CFG,		0x00001f00 },	\
 	{ RT2860_LED_CFG,		0x7f031e46 },	\
 	{ RT2860_WMM_AIFSN_CFG,		0x00002273 },	\
 	{ RT2860_WMM_CWMIN_CFG,		0x00002344 },	\
@@ -977,37 +994,6 @@
 	{ RT2860_AUTO_RSP_CFG,		0x00000013 },	\
 	{ RT2860_CCK_PROT_CFG,		0x05740003 },	\
 	{ RT2860_OFDM_PROT_CFG,		0x05740003 },	\
-	{ RT2860_GF20_PROT_CFG,		0x01744004 },	\
-	{ RT2860_GF40_PROT_CFG,		0x03f44084 },	\
-	{ RT2860_MM20_PROT_CFG,		0x01744004 },	\
-	{ RT2860_MM40_PROT_CFG,		0x03f54084 },	\
-	{ RT2860_TXOP_CTRL_CFG,		0x0000583f },	\
-	{ RT2860_TXOP_HLDR_ET,		0x00000002 },	\
-	{ RT2860_TX_RTS_CFG,		0x00092b20 },	\
-	{ RT2860_EXP_ACK_TIME,		0x002400ca },	\
-	{ RT2860_XIFS_TIME_CFG,		0x33a41010 },	\
-	{ RT2860_PWR_PIN_CFG,		0x00000003 }
-
-/* XXX only a few registers differ from above, try to merge? */
-#define RT2870_DEF_MAC					\
-	{ RT2860_BCN_OFFSET0,		0xf8f0e8e0 },	\
-	{ RT2860_LEGACY_BASIC_RATE,	0x0000013f },	\
-	{ RT2860_HT_BASIC_RATE,		0x00008003 },	\
-	{ RT2860_MAC_SYS_CTRL,		0x00000000 },	\
-	{ RT2860_BKOFF_SLOT_CFG,	0x00000209 },	\
-	{ RT2860_TX_SW_CFG0,		0x00000000 },	\
-	{ RT2860_TX_SW_CFG1,		0x00080606 },	\
-	{ RT2860_TX_LINK_CFG,		0x00001020 },	\
-	{ RT2860_TX_TIMEOUT_CFG,	0x000a2090 },	\
-	{ RT2860_LED_CFG,		0x7f031e46 },	\
-	{ RT2860_WMM_AIFSN_CFG,		0x00002273 },	\
-	{ RT2860_WMM_CWMIN_CFG,		0x00002344 },	\
-	{ RT2860_WMM_CWMAX_CFG,		0x000034aa },	\
-	{ RT2860_MAX_PCNT,		0x1f3fbf9f },	\
-	{ RT2860_TX_RTY_CFG,		0x47d01f0f },	\
-	{ RT2860_AUTO_RSP_CFG,		0x00000013 },	\
-	{ RT2860_CCK_PROT_CFG,		0x05740003 },	\
-	{ RT2860_OFDM_PROT_CFG,		0x05740003 },	\
 	{ RT2860_PBF_CFG,		0x00f40006 },	\
 	{ RT2860_WPDMA_GLO_CFG,		0x00000030 },	\
 	{ RT2860_GF20_PROT_CFG,		0x01744004 },	\
@@ -1024,9 +1010,10 @@
 /*
  * Default values for BBP registers; values taken from the reference driver.
  */
-#define RT2860_DEF_BBP	\
+#define	RT2860_DEF_BBP	\
 	{  65, 0x2c },	\
 	{  66, 0x38 },	\
+	{  68, 0x0b },	\
 	{  69, 0x12 },	\
 	{  70, 0x0a },	\
 	{  73, 0x10 },	\
@@ -1041,65 +1028,128 @@
 	{ 105, 0x05 },	\
 	{ 106, 0x35 }
 
+#define	RT5390_DEF_BBP	\
+	{  31, 0x08 },	\
+	{  65, 0x2c },	\
+	{  66, 0x38 },	\
+	{  68, 0x0b },	\
+	{  69, 0x0d },	\
+	{  70, 0x06 },	\
+	{  73, 0x13 },	\
+	{  75, 0x46 },	\
+	{  76, 0x28 },	\
+	{  77, 0x59 },	\
+	{  81, 0x37 },	\
+	{  82, 0x62 },	\
+	{  83, 0x7a },	\
+	{  84, 0x9a },	\
+	{  86, 0x38 },	\
+	{  91, 0x04 },	\
+	{  92, 0x02 },	\
+	{ 103, 0xc0 },	\
+	{ 104, 0x92 },	\
+	{ 105, 0x3c },	\
+	{ 106, 0x03 },	\
+	{ 128, 0x12 }
+
+#define	RT5592_DEF_BBP	\
+	{  20, 0x06 },	\
+	{  31, 0x08 },	\
+	{  65, 0x2c },	\
+	{  66, 0x38 },	\
+	{  68, 0xdd },	\
+	{  69, 0x1a },	\
+	{  70, 0x05 },	\
+	{  73, 0x13 },	\
+	{  74, 0x0f },	\
+	{  75, 0x4f },	\
+	{  76, 0x28 },	\
+	{  77, 0x59 },	\
+	{  81, 0x37 },	\
+	{  82, 0x62 },	\
+	{  83, 0x6a },	\
+	{  84, 0x9a },	\
+	{  86, 0x38 },	\
+	{  88, 0x90 },	\
+	{  91, 0x04 },	\
+	{  92, 0x02 },	\
+	{  95, 0x9a },	\
+	{  98, 0x12 },	\
+	{ 103, 0xc0 },	\
+	{ 104, 0x92 },	\
+	{ 105, 0x3c },	\
+	{ 106, 0x35 },	\
+	{ 128, 0x12 },	\
+	{ 134, 0xd0 },	\
+	{ 135, 0xf6 },	\
+	{ 137, 0x0f }
+
 /*
  * Default settings for RF registers; values derived from the reference driver.
  */
-#define RT2860_RF2850						\
-	{   1, 0x100bb3, 0x1301e1, 0x05a014, 0x001402 },	\
-	{   2, 0x100bb3, 0x1301e1, 0x05a014, 0x001407 },	\
-	{   3, 0x100bb3, 0x1301e2, 0x05a014, 0x001402 },	\
-	{   4, 0x100bb3, 0x1301e2, 0x05a014, 0x001407 },	\
-	{   5, 0x100bb3, 0x1301e3, 0x05a014, 0x001402 },	\
-	{   6, 0x100bb3, 0x1301e3, 0x05a014, 0x001407 },	\
-	{   7, 0x100bb3, 0x1301e4, 0x05a014, 0x001402 },	\
-	{   8, 0x100bb3, 0x1301e4, 0x05a014, 0x001407 },	\
-	{   9, 0x100bb3, 0x1301e5, 0x05a014, 0x001402 },	\
-	{  10, 0x100bb3, 0x1301e5, 0x05a014, 0x001407 },	\
-	{  11, 0x100bb3, 0x1301e6, 0x05a014, 0x001402 },	\
-	{  12, 0x100bb3, 0x1301e6, 0x05a014, 0x001407 },	\
-	{  13, 0x100bb3, 0x1301e7, 0x05a014, 0x001402 },	\
-	{  14, 0x100bb3, 0x1301e8, 0x05a014, 0x001404 },	\
-	{  36, 0x100bb3, 0x130266, 0x056014, 0x001408 },	\
-	{  38, 0x100bb3, 0x130267, 0x056014, 0x001404 },	\
-	{  40, 0x100bb2, 0x1301a0, 0x056014, 0x001400 },	\
-	{  44, 0x100bb2, 0x1301a0, 0x056014, 0x001408 },	\
-	{  46, 0x100bb2, 0x1301a1, 0x056014, 0x001402 },	\
-	{  48, 0x100bb2, 0x1301a1, 0x056014, 0x001406 },	\
-	{  52, 0x100bb2, 0x1301a2, 0x056014, 0x001404 },	\
-	{  54, 0x100bb2, 0x1301a2, 0x056014, 0x001408 },	\
-	{  56, 0x100bb2, 0x1301a3, 0x056014, 0x001402 },	\
-	{  60, 0x100bb2, 0x1301a4, 0x056014, 0x001400 },	\
-	{  62, 0x100bb2, 0x1301a4, 0x056014, 0x001404 },	\
-	{  64, 0x100bb2, 0x1301a4, 0x056014, 0x001408 },	\
-	{ 100, 0x100bb2, 0x1301ac, 0x05e014, 0x001400 },	\
-	{ 102, 0x100bb2, 0x1701ac, 0x15e014, 0x001404 },	\
-	{ 104, 0x100bb2, 0x1701ac, 0x15e014, 0x001408 },	\
-	{ 108, 0x100bb3, 0x17028c, 0x15e014, 0x001404 },	\
-	{ 110, 0x100bb3, 0x13028d, 0x05e014, 0x001400 },	\
-	{ 112, 0x100bb3, 0x13028d, 0x05e014, 0x001406 },	\
-	{ 116, 0x100bb3, 0x13028e, 0x05e014, 0x001408 },	\
-	{ 118, 0x100bb3, 0x13028f, 0x05e014, 0x001404 },	\
-	{ 120, 0x100bb1, 0x1300e0, 0x05e014, 0x001400 },	\
-	{ 124, 0x100bb1, 0x1300e0, 0x05e014, 0x001404 },	\
-	{ 126, 0x100bb1, 0x1300e0, 0x05e014, 0x001406 },	\
-	{ 128, 0x100bb1, 0x1300e0, 0x05e014, 0x001408 },	\
-	{ 132, 0x100bb1, 0x1300e1, 0x05e014, 0x001402 },	\
-	{ 134, 0x100bb1, 0x1300e1, 0x05e014, 0x001404 },	\
-	{ 136, 0x100bb1, 0x1300e1, 0x05e014, 0x001406 },	\
-	{ 140, 0x100bb1, 0x1300e2, 0x05e014, 0x001400 },	\
-	{ 149, 0x100bb1, 0x1300e2, 0x05e014, 0x001409 },	\
-	{ 151, 0x100bb1, 0x1300e3, 0x05e014, 0x001401 },	\
-	{ 153, 0x100bb1, 0x1300e3, 0x05e014, 0x001403 },	\
-	{ 157, 0x100bb1, 0x1300e3, 0x05e014, 0x001407 },	\
-	{ 159, 0x100bb1, 0x1300e3, 0x05e014, 0x001409 },	\
-	{ 161, 0x100bb1, 0x1300e4, 0x05e014, 0x001401 },	\
-	{ 165, 0x100bb1, 0x1300e4, 0x05e014, 0x001405 },	\
-	{ 167, 0x100bb1, 0x1300f4, 0x05e014, 0x001407 },	\
-	{ 169, 0x100bb1, 0x1300f4, 0x05e014, 0x001409 },	\
-	{ 171, 0x100bb1, 0x1300f5, 0x05e014, 0x001401 },	\
-	{ 173, 0x100bb1, 0x1300f5, 0x05e014, 0x001403 }
+#define	RT2860_RF2850							\
+	{   1, 0x98402ecc, 0x984c0786, 0x9816b455, 0x9800510b },	\
+	{   2, 0x98402ecc, 0x984c0786, 0x98168a55, 0x9800519f },	\
+	{   3, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800518b },	\
+	{   4, 0x98402ecc, 0x984c078a, 0x98168a55, 0x9800519f },	\
+	{   5, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800518b },	\
+	{   6, 0x98402ecc, 0x984c078e, 0x98168a55, 0x9800519f },	\
+	{   7, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800518b },	\
+	{   8, 0x98402ecc, 0x984c0792, 0x98168a55, 0x9800519f },	\
+	{   9, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800518b },	\
+	{  10, 0x98402ecc, 0x984c0796, 0x98168a55, 0x9800519f },	\
+	{  11, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800518b },	\
+	{  12, 0x98402ecc, 0x984c079a, 0x98168a55, 0x9800519f },	\
+	{  13, 0x98402ecc, 0x984c079e, 0x98168a55, 0x9800518b },	\
+	{  14, 0x98402ecc, 0x984c07a2, 0x98168a55, 0x98005193 },	\
+	{  36, 0x98402ecc, 0x984c099a, 0x98158a55, 0x980ed1a3 },	\
+	{  38, 0x98402ecc, 0x984c099e, 0x98158a55, 0x980ed193 },	\
+	{  40, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed183 },	\
+	{  44, 0x98402ec8, 0x984c0682, 0x98158a55, 0x980ed1a3 },	\
+	{  46, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed18b },	\
+	{  48, 0x98402ec8, 0x984c0686, 0x98158a55, 0x980ed19b },	\
+	{  52, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed193 },	\
+	{  54, 0x98402ec8, 0x984c068a, 0x98158a55, 0x980ed1a3 },	\
+	{  56, 0x98402ec8, 0x984c068e, 0x98158a55, 0x980ed18b },	\
+	{  60, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed183 },	\
+	{  62, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed193 },	\
+	{  64, 0x98402ec8, 0x984c0692, 0x98158a55, 0x980ed1a3 },	\
+	{ 100, 0x98402ec8, 0x984c06b2, 0x98178a55, 0x980ed783 },	\
+	{ 102, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed793 },	\
+	{ 104, 0x98402ec8, 0x985c06b2, 0x98578a55, 0x980ed1a3 },	\
+	{ 108, 0x98402ecc, 0x985c0a32, 0x98578a55, 0x980ed193 },	\
+	{ 110, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed183 },	\
+	{ 112, 0x98402ecc, 0x984c0a36, 0x98178a55, 0x980ed19b },	\
+	{ 116, 0x98402ecc, 0x984c0a3a, 0x98178a55, 0x980ed1a3 },	\
+	{ 118, 0x98402ecc, 0x984c0a3e, 0x98178a55, 0x980ed193 },	\
+	{ 120, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed183 },	\
+	{ 124, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed193 },	\
+	{ 126, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed15b },	\
+	{ 128, 0x98402ec4, 0x984c0382, 0x98178a55, 0x980ed1a3 },	\
+	{ 132, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed18b },	\
+	{ 134, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed193 },	\
+	{ 136, 0x98402ec4, 0x984c0386, 0x98178a55, 0x980ed19b },	\
+	{ 140, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed183 },	\
+	{ 149, 0x98402ec4, 0x984c038a, 0x98178a55, 0x980ed1a7 },	\
+	{ 151, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed187 },	\
+	{ 153, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed18f },	\
+	{ 157, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed19f },	\
+	{ 159, 0x98402ec4, 0x984c038e, 0x98178a55, 0x980ed1a7 },	\
+	{ 161, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed187 },	\
+	{ 165, 0x98402ec4, 0x984c0392, 0x98178a55, 0x980ed197 },	\
+	{ 167, 0x98402ec4, 0x984c03d2, 0x98179855, 0x9815531f },	\
+	{ 169, 0x98402ec4, 0x984c03d2, 0x98179855, 0x98155327 },	\
+	{ 171, 0x98402ec4, 0x984c03d6, 0x98179855, 0x98155307 },	\
+	{ 173, 0x98402ec4, 0x984c03d6, 0x98179855, 0x9815530f },	\
+	{ 184, 0x95002ccc, 0x9500491e, 0x9509be55, 0x950c0a0b },	\
+	{ 188, 0x95002ccc, 0x95004922, 0x9509be55, 0x950c0a13 },	\
+	{ 192, 0x95002ccc, 0x95004926, 0x9509be55, 0x950c0a1b },	\
+	{ 196, 0x95002ccc, 0x9500492a, 0x9509be55, 0x950c0a23 },	\
+	{ 208, 0x95002ccc, 0x9500493a, 0x9509be55, 0x950c0a13 },	\
+	{ 212, 0x95002ccc, 0x9500493e, 0x9509be55, 0x950c0a1b },	\
+	{ 216, 0x95002ccc, 0x95004982, 0x9509be55, 0x950c0a23 }
 
-#define RT3070_RF3052		\
+#define	RT3070_RF3052		\
 	{ 0xf1, 2,  2 },	\
 	{ 0xf1, 2,  7 },	\
 	{ 0xf2, 2,  2 },	\
@@ -1154,11 +1204,121 @@
 	{ 0x61, 0,  7 },	\
 	{ 0x61, 0,  9 }
 
-#define RT3070_DEF_RF	\
+#define	RT5592_RF5592_20MHZ	\
+	{ 0x1e2,  4, 10, 3 },	\
+	{ 0x1e3,  4, 10, 3 },	\
+	{ 0x1e4,  4, 10, 3 },	\
+	{ 0x1e5,  4, 10, 3 },	\
+	{ 0x1e6,  4, 10, 3 },	\
+	{ 0x1e7,  4, 10, 3 },	\
+	{ 0x1e8,  4, 10, 3 },	\
+	{ 0x1e9,  4, 10, 3 },	\
+	{ 0x1ea,  4, 10, 3 },	\
+	{ 0x1eb,  4, 10, 3 },	\
+	{ 0x1ec,  4, 10, 3 },	\
+	{ 0x1ed,  4, 10, 3 },	\
+	{ 0x1ee,  4, 10, 3 },	\
+	{ 0x1f0,  8, 10, 3 },	\
+	{  0xac,  8, 12, 1 },	\
+	{  0xad,  0, 12, 1 },	\
+	{  0xad,  4, 12, 1 },	\
+	{  0xae,  0, 12, 1 },	\
+	{  0xae,  4, 12, 1 },	\
+	{  0xae,  8, 12, 1 },	\
+	{  0xaf,  4, 12, 1 },	\
+	{  0xaf,  8, 12, 1 },	\
+	{  0xb0,  0, 12, 1 },	\
+	{  0xb0,  8, 12, 1 },	\
+	{  0xb1,  0, 12, 1 },	\
+	{  0xb1,  4, 12, 1 },	\
+	{  0xb7,  4, 12, 1 },	\
+	{  0xb7,  8, 12, 1 },	\
+	{  0xb8,  0, 12, 1 },	\
+	{  0xb8,  8, 12, 1 },	\
+	{  0xb9,  0, 12, 1 },	\
+	{  0xb9,  4, 12, 1 },	\
+	{  0xba,  0, 12, 1 },	\
+	{  0xba,  4, 12, 1 },	\
+	{  0xba,  8, 12, 1 },	\
+	{  0xbb,  4, 12, 1 },	\
+	{  0xbb,  8, 12, 1 },	\
+	{  0xbc,  0, 12, 1 },	\
+	{  0xbc,  8, 12, 1 },	\
+	{  0xbd,  0, 12, 1 },	\
+	{  0xbd,  4, 12, 1 },	\
+	{  0xbe,  0, 12, 1 },	\
+	{  0xbf,  6, 12, 1 },	\
+	{  0xbf, 10, 12, 1 },	\
+	{  0xc0,  2, 12, 1 },	\
+	{  0xc0, 10, 12, 1 },	\
+	{  0xc1,  2, 12, 1 },	\
+	{  0xc1,  6, 12, 1 },	\
+	{  0xc2,  2, 12, 1 },	\
+	{  0xa4,  0, 12, 1 },	\
+	{  0xa4,  4, 12, 1 },	\
+	{  0xa5,  8, 12, 1 },	\
+	{  0xa6,  0, 12, 1 }
+
+#define	RT5592_RF5592_40MHZ	\
+	{ 0xf1,  2, 10, 3 },	\
+	{ 0xf1,  7, 10, 3 },	\
+	{ 0xf2,  2, 10, 3 },	\
+	{ 0xf2,  7, 10, 3 },	\
+	{ 0xf3,  2, 10, 3 },	\
+	{ 0xf3,  7, 10, 3 },	\
+	{ 0xf4,  2, 10, 3 },	\
+	{ 0xf4,  7, 10, 3 },	\
+	{ 0xf5,  2, 10, 3 },	\
+	{ 0xf5,  7, 10, 3 },	\
+	{ 0xf6,  2, 10, 3 },	\
+	{ 0xf6,  7, 10, 3 },	\
+	{ 0xf7,  2, 10, 3 },	\
+	{ 0xf8,  4, 10, 3 },	\
+	{ 0x56,  4, 12, 1 },	\
+	{ 0x56,  6, 12, 1 },	\
+	{ 0x56,  8, 12, 1 },	\
+	{ 0x57,  0, 12, 1 },	\
+	{ 0x57,  2, 12, 1 },	\
+	{ 0x57,  4, 12, 1 },	\
+	{ 0x57,  8, 12, 1 },	\
+	{ 0x57, 10, 12, 1 },	\
+	{ 0x58,  0, 12, 1 },	\
+	{ 0x58,  4, 12, 1 },	\
+	{ 0x58,  6, 12, 1 },	\
+	{ 0x58,  8, 12, 1 },	\
+	{ 0x5b,  8, 12, 1 },	\
+	{ 0x5b, 10, 12, 1 },	\
+	{ 0x5c,  0, 12, 1 },	\
+	{ 0x5c,  4, 12, 1 },	\
+	{ 0x5c,  6, 12, 1 },	\
+	{ 0x5c,  8, 12, 1 },	\
+	{ 0x5d,  0, 12, 1 },	\
+	{ 0x5d,  2, 12, 1 },	\
+	{ 0x5d,  4, 12, 1 },	\
+	{ 0x5d,  8, 12, 1 },	\
+	{ 0x5d, 10, 12, 1 },	\
+	{ 0x5e,  0, 12, 1 },	\
+	{ 0x5e,  4, 12, 1 },	\
+	{ 0x5e,  6, 12, 1 },	\
+	{ 0x5e,  8, 12, 1 },	\
+	{ 0x5f,  0, 12, 1 },	\
+	{ 0x5f,  9, 12, 1 },	\
+	{ 0x5f, 11, 12, 1 },	\
+	{ 0x60,  1, 12, 1 },	\
+	{ 0x60,  5, 12, 1 },	\
+	{ 0x60,  7, 12, 1 },	\
+	{ 0x60,  9, 12, 1 },	\
+	{ 0x61,  1, 12, 1 },	\
+	{ 0x52,  0, 12, 1 },	\
+	{ 0x52,  4, 12, 1 },	\
+	{ 0x52,  8, 12, 1 },	\
+	{ 0x53,  0, 12, 1 }
+
+#define	RT3070_DEF_RF	\
 	{  4, 0x40 },	\
 	{  5, 0x03 },	\
 	{  6, 0x02 },	\
-	{  7, 0x70 },	\
+	{  7, 0x60 },	\
 	{  9, 0x0f },	\
 	{ 10, 0x41 },	\
 	{ 11, 0x21 },	\
@@ -1172,10 +1332,10 @@
 	{ 20, 0xba },	\
 	{ 21, 0xdb },	\
 	{ 24, 0x16 },	\
-	{ 25, 0x01 },	\
+	{ 25, 0x03 },	\
 	{ 29, 0x1f }
 
-#define RT3572_DEF_RF	\
+#define	RT3572_DEF_RF	\
 	{  0, 0x70 },	\
 	{  1, 0x81 },	\
 	{  2, 0xf1 },	\
@@ -1208,7 +1368,281 @@
 	{ 30, 0x09 },	\
 	{ 31, 0x10 }
 
+#define	RT3593_DEF_RF	\
+	{  1, 0x03 },	\
+	{  3, 0x80 },	\
+	{  5, 0x00 },	\
+	{  6, 0x40 },	\
+	{  8, 0xf1 },	\
+	{  9, 0x02 },	\
+	{ 10, 0xd3 },	\
+	{ 11, 0x40 },	\
+	{ 12, 0x4e },	\
+	{ 13, 0x12 },	\
+	{ 18, 0x40 },	\
+	{ 22, 0x20 },	\
+	{ 30, 0x10 },	\
+	{ 31, 0x80 },	\
+	{ 32, 0x78 },	\
+	{ 33, 0x3b },	\
+	{ 34, 0x3c },	\
+	{ 35, 0xe0 },	\
+	{ 38, 0x86 },	\
+	{ 39, 0x23 },	\
+	{ 44, 0xd3 },	\
+	{ 45, 0xbb },	\
+	{ 46, 0x60 },	\
+	{ 49, 0x81 },	\
+	{ 50, 0x86 },	\
+	{ 51, 0x75 },	\
+	{ 52, 0x45 },	\
+	{ 53, 0x18 },	\
+	{ 54, 0x18 },	\
+	{ 55, 0x18 },	\
+	{ 56, 0xdb },	\
+	{ 57, 0x6e }
 
+#define	RT5390_DEF_RF	\
+	{  1, 0x0f },	\
+	{  2, 0x80 },	\
+	{  3, 0x88 },	\
+	{  5, 0x10 },	\
+	{  6, 0xa0 },	\
+	{  7, 0x00 },	\
+	{ 10, 0x53 },	\
+	{ 11, 0x4a },	\
+	{ 12, 0x46 },	\
+	{ 13, 0x9f },	\
+	{ 14, 0x00 },	\
+	{ 15, 0x00 },	\
+	{ 16, 0x00 },	\
+	{ 18, 0x03 },	\
+	{ 19, 0x00 },	\
+	{ 20, 0x00 },	\
+	{ 21, 0x00 },	\
+	{ 22, 0x20 },  	\
+	{ 23, 0x00 },	\
+	{ 24, 0x00 },	\
+	{ 25, 0xc0 },	\
+	{ 26, 0x00 },	\
+	{ 27, 0x09 },	\
+	{ 28, 0x00 },	\
+	{ 29, 0x10 },	\
+	{ 30, 0x10 },	\
+	{ 31, 0x80 },	\
+	{ 32, 0x80 },	\
+	{ 33, 0x00 },	\
+	{ 34, 0x07 },	\
+	{ 35, 0x12 },	\
+	{ 36, 0x00 },	\
+	{ 37, 0x08 },	\
+	{ 38, 0x85 },	\
+	{ 39, 0x1b },	\
+	{ 40, 0x0b },	\
+	{ 41, 0xbb },	\
+	{ 42, 0xd2 },	\
+	{ 43, 0x9a },	\
+	{ 44, 0x0e },	\
+	{ 45, 0xa2 },	\
+	{ 46, 0x7b },	\
+	{ 47, 0x00 },	\
+	{ 48, 0x10 },	\
+	{ 49, 0x94 },	\
+	{ 52, 0x38 },	\
+	{ 53, 0x84 },	\
+	{ 54, 0x78 },	\
+	{ 55, 0x44 },	\
+	{ 56, 0x22 },	\
+	{ 57, 0x80 },	\
+	{ 58, 0x7f },	\
+	{ 59, 0x8f },	\
+	{ 60, 0x45 },	\
+	{ 61, 0xdd },	\
+	{ 62, 0x00 },	\
+	{ 63, 0x00 }
+
+#define	RT5392_DEF_RF	\
+	{  1, 0x17 },	\
+	{  3, 0x88 },	\
+	{  5, 0x10 },	\
+	{  6, 0xe0 },	\
+	{  7, 0x00 },	\
+	{ 10, 0x53 },	\
+	{ 11, 0x4a },	\
+	{ 12, 0x46 },	\
+	{ 13, 0x9f },	\
+	{ 14, 0x00 },	\
+	{ 15, 0x00 },	\
+	{ 16, 0x00 },	\
+	{ 18, 0x03 },	\
+	{ 19, 0x4d },	\
+	{ 20, 0x00 },	\
+	{ 21, 0x8d },	\
+	{ 22, 0x20 },  	\
+	{ 23, 0x0b },	\
+	{ 24, 0x44 },	\
+	{ 25, 0x80 },	\
+	{ 26, 0x82 },	\
+	{ 27, 0x09 },	\
+	{ 28, 0x00 },	\
+	{ 29, 0x10 },	\
+	{ 30, 0x10 },	\
+	{ 31, 0x80 },	\
+	{ 32, 0x20 },	\
+	{ 33, 0xc0 },	\
+	{ 34, 0x07 },	\
+	{ 35, 0x12 },	\
+	{ 36, 0x00 },	\
+	{ 37, 0x08 },	\
+	{ 38, 0x89 },	\
+	{ 39, 0x1b },	\
+	{ 40, 0x0f },	\
+	{ 41, 0xbb },	\
+	{ 42, 0xd5 },	\
+	{ 43, 0x9b },	\
+	{ 44, 0x0e },	\
+	{ 45, 0xa2 },	\
+	{ 46, 0x73 },	\
+	{ 47, 0x0c },	\
+	{ 48, 0x10 },	\
+	{ 49, 0x94 },	\
+	{ 50, 0x94 },	\
+	{ 51, 0x3a },	\
+	{ 52, 0x48 },	\
+	{ 53, 0x44 },	\
+	{ 54, 0x38 },	\
+	{ 55, 0x43 },	\
+	{ 56, 0xa1 },	\
+	{ 57, 0x00 },	\
+	{ 58, 0x39 },	\
+	{ 59, 0x07 },	\
+	{ 60, 0x45 },	\
+	{ 61, 0x91 },	\
+	{ 62, 0x39 },	\
+	{ 63, 0x07 }
+
+#define	RT5592_DEF_RF	\
+	{  1, 0x3f },	\
+	{  3, 0x08 },	\
+	{  5, 0x10 },	\
+	{  6, 0xe4 },	\
+	{  7, 0x00 },	\
+	{ 14, 0x00 },	\
+	{ 15, 0x00 },	\
+	{ 16, 0x00 },	\
+	{ 18, 0x03 },	\
+	{ 19, 0x4d },	\
+	{ 20, 0x10 },	\
+	{ 21, 0x8d },	\
+	{ 26, 0x82 },	\
+	{ 28, 0x00 },	\
+	{ 29, 0x10 },	\
+	{ 33, 0xc0 },	\
+	{ 34, 0x07 },	\
+	{ 35, 0x12 },	\
+	{ 47, 0x0c },	\
+	{ 53, 0x22 },	\
+	{ 63, 0x07 }
+
+#define	RT5592_2GHZ_DEF_RF	\
+	{ 10, 0x90 },		\
+	{ 11, 0x4a },		\
+	{ 12, 0x52 },		\
+	{ 13, 0x42 },		\
+	{ 22, 0x40 },		\
+	{ 24, 0x4a },		\
+	{ 25, 0x80 },		\
+	{ 27, 0x42 },		\
+	{ 36, 0x80 },		\
+	{ 37, 0x08 },		\
+	{ 38, 0x89 },		\
+	{ 39, 0x1b },		\
+	{ 40, 0x0d },		\
+	{ 41, 0x9b },		\
+	{ 42, 0xd5 },		\
+	{ 43, 0x72 },		\
+	{ 44, 0x0e },		\
+	{ 45, 0xa2 },		\
+	{ 46, 0x6b },		\
+	{ 48, 0x10 },		\
+	{ 51, 0x3e },		\
+	{ 52, 0x48 },		\
+	{ 54, 0x38 },		\
+	{ 56, 0xa1 },		\
+	{ 57, 0x00 },		\
+	{ 58, 0x39 },		\
+	{ 60, 0x45 },		\
+	{ 61, 0x91 },		\
+	{ 62, 0x39 }
+
+#define	RT5592_5GHZ_DEF_RF	\
+	{ 10, 0x97 },		\
+	{ 11, 0x40 },		\
+	{ 25, 0xbf },		\
+	{ 27, 0x42 },		\
+	{ 36, 0x00 },		\
+	{ 37, 0x04 },		\
+	{ 38, 0x85 },		\
+	{ 40, 0x42 },		\
+	{ 41, 0xbb },		\
+	{ 42, 0xd7 },		\
+	{ 45, 0x41 },		\
+	{ 48, 0x00 },		\
+	{ 57, 0x77 },		\
+	{ 60, 0x05 },		\
+	{ 61, 0x01 }
+
+#define	RT5592_CHAN_5GHZ	\
+	{  36,  64, 12, 0x2e },	\
+	{ 100, 165, 12, 0x0e },	\
+	{  36,  64, 13, 0x22 },	\
+	{ 100, 165, 13, 0x42 },	\
+	{  36,  64, 22, 0x60 },	\
+	{ 100, 165, 22, 0x40 },	\
+	{  36,  64, 23, 0x7f },	\
+	{ 100, 153, 23, 0x3c },	\
+	{ 155, 165, 23, 0x38 },	\
+	{  36,  50, 24, 0x09 },	\
+	{  52,  64, 24, 0x07 },	\
+	{ 100, 153, 24, 0x06 },	\
+	{ 155, 165, 24, 0x05 },	\
+	{  36,  64, 39, 0x1c },	\
+	{ 100, 138, 39, 0x1a },	\
+	{ 140, 165, 39, 0x18 },	\
+	{  36,  64, 43, 0x5b },	\
+	{ 100, 138, 43, 0x3b },	\
+	{ 140, 165, 43, 0x1b },	\
+	{  36,  64, 44, 0x40 },	\
+	{ 100, 138, 44, 0x20 },	\
+	{ 140, 165, 44, 0x10 },	\
+	{  36,  64, 46, 0x00 },	\
+	{ 100, 138, 46, 0x18 },	\
+	{ 140, 165, 46, 0x08 },	\
+	{  36,  64, 51, 0xfe },	\
+	{ 100, 124, 51, 0xfc },	\
+	{ 126, 165, 51, 0xec },	\
+	{  36,  64, 52, 0x0c },	\
+	{ 100, 138, 52, 0x06 },	\
+	{ 140, 165, 52, 0x06 },	\
+	{  36,  64, 54, 0xf8 },	\
+	{ 100, 165, 54, 0xeb },	\
+	{ 36,   50, 55, 0x06 },	\
+	{ 52,   64, 55, 0x04 },	\
+	{ 100, 138, 55, 0x01 },	\
+	{ 140, 165, 55, 0x00 },	\
+	{  36,  50, 56, 0xd3 },	\
+	{  52, 128, 56, 0xbb },	\
+	{ 130, 165, 56, 0xab },	\
+	{  36,  64, 58, 0x15 },	\
+	{ 100, 116, 58, 0x1d },	\
+	{ 118, 165, 58, 0x15 },	\
+	{  36,  64, 59, 0x7f },	\
+	{ 100, 138, 59, 0x3f },	\
+	{ 140, 165, 59, 0x7c },	\
+	{  36,  64, 62, 0x15 },	\
+	{ 100, 116, 62, 0x1d },	\
+	{ 118, 165, 62, 0x15 }
+
 union run_stats {
 	uint32_t	raw;
 	struct {

Modified: stable/0.8/sys/dev/usb/wlan/if_runvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_runvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_runvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -17,37 +17,31 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/9/sys/dev/usb/wlan/if_runvar.h 262605 2014-02-28 16:11:43Z kevlo $
  */
 
 #ifndef _IF_RUNVAR_H_
 #define	_IF_RUNVAR_H_
 
-#define RUN_MAX_RXSZ			\
+#define	RUN_MAX_RXSZ			\
 	MIN(4096, MJUMPAGESIZE)
-#if 0
-	(sizeof (uint32_t) +		\
-	 sizeof (struct rt2860_rxwi) +	\
-	 sizeof (uint16_t) +		\
-	 MCLBYTES +			\
-	 sizeof (struct rt2870_rxd))
-#endif
+
 /* NB: "11" is the maximum number of padding bytes needed for Tx */
-#define RUN_MAX_TXSZ			\
+#define	RUN_MAX_TXSZ			\
 	(sizeof (struct rt2870_txd) +	\
-	 sizeof (struct rt2860_rxwi) +	\
+	 sizeof (struct rt2860_txwi) +	\
 	 MCLBYTES + 11)
 
-#define RUN_TX_TIMEOUT	5000	/* ms */
+#define	RUN_TX_TIMEOUT	5000	/* ms */
 
 /* Tx ring count was 8/endpoint, now 32 for all 4 (or 6) endpoints. */
-#define RUN_TX_RING_COUNT	32
-#define RUN_RX_RING_COUNT	1
+#define	RUN_TX_RING_COUNT	32
+#define	RUN_RX_RING_COUNT	1
 
-#define RT2870_WCID_MAX		64
-#define RUN_AID2WCID(aid)	((aid) & 0xff)
+#define	RT2870_WCID_MAX		64
+#define	RUN_AID2WCID(aid)	((aid) & 0xff)
 
-#define RUN_VAP_MAX		8
+#define	RUN_VAP_MAX		8
 
 struct run_rx_radiotap_header {
 	struct ieee80211_radiotap_header wr_ihdr;
@@ -58,9 +52,9 @@
 	int8_t		wr_dbm_antsignal;
 	uint8_t		wr_antenna;
 	uint8_t		wr_antsignal;
-} __packed;
+} __packed __aligned(8);
 
-#define RUN_RX_RADIOTAP_PRESENT				\
+#define	RUN_RX_RADIOTAP_PRESENT				\
 	(1 << IEEE80211_RADIOTAP_FLAGS |		\
 	 1 << IEEE80211_RADIOTAP_RATE |			\
 	 1 << IEEE80211_RADIOTAP_CHANNEL |		\
@@ -75,11 +69,11 @@
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
 	uint8_t		wt_hwqueue;
-} __packed;
+} __packed __aligned(8);
 
 #define IEEE80211_RADIOTAP_HWQUEUE 15
 
-#define RUN_TX_RADIOTAP_PRESENT				\
+#define	RUN_TX_RADIOTAP_PRESENT				\
 	(1 << IEEE80211_RADIOTAP_FLAGS |		\
 	 1 << IEEE80211_RADIOTAP_RATE |			\
 	 1 << IEEE80211_RADIOTAP_CHANNEL |		\
@@ -128,7 +122,7 @@
 
 	uint8_t				rvp_id;
 };
-#define RUN_VAP(vap)    ((struct run_vap *)(vap))
+#define	RUN_VAP(vap)	((struct run_vap *)(vap))
 
 /*
  * There are 7 bulk endpoints: 1 for RX
@@ -160,6 +154,11 @@
 	device_t			sc_dev;
 	struct usb_device		*sc_udev;
 	struct ifnet			*sc_ifp;
+	int				sc_need_fwload;
+
+	int				sc_flags;
+#define	RUN_FLAG_FWLOAD_NEEDED		0x01
+
 	uint16_t			wcid_stats[RT2870_WCID_MAX + 1][3];
 #define	RUN_TXCNT	0
 #define	RUN_SUCCESS	1
@@ -170,7 +169,7 @@
 
 	uint16_t			mac_ver;
 	uint16_t			mac_rev;
-	uint8_t				rf_rev;
+	uint16_t			rf_rev;
 	uint8_t				freq;
 	uint8_t				ntxchains;
 	uint8_t				nrxchains;
@@ -189,6 +188,7 @@
 	uint8_t				txmixgain_5ghz;
 	int8_t				txpow1[54];
 	int8_t				txpow2[54];
+	int8_t				txpow3[54];
 	int8_t				rssi_2ghz[3];
 	int8_t				rssi_5ghz[3];
 	uint8_t				lna[4];
@@ -212,11 +212,11 @@
 	struct task                     ratectl_task;
 	struct usb_callout              ratectl_ch;
 	uint8_t				ratectl_run;
-#define RUN_RATECTL_OFF	0
+#define	RUN_RATECTL_OFF	0
 
 /* need to be power of 2, otherwise RUN_CMDQ_GET fails */
-#define RUN_CMDQ_MAX	16
-#define RUN_CMDQ_MASQ	(RUN_CMDQ_MAX - 1)
+#define	RUN_CMDQ_MAX	16
+#define	RUN_CMDQ_MASQ	(RUN_CMDQ_MAX - 1)
 	struct run_cmdq			cmdq[RUN_CMDQ_MAX];
 	struct task			cmdq_task;
 	uint32_t			cmdq_store;
@@ -223,8 +223,8 @@
 	uint8_t				cmdq_exec;
 	uint8_t				cmdq_run;
 	uint8_t				cmdq_key_set;
-#define RUN_CMDQ_ABORT	0
-#define RUN_CMDQ_GO	1
+#define	RUN_CMDQ_ABORT	0
+#define	RUN_CMDQ_GO	1
 
 	struct usb_xfer			*sc_xfer[RUN_N_XFER];
 
@@ -239,6 +239,7 @@
 	uint8_t				sta_running;
 	uint8_t				rvp_cnt;
 	uint8_t				rvp_bmap;
+	uint8_t				sc_detached;
 
 	union {
 		struct run_rx_radiotap_header th;
@@ -255,8 +256,8 @@
 	int				sc_txtap_len;
 };
 
-#define RUN_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
-#define RUN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
-#define RUN_LOCK_ASSERT(sc, t)	mtx_assert(&(sc)->sc_mtx, t)
+#define	RUN_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
+#define	RUN_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
+#define	RUN_LOCK_ASSERT(sc, t)	mtx_assert(&(sc)->sc_mtx, t)
 
 #endif	/* _IF_RUNVAR_H_ */

Modified: stable/0.8/sys/dev/usb/wlan/if_uath.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uath.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uath.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_uath.c 259457 2013-12-16 09:07:09Z hselasky $");
 
 /*-
  * Driver for Atheros AR5523 USB parts.
@@ -217,9 +217,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x1,
 		.direction = UE_DIR_OUT,
-		.bufsize = UATH_MAX_CMDSZ,
+		.bufsize = UATH_MAX_CMDSZ * UATH_CMD_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -242,9 +241,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x2,
 		.direction = UE_DIR_OUT,
-		.bufsize = UATH_MAX_TXBUFSZ,
+		.bufsize = UATH_MAX_TXBUFSZ * UATH_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1
 		},
@@ -258,10 +256,8 @@
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 static void	uath_vap_delete(struct ieee80211vap *);
-static int	uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
-		    int, int);
-static void	uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
-		    int);
+static int	uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd []);
+static void	uath_free_cmd_list(struct uath_softc *, struct uath_cmd []);
 static int	uath_host_available(struct uath_softc *);
 static int	uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
 static int	uath_get_devcap(struct uath_softc *);
@@ -362,22 +358,26 @@
 	callout_init(&sc->stat_ch, 0);
 	callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
 
+	error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+	    uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
+	if (error) {
+		device_printf(dev, "could not allocate USB transfers, "
+		    "err=%s\n", usbd_errstr(error));
+		goto fail;
+	}
+
+	sc->sc_cmd_dma_buf = 
+	    usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_INTR_TX], 0);
+	sc->sc_tx_dma_buf = 
+	    usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0);
+
 	/*
-	 * Allocate xfers for firmware commands.
+	 * Setup buffers for firmware commands.
 	 */
-	error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
-	    UATH_MAX_CMDSZ);
+	error = uath_alloc_cmd_list(sc, sc->sc_cmd);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "could not allocate Tx command list\n");
-		goto fail;
-	}
-
-	error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
-	    uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
-	if (error) {
-		device_printf(dev, "could not allocate USB transfers, "
-		    "err=%s\n", usbd_errstr(error));
 		goto fail1;
 	}
 
@@ -492,8 +492,8 @@
 
 fail4:	if_free(ifp);
 fail3:	UATH_UNLOCK(sc);
-fail2:	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
-fail1:	uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+fail2:	uath_free_cmd_list(sc, sc->sc_cmd);
+fail1:	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
 fail:
 	return (error);
 }
@@ -504,29 +504,48 @@
 	struct uath_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
 
-	if (!device_is_attached(dev))
-		return (0);
-
+	/*
+	 * Prevent further allocations from RX/TX/CMD
+	 * data lists and ioctls
+	 */
 	UATH_LOCK(sc);
 	sc->sc_flags |= UATH_FLAG_INVALID;
+
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
+
+	STAILQ_INIT(&sc->sc_cmd_active);
+	STAILQ_INIT(&sc->sc_cmd_pending);
+	STAILQ_INIT(&sc->sc_cmd_waiting);
+	STAILQ_INIT(&sc->sc_cmd_inactive);
 	UATH_UNLOCK(sc);
 
-	ieee80211_ifdetach(ic);
 	uath_stop(ifp);
 
 	callout_drain(&sc->stat_ch);
 	callout_drain(&sc->watchdog_ch);
 
-	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+	/* drain USB transfers */
+	for (x = 0; x != UATH_N_XFERS; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
 
-	/* free buffers */
+	/* free data buffers */
 	UATH_LOCK(sc);
 	uath_free_rx_data_list(sc);
 	uath_free_tx_data_list(sc);
-	uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+	uath_free_cmd_list(sc, sc->sc_cmd);
 	UATH_UNLOCK(sc);
 
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
 	return (0);
@@ -533,20 +552,18 @@
 }
 
 static void
-uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
+uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
 {
 	int i;
 
-	for (i = 0; i < ncmd; i++)
-		if (cmds[i].buf != NULL)
-			free(cmds[i].buf, M_USBDEV);
+	for (i = 0; i != UATH_CMD_LIST_COUNT; i++)
+		cmds[i].buf = NULL;
 }
 
 static int
-uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
-	int ncmd, int maxsz)
+uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
 {
-	int i, error;
+	int i;
 
 	STAILQ_INIT(&sc->sc_cmd_active);
 	STAILQ_INIT(&sc->sc_cmd_pending);
@@ -553,25 +570,17 @@
 	STAILQ_INIT(&sc->sc_cmd_waiting);
 	STAILQ_INIT(&sc->sc_cmd_inactive);
 
-	for (i = 0; i < ncmd; i++) {
+	for (i = 0; i != UATH_CMD_LIST_COUNT; i++) {
 		struct uath_cmd *cmd = &cmds[i];
 
 		cmd->sc = sc;	/* backpointer for callbacks */
 		cmd->msgid = i;
-		cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-		if (cmd->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate xfer buffer\n");
-			error = ENOMEM;
-			goto fail;
-		}
+		cmd->buf = ((uint8_t *)sc->sc_cmd_dma_buf) +
+		    (i * UATH_MAX_CMDSZ);
 		STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
 		UATH_STAT_INC(sc, st_cmd_inactive);
 	}
 	return (0);
-
-fail:	uath_free_cmd_list(sc, cmds, ncmd);
-	return (error);
 }
 
 static int
@@ -942,21 +951,18 @@
 				dp->buf = NULL;
 			}
 		} else {
-			if (dp->buf != NULL) {
-				free(dp->buf, M_USBDEV);
-				dp->buf = NULL;
-			}
+			dp->buf = NULL;
 		}
-#ifdef UATH_DEBUG
-		if (dp->ni != NULL)
-			device_printf(sc->sc_dev, "Node isn't NULL\n");
-#endif
+		if (dp->ni != NULL) {
+			ieee80211_free_node(dp->ni);
+			dp->ni = NULL;
+		}
 	}
 }
 
 static int
 uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
-	int ndata, int maxsz, int fillmbuf)
+    int ndata, int maxsz, void *dma_buf)
 {
 	int i, error;
 
@@ -964,7 +970,7 @@
 		struct uath_data *dp = &data[i];
 
 		dp->sc = sc;
-		if (fillmbuf) {
+		if (dma_buf == NULL) {
 			/* XXX check maxsz */
 			dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 			if (dp->m == NULL) {
@@ -976,13 +982,7 @@
 			dp->buf = mtod(dp->m, uint8_t *);
 		} else {
 			dp->m = NULL;
-			dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-			if (dp->buf == NULL) {
-				device_printf(sc->sc_dev,
-				    "could not allocate buffer\n");
-				error = ENOMEM;
-				goto fail;
-			}
+			dp->buf = ((uint8_t *)dma_buf) + (i * maxsz);
 		}
 		dp->ni = NULL;
 	}
@@ -989,7 +989,7 @@
 
 	return (0);
 
-fail:	uath_free_data_list(sc, data, ndata, fillmbuf);
+fail:	uath_free_data_list(sc, data, ndata, 1 /* free mbufs */);
 	return (error);
 }
 
@@ -1001,7 +1001,7 @@
 	/* XXX is it enough to store the RX packet with MCLBYTES bytes?  */
 	error = uath_alloc_data_list(sc,
 	    sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
-	    1 /* setup mbufs */);
+	    NULL /* setup mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -1024,7 +1024,7 @@
 
 	error = uath_alloc_data_list(sc,
 	    sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
-	    0 /* no mbufs */);
+	    sc->sc_tx_dma_buf);
 	if (error != 0)
 		return (error);
 
@@ -1044,10 +1044,6 @@
 static void
 uath_free_rx_data_list(struct uath_softc *sc)
 {
-
-	STAILQ_INIT(&sc->sc_rx_active);
-	STAILQ_INIT(&sc->sc_rx_inactive);
-
 	uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
 	    1 /* free mbufs */);
 }
@@ -1055,11 +1051,6 @@
 static void
 uath_free_tx_data_list(struct uath_softc *sc)
 {
-
-	STAILQ_INIT(&sc->sc_tx_active);
-	STAILQ_INIT(&sc->sc_tx_inactive);
-	STAILQ_INIT(&sc->sc_tx_pending);
-
 	uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
 	    0 /* no mbufs */);
 }
@@ -1081,9 +1072,14 @@
 		return (NULL);
 	vap = &uvp->vap;
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(uvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	/* override state transition machine */
 	uvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = uath_newstate;
@@ -1562,8 +1558,16 @@
 {
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	struct uath_softc *sc = ifp->if_softc;
+	int error;
+	int startall = 0;
 
+	UATH_LOCK(sc);
+	error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
+	UATH_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		if (ifp->if_flags & IFF_UP) {
@@ -2741,8 +2745,7 @@
 		UATH_STAT_DEC(sc, st_rx_inactive);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
 		UATH_STAT_INC(sc, st_rx_active);
-		usbd_xfer_set_frame_data(xfer, 0, data->buf,
-		    usbd_xfer_max_len(xfer));
+		usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
 		usbd_transfer_submit(xfer);
 
 		/*
@@ -2890,7 +2893,7 @@
 	DEVMETHOD(device_probe, uath_match),
 	DEVMETHOD(device_attach, uath_attach),
 	DEVMETHOD(device_detach, uath_detach),
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 static driver_t uath_driver = {
 	.name = "uath",

Modified: stable/0.8/sys/dev/usb/wlan/if_uathreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uathreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uathreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$OpenBSD: if_uathreg.h,v 1.2 2006/09/18 16:34:23 damien Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_uathreg.h 190688 2009-04-04 11:23:00Z weongyo $	*/
 
 /*-
  * Copyright (c) 2006

Modified: stable/0.8/sys/dev/usb/wlan/if_uathvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uathvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uathvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$OpenBSD: if_uathvar.h,v 1.3 2006/09/20 19:47:17 damien Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_uathvar.h 259460 2013-12-16 09:34:01Z hselasky $	*/
 
 /*-
  * Copyright (c) 2006
@@ -52,7 +52,7 @@
 	int8_t		wr_antsignal;
 	int8_t		wr_antnoise;
 	u_int8_t	wr_antenna;
-} __packed;
+} __packed __aligned(8);
 
 #define UATH_RX_RADIOTAP_PRESENT (		\
 	(1 << IEEE80211_RADIOTAP_TSFT)		| \
@@ -69,7 +69,7 @@
 	uint8_t		wt_flags;
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
 
 #define	UATH_TX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -186,6 +186,8 @@
 	struct ifnet			*sc_ifp;
 	device_t			sc_dev;
 	struct usb_device		*sc_udev;
+	void				*sc_cmd_dma_buf;
+	void				*sc_tx_dma_buf;
 	struct mtx			sc_mtx;
 	uint32_t			sc_debug;
 

Modified: stable/0.8/sys/dev/usb/wlan/if_upgt.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_upgt.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_upgt.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$OpenBSD: if_upgt.c,v 1.35 2008/04/16 18:32:15 damien Exp $ */
-/*	$MidnightBSD$ */
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_upgt.c 292184 2015-12-14 09:42:39Z hselasky $ */
 
 /*
  * Copyright (c) 2007 Marcus Glocker <mglocker at openbsd.org>
@@ -182,7 +182,7 @@
 	UPGT_DEV(FSC,		E5400),
 	UPGT_DEV(GLOBESPAN,	PRISM_GT_1),
 	UPGT_DEV(GLOBESPAN,	PRISM_GT_2),
-	UPGT_DEV(NETGEAR,	WG111V2_2),
+	UPGT_DEV(NETGEAR,	WG111V1_2),
 	UPGT_DEV(INTERSIL,	PRISM_GT),
 	UPGT_DEV(SMC,		2862WG),
 	UPGT_DEV(USR,		USR5422),
@@ -201,9 +201,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = MCLBYTES,
+		.bufsize = MCLBYTES * UPGT_TX_MAXCOUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1
 		},
@@ -214,9 +213,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = MCLBYTES,
+		.bufsize = MCLBYTES * UPGT_RX_MAXCOUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.pipe_bof = 1,
 			.short_xfer_ok = 1
 		},
@@ -261,22 +259,27 @@
 	callout_init(&sc->sc_led_ch, 0);
 	callout_init(&sc->sc_watchdog_ch, 0);
 
-	/* Allocate TX and RX xfers.  */
-	error = upgt_alloc_tx(sc);
-	if (error)
-		goto fail1;
-	error = upgt_alloc_rx(sc);
-	if (error)
-		goto fail2;
-
 	error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
 	    upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
 	if (error) {
 		device_printf(dev, "could not allocate USB transfers, "
 		    "err=%s\n", usbd_errstr(error));
-		goto fail3;
+		goto fail1;
 	}
 
+	sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer(
+	    sc->sc_xfer[UPGT_BULK_RX], 0);
+	sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(
+	    sc->sc_xfer[UPGT_BULK_TX], 0);
+
+	/* Setup TX and RX buffers */
+	error = upgt_alloc_tx(sc);
+	if (error)
+		goto fail2;
+	error = upgt_alloc_rx(sc);
+	if (error)
+		goto fail3;
+
 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
 	if (ifp == NULL) {
 		device_printf(dev, "can not if_alloc()\n");
@@ -379,9 +382,9 @@
 	return (0);
 
 fail5:	if_free(ifp);
-fail4:	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
-fail3:	upgt_free_rx(sc);
-fail2:	upgt_free_tx(sc);
+fail4:	upgt_free_rx(sc);
+fail3:	upgt_free_tx(sc);
+fail2:	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
 fail1:	mtx_destroy(&sc->sc_mtx);
 
 	return (error);
@@ -425,7 +428,7 @@
 
 	data_cmd = upgt_getbuf(sc);
 	if (data_cmd == NULL) {
-		device_printf(sc->sc_dev, "%s: out of buffer.\n", __func__);
+		device_printf(sc->sc_dev, "%s: out of buffers.\n", __func__);
 		return;
 	}
 
@@ -463,8 +466,15 @@
 	struct upgt_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
 
+	UPGT_LOCK(sc);
+	error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
+	UPGT_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		if (ifp->if_flags & IFF_UP) {
@@ -1030,9 +1040,14 @@
 		return NULL;
 	vap = &uvp->vap;
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(uvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	/* override state transition machine */
 	uvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = upgt_newstate;
@@ -1583,7 +1598,6 @@
 			data_tx->ni = NULL;
 			data_tx->addr = 0;
 			data_tx->m = NULL;
-			data_tx->use = 0;
 
 			DPRINTF(sc, UPGT_DEBUG_TX_PROC,
 			    "TX done: memaddr=0x%08x, status=0x%04x, rssi=%d, ",
@@ -1978,13 +1992,7 @@
 
 	for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_tx_data[i];
-
-		data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
-		if (data->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate TX buffer\n");
-			return (ENOMEM);
-		}
+		data->buf = ((uint8_t *)sc->sc_tx_dma_buf) + (i * MCLBYTES);
 		STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
 		UPGT_STAT_INC(sc, st_tx_inactive);
 	}
@@ -2002,16 +2010,9 @@
 
 	for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_rx_data[i];
-
-		data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
-		if (data->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate RX buffer\n");
-			return (ENOMEM);
-		}
+		data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
 	}
-
 	return (0);
 }
 
@@ -2021,20 +2022,42 @@
 	struct upgt_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
 
-	if (!device_is_attached(dev))
-		return 0;
+	/*
+	 * Prevent further allocations from RX/TX/CMD
+	 * data lists and ioctls
+	 */
+	UPGT_LOCK(sc);
+	sc->sc_flags |= UPGT_FLAG_DETACHED;
 
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
+
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+	UPGT_UNLOCK(sc);
+
 	upgt_stop(sc);
 
 	callout_drain(&sc->sc_led_ch);
 	callout_drain(&sc->sc_watchdog_ch);
 
-	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
-	ieee80211_ifdetach(ic);
+	/* drain USB transfers */
+	for (x = 0; x != UPGT_N_XFERS; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
+
+	/* free data buffers */
+	UPGT_LOCK(sc);
 	upgt_free_rx(sc);
 	upgt_free_tx(sc);
+	UPGT_UNLOCK(sc);
 
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
+
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
 
@@ -2049,7 +2072,7 @@
 	for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_rx_data[i];
 
-		free(data->buf, M_USBDEV);
+		data->buf = NULL;
 		data->ni = NULL;
 	}
 }
@@ -2062,7 +2085,10 @@
 	for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_tx_data[i];
 
-		free(data->buf, M_USBDEV);
+		if (data->ni != NULL)
+			ieee80211_free_node(data->ni);
+
+		data->buf = NULL;
 		data->ni = NULL;
 	}
 }
@@ -2304,8 +2330,7 @@
 			return;
 		STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
-		usbd_xfer_set_frame_data(xfer, 0, data->buf,
-		    usbd_xfer_max_len(xfer));
+		usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
 		usbd_transfer_submit(xfer);
 
 		/*
@@ -2408,8 +2433,7 @@
         DEVMETHOD(device_probe, upgt_match),
         DEVMETHOD(device_attach, upgt_attach),
         DEVMETHOD(device_detach, upgt_detach),
-	
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t upgt_driver = {

Modified: stable/0.8/sys/dev/usb/wlan/if_upgtvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_upgtvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_upgtvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,5 +1,5 @@
 /*	$OpenBSD: if_upgtvar.h,v 1.14 2008/02/02 13:48:44 mglocker Exp $ */
-/*	$MidnightBSD$ */
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_upgtvar.h 259460 2013-12-16 09:34:01Z hselasky $ */
 
 /*
  * Copyright (c) 2007 Marcus Glocker <mglocker at openbsd.org>
@@ -352,7 +352,6 @@
 	struct ieee80211_node		*ni;
 	struct mbuf			*m;
 	uint32_t			 addr;
-	uint8_t				 use;
 	STAILQ_ENTRY(upgt_data)		 next;
 };
 typedef STAILQ_HEAD(, upgt_data) upgt_datahead;
@@ -381,7 +380,7 @@
 	uint16_t	wr_chan_freq;
 	uint16_t	wr_chan_flags;
 	int8_t		wr_antsignal;
-} __packed;
+} __packed __aligned(8);
 
 #define UPGT_RX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -395,7 +394,7 @@
 	uint8_t		wt_rate;
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
 
 #define UPGT_TX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -422,11 +421,14 @@
 	device_t		 sc_dev;
 	struct ifnet		*sc_ifp;
 	struct usb_device	*sc_udev;
+	void			*sc_rx_dma_buf;
+	void			*sc_tx_dma_buf;
 	struct mtx		 sc_mtx;
 	struct upgt_stat	 sc_stat;
 	int			 sc_flags;
 #define	UPGT_FLAG_FWLOADED	 (1 << 0)
 #define	UPGT_FLAG_INITDONE	 (1 << 1)
+#define	UPGT_FLAG_DETACHED	 (1 << 2)
 	int			 sc_if_flags;
 	int			 sc_debug;
 

Modified: stable/0.8/sys/dev/usb/wlan/if_ural.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_ural.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_ural.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_ural.c 269267 2014-07-29 22:00:54Z hselasky $	*/
 
 /*-
  * Copyright (c) 2005, 2006
@@ -21,7 +21,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_ural.c 269267 2014-07-29 22:00:54Z hselasky $");
 
 /*-
  * Ralink Technology RT2500USB chipset driver
@@ -385,8 +385,7 @@
 	DEVMETHOD(device_probe,		ural_match),
 	DEVMETHOD(device_attach,	ural_attach),
 	DEVMETHOD(device_detach,	ural_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t ural_driver = {
@@ -528,6 +527,11 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
 
+	/* prevent further ioctls */
+	RAL_LOCK(sc);
+	sc->sc_detached = 1;
+	RAL_UNLOCK(sc);
+
 	/* stop all USB transfers */
 	usbd_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
 
@@ -585,9 +589,14 @@
 		return NULL;
 	vap = &uvp->vap;
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(uvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	/* override state transition machine */
 	uvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = ural_newstate;
@@ -1028,6 +1037,8 @@
 		desc->plcp_length_hi = plcp_length >> 6;
 		desc->plcp_length_lo = plcp_length & 0x3f;
 	} else {
+		if (rate == 0)
+			rate = 2;	/* avoid division by zero */
 		plcp_length = (16 * len + rate - 1) / rate;
 		if (rate == 22) {
 			remainder = (16 * len) % 22;
@@ -1129,7 +1140,7 @@
 
 		dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate, 
 		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 
 		/* tell hardware to add timestamp for probe responses */
 		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
@@ -1320,7 +1331,7 @@
 
 		dur = ieee80211_ack_duration(ic->ic_rt, rate, 
 		    ic->ic_flags & IEEE80211_F_SHPREAMBLE);
-		*(uint16_t *)wh->i_dur = htole16(dur);
+		USETW(wh->i_dur, dur);
 	}
 
 	ural_setup_tx_desc(sc, &data->desc, flags, m0->m_pkthdr.len, rate);
@@ -1371,8 +1382,15 @@
 	struct ural_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
 
+	RAL_LOCK(sc);
+	error = sc->sc_detached ? ENXIO : 0;
+	RAL_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		RAL_LOCK(sc);

Modified: stable/0.8/sys/dev/usb/wlan/if_uralreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uralreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uralreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_uralreg.h 196219 2009-08-14 20:03:53Z jhb $	*/
 
 /*-
  * Copyright (c) 2005, 2006

Modified: stable/0.8/sys/dev/usb/wlan/if_uralvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_uralvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_uralvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_uralvar.h 259460 2013-12-16 09:34:01Z hselasky $	*/
 
 /*-
  * Copyright (c) 2005
@@ -34,7 +34,7 @@
 	int8_t		wr_antsignal;
 	int8_t		wr_antnoise;
 	uint8_t		wr_antenna;
-};
+} __packed __aligned(8);
 
 #define RAL_RX_RADIOTAP_PRESENT						\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -51,7 +51,7 @@
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
 	uint8_t		wt_antenna;
-};
+} __packed __aligned(8);
 
 #define RAL_TX_RADIOTAP_PRESENT						\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -110,6 +110,7 @@
 	uint32_t			rf_regs[4];
 	uint8_t				txpow[14];
 	uint8_t				sc_bssid[6];
+	uint8_t				sc_detached;
 
 	struct {
 		uint8_t			val;

Modified: stable/0.8/sys/dev/usb/wlan/if_urtw.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtw.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtw.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -15,7 +15,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_urtw.c 260575 2014-01-12 21:21:19Z hselasky $");
 #include <sys/param.h>
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
@@ -477,6 +477,7 @@
 	{ 96, 10 }, { 108, 11 }
 };
 
+#if 0
 static const uint8_t urtw_8187b_reg_table[][3] = {
 	{ 0xf0, 0x32, 0 }, { 0xf1, 0x32, 0 }, { 0xf2, 0x00, 0 },
 	{ 0xf3, 0x00, 0 }, { 0xf4, 0x32, 0 }, { 0xf5, 0x43, 0 },
@@ -510,6 +511,7 @@
 	{ 0x4c, 0x00, 2 }, { 0x9f, 0x00, 3 }, { 0x8c, 0x01, 0 },
 	{ 0x8d, 0x10, 0 }, { 0x8e, 0x08, 0 }, { 0x8f, 0x00, 0 }
 };
+#endif
 
 static usb_callback_t urtw_bulk_rx_callback;
 static usb_callback_t urtw_bulk_tx_callback;
@@ -532,9 +534,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x89,
 		.direction = UE_DIR_IN,
-		.bufsize = MCLBYTES,
+		.bufsize = sizeof(uint64_t),
 		.flags = {
-			.ext_buffer = 1,
 			.pipe_bof = 1,
 			.short_xfer_ok = 1
 		},
@@ -544,9 +545,8 @@
 		.type = UE_BULK,
 		.endpoint = URTW_8187B_TXPIPE_BE,
 		.direction = UE_DIR_OUT,
-		.bufsize = URTW_TX_MAXSIZE,
+		.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -624,9 +624,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x2,
 		.direction = UE_DIR_OUT,
-		.bufsize = URTW_TX_MAXSIZE,
+		.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -654,8 +653,8 @@
 			    const uint8_t [IEEE80211_ADDR_LEN]);
 static void		urtw_vap_delete(struct ieee80211vap *);
 static void		urtw_init(void *);
-static void		urtw_stop(struct ifnet *, int);
-static void		urtw_stop_locked(struct ifnet *, int);
+static void		urtw_stop(struct ifnet *);
+static void		urtw_stop_locked(struct ifnet *);
 static int		urtw_ioctl(struct ifnet *, u_long, caddr_t);
 static void		urtw_start(struct ifnet *);
 static int		urtw_alloc_rx_data_list(struct urtw_softc *);
@@ -827,6 +826,16 @@
 		goto fail0;
 	}
 
+	if (sc->sc_flags & URTW_RTL8187B) {
+		sc->sc_tx_dma_buf = 
+		    usbd_xfer_get_frame_buffer(sc->sc_xfer[
+		    URTW_8187B_BULK_TX_BE], 0);
+	} else {
+		sc->sc_tx_dma_buf =
+		    usbd_xfer_get_frame_buffer(sc->sc_xfer[
+		    URTW_8187L_BULK_TX_LOW], 0);
+	}
+
 	URTW_LOCK(sc);
 
 	urtw_read32_m(sc, URTW_RX, &data);
@@ -926,11 +935,16 @@
 	struct urtw_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic = ifp->if_l2com;
+	unsigned int x;
+	unsigned int n_xfers;
 
-	if (!device_is_attached(dev))
-		return (0);
+	/* Prevent further ioctls */
+	URTW_LOCK(sc);
+	sc->sc_flags |= URTW_DETACHED;
+	URTW_UNLOCK(sc);
 
-	urtw_stop(ifp, 1);
+	urtw_stop(ifp);
+
 	ieee80211_draintask(ic, &sc->sc_updateslot_task);
 	ieee80211_draintask(ic, &sc->sc_led_task);
 
@@ -937,16 +951,35 @@
 	usb_callout_drain(&sc->sc_led_ch);
 	callout_drain(&sc->sc_watchdog_ch);
 
-	usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
-	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
-	ieee80211_ifdetach(ic);
+	n_xfers = (sc->sc_flags & URTW_RTL8187B) ?
+	    URTW_8187B_N_XFERS : URTW_8187L_N_XFERS;
 
+	/* prevent further allocations from RX/TX data lists */
+	URTW_LOCK(sc);
+	STAILQ_INIT(&sc->sc_tx_active);
+	STAILQ_INIT(&sc->sc_tx_inactive);
+	STAILQ_INIT(&sc->sc_tx_pending);
+
+	STAILQ_INIT(&sc->sc_rx_active);
+	STAILQ_INIT(&sc->sc_rx_inactive);
+	URTW_UNLOCK(sc);
+
+	/* drain USB transfers */
+	for (x = 0; x != n_xfers; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
+
+	/* free data buffers */
+	URTW_LOCK(sc);
 	urtw_free_tx_data_list(sc);
 	urtw_free_rx_data_list(sc);
+	URTW_UNLOCK(sc);
 
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
+
+	ieee80211_ifdetach(ic);
 	if_free(ifp);
 	mtx_destroy(&sc->sc_mtx);
-
 	return (0);
 }
 
@@ -953,7 +986,6 @@
 static void
 urtw_free_tx_data_list(struct urtw_softc *sc)
 {
-
 	urtw_free_data_list(sc, sc->sc_tx, URTW_TX_DATA_LIST_COUNT, 0);
 }
 
@@ -960,7 +992,6 @@
 static void
 urtw_free_rx_data_list(struct urtw_softc *sc)
 {
-
 	urtw_free_data_list(sc, sc->sc_rx, URTW_RX_DATA_LIST_COUNT, 1);
 }
 
@@ -980,10 +1011,7 @@
 				dp->buf = NULL;
 			}
 		} else {
-			if (dp->buf != NULL) {
-				free(dp->buf, M_USBDEV);
-				dp->buf = NULL;
-			}
+			dp->buf = NULL;
 		}
 		if (dp->ni != NULL) {
 			ieee80211_free_node(dp->ni);
@@ -1009,9 +1037,14 @@
 		return (NULL);
 	vap = &uvp->vap;
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
 
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(uvp, M_80211_VAP);
+		return (NULL);
+	}
+
 	/* override state transition machine */
 	uvp->newstate = vap->iv_newstate;
 	vap->iv_newstate = urtw_newstate;
@@ -1041,7 +1074,7 @@
 	usb_error_t error;
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-		urtw_stop_locked(ifp, 0);
+		urtw_stop_locked(ifp);
 
 	error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
 	    urtw_adapter_start(sc);
@@ -1304,13 +1337,12 @@
 }
 
 static void
-urtw_stop_locked(struct ifnet *ifp, int disable)
+urtw_stop_locked(struct ifnet *ifp)
 {
 	struct urtw_softc *sc = ifp->if_softc;
 	uint8_t data8;
 	usb_error_t error;
 
-	(void)disable;
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
 	error = urtw_intr_disable(sc);
@@ -1344,12 +1376,12 @@
 }
 
 static void
-urtw_stop(struct ifnet *ifp, int disable)
+urtw_stop(struct ifnet *ifp)
 {
 	struct urtw_softc *sc = ifp->if_softc;
 
 	URTW_LOCK(sc);
-	urtw_stop_locked(ifp, disable);
+	urtw_stop_locked(ifp);
 	URTW_UNLOCK(sc);
 }
 
@@ -1374,8 +1406,15 @@
 	struct urtw_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
 
+	URTW_LOCK(sc);
+	error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
+	URTW_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		if (ifp->if_flags & IFF_UP) {
@@ -1389,7 +1428,7 @@
 			}
 		} else {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-				urtw_stop(ifp, 1);
+				urtw_stop(ifp);
 		}
 		sc->sc_if_flags = ifp->if_flags;
 		if (startall)
@@ -1405,7 +1444,6 @@
 		error = EINVAL;
 		break;
 	}
-
 	return (error);
 }
 
@@ -1449,7 +1487,7 @@
 
 static int
 urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
-	int ndata, int maxsz, int fillmbuf)
+    int ndata, int maxsz, void *dma_buf)
 {
 	int i, error;
 
@@ -1457,7 +1495,7 @@
 		struct urtw_data *dp = &data[i];
 
 		dp->sc = sc;
-		if (fillmbuf) {
+		if (dma_buf == NULL) {
 			dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 			if (dp->m == NULL) {
 				device_printf(sc->sc_dev,
@@ -1468,24 +1506,15 @@
 			dp->buf = mtod(dp->m, uint8_t *);
 		} else {
 			dp->m = NULL;
-			dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-			if (dp->buf == NULL) {
-				device_printf(sc->sc_dev,
-				    "could not allocate buffer\n");
-				error = ENOMEM;
-				goto fail;
-			}
-			if (((unsigned long)dp->buf) % 4)
-				device_printf(sc->sc_dev,
-				    "warn: unaligned buffer %p\n", dp->buf);
+			dp->buf = ((uint8_t *)dma_buf) +
+			    (i * maxsz);
 		}
 		dp->ni = NULL;
 	}
+	return (0);
 
-	return 0;
-
-fail:	urtw_free_data_list(sc, data, ndata, fillmbuf);
-	return error;
+fail:	urtw_free_data_list(sc, data, ndata, 1);
+	return (error);
 }
 
 static int
@@ -1494,7 +1523,8 @@
 	int error, i;
 
 	error = urtw_alloc_data_list(sc,
-	    sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */);
+	    sc->sc_rx, URTW_RX_DATA_LIST_COUNT,
+	    MCLBYTES, NULL /* mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -1514,7 +1544,7 @@
 
 	error = urtw_alloc_data_list(sc,
 	    sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
-	    0 /* no mbufs */);
+	    sc->sc_tx_dma_buf /* no mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -1738,7 +1768,7 @@
 		else
 			dur = URTW_ASIFS_TIME + acktime;
 	}
-	*(uint16_t *)wh->i_dur = htole16(dur);
+	USETW(wh->i_dur, dur);
 
 	xferlen = m0->m_pkthdr.len;
 	xferlen += (sc->sc_flags & URTW_RTL8187B) ? (4 * 8) : (4 * 3);
@@ -1994,9 +2024,11 @@
 			data |= URTW_MSR_LINK_HOSTAP;
 			break;
 		default:
-			panic("unsupported operation mode 0x%x\n",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported operation mode 0x%x\n",
 			    ic->ic_opmode);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else
 		data |= URTW_MSR_LINK_NONE;
@@ -2427,8 +2459,10 @@
 		sc->sc_rf_stop = urtw_8225_rf_stop;
 		break;
 	default:
-		panic("unsupported RF chip %d\n", data & 0xff);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported RF chip %d\n", data & 0xff);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	device_printf(sc->sc_dev, "%s rf %s hwrev %s\n",
@@ -2709,42 +2743,28 @@
 	return (error);
 }
 
-/* XXX why we should allocalte memory buffer instead of using memory stack?  */
 static usb_error_t
 urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
     uint16_t *data)
 {
-	uint8_t *buf;
+	uint8_t buf[2];
 	uint16_t data16;
-	struct usb_device_request *req;
+	struct usb_device_request req;
 	usb_error_t error = 0;
 
 	data16 = *data;
-	req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t),
-	    M_80211_VAP, M_NOWAIT | M_ZERO);
-	if (req == NULL) {
-		device_printf(sc->sc_dev, "could not allocate a memory\n");
-		goto fail0;
-	}
-	buf = (uint8_t *)malloc(2, M_80211_VAP, M_NOWAIT | M_ZERO);
-	if (req == NULL) {
-		device_printf(sc->sc_dev, "could not allocate a memory\n");
-		goto fail1;
-	}
 
-	req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
-	req->bRequest = URTW_8187_SETREGS_REQ;
-	USETW(req->wValue, addr);
-	USETW(req->wIndex, index);
-	USETW(req->wLength, sizeof(uint16_t));
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = URTW_8187_SETREGS_REQ;
+	USETW(req.wValue, addr);
+	USETW(req.wIndex, index);
+	USETW(req.wLength, sizeof(uint16_t));
 	buf[0] = (data16 & 0x00ff);
 	buf[1] = (data16 & 0xff00) >> 8;
 
-	error = urtw_do_request(sc, req, buf);
+	error = urtw_do_request(sc, &req, buf);
 
-	free(buf, M_80211_VAP);
-fail1:	free(req, M_80211_VAP);
-fail0:	return (error);
+	return (error);
 }
 
 static usb_error_t
@@ -3622,8 +3642,10 @@
 		error = urtw_led_mode3(sc, mode);
 		break;
 	default:
-		panic("unsupported LED mode %d\n", sc->sc_strategy);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED mode %d\n", sc->sc_strategy);
+		error = USB_ERR_INVAL;
+		break;
 	}
 
 	return (error);
@@ -3648,8 +3670,9 @@
 		sc->sc_gpio_ledstate = URTW_LED_ON;
 		break;
 	default:
-		panic("unsupported LED mode 0x%x", mode);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED mode 0x%x", mode);
+		return (USB_ERR_INVAL);
 	}
 
 	switch (sc->sc_gpio_ledstate) {
@@ -3672,8 +3695,9 @@
 		urtw_led_off(sc, URTW_LED_GPIO);
 		break;
 	default:
-		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unknown LED status 0x%x", sc->sc_gpio_ledstate);
+		return (USB_ERR_INVAL);
 	}
 	return (0);
 }
@@ -3681,7 +3705,6 @@
 static usb_error_t
 urtw_led_mode1(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
@@ -3688,7 +3711,6 @@
 static usb_error_t
 urtw_led_mode2(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
@@ -3695,7 +3717,6 @@
 static usb_error_t
 urtw_led_mode3(struct urtw_softc *sc, int mode)
 {
-
 	return (USB_ERR_INVAL);
 }
 
@@ -3711,13 +3732,17 @@
 			urtw_write8_m(sc, URTW_GP_ENABLE, 0x00);
 			break;
 		default:
-			panic("unsupported LED PIN type 0x%x",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported LED PIN type 0x%x",
 			    sc->sc_gpio_ledpin);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else {
-		panic("unsupported LED type 0x%x", type);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED type 0x%x", type);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	sc->sc_gpio_ledon = 1;
@@ -3738,13 +3763,17 @@
 			    URTW_GP_ENABLE, URTW_GP_ENABLE_DATA_MAGIC1);
 			break;
 		default:
-			panic("unsupported LED PIN type 0x%x",
+			DPRINTF(sc, URTW_DEBUG_STATE,
+			    "unsupported LED PIN type 0x%x",
 			    sc->sc_gpio_ledpin);
-			/* never reach  */
+			error = USB_ERR_INVAL;
+			goto fail;
 		}
 	} else {
-		panic("unsupported LED type 0x%x", type);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unsupported LED type 0x%x", type);
+		error = USB_ERR_INVAL;
+		goto fail;
 	}
 
 	sc->sc_gpio_ledon = 0;
@@ -3768,8 +3797,12 @@
 {
 	struct urtw_softc *sc = arg;
 
-	if (sc->sc_strategy != URTW_SW_LED_MODE0)
-		panic("could not process a LED strategy 0x%x", sc->sc_strategy);
+	if (sc->sc_strategy != URTW_SW_LED_MODE0) {
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "could not process a LED strategy 0x%x",
+		    sc->sc_strategy);
+		return;
+	}
 
 	URTW_LOCK(sc);
 	urtw_led_blink(sc);
@@ -3816,8 +3849,10 @@
 		usb_callout_reset(&sc->sc_led_ch, hz, urtw_led_ch, sc);
 		break;
 	default:
-		panic("unknown LED status 0x%x", sc->sc_gpio_ledstate);
-		/* never reach  */
+		DPRINTF(sc, URTW_DEBUG_STATE,
+		    "unknown LED status 0x%x",
+		    sc->sc_gpio_ledstate);
+		return (USB_ERR_INVAL);
 	}
 	return (0);
 }
@@ -4133,6 +4168,7 @@
 {
 	struct urtw_softc *sc = usbd_xfer_softc(xfer);
 	struct ifnet *ifp = sc->sc_ifp;
+	void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
 
 	URTW_ASSERT_LOCKED(sc);
 
@@ -4142,8 +4178,8 @@
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
 setup:
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus,
-		    sizeof(int64_t));
+		memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t));
+		usbd_xfer_set_frame_len(xfer, 0, sizeof(uint64_t));
 		usbd_transfer_submit(xfer);
 		break;
 	default:
@@ -4431,7 +4467,7 @@
 	DEVMETHOD(device_probe, urtw_match),
 	DEVMETHOD(device_attach, urtw_attach),
 	DEVMETHOD(device_detach, urtw_detach),
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 static driver_t urtw_driver = {
 	.name = "urtw",

Modified: stable/0.8/sys/dev/usb/wlan/if_urtwreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtwreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtwreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_urtwreg.h 198194 2009-10-18 00:11:49Z weongyo $	*/
 
 /*-
  * Copyright (c) 2008 Weongyo Jeong <weongyo at FreeBSD.org>

Modified: stable/0.8/sys/dev/usb/wlan/if_urtwvar.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_urtwvar.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_urtwvar.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,4 +1,4 @@
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_urtwvar.h 259460 2013-12-16 09:34:01Z hselasky $	*/
 
 /*-
  * Copyright (c) 2008 Weongyo Jeong <weongyo at FreeBSD.org>
@@ -63,7 +63,7 @@
 	uint16_t	wr_chan_freq;
 	uint16_t	wr_chan_flags;
 	int8_t		wr_dbm_antsignal;
-} __packed;
+} __packed __aligned(8);
 
 #define URTW_RX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -75,7 +75,7 @@
 	uint8_t		wt_flags;
 	uint16_t	wt_chan_freq;
 	uint16_t	wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
 
 #define URTW_TX_RADIOTAP_PRESENT					\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -97,6 +97,7 @@
 	device_t			sc_dev;
 	struct usb_device		*sc_udev;
 	struct mtx			sc_mtx;
+	void				*sc_tx_dma_buf;
 
 	int				sc_debug;
 	int				sc_if_flags;
@@ -106,6 +107,7 @@
 #define	URTW_RTL8187B_REV_B		(1 << 3)
 #define	URTW_RTL8187B_REV_D		(1 << 4)
 #define	URTW_RTL8187B_REV_E		(1 << 5)
+#define	URTW_DETACHED			(1 << 6)
 	enum ieee80211_state		sc_state;
 
 	int				sc_epromtype;

Modified: stable/0.8/sys/dev/usb/wlan/if_zyd.c
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zyd.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zyd.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
 /*	$OpenBSD: if_zyd.c,v 1.52 2007/02/11 00:08:04 jsg Exp $	*/
 /*	$NetBSD: if_zyd.c,v 1.7 2007/06/21 04:04:29 kiyohara Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_zyd.c 269267 2014-07-29 22:00:54Z hselasky $	*/
 
 /*-
  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini at free.fr>
@@ -20,7 +20,7 @@
  */
 
 #include <sys/cdefs.h>
-__MBSDID("$MidnightBSD$");
+__FBSDID("$FreeBSD: stable/9/sys/dev/usb/wlan/if_zyd.c 269267 2014-07-29 22:00:54Z hselasky $");
 
 /*
  * ZyDAS ZD1211/ZD1211B USB WLAN driver.
@@ -438,13 +438,30 @@
 	struct zyd_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
+	unsigned int x;
 
-	/* stop all USB transfers */
-	usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
+	/*
+	 * Prevent further allocations from RX/TX data
+	 * lists and ioctls:
+	 */
+	ZYD_LOCK(sc);
+	sc->sc_flags |= ZYD_FLAG_DETACHED;
+	STAILQ_INIT(&sc->tx_q);
+	STAILQ_INIT(&sc->tx_free);
+	ZYD_UNLOCK(sc);
 
+	/* drain USB transfers */
+	for (x = 0; x != ZYD_N_TRANSFER; x++)
+		usbd_transfer_drain(sc->sc_xfer[x]);
+
 	/* free TX list, if any */
+	ZYD_LOCK(sc);
 	zyd_unsetup_tx_list(sc);
+	ZYD_UNLOCK(sc);
 
+	/* free USB transfers and some data buffers */
+	usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
+
 	if (ifp) {
 		ic = ifp->if_l2com;
 		ieee80211_ifdetach(ic);
@@ -471,9 +488,14 @@
 	if (zvp == NULL)
 		return (NULL);
 	vap = &zvp->vap;
+
 	/* enable s/w bmiss handling for sta mode */
-	ieee80211_vap_setup(ic, vap, name, unit, opmode,
-	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+	if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
+	    flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+		/* out of memory */
+		free(zvp, M_80211_VAP);
+		return (NULL);
+	}
 
 	/* override state transition machine */
 	zvp->newstate = vap->iv_newstate;
@@ -2457,7 +2479,7 @@
 	const struct ieee80211_txparam *tp;
 	struct ieee80211_key *k;
 	int rate, totlen;
-	static uint8_t ratediv[] = ZYD_TX_RATEDIV;
+	static const uint8_t ratediv[] = ZYD_TX_RATEDIV;
 	uint8_t phy;
 	uint16_t pktlen;
 	uint32_t bits;
@@ -2637,8 +2659,15 @@
 	struct zyd_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = ifp->if_l2com;
 	struct ifreq *ifr = (struct ifreq *) data;
-	int error = 0, startall = 0;
+	int error;
+	int startall = 0;
 
+	ZYD_LOCK(sc);
+	error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
+	ZYD_UNLOCK(sc);
+	if (error)
+		return (error);
+
 	switch (cmd) {
 	case SIOCSIFFLAGS:
 		ZYD_LOCK(sc);
@@ -2928,8 +2957,7 @@
         DEVMETHOD(device_probe, zyd_match),
         DEVMETHOD(device_attach, zyd_attach),
         DEVMETHOD(device_detach, zyd_detach),
-
-	{ 0, 0 }
+	DEVMETHOD_END
 };
 
 static driver_t zyd_driver = {

Modified: stable/0.8/sys/dev/usb/wlan/if_zydfw.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zydfw.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zydfw.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_zydfw.h 196219 2009-08-14 20:03:53Z jhb $	*/
 
 uint8_t zd1211_firmware[] = {
 	0x08, 0x91, 0xFF, 0xED, 0x09, 0x93, 0x1E, 0xEE,

Modified: stable/0.8/sys/dev/usb/wlan/if_zydreg.h
===================================================================
--- stable/0.8/sys/dev/usb/wlan/if_zydreg.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/dev/usb/wlan/if_zydreg.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -1,6 +1,6 @@
 /*	$OpenBSD: if_zydreg.h,v 1.19 2006/11/30 19:28:07 damien Exp $	*/
 /*	$NetBSD: if_zydreg.h,v 1.2 2007/06/16 11:18:45 kiyohara Exp $	*/
-/*	$MidnightBSD$	*/
+/*	$FreeBSD: stable/9/sys/dev/usb/wlan/if_zydreg.h 269267 2014-07-29 22:00:54Z hselasky $	*/
 
 /*-
  * Copyright (c) 2006 by Damien Bergamini <damien.bergamini at free.fr>
@@ -970,7 +970,7 @@
 
 #define	ZYD_TX_RATEDIV							\
 {									\
-	0x1, 0x2, 0xb, 0xb, 0x0, 0x0, 0x0, 0x0, 0x30, 0x18, 0xc, 0x6,	\
+	0x1, 0x2, 0xb, 0xb, 0x1, 0x1, 0x1, 0x1, 0x30, 0x18, 0xc, 0x6,	\
 	0x36, 0x24, 0x12, 0x9						\
 }
 
@@ -1185,7 +1185,7 @@
 	uint16_t		wr_chan_flags;
 	int8_t			wr_antsignal;
 	int8_t			wr_antnoise;
-} __packed;
+} __packed __aligned(8);
 
 #define ZYD_RX_RADIOTAP_PRESENT						\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -1200,7 +1200,7 @@
 	uint8_t			wt_rate;
 	uint16_t		wt_chan_freq;
 	uint16_t		wt_chan_flags;
-} __packed;
+} __packed __aligned(8);
 
 #define ZYD_TX_RADIOTAP_PRESENT						\
 	((1 << IEEE80211_RADIOTAP_FLAGS) |				\
@@ -1259,6 +1259,7 @@
 #define	ZYD_FLAG_FWLOADED		(1 << 0)
 #define	ZYD_FLAG_INITONCE		(1 << 1)
 #define	ZYD_FLAG_INITDONE		(1 << 2)
+#define	ZYD_FLAG_DETACHED		(1 << 3)
 
 	struct zyd_rf		sc_rf;
 

Modified: stable/0.8/sys/fs/devfs/devfs_int.h
===================================================================
--- stable/0.8/sys/fs/devfs/devfs_int.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/fs/devfs/devfs_int.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -56,6 +56,7 @@
 	u_int			cdp_flags;
 #define CDP_ACTIVE		(1 << 0)
 #define CDP_SCHED_DTR		(1 << 1)
+#define	CDP_UNREF_DTR		(1 << 2)
 
 	u_int			cdp_inuse;
 	u_int			cdp_maxdirent;


Property changes on: stable/0.8/sys/fs/devfs/devfs_int.h
___________________________________________________________________
Deleted: cvs2svn:cvs-rev
## -1 +0,0 ##
-1.7
\ No newline at end of property
Modified: stable/0.8/sys/kern/kern_conf.c
===================================================================
--- stable/0.8/sys/kern/kern_conf.c	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/kern/kern_conf.c	2017-08-19 02:11:51 UTC (rev 9518)
@@ -115,6 +115,8 @@
 
 	mtx_assert(&devmtx, MA_OWNED);
 	cdp = cdev2priv(cdev);
+	KASSERT((cdp->cdp_flags & CDP_UNREF_DTR) == 0,
+	    ("destroy_dev() was not called after delist_dev(%p)", cdev));
 	TAILQ_INSERT_HEAD(&cdevp_free_list, cdp, cdp_list);
 }
 
@@ -306,7 +308,6 @@
 
 static struct cdevsw dead_cdevsw = {
 	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT, /* XXX: does dead_strategy need this ? */
 	.d_open =	dead_open,
 	.d_close =	dead_close,
 	.d_read =	dead_read,
@@ -993,9 +994,10 @@
 	max_parentpath_len = SPECNAMELEN - physpath_len - /*/*/1;
 	parentpath_len = strlen(pdev->si_name);
 	if (max_parentpath_len < parentpath_len) {
-		printf("make_dev_physpath_alias: WARNING - Unable to alias %s "
-		    "to %s/%s - path too long\n",
-		    pdev->si_name, physpath, pdev->si_name);
+		if (bootverbose)
+			printf("WARNING: Unable to alias %s "
+			    "to %s/%s - path too long\n",
+			    pdev->si_name, physpath, pdev->si_name);
 		ret = ENAMETOOLONG;
 		goto out;
 	}
@@ -1030,6 +1032,7 @@
 {
 	struct cdevsw *csw;
 	struct cdev_privdata *p;
+	struct cdev_priv *cdp;
 
 	mtx_assert(&devmtx, MA_OWNED);
 	KASSERT(dev->si_flags & SI_NAMED,
@@ -1038,13 +1041,22 @@
 	    ("WARNING: Driver mistake: destroy_dev on eternal %d\n",
 	     dev2unit(dev)));
 
-	devfs_destroy(dev);
+	cdp = cdev2priv(dev);
+	if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
+		/*
+		 * Avoid race with dev_rel(), e.g. from the populate
+		 * loop.  If CDP_UNREF_DTR flag is set, the reference
+		 * to be dropped at the end of destroy_devl() was
+		 * already taken by delist_dev_locked().
+		 */
+		dev_refl(dev);
 
+		devfs_destroy(dev);
+	}
+
 	/* Remove name marking */
 	dev->si_flags &= ~SI_NAMED;
 
-	dev->si_refcount++;	/* Avoid race with dev_rel() */
-
 	/* If we are a child, remove us from the parents list */
 	if (dev->si_flags & SI_CHILD) {
 		LIST_REMOVE(dev, si_siblings);
@@ -1076,9 +1088,12 @@
 	}
 
 	dev_unlock();
-	notify_destroy(dev);
+	if ((cdp->cdp_flags & CDP_UNREF_DTR) == 0) {
+		/* avoid out of order notify events */
+		notify_destroy(dev);
+	}
 	mtx_lock(&cdevpriv_mtx);
-	while ((p = LIST_FIRST(&cdev2priv(dev)->cdp_fdpriv)) != NULL) {
+	while ((p = LIST_FIRST(&cdp->cdp_fdpriv)) != NULL) {
 		devfs_destroy_cdevpriv(p);
 		mtx_lock(&cdevpriv_mtx);
 	}
@@ -1100,16 +1115,55 @@
 		}
 	}
 	dev->si_flags &= ~SI_ALIAS;
-	dev->si_refcount--;	/* Avoid race with dev_rel() */
+	cdp->cdp_flags &= ~CDP_UNREF_DTR;
+	dev->si_refcount--;
 
-	if (dev->si_refcount > 0) {
+	if (dev->si_refcount > 0)
 		LIST_INSERT_HEAD(&dead_cdevsw.d_devs, dev, si_list);
-	} else {
+	else
 		dev_free_devlocked(dev);
-	}
 }
 
+static void
+delist_dev_locked(struct cdev *dev)
+{
+	struct cdev_priv *cdp;
+	struct cdev *child;
+
+	mtx_assert(&devmtx, MA_OWNED);
+	cdp = cdev2priv(dev);
+	if ((cdp->cdp_flags & CDP_UNREF_DTR) != 0)
+		return;
+	cdp->cdp_flags |= CDP_UNREF_DTR;
+	dev_refl(dev);
+	devfs_destroy(dev);
+	LIST_FOREACH(child, &dev->si_children, si_siblings)
+		delist_dev_locked(child);
+	dev_unlock();	
+	/* ensure the destroy event is queued in order */
+	notify_destroy(dev);
+	dev_lock();
+}
+
+/*
+ * This function will delist a character device and its children from
+ * the directory listing and create a destroy event without waiting
+ * for all character device references to go away. At some later point
+ * destroy_dev() must be called to complete the character device
+ * destruction. After calling this function the character device name
+ * can instantly be re-used.
+ */
 void
+delist_dev(struct cdev *dev)
+{
+
+	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "delist_dev");
+	dev_lock();
+	delist_dev_locked(dev);
+	dev_unlock();
+}
+
+void
 destroy_dev(struct cdev *dev)
 {
 

Modified: stable/0.8/sys/sys/conf.h
===================================================================
--- stable/0.8/sys/sys/conf.h	2017-08-16 13:52:17 UTC (rev 9517)
+++ stable/0.8/sys/sys/conf.h	2017-08-19 02:11:51 UTC (rev 9518)
@@ -64,6 +64,7 @@
 #define SI_DUMPDEV	0x0080	/* is kernel dumpdev */
 #define SI_CANDELETE	0x0100	/* can do BIO_DELETE */
 #define SI_CLONELIST	0x0200	/* on a clone list */
+#define	SI_UNMAPPED	0x0400	/* can handle unmapped I/O */
 	struct timespec	si_atime;
 	struct timespec	si_ctime;
 	struct timespec	si_mtime;
@@ -171,6 +172,7 @@
 #define D_PSEUDO	0x00200000	/* make_dev() can return NULL */
 #define D_NEEDGIANT	0x00400000	/* driver want Giant */
 #define	D_NEEDMINOR	0x00800000	/* driver uses clone_create() */
+#define	D_UNMAPPED_IO   0x01000000	/* d_strategy can accept unmapped IO */
 
 /*
  * Version numbers.
@@ -245,6 +247,7 @@
 int clone_create(struct clonedevs **, struct cdevsw *, int *unit, struct cdev **dev, int extra);
 
 int	count_dev(struct cdev *_dev);
+void	delist_dev(struct cdev *_dev);
 void	destroy_dev(struct cdev *_dev);
 int	destroy_dev_sched(struct cdev *dev);
 int	destroy_dev_sched_cb(struct cdev *dev, void (*cb)(void *), void *arg);
@@ -258,6 +261,7 @@
 void	dev_refl(struct cdev *dev);
 void	dev_rel(struct cdev *dev);
 void	dev_strategy(struct cdev *dev, struct buf *bp);
+void	dev_strategy_csw(struct cdev *dev, struct cdevsw *csw, struct buf *bp);
 struct cdev *make_dev(struct cdevsw *_devsw, int _unit, uid_t _uid, gid_t _gid,
 		int _perms, const char *_fmt, ...) __printflike(6, 7);
 struct cdev *make_dev_cred(struct cdevsw *_devsw, int _unit,



More information about the Midnightbsd-cvs mailing list