[Midnightbsd-cvs] src: dev/usb: merge enhancements

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Nov 29 11:16:10 EST 2008


Log Message:
-----------
merge enhancements

Modified Files:
--------------
    src/sys/dev/usb:
        if_aue.c (r1.2 -> r1.3)
        if_ural.c (r1.3 -> r1.4)
        ohci.c (r1.4 -> r1.5)
        umass.c (r1.2 -> r1.3)

-------------- next part --------------
Index: if_aue.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/if_aue.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/usb/if_aue.c -L sys/dev/usb/if_aue.c -u -r1.2 -r1.3
--- sys/dev/usb/if_aue.c
+++ sys/dev/usb/if_aue.c
@@ -2,6 +2,9 @@
  * Copyright (c) 1997, 1998, 1999, 2000
  *	Bill Paul <wpaul at ee.columbia.edu>.  All rights reserved.
  *
+ * Copyright (c) 2006
+ *      Alfred Perlstein <alfred at freebsd.org>. All rights reserved.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -31,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/if_aue.c,v 1.90.2.3 2005/10/09 03:59:36 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_aue.c,v 1.117 2007/06/23 05:59:53 imp Exp $");
 
 /*
  * ADMtek AN986 Pegasus and AN8511 Pegasus II USB to ethernet driver.
@@ -40,6 +43,9 @@
  * Written by Bill Paul <wpaul at ee.columbia.edu>
  * Electrical Engineering Department
  * Columbia University, New York City
+ *
+ * SMP locking by Alfred Perlstein <alfred at freebsd.org>.
+ * RED Inc.
  */
 
 /*
@@ -68,8 +74,12 @@
 #include <sys/mbuf.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
+#include <sys/kdb.h>
+#include <sys/lock.h>
 #include <sys/module.h>
 #include <sys/socket.h>
+#include <sys/sx.h>
+#include <sys/taskqueue.h>
 
 #include <net/if.h>
 #include <net/if_arp.h>
@@ -82,9 +92,6 @@
 
 #include <sys/bus.h>
 #include <machine/bus.h>
-#if __FreeBSD_version < 500000
-#include <machine/clock.h>
-#endif
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -102,7 +109,7 @@
 MODULE_DEPEND(aue, ether, 1, 1, 1);
 MODULE_DEPEND(aue, miibus, 1, 1, 1);
 
-/* "controller miibus0" required.  See GENERIC if you get errors here. */
+/* "device miibus" required.  See GENERIC if you get errors here. */
 #include "miibus_if.h"
 
 /*
@@ -116,7 +123,7 @@
 #define PII	0x0004		/* Pegasus II chip */
 };
 
-Static const struct aue_type aue_devs[] = {
+static const struct aue_type aue_devs[] = {
  {{ USB_VENDOR_3COM,		USB_PRODUCT_3COM_3C460B},         PII },
  {{ USB_VENDOR_ABOCOM,		USB_PRODUCT_ABOCOM_XX1},	  PNA|PII },
  {{ USB_VENDOR_ABOCOM,		USB_PRODUCT_ABOCOM_XX2},	  PII },
@@ -134,6 +141,11 @@
  {{ USB_VENDOR_ADMTEK,		USB_PRODUCT_ADMTEK_PEGASUS},	  PNA },
  {{ USB_VENDOR_ADMTEK,		USB_PRODUCT_ADMTEK_PEGASUSII},	  PII },
  {{ USB_VENDOR_ADMTEK,		USB_PRODUCT_ADMTEK_PEGASUSII_2},  PII },
+ {{ USB_VENDOR_ADMTEK,		USB_PRODUCT_ADMTEK_PEGASUSII_3},  PII },
+ {{ USB_VENDOR_ADMTEK,		USB_PRODUCT_ADMTEK_PEGASUSII_4},  PII },
+ {{ USB_VENDOR_AEI,		USB_PRODUCT_AEI_FASTETHERNET},    PII },
+ {{ USB_VENDOR_ALLIEDTELESYN,	USB_PRODUCT_ALLIEDTELESYN_ATUSB100}, PII },
+ {{ USB_VENDOR_ATEN,		USB_PRODUCT_ATEN_UC110T},         PII },
  {{ USB_VENDOR_BELKIN,		USB_PRODUCT_BELKIN_USB2LAN},	  PII },
  {{ USB_VENDOR_BILLIONTON,	USB_PRODUCT_BILLIONTON_USB100},	  0 },
  {{ USB_VENDOR_BILLIONTON,	USB_PRODUCT_BILLIONTON_USBLP100}, PNA },
@@ -148,12 +160,15 @@
  {{ USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DSB650TX3},	  LSYS|PII },
  {{ USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DSB650TX2},	  LSYS|PII },
  {{ USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DSB650},	  LSYS },
+ {{ USB_VENDOR_ELCON,		USB_PRODUCT_ELCON_PLAN},	  PNA|PII },
+ {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSB20},	  PII },
  {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSBTX0},	  0 },
  {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSBTX1},	  LSYS },
  {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSBTX2},	  0 },
  {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSBTX3},	  LSYS },
  {{ USB_VENDOR_ELECOM,		USB_PRODUCT_ELECOM_LDUSBLTX},	  PII },
  {{ USB_VENDOR_ELSA,		USB_PRODUCT_ELSA_USB2ETHERNET},	  0 },
+ {{ USB_VENDOR_GIGABYTE,	USB_PRODUCT_GIGABYTE_GNBR402W},	  0 },
  {{ USB_VENDOR_HAWKING,		USB_PRODUCT_HAWKING_UF100},       PII },
  {{ USB_VENDOR_HP,		USB_PRODUCT_HP_HN210E},           PII },
  {{ USB_VENDOR_IODATA,		USB_PRODUCT_IODATA_USBETTX},	  0 },
@@ -165,55 +180,65 @@
  {{ USB_VENDOR_LINKSYS,		USB_PRODUCT_LINKSYS_USB100H1},	  LSYS|PNA },
  {{ USB_VENDOR_LINKSYS,		USB_PRODUCT_LINKSYS_USB10TA},	  LSYS },
  {{ USB_VENDOR_LINKSYS,		USB_PRODUCT_LINKSYS_USB10TX2},	  LSYS|PII },
- {{ USB_VENDOR_MICROSOFT,	USB_PRODUCT_MICROSOFT_MN110},	  PII },
  {{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_LUATX1},	  0 },
  {{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_LUATX5},	  0 },
  {{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_LUA2TX5},	  PII },
+ {{ USB_VENDOR_MICROSOFT,	USB_PRODUCT_MICROSOFT_MN110},	  PII },
+ {{ USB_VENDOR_NETGEAR,		USB_PRODUCT_NETGEAR_FA101},	  PII },
  {{ USB_VENDOR_SIEMENS,		USB_PRODUCT_SIEMENS_SPEEDSTREAM}, PII },
+ {{ USB_VENDOR_SIIG2,		USB_PRODUCT_SIIG2_USBTOETHER},    PII },
  {{ USB_VENDOR_SMARTBRIDGES,	USB_PRODUCT_SMARTBRIDGES_SMARTNIC},PII },
  {{ USB_VENDOR_SMC,		USB_PRODUCT_SMC_2202USB},	  0 },
  {{ USB_VENDOR_SMC,		USB_PRODUCT_SMC_2206USB},	  PII },
  {{ USB_VENDOR_SOHOWARE,	USB_PRODUCT_SOHOWARE_NUB100},	  0 },
+ {{ USB_VENDOR_SOHOWARE,	USB_PRODUCT_SOHOWARE_NUB110},	  PII },
 };
 #define aue_lookup(v, p) ((const struct aue_type *)usb_lookup(aue_devs, v, p))
 
-Static int aue_match(device_ptr_t);
-Static int aue_attach(device_ptr_t);
-Static int aue_detach(device_ptr_t);
+static device_probe_t aue_match;
+static device_attach_t aue_attach;
+static device_detach_t aue_detach;
+static device_shutdown_t aue_shutdown;
+static miibus_readreg_t aue_miibus_readreg;
+static miibus_writereg_t aue_miibus_writereg;
+static miibus_statchg_t aue_miibus_statchg;
 
-Static void aue_reset_pegasus_II(struct aue_softc *sc);
-Static int aue_encap(struct aue_softc *, struct mbuf *, int);
+static void aue_reset_pegasus_II(struct aue_softc *sc);
+static int aue_encap(struct aue_softc *, struct mbuf *, int);
 #ifdef AUE_INTR_PIPE
-Static void aue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void aue_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
 #endif
-Static void aue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void aue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
-Static void aue_tick(void *);
-Static void aue_rxstart(struct ifnet *);
-Static void aue_start(struct ifnet *);
-Static int aue_ioctl(struct ifnet *, u_long, caddr_t);
-Static void aue_init(void *);
-Static void aue_stop(struct aue_softc *);
-Static void aue_watchdog(struct ifnet *);
-Static void aue_shutdown(device_ptr_t);
-Static int aue_ifmedia_upd(struct ifnet *);
-Static void aue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-
-Static void aue_eeprom_getword(struct aue_softc *, int, u_int16_t *);
-Static void aue_read_eeprom(struct aue_softc *, caddr_t, int, int, int);
-Static int aue_miibus_readreg(device_ptr_t, int, int);
-Static int aue_miibus_writereg(device_ptr_t, int, int, int);
-Static void aue_miibus_statchg(device_ptr_t);
-
-Static void aue_setmulti(struct aue_softc *);
-Static void aue_reset(struct aue_softc *);
-
-Static int aue_csr_read_1(struct aue_softc *, int);
-Static int aue_csr_write_1(struct aue_softc *, int, int);
-Static int aue_csr_read_2(struct aue_softc *, int);
-Static int aue_csr_write_2(struct aue_softc *, int, int);
+static void aue_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void aue_rxeof_thread(struct aue_softc *sc);
+static void aue_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+static void aue_txeof_thread(struct aue_softc *);
+static void aue_task_sched(struct aue_softc *, int);
+static void aue_task(void *xsc, int pending);
+static void aue_tick(void *);
+static void aue_rxstart(struct ifnet *);
+static void aue_rxstart_thread(struct aue_softc *);
+static void aue_start(struct ifnet *);
+static void aue_start_thread(struct aue_softc *);
+static int aue_ioctl(struct ifnet *, u_long, caddr_t);
+static void aue_init(void *);
+static void aue_init_body(struct aue_softc *);
+static void aue_stop(struct aue_softc *);
+static void aue_watchdog(struct aue_softc *);
+static int aue_ifmedia_upd(struct ifnet *);
+static void aue_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static void aue_eeprom_getword(struct aue_softc *, int, u_int16_t *);
+static void aue_read_eeprom(struct aue_softc *, caddr_t, int, int, int);
+
+static void aue_setmulti(struct aue_softc *);
+static void aue_reset(struct aue_softc *);
+
+static int aue_csr_read_1(struct aue_softc *, int);
+static int aue_csr_write_1(struct aue_softc *, int, int);
+static int aue_csr_read_2(struct aue_softc *, int);
+static int aue_csr_write_2(struct aue_softc *, int, int);
 
-Static device_method_t aue_methods[] = {
+static device_method_t aue_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		aue_match),
 	DEVMETHOD(device_attach,	aue_attach),
@@ -232,13 +257,13 @@
 	{ 0, 0 }
 };
 
-Static driver_t aue_driver = {
+static driver_t aue_driver = {
 	"aue",
 	aue_methods,
 	sizeof(struct aue_softc)
 };
 
-Static devclass_t aue_devclass;
+static devclass_t aue_devclass;
 
 DRIVER_MODULE(aue, uhub, aue_driver, aue_devclass, usbd_driver_load, 0);
 DRIVER_MODULE(miibus, aue, miibus_driver, miibus_devclass, 0, 0);
@@ -249,17 +274,14 @@
 #define AUE_CLRBIT(sc, reg, x)				\
 	aue_csr_write_1(sc, reg, aue_csr_read_1(sc, reg) & ~(x))
 
-Static int
+static int
 aue_csr_read_1(struct aue_softc *sc, int reg)
 {
 	usb_device_request_t	req;
 	usbd_status		err;
 	u_int8_t		val = 0;
 
-	if (sc->aue_dying)
-		return (0);
-
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
 	req.bRequest = AUE_UR_READREG;
@@ -269,8 +291,6 @@
 
 	err = usbd_do_request(sc->aue_udev, &req, &val);
 
-	AUE_UNLOCK(sc);
-
 	if (err) {
 		return (0);
 	}
@@ -278,17 +298,14 @@
 	return (val);
 }
 
-Static int
+static int
 aue_csr_read_2(struct aue_softc *sc, int reg)
 {
 	usb_device_request_t	req;
 	usbd_status		err;
 	u_int16_t		val = 0;
 
-	if (sc->aue_dying)
-		return (0);
-
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
 	req.bRequest = AUE_UR_READREG;
@@ -298,8 +315,6 @@
 
 	err = usbd_do_request(sc->aue_udev, &req, &val);
 
-	AUE_UNLOCK(sc);
-
 	if (err) {
 		return (0);
 	}
@@ -307,16 +322,13 @@
 	return (val);
 }
 
-Static int
+static int
 aue_csr_write_1(struct aue_softc *sc, int reg, int val)
 {
 	usb_device_request_t	req;
 	usbd_status		err;
 
-	if (sc->aue_dying)
-		return (0);
-
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = AUE_UR_WRITEREG;
@@ -326,8 +338,6 @@
 
 	err = usbd_do_request(sc->aue_udev, &req, &val);
 
-	AUE_UNLOCK(sc);
-
 	if (err) {
 		return (-1);
 	}
@@ -335,16 +345,13 @@
 	return (0);
 }
 
-Static int
+static int
 aue_csr_write_2(struct aue_softc *sc, int reg, int val)
 {
 	usb_device_request_t	req;
 	usbd_status		err;
 
-	if (sc->aue_dying)
-		return (0);
-
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
 	req.bRequest = AUE_UR_WRITEREG;
@@ -354,8 +361,6 @@
 
 	err = usbd_do_request(sc->aue_udev, &req, &val);
 
-	AUE_UNLOCK(sc);
-
 	if (err) {
 		return (-1);
 	}
@@ -366,7 +371,7 @@
 /*
  * Read a word of data stored in the EEPROM at address 'addr.'
  */
-Static void
+static void
 aue_eeprom_getword(struct aue_softc *sc, int addr, u_int16_t *dest)
 {
 	int		i;
@@ -394,7 +399,7 @@
 /*
  * Read a sequence of words from the EEPROM.
  */
-Static void
+static void
 aue_read_eeprom(struct aue_softc *sc, caddr_t dest, int off, int cnt, int swap)
 {
 	int			i;
@@ -412,10 +417,10 @@
 	return;
 }
 
-Static int
-aue_miibus_readreg(device_ptr_t dev, int phy, int reg)
+static int
+aue_miibus_readreg(device_t dev, int phy, int reg)
 {
-	struct aue_softc	*sc = USBGETSOFTC(dev);
+	struct aue_softc	*sc = device_get_softc(dev);
 	int			i;
 	u_int16_t		val = 0;
 
@@ -456,10 +461,10 @@
 	return (val);
 }
 
-Static int
-aue_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
+static int
+aue_miibus_writereg(device_t dev, int phy, int reg, int data)
 {
-	struct aue_softc	*sc = USBGETSOFTC(dev);
+	struct aue_softc	*sc = device_get_softc(dev);
 	int			i;
 
 	if (phy == 3)
@@ -482,10 +487,10 @@
 	return(0);
 }
 
-Static void
-aue_miibus_statchg(device_ptr_t dev)
+static void
+aue_miibus_statchg(device_t dev)
 {
-	struct aue_softc	*sc = USBGETSOFTC(dev);
+	struct aue_softc	*sc = device_get_softc(dev);
 	struct mii_data		*mii = GET_MII(sc);
 
 	AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_RX_ENB | AUE_CTL0_TX_ENB);
@@ -518,13 +523,15 @@
 
 #define AUE_BITS	6
 
-Static void
+static void
 aue_setmulti(struct aue_softc *sc)
 {
 	struct ifnet		*ifp;
 	struct ifmultiaddr	*ifma;
 	u_int32_t		h = 0, i;
+	u_int8_t		hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
+	AUE_SXASSERTLOCKED(sc);
 	ifp = sc->aue_ifp;
 
 	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
@@ -534,30 +541,26 @@
 
 	AUE_CLRBIT(sc, AUE_CTL0, AUE_CTL0_ALLMULTI);
 
-	/* first, zot all the existing hash bits */
-	for (i = 0; i < 8; i++)
-		aue_csr_write_1(sc, AUE_MAR0 + i, 0);
-
 	/* now program new ones */
 	IF_ADDR_LOCK(ifp);
-#if __FreeBSD_version >= 500000
 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-#else
-	LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
-#endif
 	{
 		if (ifma->ifma_addr->sa_family != AF_LINK)
 			continue;
 		h = ether_crc32_le(LLADDR((struct sockaddr_dl *)
 		    ifma->ifma_addr), ETHER_ADDR_LEN) & ((1 << AUE_BITS) - 1);
-		AUE_SETBIT(sc, AUE_MAR + (h >> 3), 1 << (h & 0x7));
+		hashtbl[(h >> 3)] |=  1 << (h & 0x7);
 	}
 	IF_ADDR_UNLOCK(ifp);
 
+	/* write the hashtable */
+	for (i = 0; i < 8; i++)
+		aue_csr_write_1(sc, AUE_MAR0 + i, hashtbl[i]);
+
 	return;
 }
 
-Static void
+static void
 aue_reset_pegasus_II(struct aue_softc *sc)
 {
 	/* Magic constants taken from Linux driver. */
@@ -571,11 +574,12 @@
 		aue_csr_write_1(sc, AUE_REG_81, 2);
 }
 
-Static void
+static void
 aue_reset(struct aue_softc *sc)
 {
 	int		i;
 
+	AUE_SXASSERTLOCKED(sc);
 	AUE_SETBIT(sc, AUE_CTL1, AUE_CTL1_RESETMAC);
 
 	for (i = 0; i < AUE_TIMEOUT; i++) {
@@ -618,9 +622,10 @@
 /*
  * Probe for a Pegasus chip.
  */
-USB_MATCH(aue)
+static int
+aue_match(device_t self)
 {
-	USB_MATCH_START(aue, uaa);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 
 	if (uaa->iface != NULL)
 		return (UMATCH_NONE);
@@ -633,10 +638,11 @@
  * Attach the interface. Allocate softc structures, do ifmedia
  * setup and ethernet/BPF attach.
  */
-USB_ATTACH(aue)
+static int
+aue_attach(device_t self)
 {
-	USB_ATTACH_START(aue, sc, uaa);
-	char			devinfo[1024];
+	struct aue_softc *sc = device_get_softc(self);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 	u_char			eaddr[ETHER_ADDR_LEN];
 	struct ifnet		*ifp;
 	usbd_interface_handle	iface;
@@ -645,25 +651,19 @@
 	usb_endpoint_descriptor_t	*ed;
 	int			i;
 
-	bzero(sc, sizeof(struct aue_softc));
-
-	usbd_devinfo(uaa->device, 0, devinfo);
-
 	sc->aue_dev = self;
 	sc->aue_udev = uaa->device;
 	sc->aue_unit = device_get_unit(self);
 
 	if (usbd_set_config_no(sc->aue_udev, AUE_CONFIG_NO, 0)) {
-		printf("aue%d: getting interface handle failed\n",
-		    sc->aue_unit);
-		USB_ATTACH_ERROR_RETURN;
+		device_printf(self, "getting interface handle failed\n");
+		return ENXIO;
 	}
 
 	err = usbd_device2interface_handle(uaa->device, AUE_IFACE_IDX, &iface);
 	if (err) {
-		printf("aue%d: getting interface handle failed\n",
-		    sc->aue_unit);
-		USB_ATTACH_ERROR_RETURN;
+		device_printf(self, "getting interface handle failed\n");
+		return ENXIO;
 	}
 
 	sc->aue_iface = iface;
@@ -674,17 +674,12 @@
 
 	id = usbd_get_interface_descriptor(sc->aue_iface);
 
-	usbd_devinfo(uaa->device, 0, devinfo);
-	device_set_desc_copy(self, devinfo);
-	printf("%s: %s\n", USBDEVNAME(self), devinfo);
-
 	/* Find endpoints. */
 	for (i = 0; i < id->bNumEndpoints; i++) {
 		ed = usbd_interface2endpoint_descriptor(iface, i);
 		if (ed == NULL) {
-			printf("aue%d: couldn't get ep %d\n",
-			    sc->aue_unit, i);
-			USB_ATTACH_ERROR_RETURN;
+			device_printf(self, "couldn't get ep %d\n", i);
+			return ENXIO;
 		}
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
@@ -698,11 +693,12 @@
 		}
 	}
 
-#if __FreeBSD_version >= 500000
 	mtx_init(&sc->aue_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
 	    MTX_DEF | MTX_RECURSE);
-#endif
-	AUE_LOCK(sc);
+	sx_init(&sc->aue_sx, device_get_nameunit(self));
+	TASK_INIT(&sc->aue_task, 0, aue_task, sc);
+	usb_ether_task_init(self, 0, &sc->aue_taskqueue);
+	AUE_SXLOCK(sc);
 
 	/* Reset the adapter. */
 	aue_reset(sc);
@@ -714,23 +710,23 @@
 
 	ifp = sc->aue_ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
-		printf("aue%d: can not if_alloc()\n", sc->aue_unit);
-		AUE_UNLOCK(sc);
-#if __FreeBSD_version >= 500000
+		device_printf(self, "can not if_alloc()\n");
+		AUE_SXUNLOCK(sc);
 		mtx_destroy(&sc->aue_mtx);
-#endif
-		USB_ATTACH_ERROR_RETURN;
+		sx_destroy(&sc->aue_sx);
+		usb_ether_task_destroy(&sc->aue_taskqueue);
+		return ENXIO;
 	}
 	ifp->if_softc = sc;
 	if_initname(ifp, "aue", sc->aue_unit);
 	ifp->if_mtu = ETHERMTU;
-	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
-	    IFF_NEEDSGIANT;
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = aue_ioctl;
 	ifp->if_start = aue_start;
-	ifp->if_watchdog = aue_watchdog;
 	ifp->if_init = aue_init;
-	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
+	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+	IFQ_SET_READY(&ifp->if_snd);
 
 	/*
 	 * Do MII setup.
@@ -747,13 +743,13 @@
 	 */
 	if (mii_phy_probe(self, &sc->aue_miibus,
 	    aue_ifmedia_upd, aue_ifmedia_sts)) {
-		printf("aue%d: MII without any PHY!\n", sc->aue_unit);
+		device_printf(self, "MII without any PHY!\n");
 		if_free(ifp);
-		AUE_UNLOCK(sc);
-#if __FreeBSD_version >= 500000
+		AUE_SXUNLOCK(sc);
 		mtx_destroy(&sc->aue_mtx);
-#endif
-		USB_ATTACH_ERROR_RETURN;
+		sx_destroy(&sc->aue_sx);
+		usb_ether_task_destroy(&sc->aue_taskqueue);
+		return ENXIO;
 	}
 
 	sc->aue_qdat.ifp = ifp;
@@ -762,37 +758,31 @@
 	/*
 	 * Call MI attach routine.
 	 */
-#if __FreeBSD_version >= 500000
 	ether_ifattach(ifp, eaddr);
-#else
-	ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
-#endif
-	callout_handle_init(&sc->aue_stat_ch);
 	usb_register_netisr();
 	sc->aue_dying = 0;
+	sc->aue_link = 1;
 
-	AUE_UNLOCK(sc);
-	USB_ATTACH_SUCCESS_RETURN;
+	AUE_SXUNLOCK(sc);
+	return 0;
 }
 
-Static int
-aue_detach(device_ptr_t dev)
+static int
+aue_detach(device_t dev)
 {
 	struct aue_softc	*sc;
 	struct ifnet		*ifp;
 
 	sc = device_get_softc(dev);
-	AUE_LOCK(sc);
+	AUE_SXLOCK(sc);
 	ifp = sc->aue_ifp;
-
-	sc->aue_dying = 1;
-	untimeout(aue_tick, sc, sc->aue_stat_ch);
-#if __FreeBSD_version >= 500000
 	ether_ifdetach(ifp);
+	sc->aue_dying = 1;
+	AUE_SXUNLOCK(sc);
+	callout_drain(&sc->aue_tick_callout);
+	usb_ether_task_drain(&sc->aue_taskqueue, &sc->aue_task);
+	usb_ether_task_destroy(&sc->aue_taskqueue);
 	if_free(ifp);
-#else
-	ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
-#endif
 
 	if (sc->aue_ep[AUE_ENDPT_TX] != NULL)
 		usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]);
@@ -803,70 +793,35 @@
 		usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]);
 #endif
 
-	AUE_UNLOCK(sc);
-#if __FreeBSD_version >= 500000
 	mtx_destroy(&sc->aue_mtx);
-#endif
+	sx_destroy(&sc->aue_sx);
 
 	return (0);
 }
 
-#ifdef AUE_INTR_PIPE
-Static void
-aue_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+static void
+aue_rxstart(struct ifnet *ifp)
 {
-	struct aue_softc	*sc = priv;
-	struct ifnet		*ifp;
-	struct aue_intrpkt	*p;
-
-	AUE_LOCK(sc);
-	ifp = sc->aue_ifp;
-
-	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-		AUE_UNLOCK(sc);
-		return;
-	}
-
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			AUE_UNLOCK(sc);
-			return;
-		}
-		printf("aue%d: usb error on intr: %s\n", sc->aue_unit,
-		    usbd_errstr(status));
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_RX]);
-		AUE_UNLOCK(sc);
-		return;
-	}
-
-	usbd_get_xfer_status(xfer, NULL, (void **)&p, NULL, NULL);
-
-	if (p->aue_txstat0)
-		ifp->if_oerrors++;
-
-	if (p->aue_txstat0 & (AUE_TXSTAT0_LATECOLL & AUE_TXSTAT0_EXCESSCOLL))
-		ifp->if_collisions++;
-
-	AUE_UNLOCK(sc);
-	return;
+	struct aue_softc	*sc = ifp->if_softc;
+	aue_task_sched(sc, AUE_TASK_RXSTART);
 }
-#endif
 
-Static void
-aue_rxstart(struct ifnet *ifp)
+static void
+aue_rxstart_thread(struct aue_softc *sc)
 {
-	struct aue_softc	*sc;
 	struct ue_chain	*c;
+	struct ifnet *ifp;
+
+	ifp = sc->aue_ifp;
 
 	sc = ifp->if_softc;
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 	c = &sc->aue_cdata.ue_rx_chain[sc->aue_cdata.ue_rx_prod];
 
 	c->ue_mbuf = usb_ether_newbuf();
 	if (c->ue_mbuf == NULL) {
-		printf("%s: no memory for rx list "
-		    "-- packet dropped!\n", USBDEVNAME(sc->aue_dev));
+		device_printf(sc->aue_dev, "no memory for rx list -- packet "
+		    "dropped!\n");
 		ifp->if_ierrors++;
 		AUE_UNLOCK(sc);
 		return;
@@ -878,7 +833,6 @@
 	    USBD_NO_TIMEOUT, aue_rxeof);
 	usbd_transfer(c->ue_xfer);
 
-	AUE_UNLOCK(sc);
 	return;
 }
 
@@ -886,40 +840,45 @@
  * A frame has been uploaded: pass the resulting mbuf chain up to
  * the higher level protocols.
  */
-Static void
+static void
 aue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 {
 	struct ue_chain	*c = priv;
-	struct aue_softc	*sc = c->ue_sc;
+	c->ue_status = status;
+	aue_task_sched(c->ue_sc, AUE_TASK_RXEOF);
+}
+
+static void
+aue_rxeof_thread(struct aue_softc *sc)
+{
+	struct ue_chain	*c = &(sc->aue_cdata.ue_rx_chain[0]);
         struct mbuf		*m;
         struct ifnet		*ifp;
 	int			total_len = 0;
 	struct aue_rxpkt	r;
+	usbd_status		status = c->ue_status;
 
-	if (sc->aue_dying)
-		return;
-	AUE_LOCK(sc);
+
+	AUE_SXASSERTLOCKED(sc);
 	ifp = sc->aue_ifp;
 
 	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-		AUE_UNLOCK(sc);
 		return;
 	}
 
 	if (status != USBD_NORMAL_COMPLETION) {
 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			AUE_UNLOCK(sc);
 			return;
 		}
 		if (usbd_ratecheck(&sc->aue_rx_notice))
-			printf("aue%d: usb error on rx: %s\n", sc->aue_unit,
+			device_printf(sc->aue_dev, "usb error on rx: %s\n",
 			    usbd_errstr(status));
 		if (status == USBD_STALLED)
 			usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_RX]);
 		goto done;
 	}
 
-	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
+	usbd_get_xfer_status(c->ue_xfer, NULL, NULL, &total_len, NULL);
 
 	if (total_len <= 4 + ETHER_CRC_LEN) {
 		ifp->if_ierrors++;
@@ -946,17 +905,15 @@
 
 	/* Put the packet on the special USB input queue. */
 	usb_ether_input(m);
-	AUE_UNLOCK(sc);
 	return;
 done:
 
 	/* Setup new transfer. */
-	usbd_setup_xfer(xfer, sc->aue_ep[AUE_ENDPT_RX],
+	usbd_setup_xfer(c->ue_xfer, sc->aue_ep[AUE_ENDPT_RX],
 	    c, mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
 	    USBD_NO_TIMEOUT, aue_rxeof);
-	usbd_transfer(xfer);
+	usbd_transfer(c->ue_xfer);
 
-	AUE_UNLOCK(sc);
 	return;
 }
 
@@ -965,31 +922,37 @@
  * the list buffers.
  */
 
-Static void
+static void
 aue_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 {
 	struct ue_chain	*c = priv;
-	struct aue_softc	*sc = c->ue_sc;
+	c->ue_status = status;
+	aue_task_sched(c->ue_sc, AUE_TASK_TXEOF);
+}
+
+static void
+aue_txeof_thread(struct aue_softc *sc)
+{
+	struct ue_chain	*c = &(sc->aue_cdata.ue_tx_chain[0]);
 	struct ifnet		*ifp;
-	usbd_status		err;
+	usbd_status		err, status;
 
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
+	status = c->ue_status;
 	ifp = sc->aue_ifp;
 
 	if (status != USBD_NORMAL_COMPLETION) {
 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			AUE_UNLOCK(sc);
 			return;
 		}
-		printf("aue%d: usb error on tx: %s\n", sc->aue_unit,
+		device_printf(sc->aue_dev, "usb error on tx: %s\n",
 		    usbd_errstr(status));
 		if (status == USBD_STALLED)
 			usbd_clear_endpoint_stall(sc->aue_ep[AUE_ENDPT_TX]);
-		AUE_UNLOCK(sc);
 		return;
 	}
 
-	ifp->if_timer = 0;
+	sc->aue_timer = 0;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
 
@@ -1004,52 +967,62 @@
 	else
 		ifp->if_opackets++;
 
-	AUE_UNLOCK(sc);
-
 	return;
 }
 
-Static void
+static void
 aue_tick(void *xsc)
 {
 	struct aue_softc	*sc = xsc;
+
+	aue_task_sched(sc, AUE_TASK_TICK);
+}
+
+static void
+aue_tick_thread(struct aue_softc *sc)
+{
 	struct ifnet		*ifp;
 	struct mii_data		*mii;
 
-	if (sc == NULL)
+	AUE_SXASSERTLOCKED(sc);
+	ifp = sc->aue_ifp;
+	/*
+	 * If a timer is set (non-zero) then decrement it
+	 * and if it hits zero, then call the watchdog routine.
+	 */
+	if (sc->aue_timer != 0 && --sc->aue_timer == 0) {
+		aue_watchdog(sc);
+	}
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		return;
+	}
 
-	AUE_LOCK(sc);
-
-	ifp = sc->aue_ifp;
 	mii = GET_MII(sc);
 	if (mii == NULL) {
-		AUE_UNLOCK(sc);
-		return;
+		goto resched;
 	}
 
 	mii_tick(mii);
 	if (!sc->aue_link && mii->mii_media_status & IFM_ACTIVE &&
 	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
 		sc->aue_link++;
-		if (ifp->if_snd.ifq_head != NULL)
-			aue_start(ifp);
+		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+			aue_start_thread(sc);
 	}
-
-	sc->aue_stat_ch = timeout(aue_tick, sc, hz);
-
-	AUE_UNLOCK(sc);
-
+resched:
+	(void) callout_reset(&sc->aue_tick_callout, hz, aue_tick, sc);
 	return;
 }
 
-Static int
+static int
 aue_encap(struct aue_softc *sc, struct mbuf *m, int idx)
 {
 	int			total_len;
 	struct ue_chain	*c;
 	usbd_status		err;
 
+	AUE_SXASSERTLOCKED(sc);
+
 	c = &sc->aue_cdata.ue_tx_chain[idx];
 
 	/*
@@ -1086,34 +1059,38 @@
 	return (0);
 }
 
-Static void
+
+static void
 aue_start(struct ifnet *ifp)
 {
 	struct aue_softc	*sc = ifp->if_softc;
+	aue_task_sched(sc, AUE_TASK_START);
+}
+
+static void
+aue_start_thread(struct aue_softc *sc)
+{
+	struct ifnet		*ifp = sc->aue_ifp;
 	struct mbuf		*m_head = NULL;
 
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	if (!sc->aue_link) {
-		AUE_UNLOCK(sc);
 		return;
 	}
 
 	if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
-		AUE_UNLOCK(sc);
 		return;
 	}
 
-	IF_DEQUEUE(&ifp->if_snd, m_head);
+	IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
 	if (m_head == NULL) {
-		AUE_UNLOCK(sc);
 		return;
 	}
 
 	if (aue_encap(sc, m_head, 0)) {
-		IF_PREPEND(&ifp->if_snd, m_head);
+		IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
 		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-		AUE_UNLOCK(sc);
 		return;
 	}
 
@@ -1128,26 +1105,33 @@
 	/*
 	 * Set a timeout in case the chip goes out to lunch.
 	 */
-	ifp->if_timer = 5;
-	AUE_UNLOCK(sc);
+	sc->aue_timer = 5;
 
 	return;
 }
 
-Static void
+static void
 aue_init(void *xsc)
 {
 	struct aue_softc	*sc = xsc;
+
+	AUE_SXLOCK(sc);
+	aue_init_body(sc);
+	AUE_SXUNLOCK(sc);
+}
+
+static void
+aue_init_body(struct aue_softc *sc)
+{
 	struct ifnet		*ifp = sc->aue_ifp;
 	struct mii_data		*mii = GET_MII(sc);
 	struct ue_chain	*c;
 	usbd_status		err;
 	int			i;
 
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-		AUE_UNLOCK(sc);
 		return;
 	}
 
@@ -1158,7 +1142,7 @@
 
 	/* Set MAC address */
 	for (i = 0; i < ETHER_ADDR_LEN; i++)
-		aue_csr_write_1(sc, AUE_PAR0 + i, IFP2ENADDR(sc->aue_ifp)[i]);
+		aue_csr_write_1(sc, AUE_PAR0 + i, IF_LLADDR(sc->aue_ifp)[i]);
 
 	 /* If we want promiscuous mode, set the allframes bit. */
 	if (ifp->if_flags & IFF_PROMISC)
@@ -1169,22 +1153,17 @@
 	/* Init TX ring. */
 	if (usb_ether_tx_list_init(sc, &sc->aue_cdata,
 	    sc->aue_udev) == ENOBUFS) {
-		printf("aue%d: tx list init failed\n", sc->aue_unit);
-		AUE_UNLOCK(sc);
+		device_printf(sc->aue_dev, "tx list init failed\n");
 		return;
 	}
 
 	/* Init RX ring. */
 	if (usb_ether_rx_list_init(sc, &sc->aue_cdata,
 	    sc->aue_udev) == ENOBUFS) {
-		printf("aue%d: rx list init failed\n", sc->aue_unit);
-		AUE_UNLOCK(sc);
+		device_printf(sc->aue_dev, "rx list init failed\n");
 		return;
 	}
 
-#ifdef AUE_INTR_PIPE
-	sc->aue_cdata.ue_ibuf = malloc(AUE_INTR_PKTLEN, M_USBDEV, M_NOWAIT);
-#endif
 
 	/* Load the multicast filter. */
 	aue_setmulti(sc);
@@ -1200,32 +1179,18 @@
 	err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_RX],
 	    USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_RX]);
 	if (err) {
-		printf("aue%d: open rx pipe failed: %s\n",
-		    sc->aue_unit, usbd_errstr(err));
-		AUE_UNLOCK(sc);
+		device_printf(sc->aue_dev, "open rx pipe failed: %s\n",
+		    usbd_errstr(err));
 		return;
 	}
 	err = usbd_open_pipe(sc->aue_iface, sc->aue_ed[AUE_ENDPT_TX],
 	    USBD_EXCLUSIVE_USE, &sc->aue_ep[AUE_ENDPT_TX]);
 	if (err) {
-		printf("aue%d: open tx pipe failed: %s\n",
-		    sc->aue_unit, usbd_errstr(err));
-		AUE_UNLOCK(sc);
+		device_printf(sc->aue_dev, "open tx pipe failed: %s\n",
+		    usbd_errstr(err));
 		return;
 	}
 
-#ifdef AUE_INTR_PIPE
-	err = usbd_open_pipe_intr(sc->aue_iface, sc->aue_ed[AUE_ENDPT_INTR],
-	    USBD_SHORT_XFER_OK, &sc->aue_ep[AUE_ENDPT_INTR], sc,
-	    sc->aue_cdata.ue_ibuf, AUE_INTR_PKTLEN, aue_intr,
-	    AUE_INTR_INTERVAL);
-	if (err) {
-		printf("aue%d: open intr pipe failed: %s\n",
-		    sc->aue_unit, usbd_errstr(err));
-		AUE_UNLOCK(sc);
-		return;
-	}
-#endif
 
 	/* Start up the receive pipe. */
 	for (i = 0; i < UE_RX_LIST_CNT; i++) {
@@ -1239,17 +1204,15 @@
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
-	sc->aue_stat_ch = timeout(aue_tick, sc, hz);
-
-	AUE_UNLOCK(sc);
-
+	callout_init(&sc->aue_tick_callout, 1);
+	(void) callout_reset(&sc->aue_tick_callout, hz, aue_tick, sc);
 	return;
 }
 
 /*
  * Set media options.
  */
-Static int
+static int
 aue_ifmedia_upd(struct ifnet *ifp)
 {
 	struct aue_softc	*sc = ifp->if_softc;
@@ -1262,6 +1225,7 @@
 			 mii_phy_reset(miisc);
 	}
 	mii_mediachg(mii);
+	sc->aue_link = 1;
 
 	return (0);
 }
@@ -1269,7 +1233,7 @@
 /*
  * Report current media status.
  */
-Static void
+static void
 aue_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
 	struct aue_softc	*sc = ifp->if_softc;
@@ -1282,7 +1246,7 @@
 	return;
 }
 
-Static int
+static int
 aue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
 {
 	struct aue_softc	*sc = ifp->if_softc;
@@ -1290,10 +1254,18 @@
 	struct mii_data		*mii;
 	int			error = 0;
 
-	AUE_LOCK(sc);
+	/*
+	 * This prevents recursion in the interface while it's
+	 * being torn down.
+	 */
+	if (sc->aue_dying)
+		return(0);
+
+	AUE_GIANTLOCK();
 
 	switch(command) {
 	case SIOCSIFFLAGS:
+		AUE_SXLOCK(sc);
 		if (ifp->if_flags & IFF_UP) {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
 			    ifp->if_flags & IFF_PROMISC &&
@@ -1303,54 +1275,58 @@
 			    !(ifp->if_flags & IFF_PROMISC) &&
 			    sc->aue_if_flags & IFF_PROMISC) {
 				AUE_CLRBIT(sc, AUE_CTL2, AUE_CTL2_RX_PROMISC);
-			} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
-				aue_init(sc);
+			} else if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+				aue_init_body(sc);
+			}
+			sc->aue_dying = 0;
 		} else {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 				aue_stop(sc);
 		}
 		sc->aue_if_flags = ifp->if_flags;
-		error = 0;
+		AUE_SXUNLOCK(sc);
 		break;
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
+		AUE_SXLOCK(sc);
 		aue_setmulti(sc);
-		error = 0;
+		AUE_SXUNLOCK(sc);
 		break;
 	case SIOCGIFMEDIA:
 	case SIOCSIFMEDIA:
+		AUE_SXLOCK(sc);
 		mii = GET_MII(sc);
 		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+		AUE_SXUNLOCK(sc);
 		break;
 	default:
 		error = ether_ioctl(ifp, command, data);
 		break;
 	}
 
-	AUE_UNLOCK(sc);
+	AUE_GIANTUNLOCK();
 
 	return (error);
 }
 
-Static void
-aue_watchdog(struct ifnet *ifp)
+static void
+aue_watchdog(struct aue_softc *sc)
 {
-	struct aue_softc	*sc = ifp->if_softc;
+	struct ifnet		*ifp = sc->aue_ifp;
 	struct ue_chain	*c;
 	usbd_status		stat;
 
-	AUE_LOCK(sc);
-
+	AUE_SXASSERTLOCKED(sc);
 	ifp->if_oerrors++;
-	printf("aue%d: watchdog timeout\n", sc->aue_unit);
+	device_printf(sc->aue_dev, "watchdog timeout\n");
 
 	c = &sc->aue_cdata.ue_tx_chain[0];
 	usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &stat);
-	aue_txeof(c->ue_xfer, c, stat);
+	c->ue_status = stat;
+	aue_txeof_thread(sc);
 
-	if (ifp->if_snd.ifq_head != NULL)
-		aue_start(ifp);
-	AUE_UNLOCK(sc);
+	if (!IFQ_IS_EMPTY(&ifp->if_snd))
+		aue_start_thread(sc);
 	return;
 }
 
@@ -1358,32 +1334,32 @@
  * Stop the adapter and free any mbufs allocated to the
  * RX and TX lists.
  */
-Static void
+static void
 aue_stop(struct aue_softc *sc)
 {
 	usbd_status		err;
 	struct ifnet		*ifp;
 
-	AUE_LOCK(sc);
+	AUE_SXASSERTLOCKED(sc);
 	ifp = sc->aue_ifp;
-	ifp->if_timer = 0;
+	sc->aue_timer = 0;
 
 	aue_csr_write_1(sc, AUE_CTL0, 0);
 	aue_csr_write_1(sc, AUE_CTL1, 0);
 	aue_reset(sc);
-	untimeout(aue_tick, sc, sc->aue_stat_ch);
+	sc->aue_dying = 1;
 
 	/* Stop transfers. */
 	if (sc->aue_ep[AUE_ENDPT_RX] != NULL) {
 		err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_RX]);
 		if (err) {
-			printf("aue%d: abort rx pipe failed: %s\n",
-		    	sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "abort rx pipe failed: %s\n", usbd_errstr(err));
 		}
 		err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_RX]);
 		if (err) {
-			printf("aue%d: close rx pipe failed: %s\n",
-		    	sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "close rx pipe failed: %s\n", usbd_errstr(err));
 		}
 		sc->aue_ep[AUE_ENDPT_RX] = NULL;
 	}
@@ -1391,13 +1367,13 @@
 	if (sc->aue_ep[AUE_ENDPT_TX] != NULL) {
 		err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_TX]);
 		if (err) {
-			printf("aue%d: abort tx pipe failed: %s\n",
-		    	sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "abort tx pipe failed: %s\n", usbd_errstr(err));
 		}
 		err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_TX]);
 		if (err) {
-			printf("aue%d: close tx pipe failed: %s\n",
-			    sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "close tx pipe failed: %s\n", usbd_errstr(err));
 		}
 		sc->aue_ep[AUE_ENDPT_TX] = NULL;
 	}
@@ -1406,13 +1382,13 @@
 	if (sc->aue_ep[AUE_ENDPT_INTR] != NULL) {
 		err = usbd_abort_pipe(sc->aue_ep[AUE_ENDPT_INTR]);
 		if (err) {
-			printf("aue%d: abort intr pipe failed: %s\n",
-		    	sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "abort intr pipe failed: %s\n", usbd_errstr(err));
 		}
 		err = usbd_close_pipe(sc->aue_ep[AUE_ENDPT_INTR]);
 		if (err) {
-			printf("aue%d: close intr pipe failed: %s\n",
-			    sc->aue_unit, usbd_errstr(err));
+			device_printf(sc->aue_dev,
+			    "close intr pipe failed: %s\n", usbd_errstr(err));
 		}
 		sc->aue_ep[AUE_ENDPT_INTR] = NULL;
 	}
@@ -1431,7 +1407,6 @@
 	sc->aue_link = 0;
 
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-	AUE_UNLOCK(sc);
 
 	return;
 }
@@ -1440,17 +1415,75 @@
  * Stop all chip I/O so that the kernel's probe routines don't
  * get confused by errant DMAs when rebooting.
  */
-Static void
-aue_shutdown(device_ptr_t dev)
+static int
+aue_shutdown(device_t dev)
 {
 	struct aue_softc	*sc;
 
 	sc = device_get_softc(dev);
+	AUE_SXLOCK(sc);
 	sc->aue_dying++;
-	AUE_LOCK(sc);
 	aue_reset(sc);
 	aue_stop(sc);
+	AUE_SXUNLOCK(sc);
+
+	return (0);
+}
+
+static void
+aue_task_sched(struct aue_softc *sc, int task)
+{
+
+	AUE_LOCK(sc);
+	sc->aue_deferedtasks |= task;
+	usb_ether_task_enqueue(&sc->aue_taskqueue, &sc->aue_task);
 	AUE_UNLOCK(sc);
+}
 
-	return;
+/*
+ * We defer all interrupt operations to this function.
+ *
+ * This allows us to do more complex operations, such as synchronous
+ * usb io that normally would not be allowed from interrupt context.
+ */
+static void
+aue_task(void *arg, int pending)
+{
+	struct aue_softc *sc = arg;
+	int tasks;
+
+	for ( ;; ) {
+		AUE_LOCK(sc);
+		tasks = sc->aue_deferedtasks;
+		sc->aue_deferedtasks = 0;
+		AUE_UNLOCK(sc);
+
+		if (tasks == 0)
+			break;
+
+		AUE_GIANTLOCK();	// XXX: usb not giant safe
+		AUE_SXLOCK(sc);
+		if (sc->aue_dying) {
+			AUE_SXUNLOCK(sc);
+			break;
+		}
+		if ((tasks & AUE_TASK_TICK) != 0) {
+			aue_tick_thread(sc);
+		}
+		if ((tasks & AUE_TASK_START) != 0) {
+			aue_start_thread(sc);
+		}
+		if ((tasks & AUE_TASK_RXSTART) != 0) {
+			aue_rxstart_thread(sc);
+		}
+		if ((tasks & AUE_TASK_RXEOF) != 0) {
+			aue_rxeof_thread(sc);
+		}
+		if ((tasks & AUE_TASK_TXEOF) != 0) {
+			aue_txeof_thread(sc);
+		}
+		AUE_SXUNLOCK(sc);
+		AUE_GIANTUNLOCK();	// XXX: usb not giant safe
+	}
 }
+
Index: ohci.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L sys/dev/usb/ohci.c -L sys/dev/usb/ohci.c -u -r1.4 -r1.5
--- sys/dev/usb/ohci.c
+++ sys/dev/usb/ohci.c
@@ -13,7 +13,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/ohci.c,v 1.154.2.3 2006/03/01 01:59:04 iedowse Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/ohci.c,v 1.170 2007/06/20 05:10:52 imp Exp $");
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -63,17 +63,12 @@
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/kernel.h>
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-#include <sys/device.h>
-#include <sys/select.h>
-#elif defined(__FreeBSD__)
 #include <sys/endian.h>
 #include <sys/module.h>
 #include <sys/bus.h>
 #if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
 #include <machine/cpu.h>
 #endif
-#endif
 #include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/sysctl.h>
@@ -90,157 +85,133 @@
 #include <dev/usb/ohcireg.h>
 #include <dev/usb/ohcivar.h>
 
-#if defined(__FreeBSD__)
-#include <machine/clock.h>
-
 #define delay(d)                DELAY(d)
-#endif
-
-#if defined(__OpenBSD__)
-struct cfdriver ohci_cd = {
-	NULL, "ohci", DV_DULL
-};
-#endif
 
 #ifdef USB_DEBUG
-#define DPRINTF(x)	if (ohcidebug) logprintf x
-#define DPRINTFN(n,x)	if (ohcidebug>(n)) logprintf x
+#define DPRINTF(x)	if (ohcidebug) printf x
+#define DPRINTFN(n,x)	if (ohcidebug>(n)) printf x
 int ohcidebug = 0;
 SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
 SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
 	   &ohcidebug, 0, "ohci debug level");
-#ifndef __NetBSD__
 #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
-#endif
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n,x)
 #endif
 
-/*
- * The OHCI controller is little endian, so on big endian machines
- * the data strored in memory needs to be swapped.
- */
-#if defined(__OpenBSD__)
-#if BYTE_ORDER == BIG_ENDIAN
-#define htole32(x) (bswap32(x))
-#define le32toh(x) (bswap32(x))
-#else
-#define htole32(x) (x)
-#define le32toh(x) (x)
-#endif
-#endif
-
 struct ohci_pipe;
 
-Static ohci_soft_ed_t  *ohci_alloc_sed(ohci_softc_t *);
-Static void		ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *);
+static ohci_soft_ed_t  *ohci_alloc_sed(ohci_softc_t *);
+static void		ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *);
 
-Static ohci_soft_td_t  *ohci_alloc_std(ohci_softc_t *);
-Static void		ohci_free_std(ohci_softc_t *, ohci_soft_td_t *);
+static ohci_soft_td_t  *ohci_alloc_std(ohci_softc_t *);
+static void		ohci_free_std(ohci_softc_t *, ohci_soft_td_t *);
 
-Static ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *);
-Static void		ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *);
+static ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *);
+static void		ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *);
 
 #if 0
-Static void		ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *,
+static void		ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *,
 					    ohci_soft_td_t *);
 #endif
-Static usbd_status	ohci_alloc_std_chain(struct ohci_pipe *,
+static usbd_status	ohci_alloc_std_chain(struct ohci_pipe *,
 			    ohci_softc_t *, int, int, usbd_xfer_handle,
 			    ohci_soft_td_t *, ohci_soft_td_t **);
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
-Static void		ohci_shutdown(void *v);
-Static void		ohci_power(int, void *);
+static void		ohci_shutdown(void *v);
+static void		ohci_power(int, void *);
 #endif
-Static usbd_status	ohci_open(usbd_pipe_handle);
-Static void		ohci_poll(struct usbd_bus *);
-Static void		ohci_softintr(void *);
-Static void		ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
-Static void		ohci_add_done(ohci_softc_t *, ohci_physaddr_t);
-Static void		ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
-
-Static usbd_status	ohci_device_request(usbd_xfer_handle xfer);
-Static void		ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
-Static void		ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
-Static void		ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *);
-Static void		ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *);
-Static ohci_soft_td_t  *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t);
-Static void		ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *);
-Static void		ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *);
-Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t);
-
-Static usbd_status	ohci_setup_isoc(usbd_pipe_handle pipe);
-Static void		ohci_device_isoc_enter(usbd_xfer_handle);
-
-Static usbd_status	ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
-Static void		ohci_freem(struct usbd_bus *, usb_dma_t *);
-
-Static usbd_xfer_handle	ohci_allocx(struct usbd_bus *);
-Static void		ohci_freex(struct usbd_bus *, usbd_xfer_handle);
-
-Static usbd_status	ohci_root_ctrl_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_root_ctrl_start(usbd_xfer_handle);
-Static void		ohci_root_ctrl_abort(usbd_xfer_handle);
-Static void		ohci_root_ctrl_close(usbd_pipe_handle);
-Static void		ohci_root_ctrl_done(usbd_xfer_handle);
-
-Static usbd_status	ohci_root_intr_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_root_intr_start(usbd_xfer_handle);
-Static void		ohci_root_intr_abort(usbd_xfer_handle);
-Static void		ohci_root_intr_close(usbd_pipe_handle);
-Static void		ohci_root_intr_done(usbd_xfer_handle);
-
-Static usbd_status	ohci_device_ctrl_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_device_ctrl_start(usbd_xfer_handle);
-Static void		ohci_device_ctrl_abort(usbd_xfer_handle);
-Static void		ohci_device_ctrl_close(usbd_pipe_handle);
-Static void		ohci_device_ctrl_done(usbd_xfer_handle);
-
-Static usbd_status	ohci_device_bulk_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_device_bulk_start(usbd_xfer_handle);
-Static void		ohci_device_bulk_abort(usbd_xfer_handle);
-Static void		ohci_device_bulk_close(usbd_pipe_handle);
-Static void		ohci_device_bulk_done(usbd_xfer_handle);
-
-Static usbd_status	ohci_device_intr_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_device_intr_start(usbd_xfer_handle);
-Static void		ohci_device_intr_abort(usbd_xfer_handle);
-Static void		ohci_device_intr_close(usbd_pipe_handle);
-Static void		ohci_device_intr_done(usbd_xfer_handle);
-
-Static usbd_status	ohci_device_isoc_transfer(usbd_xfer_handle);
-Static usbd_status	ohci_device_isoc_start(usbd_xfer_handle);
-Static void		ohci_device_isoc_abort(usbd_xfer_handle);
-Static void		ohci_device_isoc_close(usbd_pipe_handle);
-Static void		ohci_device_isoc_done(usbd_xfer_handle);
+static usbd_status	ohci_open(usbd_pipe_handle);
+static void		ohci_poll(struct usbd_bus *);
+static void		ohci_softintr(void *);
+static void		ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
+static void		ohci_add_done(ohci_softc_t *, ohci_physaddr_t);
+static void		ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
+
+static usbd_status	ohci_device_request(usbd_xfer_handle xfer);
+static void		ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
+static void		ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *);
+static void		ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *);
+static void		ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *);
+static ohci_soft_td_t  *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t);
+static void		ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *);
+static void		ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *);
+static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t);
+
+static usbd_status	ohci_setup_isoc(usbd_pipe_handle pipe);
+static void		ohci_device_isoc_enter(usbd_xfer_handle);
+
+static usbd_status	ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t);
+static void		ohci_freem(struct usbd_bus *, usb_dma_t *);
+
+static usbd_xfer_handle	ohci_allocx(struct usbd_bus *);
+static void		ohci_freex(struct usbd_bus *, usbd_xfer_handle);
+
+static usbd_status	ohci_root_ctrl_transfer(usbd_xfer_handle);
+static usbd_status	ohci_root_ctrl_start(usbd_xfer_handle);
+static void		ohci_root_ctrl_abort(usbd_xfer_handle);
+static void		ohci_root_ctrl_close(usbd_pipe_handle);
+static void		ohci_root_ctrl_done(usbd_xfer_handle);
+
+static usbd_status	ohci_root_intr_transfer(usbd_xfer_handle);
+static usbd_status	ohci_root_intr_start(usbd_xfer_handle);
+static void		ohci_root_intr_abort(usbd_xfer_handle);
+static void		ohci_root_intr_close(usbd_pipe_handle);
+static void		ohci_root_intr_done(usbd_xfer_handle);
+
+static usbd_status	ohci_device_ctrl_transfer(usbd_xfer_handle);
+static usbd_status	ohci_device_ctrl_start(usbd_xfer_handle);
+static void		ohci_device_ctrl_abort(usbd_xfer_handle);
+static void		ohci_device_ctrl_close(usbd_pipe_handle);
+static void		ohci_device_ctrl_done(usbd_xfer_handle);
+
+static usbd_status	ohci_device_bulk_transfer(usbd_xfer_handle);
+static usbd_status	ohci_device_bulk_start(usbd_xfer_handle);
+static void		ohci_device_bulk_abort(usbd_xfer_handle);
+static void		ohci_device_bulk_close(usbd_pipe_handle);
+static void		ohci_device_bulk_done(usbd_xfer_handle);
+
+static usbd_status	ohci_device_intr_transfer(usbd_xfer_handle);
+static usbd_status	ohci_device_intr_start(usbd_xfer_handle);
+static void		ohci_device_intr_abort(usbd_xfer_handle);
+static void		ohci_device_intr_close(usbd_pipe_handle);
+static void		ohci_device_intr_done(usbd_xfer_handle);
+
+static usbd_status	ohci_device_isoc_transfer(usbd_xfer_handle);
+static usbd_status	ohci_device_isoc_start(usbd_xfer_handle);
+static void		ohci_device_isoc_abort(usbd_xfer_handle);
+static void		ohci_device_isoc_close(usbd_pipe_handle);
+static void		ohci_device_isoc_done(usbd_xfer_handle);
 
-Static usbd_status	ohci_device_setintr(ohci_softc_t *sc,
+static usbd_status	ohci_device_setintr(ohci_softc_t *sc,
 			    struct ohci_pipe *pipe, int ival);
+static usbd_status	ohci_device_intr_insert(ohci_softc_t *sc,
+			    usbd_xfer_handle xfer);
 
-Static int		ohci_str(usb_string_descriptor_t *, int, const char *);
+static int		ohci_str(usb_string_descriptor_t *, int, const char *);
 
-Static void		ohci_timeout(void *);
-Static void		ohci_timeout_task(void *);
-Static void		ohci_rhsc_able(ohci_softc_t *, int);
-Static void		ohci_rhsc_enable(void *);
+static void		ohci_timeout(void *);
+static void		ohci_timeout_task(void *);
+static void		ohci_rhsc_able(ohci_softc_t *, int);
+static void		ohci_rhsc_enable(void *);
 
-Static void		ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *);
-Static void		ohci_abort_xfer(usbd_xfer_handle, usbd_status);
+static void		ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *);
+static void		ohci_abort_xfer(usbd_xfer_handle, usbd_status);
 
-Static void		ohci_device_clear_toggle(usbd_pipe_handle pipe);
-Static void		ohci_noop(usbd_pipe_handle pipe);
+static void		ohci_device_clear_toggle(usbd_pipe_handle pipe);
+static void		ohci_noop(usbd_pipe_handle pipe);
 
-Static usbd_status ohci_controller_init(ohci_softc_t *sc);
+static usbd_status ohci_controller_init(ohci_softc_t *sc);
 
 #ifdef USB_DEBUG
-Static void		ohci_dumpregs(ohci_softc_t *);
-Static void		ohci_dump_tds(ohci_soft_td_t *);
-Static void		ohci_dump_td(ohci_soft_td_t *);
-Static void		ohci_dump_ed(ohci_soft_ed_t *);
-Static void		ohci_dump_itd(ohci_soft_itd_t *);
-Static void		ohci_dump_itds(ohci_soft_itd_t *);
+static void		ohci_dumpregs(ohci_softc_t *);
+static void		ohci_dump_tds(ohci_soft_td_t *);
+static void		ohci_dump_td(ohci_soft_td_t *);
+static void		ohci_dump_ed(ohci_soft_ed_t *);
+static void		ohci_dump_itd(ohci_soft_itd_t *);
+static void		ohci_dump_itds(ohci_soft_itd_t *);
 #endif
 
 #define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \
@@ -256,7 +227,7 @@
 #define OREAD4(sc, r) (OBARR(sc), bus_space_read_4((sc)->iot, (sc)->ioh, (r)))
 
 /* Reverse the bits in a value 0 .. 31 */
-Static u_int8_t revbits[OHCI_NO_INTRS] =
+static u_int8_t revbits[OHCI_NO_INTRS] =
   { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
     0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
     0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
@@ -297,7 +268,7 @@
 
 #define OHCI_INTR_ENDPT 1
 
-Static struct usbd_bus_methods ohci_bus_methods = {
+static struct usbd_bus_methods ohci_bus_methods = {
 	ohci_open,
 	ohci_softintr,
 	ohci_poll,
@@ -307,7 +278,7 @@
 	ohci_freex,
 };
 
-Static struct usbd_pipe_methods ohci_root_ctrl_methods = {
+static struct usbd_pipe_methods ohci_root_ctrl_methods = {
 	ohci_root_ctrl_transfer,
 	ohci_root_ctrl_start,
 	ohci_root_ctrl_abort,
@@ -316,7 +287,7 @@
 	ohci_root_ctrl_done,
 };
 
-Static struct usbd_pipe_methods ohci_root_intr_methods = {
+static struct usbd_pipe_methods ohci_root_intr_methods = {
 	ohci_root_intr_transfer,
 	ohci_root_intr_start,
 	ohci_root_intr_abort,
@@ -325,7 +296,7 @@
 	ohci_root_intr_done,
 };
 
-Static struct usbd_pipe_methods ohci_device_ctrl_methods = {
+static struct usbd_pipe_methods ohci_device_ctrl_methods = {
 	ohci_device_ctrl_transfer,
 	ohci_device_ctrl_start,
 	ohci_device_ctrl_abort,
@@ -334,7 +305,7 @@
 	ohci_device_ctrl_done,
 };
 
-Static struct usbd_pipe_methods ohci_device_intr_methods = {
+static struct usbd_pipe_methods ohci_device_intr_methods = {
 	ohci_device_intr_transfer,
 	ohci_device_intr_start,
 	ohci_device_intr_abort,
@@ -343,7 +314,7 @@
 	ohci_device_intr_done,
 };
 
-Static struct usbd_pipe_methods ohci_device_bulk_methods = {
+static struct usbd_pipe_methods ohci_device_bulk_methods = {
 	ohci_device_bulk_transfer,
 	ohci_device_bulk_start,
 	ohci_device_bulk_abort,
@@ -352,7 +323,7 @@
 	ohci_device_bulk_done,
 };
 
-Static struct usbd_pipe_methods ohci_device_isoc_methods = {
+static struct usbd_pipe_methods ohci_device_isoc_methods = {
 	ohci_device_isoc_transfer,
 	ohci_device_isoc_start,
 	ohci_device_isoc_abort,
@@ -361,43 +332,13 @@
 	ohci_device_isoc_done,
 };
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-int
-ohci_activate(device_ptr_t self, enum devact act)
-{
-	struct ohci_softc *sc = (struct ohci_softc *)self;
-	int rv = 0;
-
-	switch (act) {
-	case DVACT_ACTIVATE:
-		return (EOPNOTSUPP);
-
-	case DVACT_DEACTIVATE:
-		if (sc->sc_child != NULL)
-			rv = config_deactivate(sc->sc_child);
-		sc->sc_dying = 1;
-		break;
-	}
-	return (rv);
-}
-#endif
-
 int
 ohci_detach(struct ohci_softc *sc, int flags)
 {
 	int i, rv = 0;
 
-#if defined(__NetBSD__) || defined(__OpenBSD__)
-	if (sc->sc_child != NULL)
-		rv = config_detach(sc->sc_child, flags);
-
-	if (rv != 0)
-		return (rv);
-#else
 	sc->sc_dying = 1;
-#endif
-
-	usb_uncallout(sc->sc_tmo_rhsc, ohci_rhsc_enable, sc);
+	callout_stop(&sc->sc_tmo_rhsc);
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
 	powerhook_disestablish(sc->sc_powerhook);
@@ -510,35 +451,36 @@
 		     int alen, int rd, usbd_xfer_handle xfer,
 		     ohci_soft_td_t *sp, ohci_soft_td_t **ep)
 {
-	ohci_soft_td_t *next, *cur;
-	ohci_physaddr_t dataphys;
+	ohci_soft_td_t *next, *cur, *end;
+	ohci_physaddr_t dataphys, physend;
 	u_int32_t tdflags;
 	int offset = 0;
-	int len, curlen;
-	usb_dma_t *dma = &xfer->dmabuf;
+	int len, maxp, curlen, curlen2, seg, segoff;
+	struct usb_dma_mapping *dma = &xfer->dmamap;
 	u_int16_t flags = xfer->flags;
 
 	DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
 
 	len = alen;
 	cur = sp;
+	end = NULL;
 
+	maxp = UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
 	tdflags = htole32(
 	    (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
 	    (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
 	    OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_SET_DI(6));
 
-	for (;;) {
+	seg = 0;
+	segoff = 0;
+	while (len > 0) {
 		next = ohci_alloc_std(sc);
 		if (next == NULL)
 			goto nomem;
 
-		dataphys = DMAADDR(dma, offset);
-
 		/*
 		 * The OHCI hardware can handle at most one 4k crossing.
-		 * XXX - currently we only allocate contigous buffers, but
-		 * the OHCI spec says: If during the data transfer the buffer
+		 * The OHCI spec says: If during the data transfer the buffer
 		 * address contained in the HC's working copy of
 		 * CurrentBufferPointer crosses a 4K boundary, the upper 20
 		 * bits of Buffer End are copied to the working value of
@@ -546,34 +488,67 @@
 		 * be the 0th byte in the same 4K page that contains the
 		 * last byte of the buffer (the 4K boundary crossing may
 		 * occur within a data packet transfer.)
-		 *
-		 * If/when dma has multiple segments, this will need to
-		 * properly handle fragmenting TD's.
-		 * 
-		 * Note that if we are gathering data from multiple SMALL
-		 * segments, e.g. mbufs, we need to do special gymnastics,
-		 * e.g. bounce buffering or data aggregation,
-		 * BEFORE WE GET HERE because a bulk USB transfer must
-		 * consist of maximally sized packets right up to the end.
-		 * A shorter than maximal packet means that it is the end
-		 * of the transfer. If the data transfer length is a
-		 * multiple of the packet size, then a 0 byte
-		 * packet will be the signal of the end of transfer.
-		 * Since packets can't cross TDs this means that
-		 * each TD except the last one must cover an exact multiple
-		 * of the maximal packet length.
 		 */
-		if (OHCI_PAGE_OFFSET(dataphys) + len <= (2 * OHCI_PAGE_SIZE)) {
-			/* We can handle all that remains in this TD */
+		KASSERT(seg < dma->nsegs, ("ohci_alloc_std_chain: overrun"));
+		dataphys = dma->segs[seg].ds_addr + segoff;
+		curlen = dma->segs[seg].ds_len - segoff;
+		if (curlen > len)
 			curlen = len;
+		physend = dataphys + curlen - 1;
+		if (OHCI_PAGE(dataphys) != OHCI_PAGE(physend)) {
+			/* Truncate to two OHCI pages if there are more. */
+			if (curlen > 2 * OHCI_PAGE_SIZE -
+			    OHCI_PAGE_OFFSET(dataphys))
+				curlen = 2 * OHCI_PAGE_SIZE -
+				    OHCI_PAGE_OFFSET(dataphys);
+			if (curlen < len)
+				curlen -= curlen % maxp;
+			physend = dataphys + curlen - 1;
+		} else if (OHCI_PAGE_OFFSET(physend + 1) == 0 && curlen < len &&
+		    curlen + segoff == dma->segs[seg].ds_len) {
+			/* We can possibly include another segment. */
+			KASSERT(seg + 1 < dma->nsegs,
+			    ("ohci_alloc_std_chain: overrun2"));
+			seg++;
+
+			/* Determine how much of the second segment to use. */
+			curlen2 = dma->segs[seg].ds_len;
+			if (curlen + curlen2 > len)
+				curlen2 = len - curlen;
+			if (OHCI_PAGE(dma->segs[seg].ds_addr) !=
+			    OHCI_PAGE(dma->segs[seg].ds_addr + curlen2 - 1))
+				curlen2 = OHCI_PAGE_SIZE -
+				    OHCI_PAGE_OFFSET(dma->segs[seg].ds_addr);
+			if (curlen + curlen2 < len)
+				curlen2 -= (curlen + curlen2) % maxp;
+
+			if (curlen2 > 0) {
+				/* We can include a second segment */
+				segoff = curlen2;
+				physend = dma->segs[seg].ds_addr + curlen2 - 1;
+				curlen += curlen2;
+			} else {
+				/* Second segment not usable now. */
+				seg--;
+				segoff += curlen;
+			}
 		} else {
-			/* must use multiple TDs, fill as much as possible. */
-			curlen = 2 * OHCI_PAGE_SIZE -
-				 OHCI_PAGE_OFFSET(dataphys);
-			/* the length must be a multiple of the max size */
-			curlen -= curlen %
-			    UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
-			KASSERT((curlen != 0), ("ohci_alloc_std: curlen == 0"));
+			/* Simple case where there is just one OHCI page. */
+			segoff += curlen;
+		}
+		if (curlen == 0 && len != 0) {
+			/*
+			 * A maxp length packet would need to be split.
+			 * This shouldn't be possible if PAGE_SIZE >= 4k
+			 * and the buffer is contiguous in virtual memory.
+			 */
+			panic("ohci_alloc_std_chain: XXX need to copy");
+		}
+		if (segoff >= dma->segs[seg].ds_len) {
+			KASSERT(segoff == dma->segs[seg].ds_len,
+			    ("ohci_alloc_std_chain: overlap"));
+			seg++;
+			segoff = 0;
 		}
 		DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
 			    "len=%d curlen=%d\n",
@@ -584,27 +559,23 @@
 		cur->td.td_cbp = htole32(dataphys);
 		cur->nexttd = next;
 		cur->td.td_nexttd = htole32(next->physaddr);
-		cur->td.td_be = htole32(DMAADDR(dma, offset + curlen - 1));
+		cur->td.td_be = htole32(physend);
 		cur->len = curlen;
 		cur->flags = OHCI_ADD_LEN;
 		cur->xfer = xfer;
 		DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
 			    dataphys, dataphys + curlen - 1));
-		if (len == 0)
-			break;
 		if (len < 0)
 			panic("Length went negative: %d curlen %d dma %p offset %08x", len, curlen, dma, (int)0);
 
 		DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
 		offset += curlen;
+		end = cur;
 		cur = next;
 	}
-	if ((flags & USBD_FORCE_SHORT_XFER) &&
+	if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
 	    alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
 		/* Force a 0 length transfer at the end. */
-
-		cur = next;
-
 		next = ohci_alloc_std(sc);
 		if (next == NULL)
 			goto nomem;
@@ -618,8 +589,9 @@
 		cur->flags = 0;
 		cur->xfer = xfer;
 		DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+		end = cur;
 	}
-	*ep = cur;
+	*ep = end;
 
 	return (USBD_NORMAL_COMPLETION);
 
@@ -629,7 +601,7 @@
 }
 
 #if 0
-Static void
+static void
 ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std,
 		    ohci_soft_td_t *stdend)
 {
@@ -715,18 +687,14 @@
 	u_int32_t rev;
 
 	DPRINTF(("ohci_init: start\n"));
-#if defined(__OpenBSD__)
-	printf(",");
-#else
-	printf("%s:", USBDEVNAME(sc->sc_bus.bdev));
-#endif
+	printf("%s:", device_get_nameunit(sc->sc_bus.bdev));
 	rev = OREAD4(sc, OHCI_REVISION);
 	printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
 	       OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
 
 	if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
 		printf("%s: unsupported OHCI revision\n",
-		       USBDEVNAME(sc->sc_bus.bdev));
+		       device_get_nameunit(sc->sc_bus.bdev));
 		sc->sc_bus.usbrev = USBREV_UNKNOWN;
 		return (USBD_INVAL);
 	}
@@ -737,7 +705,7 @@
 	for (i = 0; i < OHCI_HASH_SIZE; i++)
 		LIST_INIT(&sc->sc_hash_itds[i]);
 
-	SIMPLEQ_INIT(&sc->sc_free_xfers);
+	STAILQ_INIT(&sc->sc_free_xfers);
 
 	/* XXX determine alignment by R/W */
 	/* Allocate the HCCA area. */
@@ -821,12 +789,11 @@
 	sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
 
 #if defined(__NetBSD__) || defined(__OpenBSD__)
-	sc->sc_control = sc->sc_intre = 0;
 	sc->sc_powerhook = powerhook_establish(ohci_power, sc);
 	sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
 #endif
 
-	usb_callout_init(sc->sc_tmo_rhsc);
+	callout_init(&sc->sc_tmo_rhsc, 0);
 
 	return (USBD_NORMAL_COMPLETION);
 
@@ -844,7 +811,7 @@
 	return (err);
 }
 
-Static usbd_status
+static usbd_status
 ohci_controller_init(ohci_softc_t *sc)
 {
 	int i;
@@ -863,7 +830,7 @@
 		}
 		if ((ctl & OHCI_IR) == 0) {
 			printf("%s: SMM does not respond, resetting\n",
-			       USBDEVNAME(sc->sc_bus.bdev));
+			       device_get_nameunit(sc->sc_bus.bdev));
 			OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
 			goto reset;
 		}
@@ -888,7 +855,7 @@
 	 * This reset should not be necessary according to the OHCI spec, but
 	 * without it some controllers do not start.
 	 */
-	DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
+	DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev)));
 	OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
 	usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
 
@@ -904,7 +871,7 @@
 			break;
 	}
 	if (hcr) {
-		printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
+		printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
 		return (USBD_IOERROR);
 	}
 #ifdef USB_DEBUG
@@ -982,9 +949,9 @@
 	struct ohci_softc *sc = (struct ohci_softc *)bus;
 	usbd_xfer_handle xfer;
 
-	xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+	xfer = STAILQ_FIRST(&sc->sc_free_xfers);
 	if (xfer != NULL) {
-		SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
+		STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
 #ifdef DIAGNOSTIC
 		if (xfer->busy_free != XFER_FREE) {
 			printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer,
@@ -1010,14 +977,6 @@
 ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
 {
 	struct ohci_softc *sc = (struct ohci_softc *)bus;
-	struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer;
-	ohci_soft_itd_t *sitd;
-
-        if (oxfer->ohci_xfer_flags & OHCI_ISOC_DIRTY) {
-		for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer;
-		    sitd = sitd->nextitd)
-			ohci_free_sitd(sc, sitd);
-	}
 
 #ifdef DIAGNOSTIC
 	if (xfer->busy_free != XFER_BUSY) {
@@ -1027,7 +986,7 @@
 	}
 	xfer->busy_free = XFER_FREE;
 #endif
-	SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+	STAILQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
 }
 
 /*
@@ -1143,28 +1102,28 @@
 }
 #endif
 
-Static int ohci_intr1(ohci_softc_t *);
+static int ohci_intr1(ohci_softc_t *);
 
-int
+void
 ohci_intr(void *p)
 {
 	ohci_softc_t *sc = p;
 
 	if (sc == NULL || sc->sc_dying)
-		return (0);
+		return;
 
 	/* If we get an interrupt while polling, then just ignore it. */
 	if (sc->sc_bus.use_polling) {
 #ifdef DIAGNOSTIC
 		printf("ohci_intr: ignored interrupt while polling\n");
 #endif
-		return (0);
+		return;
 	}
 
-	return (ohci_intr1(sc));
+	ohci_intr1(sc);
 }
 
-Static int
+static int
 ohci_intr1(ohci_softc_t *sc)
 {
 	u_int32_t intrs, eintrs;
@@ -1224,7 +1183,7 @@
 		sc->sc_overrun_cnt++;
 		if (usbd_ratecheck(&sc->sc_overrun_ntc)) {
 			printf("%s: %u scheduling overruns\n",
-			    USBDEVNAME(sc->sc_bus.bdev), sc->sc_overrun_cnt);
+			    device_get_nameunit(sc->sc_bus.bdev), sc->sc_overrun_cnt);
 			sc->sc_overrun_cnt = 0;
 		}
 		/* XXX do what */
@@ -1236,12 +1195,12 @@
 		eintrs &= ~OHCI_WDH;
 	}
 	if (eintrs & OHCI_RD) {
-		printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
+		printf("%s: resume detect\n", device_get_nameunit(sc->sc_bus.bdev));
 		/* XXX process resume detect */
 	}
 	if (eintrs & OHCI_UE) {
 		printf("%s: unrecoverable error, controller halted\n",
-		       USBDEVNAME(sc->sc_bus.bdev));
+		       device_get_nameunit(sc->sc_bus.bdev));
 		OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
 		/* XXX what else */
 	}
@@ -1253,7 +1212,7 @@
 		 */
 		ohci_rhsc_able(sc, 0);
 		/* Do not allow RHSC interrupts > 1 per second */
-		usb_callout(sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc);
+		callout_reset(&sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc);
 		eintrs &= ~OHCI_RHSC;
 	}
 
@@ -1264,7 +1223,7 @@
 		OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs);
 		sc->sc_eintrs &= ~eintrs;
 		printf("%s: blocking intrs 0x%x\n",
-		       USBDEVNAME(sc->sc_bus.bdev), eintrs);
+		       device_get_nameunit(sc->sc_bus.bdev), eintrs);
 	}
 
 	return (1);
@@ -1425,7 +1384,7 @@
 			DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n",
 			  OHCI_TD_GET_CC(le32toh(std->td.td_flags)),
 			  ohci_cc_strs[OHCI_TD_GET_CC(le32toh(std->td.td_flags))]));
-			usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+			callout_stop(&xfer->timeout_handle);
 			usb_rem_task(OXFER(xfer)->xfer.pipe->device,
 			    &OXFER(xfer)->abort_task);
 
@@ -1465,7 +1424,7 @@
 			continue;
 
 		/* Normal transfer completion */
-		usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+		callout_stop(&xfer->timeout_handle);
 		usb_rem_task(OXFER(xfer)->xfer.pipe->device,
 		    &OXFER(xfer)->abort_task);
 		for (p = xfer->hcpriv; p->xfer == xfer; p = n) {
@@ -1536,6 +1495,11 @@
 				if (sitd->flags & OHCI_CALL_DONE)
 					break;
 			}
+		 	for (sitd = xfer->hcpriv; sitd->xfer == xfer;
+			    sitd = next) {
+				next = sitd->nextitd;
+				ohci_free_sitd(sc, sitd);
+			}
 
 			s = splusb();
 			usb_transfer_complete(xfer);
@@ -1572,42 +1536,18 @@
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
 	ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
-	ohci_soft_ed_t *sed = opipe->sed;
-	ohci_soft_td_t *data, *tail;
-
+	usbd_status err;
 
 	DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n",
 		     xfer, xfer->actlen));
 
 	xfer->hcpriv = NULL;
-
 	if (xfer->pipe->repeat) {
-		data = opipe->tail.td;
-		tail = ohci_alloc_std(sc); /* XXX should reuse TD */
-		if (tail == NULL) {
-			xfer->status = USBD_NOMEM;
+		err = ohci_device_intr_insert(sc, xfer);
+		if (err) {
+			xfer->status = err;
 			return;
 		}
-		tail->xfer = NULL;
-
-		data->td.td_flags = htole32(
-			OHCI_TD_IN | OHCI_TD_NOCC |
-			OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
-		if (xfer->flags & USBD_SHORT_XFER_OK)
-			data->td.td_flags |= htole32(OHCI_TD_R);
-		data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
-		data->nexttd = tail;
-		data->td.td_nexttd = htole32(tail->physaddr);
-		data->td.td_be = htole32(le32toh(data->td.td_cbp) +
-			xfer->length - 1);
-		data->len = xfer->length;
-		data->xfer = xfer;
-		data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
-		xfer->hcpriv = data;
-		xfer->actlen = 0;
-
-		sed->ed.ed_tailp = htole32(tail->physaddr);
-		opipe->tail.td = tail;
 	}
 }
 
@@ -1639,7 +1579,7 @@
 
 	pipe = xfer->pipe;
 
-	p = KERNADDR(&xfer->dmabuf, 0);
+	p = xfer->buffer;
 	m = min(sc->sc_noport, xfer->length * 8 - 1);
 	memset(p, 0, xfer->length);
 	for (i = 1; i <= m; i++) {
@@ -1728,7 +1668,6 @@
 	usb_device_request_t *req = &xfer->request;
 	usbd_device_handle dev = opipe->pipe.device;
 	ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
-	int addr = dev->address;
 	ohci_soft_td_t *setup, *stat, *next, *tail;
 	ohci_soft_ed_t *sed;
 	int isread;
@@ -1742,7 +1681,7 @@
 	DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, "
 		    "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
 		    req->bmRequestType, req->bRequest, UGETW(req->wValue),
-		    UGETW(req->wIndex), len, addr,
+		    UGETW(req->wIndex), len, dev->address,
 		    opipe->pipe.endpoint->edesc->bEndpointAddress));
 
 	setup = opipe->tail.td;
@@ -1760,16 +1699,6 @@
 
 	sed = opipe->sed;
 	opipe->u.ctl.length = len;
-
-	/* Update device address and length since they may have changed
-	   during the setup of the control pipe in usbd_new_device(). */
-	/* XXX This only needs to be done once, but it's too early in open. */
-	/* XXXX Should not touch ED here! */
-	sed->ed.ed_flags = htole32(
-	 (le32toh(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
-	 OHCI_ED_SET_FA(addr) |
-	 OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
-
 	next = stat;
 
 	/* Set up data transaction */
@@ -1824,8 +1753,8 @@
 	opipe->tail.td = tail;
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
 	if (xfer->timeout && !sc->sc_bus.use_polling) {
-		usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
-			    ohci_timeout, xfer);
+		callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
+		    ohci_timeout, xfer);
 	}
 	splx(s);
 
@@ -1928,7 +1857,7 @@
 	 * stage.
 	 */
 	KASSERT((a&~OHCI_HEADMASK) == 0, ("%s: 0x%b has lower bits set\n",
-				      USBDEVNAME(sc->sc_bus.bdev),
+				      device_get_nameunit(sc->sc_bus.bdev),
 				      (int) a, "\20\1HALT\2TOGGLE"));
 
 	for (std = LIST_FIRST(&sc->sc_hash_tds[h]);
@@ -1938,7 +1867,7 @@
 			return (std);
 
 	DPRINTF(("%s: ohci_hash_find_td: addr 0x%08lx not found\n",
-		USBDEVNAME(sc->sc_bus.bdev), (u_long) a));
+		device_get_nameunit(sc->sc_bus.bdev), (u_long) a));
 	return (NULL);
 }
 
@@ -1997,7 +1926,8 @@
 	}
 
 	/* Execute the abort in a process context. */
-	usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task);
+	usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task,
+	    USB_TASKQ_HC);
 }
 
 void
@@ -2281,10 +2211,11 @@
 		/* If we're dying, just do the software part. */
 		s = splusb();
 		xfer->status = status;	/* make software ignore it */
-		usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+		callout_stop(&xfer->timeout_handle);
 		usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
 		usb_transfer_complete(xfer);
 		splx(s);
+		return;
 	}
 
 	if (xfer->device->bus->intr_context || !curproc)
@@ -2314,7 +2245,7 @@
 	s = splusb();
 	oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTING;
 	xfer->status = status;	/* make software ignore it */
-	usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+	callout_stop(&xfer->timeout_handle);
 	usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
 	splx(s);
 	DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
@@ -2398,7 +2329,7 @@
 /*
  * Data structures and routines to emulate the root hub.
  */
-Static usb_device_descriptor_t ohci_devd = {
+static usb_device_descriptor_t ohci_devd = {
 	USB_DEVICE_DESCRIPTOR_SIZE,
 	UDESC_DEVICE,		/* type */
 	{0x00, 0x01},		/* USB version */
@@ -2411,7 +2342,7 @@
 	1			/* # of configurations */
 };
 
-Static usb_config_descriptor_t ohci_confd = {
+static usb_config_descriptor_t ohci_confd = {
 	USB_CONFIG_DESCRIPTOR_SIZE,
 	UDESC_CONFIG,
 	{USB_CONFIG_DESCRIPTOR_SIZE +
@@ -2424,7 +2355,7 @@
 	0			/* max power */
 };
 
-Static usb_interface_descriptor_t ohci_ifcd = {
+static usb_interface_descriptor_t ohci_ifcd = {
 	USB_INTERFACE_DESCRIPTOR_SIZE,
 	UDESC_INTERFACE,
 	0,
@@ -2436,7 +2367,7 @@
 	0
 };
 
-Static usb_endpoint_descriptor_t ohci_endpd = {
+static usb_endpoint_descriptor_t ohci_endpd = {
 	USB_ENDPOINT_DESCRIPTOR_SIZE,
 	UDESC_ENDPOINT,
 	UE_DIR_IN | OHCI_INTR_ENDPT,
@@ -2445,7 +2376,7 @@
 	255
 };
 
-Static usb_hub_descriptor_t ohci_hubd = {
+static usb_hub_descriptor_t ohci_hubd = {
 	USB_HUB_DESCRIPTOR_SIZE,
 	UDESC_HUB,
 	0,
@@ -2455,7 +2386,7 @@
 	{0},
 };
 
-Static int
+static int
 ohci_str(usb_string_descriptor_t *p, int l, const char *s)
 {
 	int i;
@@ -2475,7 +2406,7 @@
 /*
  * Simulate a hardware hub by handling all the necessary requests.
  */
-Static usbd_status
+static usbd_status
 ohci_root_ctrl_transfer(usbd_xfer_handle xfer)
 {
 	usbd_status err;
@@ -2486,10 +2417,10 @@
 		return (err);
 
 	/* Pipe isn't running, start first */
-	return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+	return (ohci_root_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue)));
 }
 
-Static usbd_status
+static usbd_status
 ohci_root_ctrl_start(usbd_xfer_handle xfer)
 {
 	ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
@@ -2520,7 +2451,7 @@
 	index = UGETW(req->wIndex);
 
 	if (len != 0)
-		buf = KERNADDR(&xfer->dmabuf, 0);
+		buf = xfer->buffer;
 
 #define C(x,y) ((x) | ((y) << 8))
 	switch(C(req->bRequest, req->bmRequestType)) {
@@ -2797,21 +2728,21 @@
 }
 
 /* Abort a root control request. */
-Static void
+static void
 ohci_root_ctrl_abort(usbd_xfer_handle xfer)
 {
 	/* Nothing to do, all transfers are synchronous. */
 }
 
 /* Close the root pipe. */
-Static void
+static void
 ohci_root_ctrl_close(usbd_pipe_handle pipe)
 {
 	DPRINTF(("ohci_root_ctrl_close\n"));
 	/* Nothing to do. */
 }
 
-Static usbd_status
+static usbd_status
 ohci_root_intr_transfer(usbd_xfer_handle xfer)
 {
 	usbd_status err;
@@ -2822,10 +2753,10 @@
 		return (err);
 
 	/* Pipe isn't running, start first */
-	return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+	return (ohci_root_intr_start(STAILQ_FIRST(&xfer->pipe->queue)));
 }
 
-Static usbd_status
+static usbd_status
 ohci_root_intr_start(usbd_xfer_handle xfer)
 {
 	usbd_pipe_handle pipe = xfer->pipe;
@@ -2840,7 +2771,7 @@
 }
 
 /* Abort a root interrupt request. */
-Static void
+static void
 ohci_root_intr_abort(usbd_xfer_handle xfer)
 {
 	int s;
@@ -2856,7 +2787,7 @@
 }
 
 /* Close the root pipe. */
-Static void
+static void
 ohci_root_intr_close(usbd_pipe_handle pipe)
 {
 	ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
@@ -2868,7 +2799,7 @@
 
 /************************/
 
-Static usbd_status
+static usbd_status
 ohci_device_ctrl_transfer(usbd_xfer_handle xfer)
 {
 	usbd_status err;
@@ -2879,10 +2810,10 @@
 		return (err);
 
 	/* Pipe isn't running, start first */
-	return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+	return (ohci_device_ctrl_start(STAILQ_FIRST(&xfer->pipe->queue)));
 }
 
-Static usbd_status
+static usbd_status
 ohci_device_ctrl_start(usbd_xfer_handle xfer)
 {
 	ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
@@ -2909,7 +2840,7 @@
 }
 
 /* Abort a device control request. */
-Static void
+static void
 ohci_device_ctrl_abort(usbd_xfer_handle xfer)
 {
 	DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
@@ -2917,7 +2848,7 @@
 }
 
 /* Close a device control pipe. */
-Static void
+static void
 ohci_device_ctrl_close(usbd_pipe_handle pipe)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
@@ -2930,7 +2861,7 @@
 
 /************************/
 
-Static void
+static void
 ohci_device_clear_toggle(usbd_pipe_handle pipe)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
@@ -2938,12 +2869,12 @@
 	opipe->sed->ed.ed_headp &= htole32(~OHCI_TOGGLECARRY);
 }
 
-Static void
+static void
 ohci_noop(usbd_pipe_handle pipe)
 {
 }
 
-Static usbd_status
+static usbd_status
 ohci_device_bulk_transfer(usbd_xfer_handle xfer)
 {
 	usbd_status err;
@@ -2954,10 +2885,10 @@
 		return (err);
 
 	/* Pipe isn't running, start first */
-	return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+	return (ohci_device_bulk_start(STAILQ_FIRST(&xfer->pipe->queue)));
 }
 
-Static usbd_status
+static usbd_status
 ohci_device_bulk_start(usbd_xfer_handle xfer)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
@@ -3036,8 +2967,8 @@
 	sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
 	OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
 	if (xfer->timeout && !sc->sc_bus.use_polling) {
-                usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
-			    ohci_timeout, xfer);
+                callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
+		    ohci_timeout, xfer);
 	}
 
 #if 0
@@ -3059,7 +2990,7 @@
 	return (USBD_IN_PROGRESS);
 }
 
-Static void
+static void
 ohci_device_bulk_abort(usbd_xfer_handle xfer)
 {
 	DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
@@ -3069,7 +3000,7 @@
 /*
  * Close a device bulk pipe.
  */
-Static void
+static void
 ohci_device_bulk_close(usbd_pipe_handle pipe)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
@@ -3082,7 +3013,7 @@
 
 /************************/
 
-Static usbd_status
+static usbd_status
 ohci_device_intr_transfer(usbd_xfer_handle xfer)
 {
 	usbd_status err;
@@ -3093,33 +3024,51 @@
 		return (err);
 
 	/* Pipe isn't running, start first */
-	return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+	return (ohci_device_intr_start(STAILQ_FIRST(&xfer->pipe->queue)));
 }
 
-Static usbd_status
+static usbd_status
 ohci_device_intr_start(usbd_xfer_handle xfer)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
-	usbd_device_handle dev = opipe->pipe.device;
-	ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+	ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
 	ohci_soft_ed_t *sed = opipe->sed;
-	ohci_soft_td_t *data, *tail;
-	int len;
-	int s;
+	usbd_status err;
 
 	if (sc->sc_dying)
 		return (USBD_IOERROR);
 
-	DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d "
+	DPRINTFN(3, ("ohci_device_intr_start: xfer=%p len=%d "
 		     "flags=%d priv=%p\n",
 		     xfer, xfer->length, xfer->flags, xfer->priv));
 
 #ifdef DIAGNOSTIC
 	if (xfer->rqflags & URQ_REQUEST)
-		panic("ohci_device_intr_transfer: a request");
+		panic("ohci_device_intr_start: a request");
 #endif
 
-	len = xfer->length;
+	err = ohci_device_intr_insert(sc, xfer);
+	if (err)
+		return (err);
+
+	sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
+
+	return (USBD_IN_PROGRESS);
+}
+
+/*
+ * Insert an interrupt transfer into an endpoint descriptor list
+ */
+static usbd_status
+ohci_device_intr_insert(ohci_softc_t *sc, usbd_xfer_handle xfer)
+{
+	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+	ohci_soft_ed_t *sed = opipe->sed;
+	ohci_soft_td_t *data, *tail;
+	ohci_physaddr_t dataphys, physend;
+	int s;
+
+	DPRINTFN(4, ("ohci_device_intr_insert: xfer=%p", xfer));
 
 	data = opipe->tail.td;
 	tail = ohci_alloc_std(sc);
@@ -3132,18 +3081,43 @@
 		OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
 	if (xfer->flags & USBD_SHORT_XFER_OK)
 		data->td.td_flags |= htole32(OHCI_TD_R);
-	data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
+	/*
+	 * Assume a short mapping with no complications, which
+	 * should always be true for <= 4k buffers in contiguous
+	 * virtual memory. The data can take the following forms:
+	 *	1 segment in 1 OHCI page
+	 *	1 segment in 2 OHCI pages
+	 *	2 segments in 2 OHCI pages
+	 * (see comment in ohci_alloc_std_chain() for details)
+	 */
+	KASSERT(xfer->length > 0 && xfer->length <= OHCI_PAGE_SIZE,
+	    ("ohci_device_intr_insert: bad length %d", xfer->length));
+	dataphys = xfer->dmamap.segs[0].ds_addr;
+	physend = dataphys + xfer->length - 1;
+	if (xfer->dmamap.nsegs == 2) {
+		KASSERT(OHCI_PAGE_OFFSET(dataphys +
+		    xfer->dmamap.segs[0].ds_len) == 0,
+		    ("ohci_device_intr_insert: bad seg 0 termination"));
+		physend = xfer->dmamap.segs[1].ds_addr + xfer->length -
+		    xfer->dmamap.segs[0].ds_len - 1;
+	} else {
+		KASSERT(xfer->dmamap.nsegs == 1,
+		    ("ohci_device_intr_insert: bad seg count %d",
+		    (u_int)xfer->dmamap.nsegs));
+	}
+	data->td.td_cbp = htole32(dataphys);
 	data->nexttd = tail;
 	data->td.td_nexttd = htole32(tail->physaddr);
-	data->td.td_be = htole32(le32toh(data->td.td_cbp) + len - 1);
-	data->len = len;
+	data->td.td_be = htole32(physend);
+	data->len = xfer->length;
 	data->xfer = xfer;
 	data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
 	xfer->hcpriv = data;
+	xfer->actlen = 0;
 
 #ifdef USB_DEBUG
 	if (ohcidebug > 5) {
-		DPRINTF(("ohci_device_intr_transfer:\n"));
+		DPRINTF(("ohci_device_intr_insert:\n"));
 		ohci_dump_ed(sed);
 		ohci_dump_tds(data);
 	}
@@ -3153,29 +3127,13 @@
 	s = splusb();
 	sed->ed.ed_tailp = htole32(tail->physaddr);
 	opipe->tail.td = tail;
-	sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
-
-#if 0
-/*
- * This goes horribly wrong, printing thousands of descriptors,
- * because false references are followed due to the fact that the
- * TD is gone.
- */
-	if (ohcidebug > 5) {
-		usb_delay_ms(&sc->sc_bus, 5);
-		DPRINTF(("ohci_device_intr_transfer: status=%x\n",
-			 OREAD4(sc, OHCI_COMMAND_STATUS)));
-		ohci_dump_ed(sed);
-		ohci_dump_tds(data);
-	}
-#endif
 	splx(s);
 
-	return (USBD_IN_PROGRESS);
+	return (USBD_NORMAL_COMPLETION);
 }
 
 /* Abort a device control request. */
-Static void
+static void
 ohci_device_intr_abort(usbd_xfer_handle xfer)
 {
 	if (xfer->pipe->intrxfer == xfer) {
@@ -3186,7 +3144,7 @@
 }
 
 /* Close a device interrupt pipe. */
-Static void
+static void
 ohci_device_intr_close(usbd_pipe_handle pipe)
 {
 	struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
@@ -3208,7 +3166,7 @@
 	if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
 	    (le32toh(sed->ed.ed_headp) & OHCI_HEADMASK))
 		panic("%s: Intr pipe %p still has TDs queued",
-			USBDEVNAME(sc->sc_bus.bdev), pipe);
+			device_get_nameunit(sc->sc_bus.bdev), pipe);
 #endif
 
 	for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
@@ -3228,7 +3186,7 @@
 	ohci_free_sed(sc, opipe->sed);
 }
 
-Static usbd_status
+static usbd_status
 ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival)
 {
 	int i, j, s, best;
@@ -3313,7 +3271,7 @@
 
 	/* and start if the pipe wasn't running */
 	if (!err)
-		ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+		ohci_device_isoc_start(STAILQ_FIRST(&xfer->pipe->queue));
 
 	return (err);
 }
@@ -3326,10 +3284,10 @@
 	ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
 	ohci_soft_ed_t *sed = opipe->sed;
 	struct iso *iso = &opipe->u.iso;
-	struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer;
+	struct usb_dma_mapping *dma = &xfer->dmamap;
 	ohci_soft_itd_t *sitd, *nsitd;
-	ohci_physaddr_t buf, offs, noffs, bp0, tdphys;
-	int i, ncur, nframes;
+	ohci_physaddr_t dataphys, bp0, physend, prevpage;
+	int curlen, i, len, ncur, nframes, npages, seg, segoff;
 	int s;
 
 	DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
@@ -3346,94 +3304,115 @@
 			    iso->next));
 	}
 
-	if (xfer->hcpriv) {
-		for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer;
-		    sitd = sitd->nextitd)
-			ohci_free_sitd(sc, sitd); /* Free ITDs in prev xfer*/
-
-		if (sitd == NULL) {
-			sitd = ohci_alloc_sitd(sc);
-			if (sitd == NULL)
-				panic("cant alloc isoc");
-			opipe->tail.itd = sitd;
-			tdphys = sitd->physaddr;
-			sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* Stop*/
-			sed->ed.ed_headp =
-			sed->ed.ed_tailp = htole32(tdphys);
-			sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* Start.*/
-		}
-	}
-
 	sitd = opipe->tail.itd;
-	buf = DMAADDR(&xfer->dmabuf, 0);
-	bp0 = OHCI_PAGE(buf);
-	offs = OHCI_PAGE_OFFSET(buf);
 	nframes = xfer->nframes;
 	xfer->hcpriv = sitd;
-	for (i = ncur = 0; i < nframes; i++, ncur++) {
-		noffs = offs + xfer->frlengths[i];
-		if (ncur == OHCI_ITD_NOFFSET ||	/* all offsets used */
-		    OHCI_PAGE(buf + noffs) > bp0 + OHCI_PAGE_SIZE) { /* too many page crossings */
-
-			/* Allocate next ITD */
-			nsitd = ohci_alloc_sitd(sc);
-			if (nsitd == NULL) {
-				/* XXX what now? */
-				printf("%s: isoc TD alloc failed\n",
-				       USBDEVNAME(sc->sc_bus.bdev));
-				return;
+	seg = 0;
+	segoff = 0;
+	i = 0;
+	while (i < nframes) {
+		/*
+		 * Fill in as many ITD frames as possible.
+		 */
+		KASSERT(seg < dma->nsegs, ("ohci_device_isoc_enter: overrun"));
+		bp0 = dma->segs[seg].ds_addr + segoff;
+		sitd->itd.itd_bp0 = htole32(bp0);
+		prevpage = OHCI_PAGE(bp0);
+		npages = 1;
+
+		ncur = 0;
+		while (ncur < OHCI_ITD_NOFFSET && i < nframes) {
+			/* Find the frame start and end physical addresses. */
+			len = xfer->frlengths[i];
+			dataphys = dma->segs[seg].ds_addr + segoff;
+			curlen = dma->segs[seg].ds_len - segoff;
+			if (len > curlen) {
+				KASSERT(seg + 1 < dma->nsegs,
+				    ("ohci_device_isoc_enter: overrun2"));
+				seg++;
+				segoff = len - curlen;
+			} else {
+				segoff += len;
+			}
+			KASSERT(segoff <= dma->segs[seg].ds_len,
+			    ("ohci_device_isoc_enter: overrun3"));
+			physend = dma->segs[seg].ds_addr + segoff - 1;
+
+			/* Check if there would be more than 2 pages . */
+			if (OHCI_PAGE(dataphys) != prevpage) {
+				prevpage = OHCI_PAGE(dataphys);
+				npages++;
+			}
+			if (OHCI_PAGE(physend) != prevpage) {
+				prevpage = OHCI_PAGE(physend);
+				npages++;
+			}
+			if (npages > 2) {
+				/* We cannot fit this frame now. */
+				segoff -= len;
+				if (segoff < 0) {
+					seg--;
+					segoff += dma->segs[seg].ds_len;
+				}
+				break;
 			}
 
-			/* Fill current ITD */
+			sitd->itd.itd_be = htole32(physend);
+			sitd->itd.itd_offset[ncur] =
+			    htole16(OHCI_ITD_MK_OFFS(OHCI_PAGE(dataphys) ==
+			    OHCI_PAGE(bp0) ? 0 : 1, dataphys));
+			i++;
+			ncur++;
+		}
+		if (segoff >= dma->segs[seg].ds_len) {
+			KASSERT(segoff == dma->segs[seg].ds_len,
+			    ("ohci_device_isoc_enter: overlap"));
+			seg++;
+			segoff = 0;
+		}
+
+		/* Allocate next ITD */
+		nsitd = ohci_alloc_sitd(sc);
+		if (nsitd == NULL) {
+			/* XXX what now? */
+			printf("%s: isoc TD alloc failed\n",
+			       device_get_nameunit(sc->sc_bus.bdev));
+			return;
+		}
+
+		/* Fill out remaining fields of current ITD */
+		sitd->nextitd = nsitd;
+		sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
+		sitd->xfer = xfer;
+		if (i < nframes) {
 			sitd->itd.itd_flags = htole32(
 				OHCI_ITD_NOCC |
 				OHCI_ITD_SET_SF(iso->next) |
 				OHCI_ITD_SET_DI(6) | /* delay intr a little */
 				OHCI_ITD_SET_FC(ncur));
-			sitd->itd.itd_bp0 = htole32(bp0);
-			sitd->nextitd = nsitd;
-			sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
-			sitd->itd.itd_be = htole32(bp0 + offs - 1);
-			sitd->xfer = xfer;
 			sitd->flags = OHCI_ITD_ACTIVE;
+		} else {
+			sitd->itd.itd_flags = htole32(
+				OHCI_ITD_NOCC |
+				OHCI_ITD_SET_SF(iso->next) |
+				OHCI_ITD_SET_DI(0) |
+				OHCI_ITD_SET_FC(ncur));
+			sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE;
+		}
+		iso->next += ncur;
 
-			sitd = nsitd;
-			iso->next = iso->next + ncur;
-			bp0 = OHCI_PAGE(buf + offs);
-			ncur = 0;
-		}
-		sitd->itd.itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS(offs));
-		offs = noffs;
-	}
-	nsitd = ohci_alloc_sitd(sc);
-	if (nsitd == NULL) {
-		/* XXX what now? */
-		printf("%s: isoc TD alloc failed\n",
-		       USBDEVNAME(sc->sc_bus.bdev));
-		return;
+		sitd = nsitd;
 	}
-	/* Fixup last used ITD */
-	sitd->itd.itd_flags = htole32(
-		OHCI_ITD_NOCC |
-		OHCI_ITD_SET_SF(iso->next) |
-		OHCI_ITD_SET_DI(0) |
-		OHCI_ITD_SET_FC(ncur));
-	sitd->itd.itd_bp0 = htole32(bp0);
-	sitd->nextitd = nsitd;
-	sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
-	sitd->itd.itd_be = htole32(bp0 + offs - 1);
-	sitd->xfer = xfer;
-	sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE;
 
-	iso->next = iso->next + ncur;
 	iso->inuse += nframes;
 
-	xfer->actlen = offs;	/* XXX pretend we did it all */
+	/* XXX pretend we did it all */
+	xfer->actlen = 0;
+	for (i = 0; i < nframes; i++)
+		xfer->actlen += xfer->frlengths[i];
 
 	xfer->status = USBD_IN_PROGRESS;
 
-	oxfer->ohci_xfer_flags |= OHCI_ISOC_DIRTY;
-
 #ifdef USB_DEBUG
 	if (ohcidebug > 5) {
 		DPRINTF(("ohci_device_isoc_enter: frame=%d\n",
@@ -3444,9 +3423,9 @@
 #endif
 
 	s = splusb();
-	opipe->tail.itd = nsitd;
+	opipe->tail.itd = sitd;
 	sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
-	sed->ed.ed_tailp = htole32(nsitd->physaddr);
+	sed->ed.ed_tailp = htole32(sitd->physaddr);
 	splx(s);
 
 #ifdef USB_DEBUG
@@ -3494,7 +3473,7 @@
 	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
 	ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
 	ohci_soft_ed_t *sed;
-	ohci_soft_itd_t *sitd, *tmp_sitd;
+	ohci_soft_itd_t *sitd, *sitdnext, *tmp_sitd;
 	int s,undone,num_sitds;
 
 	s = splusb();
@@ -3557,20 +3536,20 @@
 		}
 	} while( undone != 0 );
 
+	/* Free the sitds */
+ 	for (sitd = xfer->hcpriv; sitd->xfer == xfer;
+	    sitd = sitdnext) {
+		sitdnext = sitd->nextitd;
+		ohci_free_sitd(sc, sitd);
+	}
 
 	s = splusb();
 
 	/* Run callback. */
 	usb_transfer_complete(xfer);
 
-	if (sitd != NULL)
-		/*
-		 * Only if there is a `next' sitd in next xfer...
-		 * unlink this xfer's sitds.
-		 */
-		sed->ed.ed_headp = htole32(sitd->physaddr);
-	else
-		sed->ed.ed_headp = 0;
+	/* There is always a `next' sitd so link it up. */
+	sed->ed.ed_headp = htole32(sitd->physaddr);
 
 	sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */
 
Index: if_ural.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/if_ural.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L sys/dev/usb/if_ural.c -L sys/dev/usb/if_ural.c -u -r1.3 -r1.4
--- sys/dev/usb/if_ural.c
+++ sys/dev/usb/if_ural.c
@@ -1,4 +1,4 @@
-/*	$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.10.2.5 2006/01/29 14:16:36 damien Exp $	*/
+/*	$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.69 2007/09/17 19:07:24 sam Exp $	*/
 
 /*-
  * Copyright (c) 2005, 2006
@@ -18,7 +18,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.10.2.5 2006/01/29 14:16:36 damien Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/usb/if_ural.c,v 1.69 2007/09/17 19:07:24 sam Exp $");
 
 /*-
  * Ralink Technology RT2500USB chipset driver
@@ -39,7 +39,6 @@
 
 #include <machine/bus.h>
 #include <machine/resource.h>
-#include <machine/clock.h>
 #include <sys/rman.h>
 
 #include <net/bpf.h>
@@ -51,13 +50,9 @@
 #include <net/if_types.h>
 
 #include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_amrr.h>
 #include <net80211/ieee80211_radiotap.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
+#include <net80211/ieee80211_regdomain.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -68,8 +63,8 @@
 #include <dev/usb/if_uralvar.h>
 
 #ifdef USB_DEBUG
-#define DPRINTF(x)	do { if (uraldebug > 0) logprintf x; } while (0)
-#define DPRINTFN(n, x)	do { if (uraldebug >= (n)) logprintf x; } while (0)
+#define DPRINTF(x)	do { if (uraldebug > 0) printf x; } while (0)
+#define DPRINTFN(n, x)	do { if (uraldebug >= (n)) printf x; } while (0)
 int uraldebug = 0;
 SYSCTL_NODE(_hw_usb, OID_AUTO, ural, CTLFLAG_RW, 0, "USB ural");
 SYSCTL_INT(_hw_usb_ural, OID_AUTO, debug, CTLFLAG_RW, &uraldebug, 0,
@@ -79,18 +74,24 @@
 #define DPRINTFN(n, x)
 #endif
 
+#define URAL_RSSI(rssi)					\
+	((rssi) > (RAL_NOISE_FLOOR + RAL_RSSI_CORR) ?	\
+	 ((rssi) - (RAL_NOISE_FLOOR + RAL_RSSI_CORR)) : 0)
+
 /* various supported device vendors/products */
 static const struct usb_devno ural_devs[] = {
 	{ USB_VENDOR_ASUS,		USB_PRODUCT_ASUS_WL167G },
 	{ USB_VENDOR_ASUS,		USB_PRODUCT_RALINK_RT2570 },
 	{ USB_VENDOR_BELKIN,		USB_PRODUCT_BELKIN_F5D7050 },
-	{ USB_VENDOR_CONCEPTRONIC,	USB_PRODUCT_CONCEPTRONIC_C54U },
+	{ USB_VENDOR_BELKIN,		USB_PRODUCT_BELKIN_F5D7051 },
+	{ USB_VENDOR_CONCEPTRONIC2,	USB_PRODUCT_CONCEPTRONIC2_C54RU },
 	{ USB_VENDOR_DLINK,		USB_PRODUCT_DLINK_DWLG122 },
 	{ USB_VENDOR_GIGABYTE,		USB_PRODUCT_GIGABYTE_GNWBKG },
+	{ USB_VENDOR_GIGABYTE,		USB_PRODUCT_GIGABYTE_GN54G },
 	{ USB_VENDOR_GUILLEMOT,		USB_PRODUCT_GUILLEMOT_HWGUSB254 },
-	{ USB_VENDOR_LINKSYS4,		USB_PRODUCT_LINKSYS4_WUSB54G },
-	{ USB_VENDOR_LINKSYS4,		USB_PRODUCT_LINKSYS4_WUSB54GP },
-	{ USB_VENDOR_LINKSYS4,		USB_PRODUCT_LINKSYS4_HU200TS },
+	{ USB_VENDOR_CISCOLINKSYS,	USB_PRODUCT_CISCOLINKSYS_WUSB54G },
+	{ USB_VENDOR_CISCOLINKSYS,	USB_PRODUCT_CISCOLINKSYS_WUSB54GP },
+	{ USB_VENDOR_CISCOLINKSYS,	USB_PRODUCT_CISCOLINKSYS_HU200TS },
 	{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_KG54 },
 	{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_KG54AI },
 	{ USB_VENDOR_MELCO,		USB_PRODUCT_MELCO_KG54YB },
@@ -98,91 +99,90 @@
 	{ USB_VENDOR_MSI,		USB_PRODUCT_MSI_RT2570 },
 	{ USB_VENDOR_MSI,		USB_PRODUCT_MSI_RT2570_2 },
 	{ USB_VENDOR_MSI,		USB_PRODUCT_MSI_RT2570_3 },
+	{ USB_VENDOR_NOVATECH,		USB_PRODUCT_NOVATECH_NV902 },
 	{ USB_VENDOR_RALINK,		USB_PRODUCT_RALINK_RT2570 },
 	{ USB_VENDOR_RALINK,		USB_PRODUCT_RALINK_RT2570_2 },
+	{ USB_VENDOR_RALINK,		USB_PRODUCT_RALINK_RT2570_3 },
+	{ USB_VENDOR_SIEMENS2,		USB_PRODUCT_SIEMENS2_WL54G },
+	{ USB_VENDOR_SMC,		USB_PRODUCT_SMC_2862WG },
+	{ USB_VENDOR_SPHAIRON,		USB_PRODUCT_SPHAIRON_UB801R},
+	{ USB_VENDOR_SURECOM,		USB_PRODUCT_SURECOM_RT2570 },
 	{ USB_VENDOR_VTECH,		USB_PRODUCT_VTECH_RT2570 },
 	{ USB_VENDOR_ZINWELL,		USB_PRODUCT_ZINWELL_RT2570 }
 };
 
 MODULE_DEPEND(ural, wlan, 1, 1, 1);
+MODULE_DEPEND(ural, wlan_amrr, 1, 1, 1);
+MODULE_DEPEND(ural, usb, 1, 1, 1);
 
-Static int		ural_alloc_tx_list(struct ural_softc *);
-Static void		ural_free_tx_list(struct ural_softc *);
-Static int		ural_alloc_rx_list(struct ural_softc *);
-Static void		ural_free_rx_list(struct ural_softc *);
-Static int		ural_media_change(struct ifnet *);
-Static void		ural_next_scan(void *);
-Static void		ural_task(void *);
-Static int		ural_newstate(struct ieee80211com *,
+static int		ural_alloc_tx_list(struct ural_softc *);
+static void		ural_free_tx_list(struct ural_softc *);
+static int		ural_alloc_rx_list(struct ural_softc *);
+static void		ural_free_rx_list(struct ural_softc *);
+static int		ural_media_change(struct ifnet *);
+static void		ural_task(void *);
+static void		ural_scantask(void *);
+static int		ural_newstate(struct ieee80211com *,
 			    enum ieee80211_state, int);
-Static int		ural_rxrate(struct ural_rx_desc *);
-Static void		ural_txeof(usbd_xfer_handle, usbd_private_handle,
+static int		ural_rxrate(struct ural_rx_desc *);
+static void		ural_txeof(usbd_xfer_handle, usbd_private_handle,
 			    usbd_status);
-Static void		ural_rxeof(usbd_xfer_handle, usbd_private_handle,
+static void		ural_rxeof(usbd_xfer_handle, usbd_private_handle,
 			    usbd_status);
-Static int		ural_ack_rate(struct ieee80211com *, int);
-Static uint16_t		ural_txtime(int, int, uint32_t);
-Static uint8_t		ural_plcp_signal(int);
-Static void		ural_setup_tx_desc(struct ural_softc *,
+static int		ural_ack_rate(struct ieee80211com *, int);
+static uint16_t		ural_txtime(int, int, uint32_t);
+static uint8_t		ural_plcp_signal(int);
+static void		ural_setup_tx_desc(struct ural_softc *,
 			    struct ural_tx_desc *, uint32_t, int, int);
-Static int		ural_tx_bcn(struct ural_softc *, struct mbuf *,
+static int		ural_tx_bcn(struct ural_softc *, struct mbuf *,
 			    struct ieee80211_node *);
-Static int		ural_tx_mgt(struct ural_softc *, struct mbuf *,
+static int		ural_tx_mgt(struct ural_softc *, struct mbuf *,
 			    struct ieee80211_node *);
-Static int		ural_tx_data(struct ural_softc *, struct mbuf *,
+static int		ural_tx_data(struct ural_softc *, struct mbuf *,
 			    struct ieee80211_node *);
-Static void		ural_start(struct ifnet *);
-Static void		ural_watchdog(struct ifnet *);
-Static int		ural_reset(struct ifnet *);
-Static int		ural_ioctl(struct ifnet *, u_long, caddr_t);
-Static void		ural_set_testmode(struct ural_softc *);
-Static void		ural_eeprom_read(struct ural_softc *, uint16_t, void *,
+static void		ural_start(struct ifnet *);
+static void		ural_watchdog(void *);
+static int		ural_reset(struct ifnet *);
+static int		ural_ioctl(struct ifnet *, u_long, caddr_t);
+static void		ural_set_testmode(struct ural_softc *);
+static void		ural_eeprom_read(struct ural_softc *, uint16_t, void *,
 			    int);
-Static uint16_t		ural_read(struct ural_softc *, uint16_t);
-Static void		ural_read_multi(struct ural_softc *, uint16_t, void *,
+static uint16_t		ural_read(struct ural_softc *, uint16_t);
+static void		ural_read_multi(struct ural_softc *, uint16_t, void *,
 			    int);
-Static void		ural_write(struct ural_softc *, uint16_t, uint16_t);
-Static void		ural_write_multi(struct ural_softc *, uint16_t, void *,
-			    int);
-Static void		ural_bbp_write(struct ural_softc *, uint8_t, uint8_t);
-Static uint8_t		ural_bbp_read(struct ural_softc *, uint8_t);
-Static void		ural_rf_write(struct ural_softc *, uint8_t, uint32_t);
-Static void		ural_set_chan(struct ural_softc *,
+static void		ural_write(struct ural_softc *, uint16_t, uint16_t);
+static void		ural_write_multi(struct ural_softc *, uint16_t, void *,
+			    int) __unused;
+static void		ural_bbp_write(struct ural_softc *, uint8_t, uint8_t);
+static uint8_t		ural_bbp_read(struct ural_softc *, uint8_t);
+static void		ural_rf_write(struct ural_softc *, uint8_t, uint32_t);
+static void		ural_scan_start(struct ieee80211com *);
+static void		ural_scan_end(struct ieee80211com *);
+static void		ural_set_channel(struct ieee80211com *);
+static void		ural_set_chan(struct ural_softc *,
 			    struct ieee80211_channel *);
-Static void		ural_disable_rf_tune(struct ural_softc *);
-Static void		ural_enable_tsf_sync(struct ural_softc *);
-Static void		ural_update_slot(struct ifnet *);
-Static void		ural_set_txpreamble(struct ural_softc *);
-Static void		ural_set_basicrates(struct ural_softc *);
-Static void		ural_set_bssid(struct ural_softc *, uint8_t *);
-Static void		ural_set_macaddr(struct ural_softc *, uint8_t *);
-Static void		ural_update_promisc(struct ural_softc *);
-Static const char	*ural_get_rf(int);
-Static void		ural_read_eeprom(struct ural_softc *);
-Static int		ural_bbp_init(struct ural_softc *);
-Static void		ural_set_txantenna(struct ural_softc *, int);
-Static void		ural_set_rxantenna(struct ural_softc *, int);
-Static void		ural_init(void *);
-Static void		ural_stop(void *);
-Static void		ural_amrr_start(struct ural_softc *,
+static void		ural_disable_rf_tune(struct ural_softc *);
+static void		ural_enable_tsf_sync(struct ural_softc *);
+static void		ural_update_slot(struct ifnet *);
+static void		ural_set_txpreamble(struct ural_softc *);
+static void		ural_set_basicrates(struct ural_softc *);
+static void		ural_set_bssid(struct ural_softc *, const uint8_t *);
+static void		ural_set_macaddr(struct ural_softc *, uint8_t *);
+static void		ural_update_promisc(struct ural_softc *);
+static const char	*ural_get_rf(int);
+static void		ural_read_eeprom(struct ural_softc *);
+static int		ural_bbp_init(struct ural_softc *);
+static void		ural_set_txantenna(struct ural_softc *, int);
+static void		ural_set_rxantenna(struct ural_softc *, int);
+static void		ural_init(void *);
+static void		ural_stop(void *);
+static int		ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
+			    const struct ieee80211_bpf_params *);
+static void		ural_amrr_start(struct ural_softc *,
 			    struct ieee80211_node *);
-Static void		ural_amrr_timeout(void *);
-Static void		ural_amrr_update(usbd_xfer_handle, usbd_private_handle,
+static void		ural_amrr_timeout(void *);
+static void		ural_amrr_update(usbd_xfer_handle, usbd_private_handle,
 			    usbd_status status);
-Static void		ural_ratectl(struct ural_amrr *,
-			    struct ieee80211_node *);
-
-/*
- * Supported rates for 802.11a/b/g modes (in 500Kbps unit).
- */
-static const struct ieee80211_rateset ural_rateset_11a =
-	{ 8, { 12, 18, 24, 36, 48, 72, 96, 108 } };
-
-static const struct ieee80211_rateset ural_rateset_11b =
-	{ 4, { 2, 4, 11, 22 } };
-
-static const struct ieee80211_rateset ural_rateset_11g =
-	{ 12, { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 } };
 
 /*
  * Default values for MAC registers; values taken from the reference driver.
@@ -346,11 +346,33 @@
 	{ 161, 0x08808, 0x0242f, 0x00281 }
 };
 
-USB_DECLARE_DRIVER(ural);
+static device_probe_t ural_match;
+static device_attach_t ural_attach;
+static device_detach_t ural_detach;
+
+static device_method_t ural_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		ural_match),
+	DEVMETHOD(device_attach,	ural_attach),
+	DEVMETHOD(device_detach,	ural_detach),
+
+	{ 0, 0 }
+};
+
+static driver_t ural_driver = {
+	"ural",
+	ural_methods,
+	sizeof(struct ural_softc)
+};
+
+static devclass_t ural_devclass;
 
-USB_MATCH(ural)
+DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, usbd_driver_load, 0);
+
+static int
+ural_match(device_t self)
 {
-	USB_MATCH_START(ural, uaa);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 
 	if (uaa->iface != NULL)
 		return UMATCH_NONE;
@@ -359,26 +381,25 @@
 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
 }
 
-USB_ATTACH(ural)
+static int
+ural_attach(device_t self)
 {
-	USB_ATTACH_START(ural, sc, uaa);
+	struct ural_softc *sc = device_get_softc(self);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 	struct ifnet *ifp;
 	struct ieee80211com *ic = &sc->sc_ic;
 	usb_interface_descriptor_t *id;
 	usb_endpoint_descriptor_t *ed;
 	usbd_status error;
-	char devinfo[1024];
-	int i;
+	int i, bands;
 
 	sc->sc_udev = uaa->device;
-
-	usbd_devinfo(sc->sc_udev, 0, devinfo);
-	USB_ATTACH_SETUP;
+	sc->sc_dev = self;
 
 	if (usbd_set_config_no(sc->sc_udev, RAL_CONFIG_NO, 0) != 0) {
 		printf("%s: could not set configuration no\n",
-		    USBDEVNAME(sc->sc_dev));
-		USB_ATTACH_ERROR_RETURN;
+		    device_get_nameunit(sc->sc_dev));
+		return ENXIO;
 	}
 
 	/* get the first interface handle */
@@ -386,8 +407,8 @@
 	    &sc->sc_iface);
 	if (error != 0) {
 		printf("%s: could not get interface handle\n",
-		    USBDEVNAME(sc->sc_dev));
-		USB_ATTACH_ERROR_RETURN;
+		    device_get_nameunit(sc->sc_dev));
+		return ENXIO;
 	}
 
 	/*
@@ -400,8 +421,8 @@
 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
 		if (ed == NULL) {
 			printf("%s: no endpoint descriptor for %d\n",
-			    USBDEVNAME(sc->sc_dev), i);
-			USB_ATTACH_ERROR_RETURN;
+			    device_get_nameunit(sc->sc_dev), i);
+			return ENXIO;
 		}
 
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
@@ -412,15 +433,17 @@
 			sc->sc_tx_no = ed->bEndpointAddress;
 	}
 	if (sc->sc_rx_no == -1 || sc->sc_tx_no == -1) {
-		printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
-		USB_ATTACH_ERROR_RETURN;
+		printf("%s: missing endpoint\n",
+		    device_get_nameunit(sc->sc_dev));
+		return ENXIO;
 	}
 
-	mtx_init(&sc->sc_mtx, USBDEVNAME(sc->sc_dev), MTX_NETWORK_LOCK,
+	mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
 	    MTX_DEF | MTX_RECURSE);
 
 	usb_init_task(&sc->sc_task, ural_task, sc);
-	callout_init(&sc->scan_ch, debug_mpsafenet ? CALLOUT_MPSAFE : 0);
+	usb_init_task(&sc->sc_scantask, ural_scantask, sc);
+	callout_init(&sc->watchdog_ch, 0);
 	callout_init(&sc->amrr_ch, 0);
 
 	/* retrieve RT2570 rev. no */
@@ -430,22 +453,23 @@
 	ural_read_eeprom(sc);
 
 	printf("%s: MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
-	    USBDEVNAME(sc->sc_dev), sc->asic_rev, ural_get_rf(sc->rf_rev));
+	    device_get_nameunit(sc->sc_dev), sc->asic_rev,
+	    ural_get_rf(sc->rf_rev));
 
 	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
-		printf("%s: can not if_alloc()\n", USBDEVNAME(sc->sc_dev));
-		USB_ATTACH_ERROR_RETURN;
+		printf("%s: can not if_alloc()\n",
+		    device_get_nameunit(sc->sc_dev));
+		return ENXIO;
 	}
 
 	ifp->if_softc = sc;
-	if_initname(ifp, "ural", USBDEVUNIT(sc->sc_dev));
+	if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
 	    IFF_NEEDSGIANT; /* USB stack is still under Giant lock */
 	ifp->if_init = ural_init;
 	ifp->if_ioctl = ural_ioctl;
 	ifp->if_start = ural_start;
-	ifp->if_watchdog = ural_watchdog;
 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
 	IFQ_SET_READY(&ifp->if_snd);
@@ -457,59 +481,41 @@
 
 	/* set device capabilities */
 	ic->ic_caps =
-	    IEEE80211_C_IBSS |		/* IBSS mode supported */
-	    IEEE80211_C_MONITOR |	/* monitor mode supported */
-	    IEEE80211_C_HOSTAP |	/* HostAp mode supported */
-	    IEEE80211_C_TXPMGT |	/* tx power management */
-	    IEEE80211_C_SHPREAMBLE |	/* short preamble supported */
-	    IEEE80211_C_SHSLOT |	/* short slot time supported */
-	    IEEE80211_C_WPA;		/* 802.11i */
-
-	if (sc->rf_rev == RAL_RF_5222) {
-		/* set supported .11a rates */
-		ic->ic_sup_rates[IEEE80211_MODE_11A] = ural_rateset_11a;
-
-		/* set supported .11a channels */
-		for (i = 36; i <= 64; i += 4) {
-			ic->ic_channels[i].ic_freq =
-			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
-			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
-		}
-		for (i = 100; i <= 140; i += 4) {
-			ic->ic_channels[i].ic_freq =
-			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
-			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
-		}
-		for (i = 149; i <= 161; i += 4) {
-			ic->ic_channels[i].ic_freq =
-			    ieee80211_ieee2mhz(i, IEEE80211_CHAN_5GHZ);
-			ic->ic_channels[i].ic_flags = IEEE80211_CHAN_A;
-		}
-	}
-
-	/* set supported .11b and .11g rates */
-	ic->ic_sup_rates[IEEE80211_MODE_11B] = ural_rateset_11b;
-	ic->ic_sup_rates[IEEE80211_MODE_11G] = ural_rateset_11g;
-
-	/* set supported .11b and .11g channels (1 through 14) */
-	for (i = 1; i <= 14; i++) {
-		ic->ic_channels[i].ic_freq =
-		    ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ);
-		ic->ic_channels[i].ic_flags =
-		    IEEE80211_CHAN_CCK | IEEE80211_CHAN_OFDM |
-		    IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ;
-	}
+	      IEEE80211_C_IBSS		/* IBSS mode supported */
+	    | IEEE80211_C_MONITOR	/* monitor mode supported */
+	    | IEEE80211_C_HOSTAP	/* HostAp mode supported */
+	    | IEEE80211_C_TXPMGT	/* tx power management */
+	    | IEEE80211_C_SHPREAMBLE	/* short preamble supported */
+	    | IEEE80211_C_SHSLOT	/* short slot time supported */
+	    | IEEE80211_C_BGSCAN	/* bg scanning supported */
+	    | IEEE80211_C_WPA		/* 802.11i */
+	    ;
+
+	bands = 0;
+	setbit(&bands, IEEE80211_MODE_11B);
+	setbit(&bands, IEEE80211_MODE_11G);
+	if (sc->rf_rev == RAL_RF_5222)
+		setbit(&bands, IEEE80211_MODE_11A);
+	ieee80211_init_channels(ic, 0, CTRY_DEFAULT, bands, 0, 1);
 
 	ieee80211_ifattach(ic);
 	ic->ic_reset = ural_reset;
 	/* enable s/w bmiss handling in sta mode */
 	ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS;
+	ic->ic_scan_start = ural_scan_start;
+	ic->ic_scan_end = ural_scan_end;
+	ic->ic_set_channel = ural_set_channel;
 
 	/* override state transition machine */
 	sc->sc_newstate = ic->ic_newstate;
 	ic->ic_newstate = ural_newstate;
+	ic->ic_raw_xmit = ural_raw_xmit;
 	ieee80211_media_init(ic, ural_media_change, ieee80211_media_status);
 
+	ieee80211_amrr_init(&sc->amrr, ic,
+		IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
+		IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD);
+
 	bpfattach2(ifp, DLT_IEEE802_11_RADIO,
 	    sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf);
 
@@ -524,18 +530,19 @@
 	if (bootverbose)
 		ieee80211_announce(ic);
 
-	USB_ATTACH_SUCCESS_RETURN;
+	return 0;
 }
 
-USB_DETACH(ural)
+static int
+ural_detach(device_t self)
 {
-	USB_DETACH_START(ural, sc);
+	struct ural_softc *sc = device_get_softc(self);
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 
 	ural_stop(sc);
 	usb_rem_task(sc->sc_udev, &sc->sc_task);
-	callout_stop(&sc->scan_ch);
+	callout_stop(&sc->watchdog_ch);
 	callout_stop(&sc->amrr_ch);
 
 	if (sc->amrr_xfer != NULL) {
@@ -565,7 +572,7 @@
 	return 0;
 }
 
-Static int
+static int
 ural_alloc_tx_list(struct ural_softc *sc)
 {
 	struct ural_tx_data *data;
@@ -581,7 +588,7 @@
 		data->xfer = usbd_alloc_xfer(sc->sc_udev);
 		if (data->xfer == NULL) {
 			printf("%s: could not allocate tx xfer\n",
-			    USBDEVNAME(sc->sc_dev));
+			    device_get_nameunit(sc->sc_dev));
 			error = ENOMEM;
 			goto fail;
 		}
@@ -590,7 +597,7 @@
 		    RAL_TX_DESC_SIZE + MCLBYTES);
 		if (data->buf == NULL) {
 			printf("%s: could not allocate tx buffer\n",
-			    USBDEVNAME(sc->sc_dev));
+			    device_get_nameunit(sc->sc_dev));
 			error = ENOMEM;
 			goto fail;
 		}
@@ -602,7 +609,7 @@
 	return error;
 }
 
-Static void
+static void
 ural_free_tx_list(struct ural_softc *sc)
 {
 	struct ural_tx_data *data;
@@ -623,7 +630,7 @@
 	}
 }
 
-Static int
+static int
 ural_alloc_rx_list(struct ural_softc *sc)
 {
 	struct ural_rx_data *data;
@@ -637,14 +644,14 @@
 		data->xfer = usbd_alloc_xfer(sc->sc_udev);
 		if (data->xfer == NULL) {
 			printf("%s: could not allocate rx xfer\n",
-			    USBDEVNAME(sc->sc_dev));
+			    device_get_nameunit(sc->sc_dev));
 			error = ENOMEM;
 			goto fail;
 		}
 
 		if (usbd_alloc_buffer(data->xfer, MCLBYTES) == NULL) {
 			printf("%s: could not allocate rx buffer\n",
-			    USBDEVNAME(sc->sc_dev));
+			    device_get_nameunit(sc->sc_dev));
 			error = ENOMEM;
 			goto fail;
 		}
@@ -652,7 +659,7 @@
 		data->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
 		if (data->m == NULL) {
 			printf("%s: could not allocate rx mbuf\n",
-			    USBDEVNAME(sc->sc_dev));
+			    device_get_nameunit(sc->sc_dev));
 			error = ENOMEM;
 			goto fail;
 		}
@@ -666,7 +673,7 @@
 	return error;
 }
 
-Static void
+static void
 ural_free_rx_list(struct ural_softc *sc)
 {
 	struct ural_rx_data *data;
@@ -687,7 +694,7 @@
 	}
 }
 
-Static int
+static int
 ural_media_change(struct ifnet *ifp)
 {
 	struct ural_softc *sc = ifp->if_softc;
@@ -710,24 +717,10 @@
 	return 0;
 }
 
-/*
- * This function is called periodically (every 200ms) during scanning to
- * switch from one channel to another.
- */
-Static void
-ural_next_scan(void *arg)
+static void
+ural_task(void *xarg)
 {
-	struct ural_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-
-	if (ic->ic_state == IEEE80211_S_SCAN)
-		ieee80211_next_scan(ic);
-}
-
-Static void
-ural_task(void *arg)
-{
-	struct ural_softc *sc = arg;
+	struct ural_softc *sc = xarg;
 	struct ieee80211com *ic = &sc->sc_ic;
 	enum ieee80211_state ostate;
 	struct ieee80211_node *ni;
@@ -735,6 +728,7 @@
 
 	ostate = ic->ic_state;
 
+	RAL_LOCK(sc);
 	switch (sc->sc_state) {
 	case IEEE80211_S_INIT:
 		if (ostate == IEEE80211_S_RUN) {
@@ -746,22 +740,7 @@
 		}
 		break;
 
-	case IEEE80211_S_SCAN:
-		ural_set_chan(sc, ic->ic_curchan);
-		callout_reset(&sc->scan_ch, hz / 5, ural_next_scan, sc);
-		break;
-
-	case IEEE80211_S_AUTH:
-		ural_set_chan(sc, ic->ic_curchan);
-		break;
-
-	case IEEE80211_S_ASSOC:
-		ural_set_chan(sc, ic->ic_curchan);
-		break;
-
 	case IEEE80211_S_RUN:
-		ural_set_chan(sc, ic->ic_curchan);
-
 		ni = ic->ic_bss;
 
 		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
@@ -773,16 +752,16 @@
 
 		if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
 		    ic->ic_opmode == IEEE80211_M_IBSS) {
-			m = ieee80211_beacon_alloc(ic, ni, &sc->sc_bo);
+			m = ieee80211_beacon_alloc(ni, &sc->sc_bo);
 			if (m == NULL) {
 				printf("%s: could not allocate beacon\n",
-				    USBDEVNAME(sc->sc_dev));
+				    device_get_nameunit(sc->sc_dev));
 				return;
 			}
 
 			if (ural_tx_bcn(sc, m, ni) != 0) {
 				printf("%s: could not send beacon\n",
-				    USBDEVNAME(sc->sc_dev));
+				    device_get_nameunit(sc->sc_dev));
 				return;
 			}
 		}
@@ -799,24 +778,55 @@
 			ural_amrr_start(sc, ni);
 
 		break;
+
+	default:
+		break;
 	}
 
-	sc->sc_newstate(ic, sc->sc_state, -1);
+	RAL_UNLOCK(sc);
+	sc->sc_newstate(ic, sc->sc_state, sc->sc_arg);
 }
 
-Static int
+static void
+ural_scantask(void *arg)
+{
+	struct ural_softc *sc = arg;
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = ic->ic_ifp;
+
+	RAL_LOCK(sc);
+	if (sc->sc_scan_action == URAL_SCAN_START) {
+		/* abort TSF synchronization */
+		ural_write(sc, RAL_TXRX_CSR19, 0);
+		ural_set_bssid(sc, ifp->if_broadcastaddr);
+	} else if (sc->sc_scan_action == URAL_SET_CHANNEL) {
+		mtx_lock(&Giant);
+		ural_set_chan(sc, ic->ic_curchan);
+		mtx_unlock(&Giant);
+	} else {
+		ural_enable_tsf_sync(sc);
+		/* XXX keep local copy */
+		ural_set_bssid(sc, ic->ic_bss->ni_bssid);
+	} 
+	RAL_UNLOCK(sc);
+}
+
+static int
 ural_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 {
 	struct ural_softc *sc = ic->ic_ifp->if_softc;
 
-	usb_rem_task(sc->sc_udev, &sc->sc_task);
-	callout_stop(&sc->scan_ch);
 	callout_stop(&sc->amrr_ch);
 
 	/* do it in a process context */
 	sc->sc_state = nstate;
-	usb_add_task(sc->sc_udev, &sc->sc_task);
+	sc->sc_arg = arg;
 
+	usb_rem_task(sc->sc_udev, &sc->sc_task);
+	if (nstate == IEEE80211_S_INIT)
+		sc->sc_newstate(ic, nstate, arg);
+	else
+		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
 	return 0;
 }
 
@@ -833,7 +843,7 @@
 /*
  * This function is only used by the Rx radiotap code.
  */
-Static int
+static int
 ural_rxrate(struct ural_rx_desc *desc)
 {
 	if (le32toh(desc->flags) & RAL_RX_OFDM) {
@@ -861,24 +871,28 @@
 	return 2;	/* should not get there */
 }
 
-Static void
+static void
 ural_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 {
 	struct ural_tx_data *data = priv;
 	struct ural_softc *sc = data->sc;
 	struct ifnet *ifp = sc->sc_ic.ic_ifp;
 
+	if (data->m->m_flags & M_TXCB)
+		ieee80211_process_callback(data->ni, data->m,
+			status == USBD_NORMAL_COMPLETION ? 0 : ETIMEDOUT);
 	if (status != USBD_NORMAL_COMPLETION) {
 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
 			return;
 
 		printf("%s: could not transmit buffer: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(status));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(status));
 
 		if (status == USBD_STALLED)
 			usbd_clear_endpoint_stall_async(sc->sc_rx_pipeh);
 
 		ifp->if_oerrors++;
+		/* XXX mbuf leak? */
 		return;
 	}
 
@@ -897,7 +911,7 @@
 	ural_start(ifp);
 }
 
-Static void
+static void
 ural_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
 {
 	struct ural_rx_data *data = priv;
@@ -922,7 +936,7 @@
 	usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL);
 
 	if (len < RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN) {
-		DPRINTF(("%s: xfer too short %d\n", USBDEVNAME(sc->sc_dev),
+		DPRINTF(("%s: xfer too short %d\n", device_get_nameunit(sc->sc_dev),
 		    len));
 		ifp->if_ierrors++;
 		goto skip;
@@ -955,9 +969,8 @@
 	/* finalize mbuf */
 	m->m_pkthdr.rcvif = ifp;
 	m->m_pkthdr.len = m->m_len = (le32toh(desc->flags) >> 16) & 0xfff;
-	m->m_flags |= M_HASFCS;	/* h/w leaves FCS */
 
-	if (sc->sc_drvbpf != NULL) {
+	if (bpf_peers_present(sc->sc_drvbpf)) {
 		struct ural_rx_radiotap_header *tap = &sc->sc_rxtap;
 
 		tap->wr_flags = IEEE80211_RADIOTAP_F_FCS;   
@@ -965,16 +978,19 @@
 		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
 		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
 		tap->wr_antenna = sc->rx_ant;
-		tap->wr_antsignal = desc->rssi;
+		tap->wr_antsignal = URAL_RSSI(desc->rssi);
 
 		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m);
 	}
 
+	/* Strip trailing 802.11 MAC FCS. */
+	m_adj(m, -IEEE80211_CRC_LEN);
+
 	wh = mtod(m, struct ieee80211_frame *);
 	ni = ieee80211_find_rxnode(ic, (struct ieee80211_frame_min *)wh);
 
 	/* send the frame to the 802.11 layer */
-	ieee80211_input(ic, m, ni, desc->rssi, 0);
+	ieee80211_input(ic, m, ni, URAL_RSSI(desc->rssi), RAL_NOISE_FLOOR, 0);
 
 	/* node is no longer needed */
 	ieee80211_free_node(ni);
@@ -991,7 +1007,7 @@
  * Return the expected ack rate for a frame transmitted at rate `rate'.
  * XXX: this should depend on the destination node basic rate set.
  */
-Static int
+static int
 ural_ack_rate(struct ieee80211com *ic, int rate)
 {
 	switch (rate) {
@@ -1026,7 +1042,7 @@
  * The function automatically determines the operating mode depending on the
  * given rate. `flags' indicates whether short preamble is in use or not.
  */
-Static uint16_t
+static uint16_t
 ural_txtime(int len, int rate, uint32_t flags)
 {
 	uint16_t txtime;
@@ -1046,7 +1062,7 @@
 	return txtime;
 }
 
-Static uint8_t
+static uint8_t
 ural_plcp_signal(int rate)
 {
 	switch (rate) {
@@ -1071,7 +1087,7 @@
 	}
 }
 
-Static void
+static void
 ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
     uint32_t flags, int len, int rate)
 {
@@ -1117,7 +1133,7 @@
 
 #define RAL_TX_TIMEOUT	5000
 
-Static int
+static int
 ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
 {
 	struct ural_tx_desc *desc;
@@ -1169,7 +1185,7 @@
 	return error;
 }
 
-Static int
+static int
 ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1205,7 +1221,7 @@
 			flags |= RAL_TX_TIMESTAMP;
 	}
 
-	if (sc->sc_drvbpf != NULL) {
+	if (bpf_peers_present(sc->sc_drvbpf)) {
 		struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
 
 		tap->wt_flags = 0;
@@ -1238,15 +1254,93 @@
 	    ural_txeof);
 
 	error = usbd_transfer(data->xfer);
-	if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS)
+	if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
+		m_freem(m0);
+		data->m = NULL;
+		data->ni = NULL;
 		return error;
+	}
 
 	sc->tx_queued++;
 
 	return 0;
 }
 
-Static int
+static int
+ural_tx_raw(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
+    const struct ieee80211_bpf_params *params)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ural_tx_desc *desc;
+	struct ural_tx_data *data;
+	uint32_t flags;
+	usbd_status error;
+	int xferlen, rate;
+
+	data = &sc->tx_data[0];
+	desc = (struct ural_tx_desc *)data->buf;
+
+	rate = params->ibp_rate0 & IEEE80211_RATE_VAL;
+	/* XXX validate */
+	if (rate == 0) {
+		m_freem(m0);
+		return EINVAL;
+	}
+
+	if (bpf_peers_present(sc->sc_drvbpf)) {
+		struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
+
+		tap->wt_flags = 0;
+		tap->wt_rate = rate;
+		tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
+		tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
+		tap->wt_antenna = sc->tx_ant;
+
+		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
+	}
+
+	data->m = m0;
+	data->ni = ni;
+
+	flags = 0;
+	if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
+		flags |= RAL_TX_ACK;
+
+	m_copydata(m0, 0, m0->m_pkthdr.len, data->buf + RAL_TX_DESC_SIZE);
+	/* XXX need to setup descriptor ourself */
+	ural_setup_tx_desc(sc, desc, flags, m0->m_pkthdr.len, rate);
+
+	/* align end on a 2-bytes boundary */
+	xferlen = (RAL_TX_DESC_SIZE + m0->m_pkthdr.len + 1) & ~1;
+
+	/*
+	 * No space left in the last URB to store the extra 2 bytes, force
+	 * sending of another URB.
+	 */
+	if ((xferlen % 64) == 0)
+		xferlen += 2;
+
+	DPRINTFN(10, ("sending raw frame len=%u rate=%u xfer len=%u\n",
+	    m0->m_pkthdr.len, rate, xferlen));
+
+	usbd_setup_xfer(data->xfer, sc->sc_tx_pipeh, data, data->buf,
+	    xferlen, USBD_FORCE_SHORT_XFER | USBD_NO_COPY, RAL_TX_TIMEOUT,
+	    ural_txeof);
+
+	error = usbd_transfer(data->xfer);
+	if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
+		m_freem(m0);
+		data->m = NULL;
+		data->ni = NULL;
+		return error;
+	}
+
+	sc->tx_queued++;
+
+	return 0;
+}
+
+static int
 ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1262,7 +1356,7 @@
 	wh = mtod(m0, struct ieee80211_frame *);
 
 	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
-		rate = ic->ic_bss->ni_rates.rs_rates[ic->ic_fixed_rate];
+		rate = ic->ic_fixed_rate;
 	else
 		rate = ni->ni_rates.rs_rates[ni->ni_txrate];
 
@@ -1294,7 +1388,7 @@
 		*(uint16_t *)wh->i_dur = htole16(dur);
 	}
 
-	if (sc->sc_drvbpf != NULL) {
+	if (bpf_peers_present(sc->sc_drvbpf)) {
 		struct ural_tx_radiotap_header *tap = &sc->sc_txtap;
 
 		tap->wt_flags = 0;
@@ -1327,15 +1421,19 @@
 	    ural_txeof);
 
 	error = usbd_transfer(data->xfer);
-	if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS)
+	if (error != USBD_NORMAL_COMPLETION && error != USBD_IN_PROGRESS) {
+		m_freem(m0);
+		data->m = NULL;
+		data->ni = NULL;
 		return error;
+	}
 
 	sc->tx_queued++;
 
 	return 0;
 }
 
-Static void
+static void
 ural_start(struct ifnet *ifp)
 {
 	struct ural_softc *sc = ifp->if_softc;
@@ -1356,12 +1454,13 @@
 			ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
 			m0->m_pkthdr.rcvif = NULL;
 
-			if (ic->ic_rawbpf != NULL)
+			if (bpf_peers_present(ic->ic_rawbpf))
 				bpf_mtap(ic->ic_rawbpf, m0);
 
-			if (ural_tx_mgt(sc, m0, ni) != 0)
+			if (ural_tx_mgt(sc, m0, ni) != 0) {
+				ieee80211_free_node(ni);
 				break;
-
+			}
 		} else {
 			if (ic->ic_state != IEEE80211_S_RUN)
 				break;
@@ -1373,6 +1472,11 @@
 				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 				break;
 			}
+			/*
+			 * Cancel any background scan.
+			 */
+			if (ic->ic_flags & IEEE80211_F_SCAN)
+				ieee80211_cancel_scan(ic);
 
 			if (m0->m_len < sizeof (struct ether_header) &&
 			    !(m0 = m_pullup(m0, sizeof (struct ether_header))))
@@ -1392,7 +1496,7 @@
 				continue;
 			}
 
-			if (ic->ic_rawbpf != NULL)
+			if (bpf_peers_present(ic->ic_rawbpf))
 				bpf_mtap(ic->ic_rawbpf, m0);
 
 			if (ural_tx_data(sc, m0, ni) != 0) {
@@ -1403,33 +1507,29 @@
 		}
 
 		sc->sc_tx_timer = 5;
-		ifp->if_timer = 1;
+		ic->ic_lastdata = ticks;
+		callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
 	}
 }
 
-Static void
-ural_watchdog(struct ifnet *ifp)
+static void
+ural_watchdog(void *arg)
 {
-	struct ural_softc *sc = ifp->if_softc;
-	struct ieee80211com *ic = &sc->sc_ic;
+	struct ural_softc *sc = (struct ural_softc *)arg;
 
 	RAL_LOCK(sc);
 
-	ifp->if_timer = 0;
-
 	if (sc->sc_tx_timer > 0) {
 		if (--sc->sc_tx_timer == 0) {
 			device_printf(sc->sc_dev, "device timeout\n");
 			/*ural_init(sc); XXX needs a process context! */
-			ifp->if_oerrors++;
+			sc->sc_ifp->if_oerrors++;
 			RAL_UNLOCK(sc);
 			return;
 		}
-		ifp->if_timer = 1;
+		callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
 	}
 
-	ieee80211_watchdog(ic);
-
 	RAL_UNLOCK(sc);
 }
 
@@ -1438,7 +1538,7 @@
  * net-mgmt/kismet). In IBSS mode, we must explicitly reset the interface to
  * generate a new beacon frame.
  */
-Static int
+static int
 ural_reset(struct ifnet *ifp)
 {
 	struct ural_softc *sc = ifp->if_softc;
@@ -1452,7 +1552,7 @@
 	return 0;
 }
 
-Static int
+static int
 ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
 	struct ural_softc *sc = ifp->if_softc;
@@ -1491,7 +1591,7 @@
 	return error;
 }
 
-Static void
+static void
 ural_set_testmode(struct ural_softc *sc)
 {
 	usb_device_request_t req;
@@ -1506,11 +1606,11 @@
 	error = usbd_do_request(sc->sc_udev, &req, NULL);
 	if (error != 0) {
 		printf("%s: could not set test mode: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 	}
 }
 
-Static void
+static void
 ural_eeprom_read(struct ural_softc *sc, uint16_t addr, void *buf, int len)
 {
 	usb_device_request_t req;
@@ -1525,11 +1625,11 @@
 	error = usbd_do_request(sc->sc_udev, &req, buf);
 	if (error != 0) {
 		printf("%s: could not read EEPROM: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 	}
 }
 
-Static uint16_t
+static uint16_t
 ural_read(struct ural_softc *sc, uint16_t reg)
 {
 	usb_device_request_t req;
@@ -1545,14 +1645,14 @@
 	error = usbd_do_request(sc->sc_udev, &req, &val);
 	if (error != 0) {
 		printf("%s: could not read MAC register: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 		return 0;
 	}
 
 	return le16toh(val);
 }
 
-Static void
+static void
 ural_read_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
 {
 	usb_device_request_t req;
@@ -1567,11 +1667,11 @@
 	error = usbd_do_request(sc->sc_udev, &req, buf);
 	if (error != 0) {
 		printf("%s: could not read MAC register: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 	}
 }
 
-Static void
+static void
 ural_write(struct ural_softc *sc, uint16_t reg, uint16_t val)
 {
 	usb_device_request_t req;
@@ -1586,11 +1686,11 @@
 	error = usbd_do_request(sc->sc_udev, &req, NULL);
 	if (error != 0) {
 		printf("%s: could not write MAC register: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 	}
 }
 
-Static void
+static void
 ural_write_multi(struct ural_softc *sc, uint16_t reg, void *buf, int len)
 {
 	usb_device_request_t req;
@@ -1605,11 +1705,11 @@
 	error = usbd_do_request(sc->sc_udev, &req, buf);
 	if (error != 0) {
 		printf("%s: could not write MAC register: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 	}
 }
 
-Static void
+static void
 ural_bbp_write(struct ural_softc *sc, uint8_t reg, uint8_t val)
 {
 	uint16_t tmp;
@@ -1620,7 +1720,7 @@
 			break;
 	}
 	if (ntries == 5) {
-		printf("%s: could not write to BBP\n", USBDEVNAME(sc->sc_dev));
+		printf("%s: could not write to BBP\n", device_get_nameunit(sc->sc_dev));
 		return;
 	}
 
@@ -1628,7 +1728,7 @@
 	ural_write(sc, RAL_PHY_CSR7, tmp);
 }
 
-Static uint8_t
+static uint8_t
 ural_bbp_read(struct ural_softc *sc, uint8_t reg)
 {
 	uint16_t val;
@@ -1642,14 +1742,14 @@
 			break;
 	}
 	if (ntries == 5) {
-		printf("%s: could not read BBP\n", USBDEVNAME(sc->sc_dev));
+		printf("%s: could not read BBP\n", device_get_nameunit(sc->sc_dev));
 		return 0;
 	}
 
 	return ural_read(sc, RAL_PHY_CSR7) & 0xff;
 }
 
-Static void
+static void
 ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
 {
 	uint32_t tmp;
@@ -1660,7 +1760,7 @@
 			break;
 	}
 	if (ntries == 5) {
-		printf("%s: could not write to RF\n", USBDEVNAME(sc->sc_dev));
+		printf("%s: could not write to RF\n", device_get_nameunit(sc->sc_dev));
 		return;
 	}
 
@@ -1674,7 +1774,46 @@
 	DPRINTFN(15, ("RF R[%u] <- 0x%05x\n", reg & 0x3, val & 0xfffff));
 }
 
-Static void
+static void
+ural_scan_start(struct ieee80211com *ic)
+{
+	struct ural_softc *sc = ic->ic_ifp->if_softc;
+
+	usb_rem_task(sc->sc_udev, &sc->sc_scantask);
+
+	/* do it in a process context */
+	sc->sc_scan_action = URAL_SCAN_START;
+	usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER);
+
+}
+
+static void
+ural_scan_end(struct ieee80211com *ic)
+{
+	struct ural_softc *sc = ic->ic_ifp->if_softc;
+
+	usb_rem_task(sc->sc_udev, &sc->sc_scantask);
+
+	/* do it in a process context */
+	sc->sc_scan_action = URAL_SCAN_END;
+	usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER);
+
+}
+
+static void
+ural_set_channel(struct ieee80211com *ic)
+{
+
+	struct ural_softc *sc = ic->ic_ifp->if_softc;
+
+	usb_rem_task(sc->sc_udev, &sc->sc_scantask);
+
+	/* do it in a process context */
+	sc->sc_scan_action = URAL_SET_CHANNEL;
+	usb_add_task(sc->sc_udev, &sc->sc_scantask, USB_TASKQ_DRIVER);
+}
+
+static void
 ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1747,7 +1886,7 @@
 
 	/* dual-band RF */
 	case RAL_RF_5222:
-		for (i = 0; i < ural_rf5222[i].chan != chan; i++);
+		for (i = 0; ural_rf5222[i].chan != chan; i++);
 
 		ural_rf_write(sc, RAL_RF1, ural_rf5222[i].r1);
 		ural_rf_write(sc, RAL_RF2, ural_rf5222[i].r2);
@@ -1757,7 +1896,7 @@
 	}
 
 	if (ic->ic_opmode != IEEE80211_M_MONITOR &&
-	    ic->ic_state != IEEE80211_S_SCAN) {
+	    (ic->ic_flags & IEEE80211_F_SCAN) == 0) {
 		/* set Japan filter bit for channel 14 */
 		tmp = ural_bbp_read(sc, 70);
 
@@ -1773,12 +1912,24 @@
 		DELAY(10000);
 		ural_disable_rf_tune(sc);
 	}
+
+	/* update basic rate set */
+	if (IEEE80211_IS_CHAN_B(c)) {
+		/* 11b basic rates: 1, 2Mbps */
+		ural_write(sc, RAL_TXRX_CSR11, 0x3);
+	} else if (IEEE80211_IS_CHAN_A(c)) {
+		/* 11a basic rates: 6, 12, 24Mbps */
+		ural_write(sc, RAL_TXRX_CSR11, 0x150);
+	} else {
+		/* 11g basic rates: 1, 2, 5.5, 11, 6, 12, 24Mbps */
+		ural_write(sc, RAL_TXRX_CSR11, 0x15f);
+	}
 }
 
 /*
  * Disable RF auto-tuning.
  */
-Static void
+static void
 ural_disable_rf_tune(struct ural_softc *sc)
 {
 	uint32_t tmp;
@@ -1798,7 +1949,7 @@
  * Refer to IEEE Std 802.11-1999 pp. 123 for more information on TSF
  * synchronization.
  */
-Static void
+static void
 ural_enable_tsf_sync(struct ural_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1826,7 +1977,7 @@
 	DPRINTF(("enabling TSF synchronization\n"));
 }
 
-Static void
+static void
 ural_update_slot(struct ifnet *ifp)
 {
 	struct ural_softc *sc = ifp->if_softc;
@@ -1852,7 +2003,7 @@
 	ural_write(sc, RAL_MAC_CSR12, eifs);
 }
 
-Static void
+static void
 ural_set_txpreamble(struct ural_softc *sc)
 {
 	uint16_t tmp;
@@ -1866,7 +2017,7 @@
 	ural_write(sc, RAL_TXRX_CSR10, tmp);
 }
 
-Static void
+static void
 ural_set_basicrates(struct ural_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1884,8 +2035,8 @@
 	}
 }
 
-Static void
-ural_set_bssid(struct ural_softc *sc, uint8_t *bssid)
+static void
+ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
 {
 	uint16_t tmp;
 
@@ -1901,7 +2052,7 @@
 	DPRINTF(("setting BSSID to %6D\n", bssid, ":"));
 }
 
-Static void
+static void
 ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
 {
 	uint16_t tmp;
@@ -1918,7 +2069,7 @@
 	DPRINTF(("setting MAC address to %6D\n", addr, ":"));
 }
 
-Static void
+static void
 ural_update_promisc(struct ural_softc *sc)
 {
 	struct ifnet *ifp = sc->sc_ic.ic_ifp;
@@ -1936,7 +2087,7 @@
 	    "entering" : "leaving"));
 }
 
-Static const char *
+static const char *
 ural_get_rf(int rev)
 {
 	switch (rev) {
@@ -1951,7 +2102,7 @@
 	}
 }
 
-Static void
+static void
 ural_read_eeprom(struct ural_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1976,7 +2127,7 @@
 	ural_eeprom_read(sc, RAL_EEPROM_TXPOWER, sc->txpow, 14);
 }
 
-Static int
+static int
 ural_bbp_init(struct ural_softc *sc)
 {
 #define N(a)	(sizeof (a) / sizeof ((a)[0]))
@@ -2010,7 +2161,7 @@
 #undef N
 }
 
-Static void
+static void
 ural_set_txantenna(struct ural_softc *sc, int antenna)
 {
 	uint16_t tmp;
@@ -2039,7 +2190,7 @@
 	ural_write(sc, RAL_PHY_CSR6, tmp | (tx & 0x7));
 }
 
-Static void
+static void
 ural_set_rxantenna(struct ural_softc *sc, int antenna)
 {
 	uint8_t rx;
@@ -2059,14 +2210,13 @@
 	ural_bbp_write(sc, RAL_BBP_RX, rx);
 }
 
-Static void
+static void
 ural_init(void *priv)
 {
 #define N(a)	(sizeof (a) / sizeof ((a)[0]))
 	struct ural_softc *sc = priv;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
-	struct ieee80211_key *wk;
 	struct ural_rx_data *data;
 	uint16_t tmp;
 	usbd_status error;
@@ -2091,7 +2241,7 @@
 	}
 	if (ntries == 100) {
 		printf("%s: timeout waiting for BBP/RF to wakeup\n",
-		    USBDEVNAME(sc->sc_dev));
+		    device_get_nameunit(sc->sc_dev));
 		goto fail;
 	}
 
@@ -2104,7 +2254,6 @@
 	if (ural_bbp_init(sc) != 0)
 		goto fail;
 
-	/* set default BSS channel */
 	ural_set_chan(sc, ic->ic_curchan);
 
 	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
@@ -2117,21 +2266,12 @@
 	ural_set_macaddr(sc, ic->ic_myaddr);
 
 	/*
-	 * Copy WEP keys into adapter's memory (SEC_CSR0 to SEC_CSR31).
-	 */
-	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
-		wk = &ic->ic_crypto.cs_nw_keys[i];
-		ural_write_multi(sc, wk->wk_keyix * IEEE80211_KEYBUF_SIZE +
-		    RAL_SEC_CSR0, wk->wk_key, IEEE80211_KEYBUF_SIZE);
-	}
-
-	/*
 	 * Allocate xfer for AMRR statistics requests.
 	 */
 	sc->amrr_xfer = usbd_alloc_xfer(sc->sc_udev);
 	if (sc->amrr_xfer == NULL) {
 		printf("%s: could not allocate AMRR xfer\n",
-		    USBDEVNAME(sc->sc_dev));
+		    device_get_nameunit(sc->sc_dev));
 		goto fail;
 	}
 
@@ -2142,7 +2282,7 @@
 	    &sc->sc_tx_pipeh);
 	if (error != 0) {
 		printf("%s: could not open Tx pipe: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 		goto fail;
 	}
 
@@ -2150,7 +2290,7 @@
 	    &sc->sc_rx_pipeh);
 	if (error != 0) {
 		printf("%s: could not open Rx pipe: %s\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(error));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(error));
 		goto fail;
 	}
 
@@ -2160,14 +2300,14 @@
 	error = ural_alloc_tx_list(sc);
 	if (error != 0) {
 		printf("%s: could not allocate Tx list\n",
-		    USBDEVNAME(sc->sc_dev));
+		    device_get_nameunit(sc->sc_dev));
 		goto fail;
 	}
 
 	error = ural_alloc_rx_list(sc);
 	if (error != 0) {
 		printf("%s: could not allocate Rx list\n",
-		    USBDEVNAME(sc->sc_dev));
+		    device_get_nameunit(sc->sc_dev));
 		goto fail;
 	}
 
@@ -2208,19 +2348,18 @@
 #undef N
 }
 
-Static void
+static void
 ural_stop(void *priv)
 {
 	struct ural_softc *sc = priv;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 
-	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
-
 	sc->sc_tx_timer = 0;
-	ifp->if_timer = 0;
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
+	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+
 	/* disable Rx */
 	ural_write(sc, RAL_TXRX_CSR2, RAL_DISABLE_RX);
 
@@ -2249,22 +2388,66 @@
 	ural_free_tx_list(sc);
 }
 
-#define URAL_AMRR_MIN_SUCCESS_THRESHOLD	 1
-#define URAL_AMRR_MAX_SUCCESS_THRESHOLD	10
+static int
+ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
+	const struct ieee80211_bpf_params *params)
+{
+	struct ieee80211com *ic = ni->ni_ic;
+	struct ifnet *ifp = ic->ic_ifp;
+	struct ural_softc *sc = ifp->if_softc;
+
+	/* prevent management frames from being sent if we're not ready */
+	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+		m_freem(m);
+		ieee80211_free_node(ni);
+		return ENETDOWN;
+	}
+	if (sc->tx_queued >= RAL_TX_LIST_COUNT) {
+		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+		m_freem(m);
+		ieee80211_free_node(ni);
+		return EIO;
+	}
+
+	if (bpf_peers_present(ic->ic_rawbpf))
+		bpf_mtap(ic->ic_rawbpf, m);
+
+	ifp->if_opackets++;
+
+	if (params == NULL) {
+		/*
+		 * Legacy path; interpret frame contents to decide
+		 * precisely how to send the frame.
+		 */
+		if (ural_tx_mgt(sc, m, ni) != 0)
+			goto bad;
+	} else {
+		/*
+		 * Caller supplied explicit parameters to use in
+		 * sending the frame.
+		 */
+		if (ural_tx_raw(sc, m, ni, params) != 0)
+			goto bad;
+	}
+	sc->sc_tx_timer = 5;
+	callout_reset(&sc->watchdog_ch, hz, ural_watchdog, sc);
 
-Static void
+	return 0;
+bad:
+	ifp->if_oerrors++;
+	ieee80211_free_node(ni);
+	return EIO;		/* XXX */
+}
+
+static void
 ural_amrr_start(struct ural_softc *sc, struct ieee80211_node *ni)
 {
-	struct ural_amrr *amrr = &sc->amrr;
 	int i;
 
 	/* clear statistic registers (STA_CSR0 to STA_CSR10) */
 	ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof sc->sta);
 
-	amrr->success = 0;
-	amrr->recovery = 0;
-	amrr->txcnt = amrr->retrycnt = 0;
-	amrr->success_threshold = URAL_AMRR_MIN_SUCCESS_THRESHOLD;
+	ieee80211_amrr_node_init(&sc->amrr, &sc->amn);
 
 	/* set rate to some reasonable initial value */
 	for (i = ni->ni_rates.rs_nrates - 1;
@@ -2276,14 +2459,11 @@
 	callout_reset(&sc->amrr_ch, hz, ural_amrr_timeout, sc);
 }
 
-Static void
+static void
 ural_amrr_timeout(void *arg)
 {
 	struct ural_softc *sc = (struct ural_softc *)arg;
 	usb_device_request_t req;
-	int s;
-
-	s = splusb();
 
 	/*
 	 * Asynchronously read statistic registers (cleared by read).
@@ -2298,16 +2478,13 @@
 	    USBD_DEFAULT_TIMEOUT, &req, sc->sta, sizeof sc->sta, 0,
 	    ural_amrr_update);
 	(void)usbd_transfer(sc->amrr_xfer);
-
-	splx(s);
 }
 
-Static void
+static void
 ural_amrr_update(usbd_xfer_handle xfer, usbd_private_handle priv,
     usbd_status status)
 {
 	struct ural_softc *sc = (struct ural_softc *)priv;
-	struct ural_amrr *amrr = &sc->amrr;
 	struct ifnet *ifp = sc->sc_ic.ic_ifp;
 
 	if (status != USBD_NORMAL_COMPLETION) {
@@ -2319,85 +2496,16 @@
 	/* count TX retry-fail as Tx errors */
 	ifp->if_oerrors += sc->sta[9];
 
-	amrr->retrycnt =
+	sc->amn.amn_retrycnt =
 	    sc->sta[7] +	/* TX one-retry ok count */
 	    sc->sta[8] +	/* TX more-retry ok count */
 	    sc->sta[9];		/* TX retry-fail count */
 
-	amrr->txcnt =
-	    amrr->retrycnt +
+	sc->amn.amn_txcnt =
+	    sc->amn.amn_retrycnt +
 	    sc->sta[6];		/* TX no-retry ok count */
 
-	ural_ratectl(amrr, sc->sc_ic.ic_bss);
+	ieee80211_amrr_choose(&sc->amrr, sc->sc_ic.ic_bss, &sc->amn);
 
 	callout_reset(&sc->amrr_ch, hz, ural_amrr_timeout, sc);
 }
-
-/*-
- * Naive implementation of the Adaptive Multi Rate Retry algorithm:
- *     "IEEE 802.11 Rate Adaptation: A Practical Approach"
- *     Mathieu Lacage, Hossein Manshaei, Thierry Turletti
- *     INRIA Sophia - Projet Planete
- *     http://www-sop.inria.fr/rapports/sophia/RR-5208.html
- *
- * This algorithm is particularly well suited for ural since it does not
- * require per-frame retry statistics.  Note however that since h/w does
- * not provide per-frame stats, we can't do per-node rate adaptation and
- * thus automatic rate adaptation is only enabled in STA operating mode.
- */
-#define is_success(amrr)	\
-	((amrr)->retrycnt < (amrr)->txcnt / 10)
-#define is_failure(amrr)	\
-	((amrr)->retrycnt > (amrr)->txcnt / 3)
-#define is_enough(amrr)		\
-	((amrr)->txcnt > 10)
-#define is_min_rate(ni)		\
-	((ni)->ni_txrate == 0)
-#define is_max_rate(ni)		\
-	((ni)->ni_txrate == (ni)->ni_rates.rs_nrates - 1)
-#define increase_rate(ni)	\
-	((ni)->ni_txrate++)
-#define decrease_rate(ni)	\
-	((ni)->ni_txrate--)
-#define reset_cnt(amrr)		\
-	do { (amrr)->txcnt = (amrr)->retrycnt = 0; } while (0)
-Static void
-ural_ratectl(struct ural_amrr *amrr, struct ieee80211_node *ni)
-{
-	int need_change = 0;
-
-	if (is_success(amrr) && is_enough(amrr)) {
-		amrr->success++;
-		if (amrr->success >= amrr->success_threshold &&
-		    !is_max_rate(ni)) {
-			amrr->recovery = 1;
-			amrr->success = 0;
-			increase_rate(ni);
-			need_change = 1;
-		} else {
-			amrr->recovery = 0;
-		}
-	} else if (is_failure(amrr)) {
-		amrr->success = 0;
-		if (!is_min_rate(ni)) {
-			if (amrr->recovery) {
-				amrr->success_threshold *= 2;
-				if (amrr->success_threshold >
-				    URAL_AMRR_MAX_SUCCESS_THRESHOLD)
-					amrr->success_threshold =
-					    URAL_AMRR_MAX_SUCCESS_THRESHOLD;
-			} else {
-				amrr->success_threshold =
-				    URAL_AMRR_MIN_SUCCESS_THRESHOLD;
-			}
-			decrease_rate(ni);
-			need_change = 1;
-		}
-		amrr->recovery = 0;	/* original paper was incorrect */
-	}
-
-	if (is_enough(amrr) || need_change)
-		reset_cnt(amrr);
-}
-
-DRIVER_MODULE(ural, uhub, ural_driver, ural_devclass, usbd_driver_load, 0);
Index: umass.c
===================================================================
RCS file: /home/cvs/src/sys/dev/usb/umass.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L sys/dev/usb/umass.c -L sys/dev/usb/umass.c -u -r1.2 -r1.3
--- sys/dev/usb/umass.c
+++ sys/dev/usb/umass.c
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD: src/sys/dev/usb/umass.c,v 1.122.2.8 2006/03/24 21:42:02 iedowse Exp $
+ *	$FreeBSD: src/sys/dev/usb/umass.c,v 1.160 2007/07/05 05:26:08 imp Exp $
  *	$NetBSD: umass.c,v 1.28 2000/04/02 23:46:53 augustss Exp $
  */
 
@@ -110,6 +110,8 @@
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
 #include <sys/bus.h>
 #include <sys/sysctl.h>
 
@@ -129,7 +131,7 @@
 
 #ifdef USB_DEBUG
 #define DIF(m, x)	if (umassdebug & (m)) do { x ; } while (0)
-#define	DPRINTF(m, x)	if (umassdebug & (m)) logprintf x
+#define	DPRINTF(m, x)	if (umassdebug & (m)) printf x
 #define UDMASS_GEN	0x00010000	/* general */
 #define UDMASS_SCSI	0x00020000	/* scsi */
 #define UDMASS_UFI	0x00040000	/* ufi command set */
@@ -317,13 +319,85 @@
 #	define NO_INQUIRY_EVPD		0x0800
 	/* Pad all RBC requests to 12 bytes. */
 #	define RBC_PAD_TO_12		0x1000
+	/* Device reports number of sectors from READ_CAPACITY, not max
+	 * sector number.
+	 */
+#	define READ_CAPACITY_OFFBY1	0x2000
 };
 
-Static struct umass_devdescr_t umass_devdescrs[] = {
+static struct umass_devdescr_t umass_devdescrs[] = {
+	{ USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_CABLE_205, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_AIPTEK, USB_PRODUCT_AIPTEK_POCKETCAM3M, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO330, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
 	{ USB_VENDOR_ASAHIOPTICAL, PID_WILDCARD, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  RS_NO_CLEAR_UA
 	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2SCSI, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_CASIO, USB_PRODUCT_CASIO_QV_DIGICAM, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_CCYU, USB_PRODUCT_CCYU_ED1064, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35QUAT, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
+	{ USB_VENDOR_DESKNOTE, USB_PRODUCT_DESKNOTE_UCR_61S2B, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_DMI, USB_PRODUCT_DMI_CFSM_RW, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_895, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_DVD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  RS_NO_CLEAR_UA
@@ -344,10 +418,26 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  WRONG_CSWSIG
 	},
+	{ USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FG, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGSM, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  NO_INQUIRY
 	},
+	{ USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_HP, USB_PRODUCT_HP_CDW4E, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  NO_TEST_UNIT_READY | NO_START_STOP
@@ -356,6 +446,14 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  WRONG_CSWSIG
 	},
+	{ USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_STORAGE_V2, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
 	  NO_TEST_UNIT_READY | NO_START_STOP | ALT_IFACE_1
@@ -374,6 +472,34 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  NO_TEST_UNIT_READY
 	},
+	{ USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S3X, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S4, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S5, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_LACIE, USB_PRODUCT_LACIE_HD, RID_WILDCARD,
+	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_CF_READER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_JUMPSHOT, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2, RID_WILDCARD,
 	  UMASS_PROTO_SCSI,
 	  NO_QUIRKS
@@ -390,6 +516,30 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
 	  NO_TEST_UNIT_READY | NO_START_STOP
 	},
+	{ USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIHD50, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_E223, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_F300, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_CDRRW, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_FDD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_GETMAXLUN
+	},
 	{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  FORCE_SHORT_INQUIRY | NO_INQUIRY_EVPD | NO_GETMAXLUN
@@ -402,18 +552,70 @@
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_MYSON,  USB_PRODUCT_MYSON_HEDEN, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY | IGNORE_RESIDUE
+	},
 	{ USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  FORCE_SHORT_INQUIRY
 	},
+	{ USB_VENDOR_NETAC, USB_PRODUCT_NETAC_CF_CARD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_CLIK_40, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI,
+	  NO_INQUIRY
+	},
 	{ USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  WRONG_CSWSIG
 	},
+	{ USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_COMBO, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDSM_B_READER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_READER, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
 	  NO_INQUIRY | NO_GETMAXLUN
 	},
+	{ USB_VENDOR_ONSPEC2, USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXL840AN, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
+	  NO_GETMAXLUN
+	},
 	{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  NO_QUIRKS
@@ -422,21 +624,41 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_LS120CAM, RID_WILDCARD,
+	  UMASS_PROTO_UFI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  NO_TEST_UNIT_READY
 	},
-	{ USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE, RID_WILDCARD,
+	{ USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
-	  IGNORE_RESIDUE
+	  IGNORE_RESIDUE | NO_START_STOP
 	},
-	{ USB_VENDOR_PNY, USB_PRODUCT_PNY_A256MB, RID_WILDCARD,
+	{ USB_VENDOR_SAMSUNG,  USB_PRODUCT_SAMSUNG_YP_U2, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
-	  IGNORE_RESIDUE
+	  SHUTTLE_INIT | NO_GETMAXLUN
 	},
-	{ USB_VENDOR_PNY, USB_PRODUCT_PNY_DISKPRO512, RID_WILDCARD,
+	{ USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
-	  IGNORE_RESIDUE
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05A, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  READ_CAPACITY_OFFBY1 | NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR09, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  READ_CAPACITY_OFFBY1 | NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR12, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  READ_CAPACITY_OFFBY1 | NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  READ_CAPACITY_OFFBY1
 	},
 	{ USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
@@ -454,10 +676,42 @@
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
 	  NO_INQUIRY
 	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CDRW, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CF, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  NO_TEST_UNIT_READY | NO_START_STOP | SHUTTLE_INIT
 	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBATAPI, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBCFSM, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_HIFD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SDDR09, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_GETMAXLUN
+	},
 	{ USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  SHUTTLE_INIT
@@ -466,6 +720,18 @@
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  IGNORE_RESIDUE
 	},
+	{ USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_MD_7425, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_SX_520Z, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40_MS, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
 	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC, 0x0500,
 	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
 	  RBC_PAD_TO_12
@@ -482,10 +748,42 @@
 	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_MSC_U03, RID_WILDCARD,
+	  UMASS_PROTO_UFI | UMASS_PROTO_CBI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_NW_MS7, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_PEG_N760C, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MSACUS1, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_GETMAXLUN
+	},
 	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC, RID_WILDCARD,
 	  UMASS_PROTO_RBC | UMASS_PROTO_CBI,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_SONY, USB_PRODUCT_SONY_PORTABLE_HDD_V2, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB, RID_WILDCARD,
+	  UMASS_PROTO_UFI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
 	{ USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB, RID_WILDCARD,
           UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
 	  IGNORE_RESIDUE
@@ -494,25 +792,61 @@
 	  UMASS_PROTO_UFI | UMASS_PROTO_CBI,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_MP3, RID_WILDCARD,
+	  UMASS_PROTO_RBC,
+	  NO_QUIRKS
+	},
+	{ USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_T33520, RID_WILDCARD,
+	  UMASS_PROTO_SCSI,
+	  NO_QUIRKS
+	},
 	{ USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  NO_QUIRKS
 	},
+	{ USB_VENDOR_VIVITAR, USB_PRODUCT_VIVITAR_35XX, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_WESTERN,  USB_PRODUCT_WESTERN_COMBO, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
 	{ USB_VENDOR_WESTERN,  USB_PRODUCT_WESTERN_EXTHDD, RID_WILDCARD,
 	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
 	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
 	},
+	{ USB_VENDOR_WESTERN,  USB_PRODUCT_WESTERN_MYBOOK, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY_EVPD
+	},
+	{ USB_VENDOR_WINMAXGROUP, USB_PRODUCT_WINMAXGROUP_FLASH64MC, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  NO_INQUIRY
+	},
+	{ USB_VENDOR_YANO,  USB_PRODUCT_YANO_FW800HD, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+	  FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+	},
 	{ USB_VENDOR_YANO,  USB_PRODUCT_YANO_U640MO, RID_WILDCARD,
 	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI_I,
 	  FORCE_SHORT_INQUIRY
 	},
+	{ USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU, RID_WILDCARD,
+	  UMASS_PROTO_SCSI | UMASS_PROTO_CBI,
+	  NO_GETMAXLUN
+	},
+	{ USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC, RID_WILDCARD,
+	  UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
+	  NO_QUIRKS
+	},
 	{ VID_EOT, PID_EOT, RID_EOT, 0, 0 }
 };
 
 
 /* the per device structure */
 struct umass_softc {
-	USBBASEDEVICE		sc_dev;		/* base device */
+	device_t		sc_dev;		/* base device */
 	usbd_device_handle	sc_udev;	/* USB device */
 
 	struct cam_sim		*umass_sim;	/* SCSI Interface Module */
@@ -626,7 +960,7 @@
 	unsigned char 		cam_scsi_command2[CAM_MAX_CDBLEN];
 	struct scsi_sense	cam_scsi_sense;
 	struct scsi_sense	cam_scsi_test_unit_ready;
-	usb_callout_t		cam_scsi_rescan_ch;
+	struct callout		cam_scsi_rescan_ch;
 
 	int			timeout;		/* in msecs */
 
@@ -660,114 +994,133 @@
 #endif
 
 /* If device cannot return valid inquiry data, fake it */
-Static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = {
+static uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = {
 	0, /*removable*/ 0x80, SCSI_REV_2, SCSI_REV_2,
 	/*additional_length*/ 31, 0, 0, 0
 };
 
 /* USB device probe/attach/detach functions */
-USB_DECLARE_DRIVER(umass);
-Static int umass_match_proto	(struct umass_softc *sc,
+static device_probe_t umass_match;
+static device_attach_t umass_attach;
+static device_detach_t umass_detach;
+
+static device_method_t umass_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		umass_match),
+	DEVMETHOD(device_attach,	umass_attach),
+	DEVMETHOD(device_detach,	umass_detach),
+
+	{ 0, 0 }
+};
+
+static driver_t umass_driver = {
+	"umass",
+	umass_methods,
+	sizeof(struct umass_softc)
+};
+
+static devclass_t umass_devclass;
+
+static int umass_match_proto	(struct umass_softc *sc,
 				usbd_interface_handle iface,
 				usbd_device_handle udev);
 
 /* quirk functions */
-Static void umass_init_shuttle	(struct umass_softc *sc);
+static void umass_init_shuttle	(struct umass_softc *sc);
 
 /* generic transfer functions */
-Static usbd_status umass_setup_transfer	(struct umass_softc *sc,
+static usbd_status umass_setup_transfer	(struct umass_softc *sc,
 				usbd_pipe_handle pipe,
 				void *buffer, int buflen, int flags,
 				usbd_xfer_handle xfer);
-Static usbd_status umass_setup_ctrl_transfer	(struct umass_softc *sc,
+static usbd_status umass_setup_ctrl_transfer	(struct umass_softc *sc,
 				usbd_device_handle udev,
 				usb_device_request_t *req,
 				void *buffer, int buflen, int flags,
 				usbd_xfer_handle xfer);
-Static void umass_clear_endpoint_stall	(struct umass_softc *sc,
+static void umass_clear_endpoint_stall	(struct umass_softc *sc,
 				u_int8_t endpt, usbd_pipe_handle pipe,
 				int state, usbd_xfer_handle xfer);
-Static void umass_reset		(struct umass_softc *sc,
+static void umass_reset		(struct umass_softc *sc,
 				transfer_cb_f cb, void *priv);
 
 /* Bulk-Only related functions */
-Static void umass_bbb_reset	(struct umass_softc *sc, int status);
-Static void umass_bbb_transfer	(struct umass_softc *sc, int lun,
+static void umass_bbb_reset	(struct umass_softc *sc, int status);
+static void umass_bbb_transfer	(struct umass_softc *sc, int lun,
 				void *cmd, int cmdlen,
 		    		void *data, int datalen, int dir, u_int timeout,
 				transfer_cb_f cb, void *priv);
-Static void umass_bbb_state	(usbd_xfer_handle xfer,
+static void umass_bbb_state	(usbd_xfer_handle xfer,
 				usbd_private_handle priv,
 				usbd_status err);
-Static int umass_bbb_get_max_lun
+static int umass_bbb_get_max_lun
 				(struct umass_softc *sc);
 
 /* CBI related functions */
-Static int umass_cbi_adsc	(struct umass_softc *sc,
+static int umass_cbi_adsc	(struct umass_softc *sc,
 				char *buffer, int buflen,
 				usbd_xfer_handle xfer);
-Static void umass_cbi_reset	(struct umass_softc *sc, int status);
-Static void umass_cbi_transfer	(struct umass_softc *sc, int lun,
+static void umass_cbi_reset	(struct umass_softc *sc, int status);
+static void umass_cbi_transfer	(struct umass_softc *sc, int lun,
 				void *cmd, int cmdlen,
 		    		void *data, int datalen, int dir, u_int timeout,
 				transfer_cb_f cb, void *priv);
-Static void umass_cbi_state	(usbd_xfer_handle xfer,
+static void umass_cbi_state	(usbd_xfer_handle xfer,
 				usbd_private_handle priv, usbd_status err);
 
 /* CAM related functions */
-Static void umass_cam_action	(struct cam_sim *sim, union ccb *ccb);
-Static void umass_cam_poll	(struct cam_sim *sim);
+static void umass_cam_action	(struct cam_sim *sim, union ccb *ccb);
+static void umass_cam_poll	(struct cam_sim *sim);
 
-Static void umass_cam_cb	(struct umass_softc *sc, void *priv,
+static void umass_cam_cb	(struct umass_softc *sc, void *priv,
 				int residue, int status);
-Static void umass_cam_sense_cb	(struct umass_softc *sc, void *priv,
+static void umass_cam_sense_cb	(struct umass_softc *sc, void *priv,
 				int residue, int status);
-Static void umass_cam_quirk_cb	(struct umass_softc *sc, void *priv,
+static void umass_cam_quirk_cb	(struct umass_softc *sc, void *priv,
 				int residue, int status);
 
-Static void umass_cam_rescan_callback
+static void umass_cam_rescan_callback
 				(struct cam_periph *periph,union ccb *ccb);
-Static void umass_cam_rescan	(void *addr);
+static void umass_cam_rescan	(void *addr);
 
-Static int umass_cam_attach_sim	(struct umass_softc *sc);
-Static int umass_cam_attach	(struct umass_softc *sc);
-Static int umass_cam_detach_sim	(struct umass_softc *sc);
+static int umass_cam_attach_sim	(struct umass_softc *sc);
+static int umass_cam_attach	(struct umass_softc *sc);
+static int umass_cam_detach_sim	(struct umass_softc *sc);
 
 
 /* SCSI specific functions */
-Static int umass_scsi_transform	(struct umass_softc *sc,
+static int umass_scsi_transform	(struct umass_softc *sc,
 				unsigned char *cmd, int cmdlen,
 		     		unsigned char **rcmd, int *rcmdlen);
 
 /* UFI specific functions */
 #define UFI_COMMAND_LENGTH	12	/* UFI commands are always 12 bytes */
-Static int umass_ufi_transform	(struct umass_softc *sc,
+static int umass_ufi_transform	(struct umass_softc *sc,
 				unsigned char *cmd, int cmdlen,
 		    		unsigned char **rcmd, int *rcmdlen);
 
 /* ATAPI (8070i) specific functions */
 #define ATAPI_COMMAND_LENGTH	12	/* ATAPI commands are always 12 bytes */
-Static int umass_atapi_transform	(struct umass_softc *sc,
+static int umass_atapi_transform	(struct umass_softc *sc,
 				unsigned char *cmd, int cmdlen,
 		     		unsigned char **rcmd, int *rcmdlen);
 
 /* RBC specific functions */
-Static int umass_rbc_transform	(struct umass_softc *sc,
+static int umass_rbc_transform	(struct umass_softc *sc,
 				unsigned char *cmd, int cmdlen,
 		     		unsigned char **rcmd, int *rcmdlen);
 
 #ifdef USB_DEBUG
 /* General debugging functions */
-Static void umass_bbb_dump_cbw	(struct umass_softc *sc, umass_bbb_cbw_t *cbw);
-Static void umass_bbb_dump_csw	(struct umass_softc *sc, umass_bbb_csw_t *csw);
-Static void umass_cbi_dump_cmd	(struct umass_softc *sc, void *cmd, int cmdlen);
-Static void umass_dump_buffer	(struct umass_softc *sc, u_int8_t *buffer,
+static void umass_bbb_dump_cbw	(struct umass_softc *sc, umass_bbb_cbw_t *cbw);
+static void umass_bbb_dump_csw	(struct umass_softc *sc, umass_bbb_csw_t *csw);
+static void umass_cbi_dump_cmd	(struct umass_softc *sc, void *cmd, int cmdlen);
+static void umass_dump_buffer	(struct umass_softc *sc, u_int8_t *buffer,
 				int buflen, int printlen);
 #endif
 
-#if defined(__FreeBSD__)
-MODULE_DEPEND(umass, cam, 1,1,1);
-#endif
+MODULE_DEPEND(umass, cam, 1, 1, 1);
+MODULE_DEPEND(umass, usb, 1, 1, 1);
 
 /*
  * USB device probe/attach/detach
@@ -779,7 +1132,7 @@
  * probe and attach.
  */
 
-Static int
+static int
 umass_match_proto(struct umass_softc *sc, usbd_interface_handle iface,
 		  usbd_device_handle udev)
 {
@@ -868,7 +1221,7 @@
 		break;
 	default:
 		DPRINTF(UDMASS_GEN, ("%s: Unsupported command protocol %d\n",
-			USBDEVNAME(sc->sc_dev), id->bInterfaceSubClass));
+			device_get_nameunit(sc->sc_dev), id->bInterfaceSubClass));
 		return(UMATCH_NONE);
 	}
 
@@ -885,32 +1238,32 @@
 		break;
 	default:
 		DPRINTF(UDMASS_GEN, ("%s: Unsupported wire protocol %d\n",
-			USBDEVNAME(sc->sc_dev), id->bInterfaceProtocol));
+			device_get_nameunit(sc->sc_dev), id->bInterfaceProtocol));
 		return(UMATCH_NONE);
 	}
 
 	return(UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO);
 }
 
-USB_MATCH(umass)
+static int
+umass_match(device_t self)
 {
-	USB_MATCH_START(umass, uaa);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 	struct umass_softc *sc = device_get_softc(self);
 
-	USB_MATCH_SETUP;
-
+	sc->sc_dev = self;
 	if (uaa->iface == NULL)
 		return(UMATCH_NONE);
-
 	return(umass_match_proto(sc, uaa->iface, uaa->device));
 }
 
-USB_ATTACH(umass)
+static int
+umass_attach(device_t self)
 {
-	USB_ATTACH_START(umass, sc, uaa);
+	struct umass_softc *sc = device_get_softc(self);
+	struct usb_attach_arg *uaa = device_get_ivars(self);
 	usb_interface_descriptor_t *id;
 	usb_endpoint_descriptor_t *ed;
-	char devinfo[1024];
 	int i;
 	int err;
 
@@ -918,20 +1271,17 @@
 	 * the softc struct is bzero-ed in device_set_driver. We can safely
 	 * call umass_detach without specifically initialising the struct.
 	 */
-
-	usbd_devinfo(uaa->device, 0, devinfo);
-	USB_ATTACH_SETUP;
-
+	sc->sc_dev = self;
 	sc->iface = uaa->iface;
 	sc->ifaceno = uaa->ifaceno;
-	usb_callout_init(sc->cam_scsi_rescan_ch);
+	callout_init(&sc->cam_scsi_rescan_ch, 0);
 
 	/* initialise the proto and drive values in the umass_softc (again) */
 	(void) umass_match_proto(sc, sc->iface, uaa->device);
 
 	id = usbd_get_interface_descriptor(sc->iface);
 #ifdef USB_DEBUG
-	printf("%s: ", USBDEVNAME(sc->sc_dev));
+	printf("%s: ", device_get_nameunit(sc->sc_dev));
 	switch (sc->proto&UMASS_PROTO_COMMAND) {
 	case UMASS_PROTO_SCSI:
 		printf("SCSI");
@@ -981,9 +1331,9 @@
 		if (err) {
 			DPRINTF(UDMASS_USB, ("%s: could not switch to "
 				"Alt Interface %d\n",
-				USBDEVNAME(sc->sc_dev), 1));
+				device_get_nameunit(sc->sc_dev), 1));
 			umass_detach(self);
-			USB_ATTACH_ERROR_RETURN;
+			return ENXIO;
 		}
 	}
 
@@ -1002,8 +1352,8 @@
 		ed = usbd_interface2endpoint_descriptor(sc->iface, i);
 		if (!ed) {
 			printf("%s: could not read endpoint descriptor\n",
-			       USBDEVNAME(sc->sc_dev));
-			USB_ATTACH_ERROR_RETURN;
+			       device_get_nameunit(sc->sc_dev));
+			return ENXIO;
 		}
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
 		    && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
@@ -1018,7 +1368,7 @@
 #ifdef USB_DEBUG
 			if (UGETW(ed->wMaxPacketSize) > 2) {
 				DPRINTF(UDMASS_CBI, ("%s: intr size is %d\n",
-					USBDEVNAME(sc->sc_dev),
+					device_get_nameunit(sc->sc_dev),
 					UGETW(ed->wMaxPacketSize)));
 			}
 #endif
@@ -1029,10 +1379,10 @@
 	if (!sc->bulkin || !sc->bulkout
 	    || (sc->proto & UMASS_PROTO_CBI_I && !sc->intrin) ) {
 	    	DPRINTF(UDMASS_USB, ("%s: endpoint not found %d/%d/%d\n",
-			USBDEVNAME(sc->sc_dev),
+			device_get_nameunit(sc->sc_dev),
 			sc->bulkin, sc->bulkout, sc->intrin));
 		umass_detach(self);
-		USB_ATTACH_ERROR_RETURN;
+		return ENXIO;
 	}
 
 	/* Open the bulk-in and -out pipe */
@@ -1040,17 +1390,17 @@
 				USBD_EXCLUSIVE_USE, &sc->bulkout_pipe);
 	if (err) {
 		DPRINTF(UDMASS_USB, ("%s: cannot open %d-out pipe (bulk)\n",
-			USBDEVNAME(sc->sc_dev), sc->bulkout));
+			device_get_nameunit(sc->sc_dev), sc->bulkout));
 		umass_detach(self);
-		USB_ATTACH_ERROR_RETURN;
+		return ENXIO;
 	}
 	err = usbd_open_pipe(sc->iface, sc->bulkin,
 				USBD_EXCLUSIVE_USE, &sc->bulkin_pipe);
 	if (err) {
 		DPRINTF(UDMASS_USB, ("%s: could not open %d-in pipe (bulk)\n",
-			USBDEVNAME(sc->sc_dev), sc->bulkin));
+			device_get_nameunit(sc->sc_dev), sc->bulkin));
 		umass_detach(self);
-		USB_ATTACH_ERROR_RETURN;
+		return ENXIO;
 	}
 	/* Open the intr-in pipe if the protocol is CBI with CCI.
 	 * Note: early versions of the Zip drive do have an interrupt pipe, but
@@ -1068,9 +1418,9 @@
 				USBD_EXCLUSIVE_USE, &sc->intrin_pipe);
 		if (err) {
 			DPRINTF(UDMASS_USB, ("%s: couldn't open %d-in (intr)\n",
-				USBDEVNAME(sc->sc_dev), sc->intrin));
+				device_get_nameunit(sc->sc_dev), sc->intrin));
 			umass_detach(self);
-			USB_ATTACH_ERROR_RETURN;
+			return ENXIO;
 		}
 	}
 
@@ -1082,9 +1432,9 @@
 		sc->transfer_xfer[i] = usbd_alloc_xfer(uaa->device);
 		if (!sc->transfer_xfer[i]) {
 			DPRINTF(UDMASS_USB, ("%s: Out of memory\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			umass_detach(self);
-			USB_ATTACH_ERROR_RETURN;
+			return ENXIO;
 		}
 	}
 
@@ -1143,14 +1493,14 @@
 		err = umass_cam_attach_sim(sc);
 		if (err) {
 			umass_detach(self);
-			USB_ATTACH_ERROR_RETURN;
+			return ENXIO;
 		}
 		/* scan the new sim */
 		err = umass_cam_attach(sc);
 		if (err) {
 			umass_cam_detach_sim(sc);
 			umass_detach(self);
-			USB_ATTACH_ERROR_RETURN;
+			return ENXIO;
 		}
 	} else {
 		panic("%s:%d: Unknown proto 0x%02x",
@@ -1158,18 +1508,19 @@
 	}
 
 	sc->transfer_state = TSTATE_IDLE;
-	DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", USBDEVNAME(sc->sc_dev)));
+	DPRINTF(UDMASS_GEN, ("%s: Attach finished\n", device_get_nameunit(sc->sc_dev)));
 
-	USB_ATTACH_SUCCESS_RETURN;
+	return 0;
 }
 
-USB_DETACH(umass)
+static int
+umass_detach(device_t self)
 {
-	USB_DETACH_START(umass, sc);
+	struct umass_softc *sc = device_get_softc(self);
 	int err = 0;
 	int i;
 
-	DPRINTF(UDMASS_USB, ("%s: detached\n", USBDEVNAME(sc->sc_dev)));
+	DPRINTF(UDMASS_USB, ("%s: detached\n", device_get_nameunit(sc->sc_dev)));
 
 	sc->flags |= UMASS_FLAGS_GONE;
 
@@ -1182,7 +1533,7 @@
 	if (sc->intrin_pipe)
 		usbd_abort_pipe(sc->intrin_pipe);
 
-	usb_uncallout_drain(sc->cam_scsi_rescan_ch, umass_cam_rescan, sc);
+	callout_drain(&sc->cam_scsi_rescan_ch);
 	if ((sc->proto & UMASS_PROTO_SCSI) ||
 	    (sc->proto & UMASS_PROTO_ATAPI) ||
 	    (sc->proto & UMASS_PROTO_UFI) ||
@@ -1205,7 +1556,7 @@
 	return(err);
 }
 
-Static void
+static void
 umass_init_shuttle(struct umass_softc *sc)
 {
 	usb_device_request_t req;
@@ -1222,14 +1573,14 @@
 	(void) usbd_do_request(sc->sc_udev, &req, &status);
 
 	DPRINTF(UDMASS_GEN, ("%s: Shuttle init returned 0x%02x%02x\n",
-		USBDEVNAME(sc->sc_dev), status[0], status[1]));
+		device_get_nameunit(sc->sc_dev), status[0], status[1]));
 }
 
  /*
  * Generic functions to handle transfers
  */
 
-Static usbd_status
+static usbd_status
 umass_setup_transfer(struct umass_softc *sc, usbd_pipe_handle pipe,
 			void *buffer, int buflen, int flags,
 			usbd_xfer_handle xfer)
@@ -1244,7 +1595,7 @@
 	err = usbd_transfer(xfer);
 	if (err && err != USBD_IN_PROGRESS) {
 		DPRINTF(UDMASS_BBB, ("%s: failed to setup transfer, %s\n",
-			USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
+			device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
 		return(err);
 	}
 
@@ -1252,7 +1603,7 @@
 }
 
 
-Static usbd_status
+static usbd_status
 umass_setup_ctrl_transfer(struct umass_softc *sc, usbd_device_handle udev,
 	 usb_device_request_t *req,
 	 void *buffer, int buflen, int flags,
@@ -1268,7 +1619,7 @@
 	err = usbd_transfer(xfer);
 	if (err && err != USBD_IN_PROGRESS) {
 		DPRINTF(UDMASS_BBB, ("%s: failed to setup ctrl transfer, %s\n",
-			 USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
+			 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
 
 		/* do not reset, as this would make us loop */
 		return(err);
@@ -1277,7 +1628,7 @@
 	return (USBD_NORMAL_COMPLETION);
 }
 
-Static void
+static void
 umass_clear_endpoint_stall(struct umass_softc *sc,
 				u_int8_t endpt, usbd_pipe_handle pipe,
 				int state, usbd_xfer_handle xfer)
@@ -1285,7 +1636,7 @@
 	usbd_device_handle udev;
 
 	DPRINTF(UDMASS_BBB, ("%s: Clear endpoint 0x%02x stall\n",
-		USBDEVNAME(sc->sc_dev), endpt));
+		device_get_nameunit(sc->sc_dev), endpt));
 
 	usbd_interface2device_handle(sc->iface, &udev);
 
@@ -1301,7 +1652,7 @@
 	umass_setup_ctrl_transfer(sc, udev, &sc->request, NULL, 0, 0, xfer);
 }
 
-Static void
+static void
 umass_reset(struct umass_softc *sc, transfer_cb_f cb, void *priv)
 {
 	sc->transfer_cb = cb;
@@ -1315,14 +1666,14 @@
  * Bulk protocol specific functions
  */
 
-Static void
+static void
 umass_bbb_reset(struct umass_softc *sc, int status)
 {
 	usbd_device_handle udev;
 
 	KASSERT(sc->proto & UMASS_PROTO_BBB,
 		("%s: umass_bbb_reset: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/*
 	 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
@@ -1341,7 +1692,7 @@
 	 */
 
 	DPRINTF(UDMASS_BBB, ("%s: Bulk Reset\n",
-		USBDEVNAME(sc->sc_dev)));
+		device_get_nameunit(sc->sc_dev)));
 
 	sc->transfer_state = TSTATE_BBB_RESET1;
 	sc->transfer_status = status;
@@ -1358,14 +1709,14 @@
 				  sc->transfer_xfer[XFER_BBB_RESET1]);
 }
 
-Static void
+static void
 umass_bbb_transfer(struct umass_softc *sc, int lun, void *cmd, int cmdlen,
 		    void *data, int datalen, int dir, u_int timeout,
 		    transfer_cb_f cb, void *priv)
 {
 	KASSERT(sc->proto & UMASS_PROTO_BBB,
 		("%s: umass_bbb_transfer: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/* Be a little generous. */
 	sc->timeout = timeout + UMASS_TIMEOUT;
@@ -1392,23 +1743,23 @@
 
 	/* check the given arguments */
 	KASSERT(datalen == 0 || data != NULL,
-		("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev)));
+		("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev)));
 	KASSERT(cmdlen <= CBWCDBLENGTH,
 		("%s: cmdlen exceeds CDB length in CBW (%d > %d)",
-			USBDEVNAME(sc->sc_dev), cmdlen, CBWCDBLENGTH));
+			device_get_nameunit(sc->sc_dev), cmdlen, CBWCDBLENGTH));
 	KASSERT(dir == DIR_NONE || datalen > 0,
 		("%s: datalen == 0 while direction is not NONE\n",
-			USBDEVNAME(sc->sc_dev)));
+			device_get_nameunit(sc->sc_dev)));
 	KASSERT(datalen == 0 || dir != DIR_NONE,
 		("%s: direction is NONE while datalen is not zero\n",
-			USBDEVNAME(sc->sc_dev)));
+			device_get_nameunit(sc->sc_dev)));
 	KASSERT(sizeof(umass_bbb_cbw_t) == UMASS_BBB_CBW_SIZE,
 		("%s: CBW struct does not have the right size (%ld vs. %d)\n",
-			USBDEVNAME(sc->sc_dev),
+			device_get_nameunit(sc->sc_dev),
 			(long)sizeof(umass_bbb_cbw_t), UMASS_BBB_CBW_SIZE));
 	KASSERT(sizeof(umass_bbb_csw_t) == UMASS_BBB_CSW_SIZE,
 		("%s: CSW struct does not have the right size (%ld vs. %d)\n",
-			USBDEVNAME(sc->sc_dev),
+			device_get_nameunit(sc->sc_dev),
 			(long)sizeof(umass_bbb_csw_t), UMASS_BBB_CSW_SIZE));
 
 	/*
@@ -1467,7 +1818,7 @@
 }
 
 
-Static void
+static void
 umass_bbb_state(usbd_xfer_handle xfer, usbd_private_handle priv,
 		usbd_status err)
 {
@@ -1476,7 +1827,7 @@
 
 	KASSERT(sc->proto & UMASS_PROTO_BBB,
 		("%s: umass_bbb_state: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/*
 	 * State handling for BBB transfers.
@@ -1490,7 +1841,7 @@
 	 */
 
 	DPRINTF(UDMASS_BBB, ("%s: Handling BBB state %d (%s), xfer=%p, %s\n",
-		USBDEVNAME(sc->sc_dev), sc->transfer_state,
+		device_get_nameunit(sc->sc_dev), sc->transfer_state,
 		states[sc->transfer_state], xfer, usbd_errstr(err)));
 
 	/* Give up if the device has detached. */
@@ -1508,7 +1859,7 @@
 		/* Command transport phase, error handling */
 		if (err) {
 			DPRINTF(UDMASS_BBB, ("%s: failed to send CBW\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			/* If the device detects that the CBW is invalid, then
 			 * the device may STALL both bulk endpoints and require
 			 * a Bulk-Reset
@@ -1537,7 +1888,7 @@
 			return;
 		} else {
 			DPRINTF(UDMASS_BBB, ("%s: no data phase\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 		}
 
 		/* FALLTHROUGH if no data phase, err == 0 */
@@ -1551,7 +1902,7 @@
 
 			if (err) {
 				DPRINTF(UDMASS_BBB, ("%s: Data-%s %db failed, "
-					"%s\n", USBDEVNAME(sc->sc_dev),
+					"%s\n", device_get_nameunit(sc->sc_dev),
 					(sc->transfer_dir == DIR_IN?"in":"out"),
 					sc->transfer_datalen,usbd_errstr(err)));
 
@@ -1592,7 +1943,7 @@
 		if (err) {	/* should not occur */
 			/* try the transfer below, even if clear stall failed */
 			DPRINTF(UDMASS_BBB, ("%s: bulk-%s stall clear failed"
-				", %s\n", USBDEVNAME(sc->sc_dev),
+				", %s\n", device_get_nameunit(sc->sc_dev),
 				(sc->transfer_dir == DIR_IN? "in":"out"),
 				usbd_errstr(err)));
 			umass_bbb_reset(sc, STATUS_WIRE_FAILED);
@@ -1628,7 +1979,7 @@
 		/* Status transfer, error handling */
 		if (err) {
 			DPRINTF(UDMASS_BBB, ("%s: Failed to read CSW, %s%s\n",
-				USBDEVNAME(sc->sc_dev), usbd_errstr(err),
+				device_get_nameunit(sc->sc_dev), usbd_errstr(err),
 				(sc->transfer_state == TSTATE_BBB_STATUS1?
 					", retrying":"")));
 
@@ -1669,7 +2020,7 @@
 			 * indicate that the device is confused -> reset it.
 			 */
 			printf("%s: Invalid CSW: sig 0x%08x should be 0x%08x\n",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				UGETDW(sc->csw.dCSWSignature),
 				CSWSIGNATURE);
 
@@ -1678,7 +2029,7 @@
 		} else if (UGETDW(sc->csw.dCSWTag)
 				!= UGETDW(sc->cbw.dCBWTag)) {
 			printf("%s: Invalid CSW: tag %d should be %d\n",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				UGETDW(sc->csw.dCSWTag),
 				UGETDW(sc->cbw.dCBWTag));
 
@@ -1688,7 +2039,7 @@
 		/* CSW is valid here */
 		} else if (sc->csw.bCSWStatus > CSWSTATUS_PHASE) {
 			printf("%s: Invalid CSW: status %d > %d\n",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				sc->csw.bCSWStatus,
 				CSWSTATUS_PHASE);
 
@@ -1696,7 +2047,7 @@
 			return;
 		} else if (sc->csw.bCSWStatus == CSWSTATUS_PHASE) {
 			printf("%s: Phase Error, residue = %d\n",
-				USBDEVNAME(sc->sc_dev), Residue);
+				device_get_nameunit(sc->sc_dev), Residue);
 
 			umass_bbb_reset(sc, STATUS_WIRE_FAILED);
 			return;
@@ -1704,12 +2055,12 @@
 		} else if (sc->transfer_actlen > sc->transfer_datalen) {
 			/* Buffer overrun! Don't let this go by unnoticed */
 			panic("%s: transferred %db instead of %db",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				sc->transfer_actlen, sc->transfer_datalen);
 
 		} else if (sc->csw.bCSWStatus == CSWSTATUS_FAILED) {
 			DPRINTF(UDMASS_BBB, ("%s: Command Failed, res = %d\n",
-				USBDEVNAME(sc->sc_dev), Residue));
+				device_get_nameunit(sc->sc_dev), Residue));
 
 			/* SCSI command failed but transfer was succesful */
 			sc->transfer_state = TSTATE_IDLE;
@@ -1729,7 +2080,7 @@
 	case TSTATE_BBB_RESET1:
 		if (err)
 			printf("%s: BBB reset failed, %s\n",
-				USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+				device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 
 		umass_clear_endpoint_stall(sc,
 			sc->bulkin, sc->bulkin_pipe, TSTATE_BBB_RESET2,
@@ -1739,7 +2090,7 @@
 	case TSTATE_BBB_RESET2:
 		if (err)	/* should not occur */
 			printf("%s: BBB bulk-in clear stall failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
 		umass_clear_endpoint_stall(sc,
@@ -1750,7 +2101,7 @@
 	case TSTATE_BBB_RESET3:
 		if (err)	/* should not occur */
 			printf("%s: BBB bulk-out clear stall failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
 		sc->transfer_state = TSTATE_IDLE;
@@ -1765,11 +2116,11 @@
 	/***** Default *****/
 	default:
 		panic("%s: Unknown state %d",
-		      USBDEVNAME(sc->sc_dev), sc->transfer_state);
+		      device_get_nameunit(sc->sc_dev), sc->transfer_state);
 	}
 }
 
-Static int
+static int
 umass_bbb_get_max_lun(struct umass_softc *sc)
 {
 	usbd_device_handle udev;
@@ -1794,14 +2145,14 @@
 	case USBD_NORMAL_COMPLETION:
 		maxlun = buf;
 		DPRINTF(UDMASS_BBB, ("%s: Max Lun is %d\n",
-		    USBDEVNAME(sc->sc_dev), maxlun));
+		    device_get_nameunit(sc->sc_dev), maxlun));
 		break;
 	case USBD_STALLED:
 	case USBD_SHORT_XFER:
 	default:
 		/* Device doesn't support Get Max Lun request. */
 		printf("%s: Get Max Lun not supported (%s)\n",
-		    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+		    device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 		/* XXX Should we port_reset the device? */
 		break;
 	}
@@ -1813,7 +2164,7 @@
  * Command/Bulk/Interrupt (CBI) specific functions
  */
 
-Static int
+static int
 umass_cbi_adsc(struct umass_softc *sc, char *buffer, int buflen,
 	       usbd_xfer_handle xfer)
 {
@@ -1821,7 +2172,7 @@
 
 	KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
 		("%s: umass_cbi_adsc: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	usbd_interface2device_handle(sc->iface, &udev);
 
@@ -1835,7 +2186,7 @@
 }
 
 
-Static void
+static void
 umass_cbi_reset(struct umass_softc *sc, int status)
 {
 	int i;
@@ -1843,7 +2194,7 @@
 
 	KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
 		("%s: umass_cbi_reset: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/*
 	 * Command Block Reset Protocol
@@ -1860,11 +2211,11 @@
 	 */
 
 	DPRINTF(UDMASS_CBI, ("%s: CBI Reset\n",
-		USBDEVNAME(sc->sc_dev)));
+		device_get_nameunit(sc->sc_dev)));
 
 	KASSERT(sizeof(sc->cbl) >= SEND_DIAGNOSTIC_CMDLEN,
 		("%s: CBL struct is too small (%ld < %d)\n",
-			USBDEVNAME(sc->sc_dev),
+			device_get_nameunit(sc->sc_dev),
 			(long)sizeof(sc->cbl), SEND_DIAGNOSTIC_CMDLEN));
 
 	sc->transfer_state = TSTATE_CBI_RESET1;
@@ -1884,14 +2235,14 @@
 	/* XXX if the command fails we should reset the port on the hub */
 }
 
-Static void
+static void
 umass_cbi_transfer(struct umass_softc *sc, int lun,
 		void *cmd, int cmdlen, void *data, int datalen, int dir,
 		u_int timeout, transfer_cb_f cb, void *priv)
 {
 	KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
 		("%s: umass_cbi_transfer: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/* Be a little generous. */
 	sc->timeout = timeout + UMASS_TIMEOUT;
@@ -1915,10 +2266,10 @@
 
 	/* check the given arguments */
 	KASSERT(datalen == 0 || data != NULL,
-		("%s: datalen > 0, but no buffer",USBDEVNAME(sc->sc_dev)));
+		("%s: datalen > 0, but no buffer",device_get_nameunit(sc->sc_dev)));
 	KASSERT(datalen == 0 || dir != DIR_NONE,
 		("%s: direction is NONE while datalen is not zero\n",
-			USBDEVNAME(sc->sc_dev)));
+			device_get_nameunit(sc->sc_dev)));
 
 	/* store the details for the data transfer phase */
 	sc->transfer_dir = dir;
@@ -1939,7 +2290,7 @@
 		umass_cbi_reset(sc, STATUS_WIRE_FAILED);
 }
 
-Static void
+static void
 umass_cbi_state(usbd_xfer_handle xfer, usbd_private_handle priv,
 		usbd_status err)
 {
@@ -1947,14 +2298,14 @@
 
 	KASSERT(sc->proto & (UMASS_PROTO_CBI|UMASS_PROTO_CBI_I),
 		("%s: umass_cbi_state: wrong sc->proto 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), sc->proto));
+			device_get_nameunit(sc->sc_dev), sc->proto));
 
 	/*
 	 * State handling for CBI transfers.
 	 */
 
 	DPRINTF(UDMASS_CBI, ("%s: Handling CBI state %d (%s), xfer=%p, %s\n",
-		USBDEVNAME(sc->sc_dev), sc->transfer_state,
+		device_get_nameunit(sc->sc_dev), sc->transfer_state,
 		states[sc->transfer_state], xfer, usbd_errstr(err)));
 
 	/* Give up if the device has detached. */
@@ -1971,7 +2322,7 @@
 	case TSTATE_CBI_COMMAND:
 		if (err == USBD_STALLED) {
 			DPRINTF(UDMASS_CBI, ("%s: Command Transport failed\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			/* Status transport by control pipe (section 2.3.2.1).
 			 * The command contained in the command block failed.
 			 *
@@ -1989,7 +2340,7 @@
 			return;
 		} else if (err) {
 			DPRINTF(UDMASS_CBI, ("%s: failed to send ADSC\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			umass_cbi_reset(sc, STATUS_WIRE_FAILED);
 
 			return;
@@ -2012,7 +2363,7 @@
 
 		} else if (sc->proto & UMASS_PROTO_CBI_I) {
 			DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			sc->transfer_state = TSTATE_CBI_STATUS;
 			if (umass_setup_transfer(sc, sc->intrin_pipe,
 					&sc->sbl, sizeof(sc->sbl),
@@ -2022,7 +2373,7 @@
 			}
 		} else {
 			DPRINTF(UDMASS_CBI, ("%s: no data phase\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			/* No command completion interrupt. Request
 			 * sense data.
 			 */
@@ -2039,7 +2390,7 @@
 
 		if (err) {
 			DPRINTF(UDMASS_CBI, ("%s: Data-%s %db failed, "
-				"%s\n", USBDEVNAME(sc->sc_dev),
+				"%s\n", device_get_nameunit(sc->sc_dev),
 				(sc->transfer_dir == DIR_IN?"in":"out"),
 				sc->transfer_datalen,usbd_errstr(err)));
 
@@ -2080,7 +2431,7 @@
 	case TSTATE_CBI_STATUS:
 		if (err) {
 			DPRINTF(UDMASS_CBI, ("%s: Status Transport failed\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 			/* Status transport by interrupt pipe (section 2.3.2.2).
 			 */
 
@@ -2107,7 +2458,7 @@
 
 			DPRINTF(UDMASS_CBI, ("%s: UFI CCI, ASC = 0x%02x, "
 				"ASCQ = 0x%02x\n",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				sc->sbl.ufi.asc, sc->sbl.ufi.ascq));
 
 			if (sc->sbl.ufi.asc == 0 && sc->sbl.ufi.ascq == 0)
@@ -2122,7 +2473,7 @@
 		} else {
 			/* Command Interrupt Data Block */
 			DPRINTF(UDMASS_CBI, ("%s: type=0x%02x, value=0x%02x\n",
-				USBDEVNAME(sc->sc_dev),
+				device_get_nameunit(sc->sc_dev),
 				sc->sbl.common.type, sc->sbl.common.value));
 
 			if (sc->sbl.common.type == IDB_TYPE_CCI) {
@@ -2151,7 +2502,7 @@
 	case TSTATE_CBI_DCLEAR:
 		if (err) {	/* should not occur */
 			printf("%s: CBI bulk-in/out stall clear failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 			umass_cbi_reset(sc, STATUS_WIRE_FAILED);
 		}
 
@@ -2164,7 +2515,7 @@
 	case TSTATE_CBI_SCLEAR:
 		if (err)	/* should not occur */
 			printf("%s: CBI intr-in stall clear failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 
 		/* Something really bad is going on. Reset the device */
 		umass_cbi_reset(sc, STATUS_CMD_FAILED);
@@ -2174,7 +2525,7 @@
 	case TSTATE_CBI_RESET1:
 		if (err)
 			printf("%s: CBI reset failed, %s\n",
-				USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+				device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 
 		umass_clear_endpoint_stall(sc,
 			sc->bulkin, sc->bulkin_pipe, TSTATE_CBI_RESET2,
@@ -2184,7 +2535,7 @@
 	case TSTATE_CBI_RESET2:
 		if (err)	/* should not occur */
 			printf("%s: CBI bulk-in stall clear failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
 		umass_clear_endpoint_stall(sc,
@@ -2195,7 +2546,7 @@
 	case TSTATE_CBI_RESET3:
 		if (err)	/* should not occur */
 			printf("%s: CBI bulk-out stall clear failed, %s\n",
-			       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+			       device_get_nameunit(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
 		sc->transfer_state = TSTATE_IDLE;
@@ -2211,7 +2562,7 @@
 	/***** Default *****/
 	default:
 		panic("%s: Unknown state %d",
-		      USBDEVNAME(sc->sc_dev), sc->transfer_state);
+		      device_get_nameunit(sc->sc_dev), sc->transfer_state);
 	}
 }
 
@@ -2222,7 +2573,7 @@
  * CAM specific functions (used by SCSI, UFI, 8070i (ATAPI))
  */
 
-Static int
+static int
 umass_cam_attach_sim(struct umass_softc *sc)
 {
 	struct cam_devq	*devq;		/* Per device Queue */
@@ -2240,7 +2591,8 @@
 	sc->umass_sim = cam_sim_alloc(umass_cam_action, umass_cam_poll,
 				DEVNAME_SIM,
 				sc /*priv*/,
-				USBDEVUNIT(sc->sc_dev) /*unit number*/,
+				device_get_unit(sc->sc_dev) /*unit number*/,
+				&Giant,
 				1 /*maximum device openings*/,
 				0 /*maximum tagged device openings*/,
 				devq);
@@ -2249,14 +2601,14 @@
 		return(ENOMEM);
 	}
 
-	if(xpt_bus_register(sc->umass_sim, USBDEVUNIT(sc->sc_dev)) !=
+	if(xpt_bus_register(sc->umass_sim, NULL, device_get_unit(sc->sc_dev)) !=
 	    CAM_SUCCESS)
 		return(ENOMEM);
 
 	return(0);
 }
 
-Static void
+static void
 umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
 {
 #ifdef USB_DEBUG
@@ -2274,7 +2626,7 @@
 	free(ccb, M_USBDEV);
 }
 
-Static void
+static void
 umass_cam_rescan(void *addr)
 {
 	struct umass_softc *sc = (struct umass_softc *) addr;
@@ -2283,14 +2635,14 @@
 
 	DPRINTF(UDMASS_SCSI, ("scbus%d: scanning for %s:%d:%d:%d\n",
 		cam_sim_path(sc->umass_sim),
-		USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
-		USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD));
+		device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
+		device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD));
 
 	ccb = malloc(sizeof(union ccb), M_USBDEV, M_NOWAIT | M_ZERO);
 	if (ccb == NULL)
 		return;
 	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->umass_sim),
-			    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)
+			    device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD)
 	    != CAM_REQ_CMP) {
 		free(ccb, M_USBDEV);
 		return;
@@ -2305,15 +2657,15 @@
 	/* The scan is in progress now. */
 }
 
-Static int
+static int
 umass_cam_attach(struct umass_softc *sc)
 {
 #ifndef USB_DEBUG
 	if (bootverbose)
 #endif
 		printf("%s:%d:%d:%d: Attached to scbus%d\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
-			USBDEVUNIT(sc->sc_dev), CAM_LUN_WILDCARD,
+			device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
+			device_get_unit(sc->sc_dev), CAM_LUN_WILDCARD,
 			cam_sim_path(sc->umass_sim));
 
 	if (!cold) {
@@ -2324,7 +2676,7 @@
 		 * completed, when interrupts have been enabled.
 		 */
 
-		usb_callout(sc->cam_scsi_rescan_ch, MS_TO_TICKS(200),
+		callout_reset(&sc->cam_scsi_rescan_ch, MS_TO_TICKS(200),
 		    umass_cam_rescan, sc);
 	}
 
@@ -2335,7 +2687,7 @@
  *	detach from the CAM layer
  */
 
-Static int
+static int
 umass_cam_detach_sim(struct umass_softc *sc)
 {
 	if (sc->umass_sim) {
@@ -2354,7 +2706,7 @@
  * 	CAM requests for action come through here
  */
 
-Static void
+static void
 umass_cam_action(struct cam_sim *sim, union ccb *ccb)
 {
 	struct umass_softc *sc = (struct umass_softc *)sim->softc;
@@ -2365,7 +2717,7 @@
 	if (sc && (sc->flags & UMASS_FLAGS_GONE)) {
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
 			"Invalid target (gone)\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+			device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
 			ccb->ccb_h.func_code));
 		ccb->ccb_h.status = CAM_TID_INVALID;
@@ -2436,7 +2788,7 @@
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
 			"cmd: 0x%02x, flags: 0x%02x, "
 			"%db cmd/%db data/%db sense\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+			device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
 			csio->cdb_io.cdb_bytes[0],
 			ccb->ccb_h.flags & CAM_DIR_MASK,
@@ -2454,7 +2806,7 @@
 		if (sc->transfer_state != TSTATE_IDLE) {
 			DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SCSI_IO: "
 				"I/O in progress, deferring (state %d, %s)\n",
-				USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+				device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
 				ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
 				sc->transfer_state,states[sc->transfer_state]));
 			ccb->ccb_h.status = CAM_SCSI_BUSY;
@@ -2493,7 +2845,8 @@
 		 * buffer (see umass_scsi_transform).
 		 */
 
-		if (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) {
+		switch (sc->transform(sc, cmd, cmdlen, &rcmd, &rcmdlen)) {
+		case 1:
 			/*
 			 * Handle EVPD inquiry for broken devices first
 			 * NO_INQUIRY also implies NO_INQUIRY_EVPD
@@ -2533,9 +2886,15 @@
 				     csio->data_ptr,
 				     csio->dxfer_len, dir, ccb->ccb_h.timeout,
 				     umass_cam_cb, (void *) ccb);
-		} else {
+			break;
+		case 0:
 			ccb->ccb_h.status = CAM_REQ_INVALID;
 			xpt_done(ccb);
+			break;
+		case 2:
+			ccb->ccb_h.status = CAM_REQ_CMP;
+			xpt_done(ccb);
+			break;
 		}
 
 		break;
@@ -2545,7 +2904,7 @@
 		struct ccb_pathinq *cpi = &ccb->cpi;
 
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_PATH_INQ:.\n",
-			(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
+			(sc == NULL? DEVNAME_SIM:device_get_nameunit(sc->sc_dev)),
 			cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
 
@@ -2561,7 +2920,11 @@
 		strncpy(cpi->hba_vid, "USB SCSI", HBA_IDLEN);
 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
 		cpi->unit_number = cam_sim_unit(sim);
-		cpi->bus_id = USBDEVUNIT(sc->sc_dev);
+		cpi->bus_id = device_get_unit(sc->sc_dev);
+		cpi->protocol = PROTO_SCSI;
+		cpi->protocol_version = SCSI_REV_2;
+		cpi->transport = XPORT_USB;
+		cpi->transport_version = 0;
 
 		if (sc == NULL) {
 			cpi->base_transfer_speed = 0;
@@ -2588,7 +2951,7 @@
 	case XPT_RESET_DEV:
 	{
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_RESET_DEV:.\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+			device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
 
 		ccb->ccb_h.status = CAM_REQ_INPROG;
@@ -2598,13 +2961,12 @@
 	case XPT_GET_TRAN_SETTINGS:
 	{
 		struct ccb_trans_settings *cts = &ccb->cts;
+		cts->protocol = PROTO_SCSI;
+		cts->protocol_version = SCSI_REV_2;
+		cts->transport = XPORT_USB;
+		cts->transport_version = 0;
+		cts->xport_specific.valid = 0;
 
-		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_GET_TRAN_SETTINGS:.\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
-			ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
-
-		cts->valid = 0;
-		cts->flags = 0;		/* no disconnection, tagging */
 
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
@@ -2613,7 +2975,7 @@
 	case XPT_SET_TRAN_SETTINGS:
 	{
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_SET_TRAN_SETTINGS:.\n",
-			USBDEVNAME(sc->sc_dev), cam_sim_path(sc->umass_sim),
+			device_get_nameunit(sc->sc_dev), cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
 
 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
@@ -2629,7 +2991,7 @@
 	case XPT_NOOP:
 	{
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:XPT_NOOP:.\n",
-			(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
+			(sc == NULL? DEVNAME_SIM:device_get_nameunit(sc->sc_dev)),
 			cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun));
 
@@ -2640,7 +3002,7 @@
 	default:
 		DPRINTF(UDMASS_SCSI, ("%s:%d:%d:%d:func_code 0x%04x: "
 			"Not implemented\n",
-			(sc == NULL? DEVNAME_SIM:USBDEVNAME(sc->sc_dev)),
+			(sc == NULL? DEVNAME_SIM:device_get_nameunit(sc->sc_dev)),
 			cam_sim_path(sc->umass_sim),
 			ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
 			ccb->ccb_h.func_code));
@@ -2651,21 +3013,17 @@
 	}
 }
 
-/* umass_cam_poll
- *	all requests are handled through umass_cam_action, requests
- *	are never pending. So, nothing to do here.
- */
-Static void
+static void
 umass_cam_poll(struct cam_sim *sim)
 {
-#ifdef USB_DEBUG
 	struct umass_softc *sc = (struct umass_softc *) sim->softc;
 
 	DPRINTF(UDMASS_SCSI, ("%s: CAM poll\n",
-		USBDEVNAME(sc->sc_dev)));
-#endif
+		device_get_nameunit(sc->sc_dev)));
 
-	/* nop */
+	usbd_set_polling(sc->sc_udev, 1);
+	usbd_dopoll(sc->iface);
+	usbd_set_polling(sc->sc_udev, 0);
 }
 
 
@@ -2673,7 +3031,7 @@
  *	finalise a completed CAM command
  */
 
-Static void
+static void
 umass_cam_cb(struct umass_softc *sc, void *priv, int residue, int status)
 {
 	union ccb *ccb = (union ccb *) priv;
@@ -2691,6 +3049,16 @@
 	switch (status) {
 	case STATUS_CMD_OK:
 		ccb->ccb_h.status = CAM_REQ_CMP;
+		if ((sc->quirks & READ_CAPACITY_OFFBY1) &&
+		    (ccb->ccb_h.func_code == XPT_SCSI_IO) &&
+		    (csio->cdb_io.cdb_bytes[0] == READ_CAPACITY)) {
+			struct scsi_read_capacity_data *rcap;
+			uint32_t maxsector;
+
+			rcap = (struct scsi_read_capacity_data *)csio->data_ptr;
+			maxsector = scsi_4btoul(rcap->addr) - 1;
+			scsi_ulto4b(maxsector, rcap->addr);
+		}
 		xpt_done(ccb);
 		break;
 
@@ -2707,7 +3075,7 @@
 			sc->cam_scsi_sense.length = csio->sense_len;
 
 			DPRINTF(UDMASS_SCSI,("%s: Fetching %db sense data\n",
-				USBDEVNAME(sc->sc_dev), csio->sense_len));
+				device_get_nameunit(sc->sc_dev), csio->sense_len));
 
 			rcmd = (unsigned char *) &sc->cam_scsi_command;
 			rcmdlen = sizeof(sc->cam_scsi_command);
@@ -2715,7 +3083,7 @@
 			if (sc->transform(sc,
 				    (unsigned char *) &sc->cam_scsi_sense,
 				    sizeof(sc->cam_scsi_sense),
-				    &rcmd, &rcmdlen)) {
+				    &rcmd, &rcmdlen) == 1) {
 				if ((sc->quirks & FORCE_SHORT_INQUIRY) && (rcmd[0] == INQUIRY)) {
 					csio->sense_len = SHORT_INQUIRY_LENGTH;
 				}
@@ -2749,13 +3117,13 @@
 		break;
 	default:
 		panic("%s: Unknown status %d in umass_cam_cb",
-			USBDEVNAME(sc->sc_dev), status);
+			device_get_nameunit(sc->sc_dev), status);
 	}
 }
 
 /* Finalise a completed autosense operation
  */
-Static void
+static void
 umass_cam_sense_cb(struct umass_softc *sc, void *priv, int residue, int status)
 {
 	union ccb *ccb = (union ccb *) priv;
@@ -2814,7 +3182,7 @@
 
 			DPRINTF(UDMASS_SCSI,("%s: Doing a sneaky"
 					     "TEST_UNIT_READY\n",
-				USBDEVNAME(sc->sc_dev)));
+				device_get_nameunit(sc->sc_dev)));
 
 			/* the rest of the command was filled in at attach */
 
@@ -2825,7 +3193,7 @@
 					(unsigned char *)
 					&sc->cam_scsi_test_unit_ready,
 					sizeof(sc->cam_scsi_test_unit_ready),
-					&rcmd, &rcmdlen)) {
+					&rcmd, &rcmdlen) == 1) {
 				sc->transfer(sc, ccb->ccb_h.target_lun,
 					     rcmd, rcmdlen,
 					     NULL, 0, DIR_NONE, ccb->ccb_h.timeout,
@@ -2844,7 +3212,7 @@
 
 	default:
 		DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
-			USBDEVNAME(sc->sc_dev), status));
+			device_get_nameunit(sc->sc_dev), status));
 		ccb->ccb_h.status = CAM_AUTOSENSE_FAIL;
 		xpt_done(ccb);
 	}
@@ -2855,13 +3223,13 @@
  * after having previously failed a READ CAPACITY with CHECK_COND.  Even
  * though this command succeeded, we have to tell CAM to retry.
  */
-Static void
+static void
 umass_cam_quirk_cb(struct umass_softc *sc, void *priv, int residue, int status)
 {
 	union ccb *ccb = (union ccb *) priv;
 
 	DPRINTF(UDMASS_SCSI, ("%s: Test unit ready returned status %d\n",
-	USBDEVNAME(sc->sc_dev), status));
+	device_get_nameunit(sc->sc_dev), status));
 
 	if (sc->flags & UMASS_FLAGS_GONE) {
 		ccb->ccb_h.status = CAM_TID_INVALID;
@@ -2877,7 +3245,7 @@
 	xpt_done(ccb);
 }
 
-Static int
+static int
 umass_driver_load(module_t mod, int what, void *arg)
 {
 	switch (what) {
@@ -2892,7 +3260,7 @@
  * SCSI specific functions
  */
 
-Static int
+static int
 umass_scsi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
 		     unsigned char **rcmd, int *rcmdlen)
 {
@@ -2904,7 +3272,7 @@
 				 *rcmdlen,
 				 (long)sizeof(struct scsi_start_stop_unit)));
 			DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY "
-				"to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
+				"to START_UNIT\n", device_get_nameunit(sc->sc_dev)));
 			memset(*rcmd, 0, *rcmdlen);
 			(*rcmd)[0] = START_STOP_UNIT;
 			(*rcmd)[4] = SSS_START;
@@ -2928,7 +3296,7 @@
 	return 1;
 }
 /* RBC specific functions */
-Static int
+static int
 umass_rbc_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
 		     unsigned char **rcmd, int *rcmdlen)
 {
@@ -2962,7 +3330,7 @@
 	/* All other commands are not legal in RBC */
 	default:
 		printf("%s: Unsupported RBC command 0x%02x",
-			USBDEVNAME(sc->sc_dev), cmd[0]);
+			device_get_nameunit(sc->sc_dev), cmd[0]);
 		printf("\n");
 		return 0;	/* failure */
 	}
@@ -2971,7 +3339,7 @@
 /*
  * UFI specific functions
  */
-Static int
+static int
 umass_ufi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
 		    unsigned char **rcmd, int *rcmdlen)
 {
@@ -2993,7 +3361,7 @@
 			 * Start Stop Unit should give the same results
 			 */
 			DPRINTF(UDMASS_UFI, ("%s: Converted TEST_UNIT_READY "
-				"to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
+				"to START_UNIT\n", device_get_nameunit(sc->sc_dev)));
 			(*rcmd)[0] = START_STOP_UNIT;
 			(*rcmd)[4] = SSS_START;
 		} else {
@@ -3022,9 +3390,17 @@
 		memcpy(*rcmd, cmd, cmdlen);
 		return 1;
 
+	/*
+	 * SYNCHRONIZE_CACHE isn't supported by UFI, nor should it be
+	 * required for UFI devices, so it is appropriate to fake
+	 * success.
+	 */
+	case SYNCHRONIZE_CACHE:
+		return 2;
+
 	default:
 		printf("%s: Unsupported UFI command 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), cmd[0]);
+			device_get_nameunit(sc->sc_dev), cmd[0]);
 		return 0;	/* failure */
 	}
 }
@@ -3032,7 +3408,7 @@
 /*
  * 8070i (ATAPI) specific functions
  */
-Static int
+static int
 umass_atapi_transform(struct umass_softc *sc, unsigned char *cmd, int cmdlen,
 		      unsigned char **rcmd, int *rcmdlen)
 {
@@ -3062,7 +3438,7 @@
 				 *rcmdlen,
 				 (long)sizeof(struct scsi_start_stop_unit)));
 			DPRINTF(UDMASS_SCSI, ("%s: Converted TEST_UNIT_READY "
-				"to START_UNIT\n", USBDEVNAME(sc->sc_dev)));
+				"to START_UNIT\n", device_get_nameunit(sc->sc_dev)));
 			memset(*rcmd, 0, *rcmdlen);
 			(*rcmd)[0] = START_STOP_UNIT;
 			(*rcmd)[4] = SSS_START;
@@ -3108,9 +3484,11 @@
 	case READ_12:
 	case WRITE_12:
 	default:
-		printf("%s: Unsupported ATAPI command 0x%02x\n",
-			USBDEVNAME(sc->sc_dev), cmd[0]);
-		return 0;	/* failure */
+		printf("%s: Unsupported ATAPI command 0x%02x"
+			" - trying anyway\n",
+			device_get_nameunit(sc->sc_dev), cmd[0]);
+		memcpy(*rcmd, cmd, cmdlen);
+		return 1;
 	}
 }
 
@@ -3122,7 +3500,7 @@
 
 
 #ifdef USB_DEBUG
-Static void
+static void
 umass_bbb_dump_cbw(struct umass_softc *sc, umass_bbb_cbw_t *cbw)
 {
 	int clen = cbw->bCDBLength;
@@ -3134,13 +3512,13 @@
 	DPRINTF(UDMASS_BBB, ("%s: CBW %d: cmd = %db "
 		"(0x%02x%02x%02x%02x%02x%02x%s), "
 		"data = %db, dir = %s\n",
-		USBDEVNAME(sc->sc_dev), tag, clen,
+		device_get_nameunit(sc->sc_dev), tag, clen,
 		c[0], c[1], c[2], c[3], c[4], c[5], (clen > 6? "...":""),
 		dlen, (flags == CBWFLAGS_IN? "in":
 		       (flags == CBWFLAGS_OUT? "out":"<invalid>"))));
 }
 
-Static void
+static void
 umass_bbb_dump_csw(struct umass_softc *sc, umass_bbb_csw_t *csw)
 {
 	int sig = UGETDW(csw->dCSWSignature);
@@ -3149,7 +3527,7 @@
 	int status = csw->bCSWStatus;
 
 	DPRINTF(UDMASS_BBB, ("%s: CSW %d: sig = 0x%08x (%s), tag = %d, "
-		"res = %d, status = 0x%02x (%s)\n", USBDEVNAME(sc->sc_dev),
+		"res = %d, status = 0x%02x (%s)\n", device_get_nameunit(sc->sc_dev),
 		tag, sig, (sig == CSWSIGNATURE?  "valid":"invalid"),
 		tag, res,
 		status, (status == CSWSTATUS_GOOD? "good":
@@ -3157,7 +3535,7 @@
 			  (status == CSWSTATUS_PHASE? "phase":"<invalid>")))));
 }
 
-Static void
+static void
 umass_cbi_dump_cmd(struct umass_softc *sc, void *cmd, int cmdlen)
 {
 	u_int8_t *c = cmd;
@@ -3166,7 +3544,7 @@
 	DPRINTF(UDMASS_BBB, ("%s: cmd = %db "
 		"(0x%02x%02x%02x%02x%02x%02x%s), "
 		"data = %db, dir = %s\n",
-		USBDEVNAME(sc->sc_dev), cmdlen,
+		device_get_nameunit(sc->sc_dev), cmdlen,
 		c[0], c[1], c[2], c[3], c[4], c[5], (cmdlen > 6? "...":""),
 		sc->transfer_datalen,
 		(dir == DIR_IN? "in":
@@ -3174,7 +3552,7 @@
 		  (dir == DIR_NONE? "no data phase": "<invalid>")))));
 }
 
-Static void
+static void
 umass_dump_buffer(struct umass_softc *sc, u_int8_t *buffer, int buflen,
 		  int printlen)
 {
@@ -3191,7 +3569,7 @@
 		j = i % 16;
 		if (j == 0 && i != 0) {
 			DPRINTF(UDMASS_GEN, ("%s: 0x %s%s\n",
-				USBDEVNAME(sc->sc_dev), s1, s2));
+				device_get_nameunit(sc->sc_dev), s1, s2));
 			s2[0] = '\0';
 		}
 		sprintf(&s1[j*2], "%02x", buffer[i] & 0xff);
@@ -3199,6 +3577,6 @@
 	if (buflen > printlen)
 		sprintf(s3, " ...");
 	DPRINTF(UDMASS_GEN, ("%s: 0x %s%s%s\n",
-		USBDEVNAME(sc->sc_dev), s1, s2, s3));
+		device_get_nameunit(sc->sc_dev), s1, s2, s3));
 }
 #endif


More information about the Midnightbsd-cvs mailing list