Module Name:    src
Committed By:   skrll
Date:           Wed Aug  7 19:21:48 UTC 2019

Modified Files:
        src/sys/dev/usb: files.usb if_udav.c if_udavreg.h

Log Message:
Convert udav(4) to usbnet.  Based on a diff from mrg@


To generate a diff of this commit:
cvs rdiff -u -r1.160 -r1.161 src/sys/dev/usb/files.usb
cvs rdiff -u -r1.60 -r1.61 src/sys/dev/usb/if_udav.c
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/usb/if_udavreg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/files.usb
diff -u src/sys/dev/usb/files.usb:1.160 src/sys/dev/usb/files.usb:1.161
--- src/sys/dev/usb/files.usb:1.160	Wed Aug  7 07:25:09 2019
+++ src/sys/dev/usb/files.usb	Wed Aug  7 19:21:48 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.usb,v 1.160 2019/08/07 07:25:09 skrll Exp $
+#	$NetBSD: files.usb,v 1.161 2019/08/07 19:21:48 skrll Exp $
 #
 # Config file and device description for machine-independent USB code.
 # Included by ports that need it.  Ports that use it must provide
@@ -378,7 +378,7 @@ attach	mue at usbdevif
 file	dev/usb/if_mue.c		mue
 
 # DAVICOM DM9601
-device	udav: arp, ether, ifnet, mii, mii_phy
+device	udav: arp, ether, ifnet, mii, mii_phy, usbnet
 attach	udav at usbdevif
 file	dev/usb/if_udav.c		udav
 

Index: src/sys/dev/usb/if_udav.c
diff -u src/sys/dev/usb/if_udav.c:1.60 src/sys/dev/usb/if_udav.c:1.61
--- src/sys/dev/usb/if_udav.c:1.60	Thu Aug  1 00:10:22 2019
+++ src/sys/dev/usb/if_udav.c	Wed Aug  7 19:21:48 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_udav.c,v 1.60 2019/08/01 00:10:22 mrg Exp $	*/
+/*	$NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $	*/
 /*	$nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $	*/
 
 /*
@@ -45,95 +45,64 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.60 2019/08/01 00:10:22 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.61 2019/08/07 19:21:48 skrll Exp $");
 
 #ifdef _KERNEL_OPT
-#include "opt_inet.h"
 #include "opt_usb.h"
 #endif
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/mutex.h>
-#include <sys/mbuf.h>
+#include <sys/module.h>
 #include <sys/kernel.h>
-#include <sys/socket.h>
-#include <sys/device.h>
-#include <sys/rndsource.h>
-
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-
-#include <net/bpf.h>
-
-#include <net/if_ether.h>
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_inarp.h>
-#endif
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdevs.h>
 
+#include <dev/usb/usbnet.h>
 #include <dev/usb/if_udavreg.h>
 
+struct udav_softc {
+	struct usbnet		sc_un;
+	uint16_t		sc_flags;
+};
 
 /* Function declarations */
 int	udav_match(device_t, cfdata_t, void *);
 void	udav_attach(device_t, device_t, void *);
-int	udav_detach(device_t, int);
-int	udav_activate(device_t, enum devact);
 
 CFATTACH_DECL_NEW(udav, sizeof(struct udav_softc), udav_match, udav_attach,
-    udav_detach, udav_activate);
+    usbnet_detach, usbnet_activate);
+
+static void udav_chip_init(struct usbnet *);
 
-Static int udav_openpipes(struct udav_softc *);
-Static int udav_rx_list_init(struct udav_softc *);
-Static int udav_tx_list_init(struct udav_softc *);
-Static int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
-Static void udav_start(struct ifnet *);
-Static int udav_send(struct udav_softc *, struct mbuf *, int);
-Static void udav_txeof(struct usbd_xfer *, void *, usbd_status);
-Static void udav_rxeof(struct usbd_xfer *, void *, usbd_status);
-Static void udav_tick(void *);
-Static void udav_tick_task(void *);
-Static int udav_ioctl(struct ifnet *, u_long, void *);
-Static void udav_stop_task(struct udav_softc *);
-Static void udav_stop(struct ifnet *, int);
-Static void udav_watchdog(struct ifnet *);
-Static int udav_ifmedia_change(struct ifnet *);
-Static void udav_lock_mii(struct udav_softc *);
-Static void udav_unlock_mii(struct udav_softc *);
-Static int udav_miibus_readreg(device_t, int, int, uint16_t *);
-Static int udav_miibus_writereg(device_t, int, int, uint16_t);
-Static void udav_miibus_statchg(struct ifnet *);
-Static int udav_init(struct ifnet *);
-Static void udav_setmulti(struct udav_softc *);
-Static void udav_reset(struct udav_softc *);
-
-Static int udav_csr_read(struct udav_softc *, int, void *, int);
-Static int udav_csr_write(struct udav_softc *, int, void *, int);
-Static int udav_csr_read1(struct udav_softc *, int);
-Static int udav_csr_write1(struct udav_softc *, int, unsigned char);
+static unsigned udav_tx_prepare(struct usbnet *, struct mbuf *,
+			        struct usbnet_chain *);
+static void udav_rxeof_loop(struct usbnet *, struct usbd_xfer *,
+			    struct usbnet_chain *, uint32_t);
+static void udav_stop_cb(struct ifnet *, int);
+static int udav_ioctl_cb(struct ifnet *, u_long, void *);
+static usbd_status udav_mii_read_reg(struct usbnet *, int, int, uint16_t *);
+static usbd_status udav_mii_write_reg(struct usbnet *, int, int, uint16_t);
+static void udav_mii_statchg(struct ifnet *);
+static int udav_init(struct ifnet *);
+static void udav_setiff(struct usbnet *);
+static void udav_setiff_locked(struct usbnet *);
+static void udav_reset(struct usbnet *);
+
+static int udav_csr_read(struct udav_softc *, int, void *, int);
+static int udav_csr_write(struct udav_softc *, int, void *, int);
+static int udav_csr_read1(struct udav_softc *, int);
+static int udav_csr_write1(struct udav_softc *, int, unsigned char);
 
 #if 0
-Static int udav_mem_read(struct udav_softc *, int, void *, int);
-Static int udav_mem_write(struct udav_softc *, int, void *, int);
-Static int udav_mem_write1(struct udav_softc *, int, unsigned char);
+static int udav_mem_read(struct udav_softc *, int, void *, int);
+static int udav_mem_write(struct udav_softc *, int, void *, int);
+static int udav_mem_write1(struct udav_softc *, int, unsigned char);
 #endif
 
 /* Macros */
 #ifdef UDAV_DEBUG
 #define DPRINTF(x)	if (udavdebug) printf x
 #define DPRINTFN(n, x)	if (udavdebug >= (n)) printf x
-int udavdebug = 0;
+int udavdebug = 10;
 #else
 #define DPRINTF(x)
 #define DPRINTFN(n, x)
@@ -187,6 +156,7 @@ void
 udav_attach(device_t parent, device_t self, void *aux)
 {
 	struct udav_softc *sc = device_private(self);
+	struct usbnet * const un = &sc->sc_un;
 	struct usb_attach_arg *uaa = aux;
 	struct usbd_device *dev = uaa->uaa_device;
 	struct usbd_interface *iface;
@@ -194,208 +164,114 @@ udav_attach(device_t parent, device_t se
 	usb_interface_descriptor_t *id;
 	usb_endpoint_descriptor_t *ed;
 	char *devinfop;
-	struct ifnet *ifp;
-	struct mii_data *mii;
-	u_char eaddr[ETHER_ADDR_LEN];
-	int i, s;
+	int i;
 
-	sc->sc_dev = self;
+	/* Switch to usbnet for device_private() */
+	self->dv_private = un;
 
 	aprint_naive("\n");
 	aprint_normal("\n");
-
 	devinfop = usbd_devinfo_alloc(dev, 0);
 	aprint_normal_dev(self, "%s\n", devinfop);
 	usbd_devinfo_free(devinfop);
 
+	un->un_dev = self;
+	un->un_udev = dev;
+	un->un_sc = sc;
+	un->un_stop_cb = udav_stop_cb;
+	un->un_ioctl_cb = udav_ioctl_cb;
+	un->un_read_reg_cb = udav_mii_read_reg;
+	un->un_write_reg_cb = udav_mii_write_reg;
+	un->un_statchg_cb = udav_mii_statchg;
+	un->un_tx_prepare_cb = udav_tx_prepare;
+	un->un_rx_loop_cb = udav_rxeof_loop;
+	un->un_init_cb = udav_init;
+	un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
+	un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
+
 	/* Move the device into the configured state. */
 	err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1); /* idx 0 */
 	if (err) {
 		aprint_error_dev(self, "failed to set configuration"
 		    ", err=%s\n", usbd_errstr(err));
-		goto bad;
+		return;
 	}
 
-	usb_init_task(&sc->sc_tick_task, udav_tick_task, sc, 0);
-	mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE);
-	usb_init_task(&sc->sc_stop_task, (void (*)(void *))udav_stop_task, sc,
-	    0);
-
 	/* get control interface */
 	err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
 	if (err) {
 		aprint_error_dev(self, "failed to get interface, err=%s\n",
 		       usbd_errstr(err));
-		goto bad;
+		return;
 	}
 
-	sc->sc_udev = dev;
-	sc->sc_ctl_iface = iface;
+	un->un_iface = iface;
 	sc->sc_flags = udav_lookup(uaa->uaa_vendor,
 	    uaa->uaa_product)->udav_flags;
 
 	/* get interface descriptor */
-	id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
+	id = usbd_get_interface_descriptor(un->un_iface);
 
 	/* find endpoints */
-	sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
+	un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] =
+	    un->un_ed[USBNET_ENDPT_INTR] = -1;
 	for (i = 0; i < id->bNumEndpoints; i++) {
-		ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
+		ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
 		if (ed == NULL) {
 			aprint_error_dev(self, "couldn't get endpoint %d\n", i);
-			goto bad;
+			return;
 		}
 		if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
 		    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
-			sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
+			un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
-			sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
+			un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
 		else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
 			 UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
-			sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
+			un->un_ed[USBNET_ENDPT_INTR] = ed->bEndpointAddress;
 	}
 
-	if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
-	    sc->sc_intrin_no == -1) {
+	if (un->un_ed[USBNET_ENDPT_RX] == -1 ||
+	    un->un_ed[USBNET_ENDPT_TX] == -1 ||
+	    un->un_ed[USBNET_ENDPT_INTR] == -1) {
 		aprint_error_dev(self, "missing endpoint\n");
-		goto bad;
+		return;
 	}
 
-	s = splnet();
+	/* Not supported yet. */
+	un->un_ed[USBNET_ENDPT_INTR] = 0;
+
+	un->un_cdata.uncd_rx_bufsz = un->un_cdata.uncd_tx_bufsz = UDAV_BUFSZ;
+
+// 	/* reset the adapter */
+// 	udav_reset(un);
 
-	/* reset the adapter */
-	udav_reset(sc);
+	usbnet_attach(un, "udavdet", UDAV_RX_LIST_CNT, UDAV_TX_LIST_CNT);
 
 	/* Get Ethernet Address */
-	err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
+	usbnet_lock_mii(un);
+	err = udav_csr_read(sc, UDAV_PAR, un->un_eaddr, ETHER_ADDR_LEN);
+	usbnet_unlock_mii(un);
 	if (err) {
 		aprint_error_dev(self, "read MAC address failed\n");
-		splx(s);
-		goto bad;
+		return;
 	}
 
-	/* Print Ethernet Address */
-	aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr));
+	bool have_mii = !ISSET(sc->sc_flags, UDAV_NO_PHY);
+	if (!have_mii)
+		un->un_link = 1;
 
 	/* initialize interface information */
-	ifp = GET_IFP(sc);
-	ifp->if_softc = sc;
-	ifp->if_mtu = ETHERMTU;
-	strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
-	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_start = udav_start;
-	ifp->if_ioctl = udav_ioctl;
-	ifp->if_watchdog = udav_watchdog;
-	ifp->if_init = udav_init;
-	ifp->if_stop = udav_stop;
-
-	IFQ_SET_READY(&ifp->if_snd);
-
-	if (ISSET(sc->sc_flags, UDAV_NO_PHY)) {
-		sc->sc_link = 1;
-		goto skipmii;
-	}
+	usbnet_attach_ifp(un, have_mii,
+	    IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST, 0, 0);
 
-	/*
-	 * Do ifmedia setup.
-	 */
-	mii = &sc->sc_mii;
-	mii->mii_ifp = ifp;
-	mii->mii_readreg = udav_miibus_readreg;
-	mii->mii_writereg = udav_miibus_writereg;
-	mii->mii_statchg = udav_miibus_statchg;
-	mii->mii_flags = MIIF_AUTOTSLEEP;
-	sc->sc_ec.ec_mii = mii;
-	ifmedia_init(&mii->mii_media, 0,
-		     udav_ifmedia_change, ether_mediastatus);
-	mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
-	if (LIST_FIRST(&mii->mii_phys) == NULL) {
-		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
-		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
-	} else
-		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
-
-skipmii:
-	/* attach the interface */
-	if_attach(ifp);
-	ether_ifattach(ifp, eaddr);
-
-	rnd_attach_source(&sc->rnd_source, device_xname(self),
-	    RND_TYPE_NET, RND_FLAG_DEFAULT);
-
-	callout_init(&sc->sc_stat_ch, 0);
-	sc->sc_attached = 1;
-	splx(s);
-
-	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, sc->sc_dev);
-
-	return;
-
- bad:
-	sc->sc_dying = 1;
 	return;
 }
 
-/* detach */
-int
-udav_detach(device_t self, int flags)
-{
-	struct udav_softc *sc = device_private(self);
-	struct ifnet *ifp = GET_IFP(sc);
-	int s;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	/* Detached before attached finished */
-	if (!sc->sc_attached)
-		return 0;
-
-	callout_halt(&sc->sc_stat_ch, NULL);
-
-	/* Remove any pending tasks */
-	usb_rem_task_wait(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER,
-	    NULL);
-	usb_rem_task_wait(sc->sc_udev, &sc->sc_stop_task, USB_TASKQ_DRIVER,
-	    NULL);
-
-	s = splusb();
-
-	if (--sc->sc_refcnt >= 0) {
-		/* Wait for processes to go away */
-		usb_detach_waitold(sc->sc_dev);
-	}
-	if (ifp->if_flags & IFF_RUNNING)
-		udav_stop(GET_IFP(sc), 1);
-
-	rnd_detach_source(&sc->rnd_source);
-	mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
-	ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
-	ether_ifdetach(ifp);
-	if_detach(ifp);
-
-#ifdef DIAGNOSTIC
-	if (sc->sc_pipe_tx != NULL)
-		aprint_debug_dev(self, "detach has active tx endpoint.\n");
-	if (sc->sc_pipe_rx != NULL)
-		aprint_debug_dev(self, "detach has active rx endpoint.\n");
-	if (sc->sc_pipe_intr != NULL)
-		aprint_debug_dev(self, "detach has active intr endpoint.\n");
-#endif
-	sc->sc_attached = 0;
-
-	splx(s);
-
-	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
-
-	mutex_destroy(&sc->sc_mii_lock);
-
-	return 0;
-}
-
 #if 0
 /* read memory */
-Static int
+static int
 udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
 {
 	usb_device_request_t req;
@@ -405,9 +281,9 @@ udav_mem_read(struct udav_softc *sc, int
 		return 0;
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return 0;
 
 	offset &= 0xffff;
@@ -419,20 +295,17 @@ udav_mem_read(struct udav_softc *sc, int
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, len);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, buf);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, buf);
 	if (err) {
 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
 }
 
 /* write memory */
-Static int
+static int
 udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
 {
 	usb_device_request_t req;
@@ -442,9 +315,9 @@ udav_mem_write(struct udav_softc *sc, in
 		return 0;
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return 0;
 
 	offset &= 0xffff;
@@ -456,20 +329,17 @@ udav_mem_write(struct udav_softc *sc, in
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, len);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, buf);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, buf);
 	if (err) {
 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
 }
 
 /* write memory */
-Static int
+static int
 udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
 {
 	usb_device_request_t req;
@@ -479,9 +349,9 @@ udav_mem_write1(struct udav_softc *sc, i
 		return 0;
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return 0;
 
 	offset &= 0xffff;
@@ -492,13 +362,10 @@ udav_mem_write1(struct udav_softc *sc, i
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, 0x0000);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, NULL);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, NULL);
 	if (err) {
 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
@@ -506,20 +373,18 @@ udav_mem_write1(struct udav_softc *sc, i
 #endif
 
 /* read register(s) */
-Static int
+static int
 udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
 {
+	struct usbnet * const un = &sc->sc_un;
 	usb_device_request_t req;
 	usbd_status err;
 
-	if (sc == NULL)
-		return 0;
+	usbnet_isowned_mii(un);
+	KASSERT(!un->un_dying);
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (sc->sc_dying)
-		return 0;
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
 	offset &= 0xff;
 	len &= 0xff;
@@ -530,33 +395,28 @@ udav_csr_read(struct udav_softc *sc, int
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, len);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, buf);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, buf);
 	if (err) {
 		DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
 }
 
 /* write register(s) */
-Static int
+static int
 udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
 {
+	struct usbnet * const un = &sc->sc_un;
 	usb_device_request_t req;
 	usbd_status err;
 
-	if (sc == NULL)
-		return 0;
+	usbnet_isowned_mii(un);
+	KASSERT(!un->un_dying);
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (sc->sc_dying)
-		return 0;
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
 	offset &= 0xff;
 	len &= 0xff;
@@ -567,50 +427,45 @@ udav_csr_write(struct udav_softc *sc, in
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, len);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, buf);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, buf);
 	if (err) {
 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
 }
 
-Static int
+static int
 udav_csr_read1(struct udav_softc *sc, int offset)
 {
+	struct usbnet * const un = &sc->sc_un;
 	uint8_t val = 0;
 
-	if (sc == NULL)
-		return 0;
+	usbnet_isowned_mii(un);
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return 0;
 
 	return udav_csr_read(sc, offset, &val, 1) ? 0 : val;
 }
 
 /* write a register */
-Static int
+static int
 udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
 {
+	struct usbnet * const un = &sc->sc_un;
 	usb_device_request_t req;
 	usbd_status err;
 
-	if (sc == NULL)
-		return 0;
+	usbnet_isowned_mii(un);
+	KASSERT(!un->un_dying);
 
 	DPRINTFN(0x200,
-		("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (sc->sc_dying)
-		return 0;
+		("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
 	offset &= 0xff;
 
@@ -620,35 +475,36 @@ udav_csr_write1(struct udav_softc *sc, i
 	USETW(req.wIndex, offset);
 	USETW(req.wLength, 0x0000);
 
-	sc->sc_refcnt++;
-	err = usbd_do_request(sc->sc_udev, &req, NULL);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	err = usbd_do_request(un->un_udev, &req, NULL);
 	if (err) {
 		DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
-			 device_xname(sc->sc_dev), __func__, offset, err));
+			 device_xname(un->un_dev), __func__, offset, err));
 	}
 
 	return err;
 }
 
-Static int
-udav_init(struct ifnet *ifp)
+static int
+udav_init_locked(struct ifnet *ifp)
 {
-	struct udav_softc *sc = ifp->if_softc;
-	struct mii_data *mii = GET_MII(sc);
+	struct usbnet * const un = ifp->if_softc;
+	struct mii_data * const mii = usbnet_mii(un);
+	struct udav_softc *sc = usbnet_softc(un);
 	uint8_t eaddr[ETHER_ADDR_LEN];
-	int rc, s;
+	int rc;
 
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
-		return EIO;
+	usbnet_isowned(un);
 
-	s = splnet();
+	if (un->un_dying)
+		return EIO;
 
 	/* Cancel pending I/O and free all TX/RX buffers */
-	udav_stop(ifp, 1);
+	if (ifp->if_flags & IFF_RUNNING)
+		usbnet_stop(un, ifp, 1);
+
+	usbnet_lock_mii_un_locked(un);
 
 	memcpy(eaddr, CLLADDR(ifp->if_sadl), sizeof(eaddr));
 	udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
@@ -667,7 +523,7 @@ udav_init(struct ifnet *ifp)
 		UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL | UDAV_RCR_PRMSC);
 
 	/* Load the multicast filter */
-	udav_setmulti(sc);
+	udav_setiff_locked(un);
 
 	/* Enable RX */
 	UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
@@ -676,62 +532,52 @@ udav_init(struct ifnet *ifp)
 	UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
 	UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
 
-	if ((rc = mii_mediachg(mii)) == ENXIO)
-		rc = 0;
-	else if (rc != 0)
-		goto out;
-
-	if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
-		if (udav_openpipes(sc)) {
-			splx(s);
-			return EIO;
-		}
-	}
+	usbnet_unlock_mii_un_locked(un);
 
-	/* Initialize transmit ring */
-	if (udav_tx_list_init(sc)) {
-		printf("%s: tx list init failed\n", device_xname(sc->sc_dev));
-		splx(s);
-		return EIO;
+	rc = 0;
+	if (mii) {
+		if ((rc = mii_mediachg(mii)) == ENXIO)
+			rc = 0;
 	}
 
-	/* Initialize receive ring */
-	if (udav_rx_list_init(sc)) {
-		printf("%s: rx list init failed\n", device_xname(sc->sc_dev));
-		splx(s);
-		return EIO;
-	}
+	if (rc != 0)
+		return rc;
 
-	/* Start up the receive pipe. */
-	for (size_t i = 0; i < UDAV_RX_LIST_CNT; i++) {
-		struct udav_chain *c = &sc->sc_cdata.udav_rx_chain[i];
-		usbd_setup_xfer(c->udav_xfer, c, c->udav_buf, UDAV_BUFSZ,
-		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, udav_rxeof);
-		(void)usbd_transfer(c->udav_xfer);
-		DPRINTF(("%s: %s: start read\n", device_xname(sc->sc_dev),
-			 __func__));
-	}
+	return usbnet_init_rx_tx(un, 0, USBD_FORCE_SHORT_XFER);
+}
 
-	ifp->if_flags |= IFF_RUNNING;
-	ifp->if_flags &= ~IFF_OACTIVE;
+static int
+udav_init(struct ifnet *ifp)
+{
+	struct usbnet * const un = ifp->if_softc;
 
-	callout_reset(&sc->sc_stat_ch, hz, udav_tick, sc);
+	usbnet_lock(un);
+	int ret = udav_init_locked(ifp);
+	usbnet_unlock(un);
 
-out:
-	splx(s);
-	return rc;
+	return ret;
 }
 
-Static void
-udav_reset(struct udav_softc *sc)
+static void
+udav_reset(struct usbnet *un)
 {
-	int i;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+    	usbnet_isowned(un);
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return;
 
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
+
+	udav_chip_init(un);
+}
+
+static void
+udav_chip_init(struct usbnet *un)
+{
+    	struct udav_softc * const sc = usbnet_softc(un);
+
+	usbnet_lock_mii_un_locked(un);
+
 	/* Select PHY */
 #if 1
 	/*
@@ -749,29 +595,14 @@ udav_reset(struct udav_softc *sc)
 
 	UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
 
-	for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
+	for (int i = 0; i < UDAV_TX_TIMEOUT; i++) {
 		if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
 			break;
 		delay(10);	/* XXX */
 	}
 	delay(10000);		/* XXX */
-}
-
-int
-udav_activate(device_t self, enum devact act)
-{
-	struct udav_softc *sc = device_private(self);
 
-	DPRINTF(("%s: %s: enter, act=%d\n", device_xname(sc->sc_dev),
-		 __func__, act));
-	switch (act) {
-	case DVACT_DEACTIVATE:
-		if_deactivate(&sc->sc_ec.ec_if);
-		sc->sc_dying = 1;
-		return 0;
-	default:
-		return EOPNOTSUPP;
-	}
+	usbnet_unlock_mii_un_locked(un);
 }
 
 #define UDAV_BITS	6
@@ -779,22 +610,23 @@ udav_activate(device_t self, enum devact
 #define UDAV_CALCHASH(addr) \
 	(ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
 
-Static void
-udav_setmulti(struct udav_softc *sc)
+static void
+udav_setiff_locked(struct usbnet *un)
 {
-	struct ethercom *ec = &sc->sc_ec;
-	struct ifnet *ifp;
+	struct udav_softc *sc = usbnet_softc(un);
+	struct ethercom *ec = usbnet_ec(un);
+	struct ifnet * const ifp = usbnet_ifp(un);
 	struct ether_multi *enm;
 	struct ether_multistep step;
 	uint8_t hashes[8];
 	int h = 0;
 
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	if (sc->sc_dying)
-		return;
+	usbnet_isowned_mii(un);
 
-	ifp = GET_IFP(sc);
+	if (un->un_dying)
+		return;
 
 	if (ISSET(sc->sc_flags, UDAV_NO_PHY)) {
 		UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
@@ -842,661 +674,146 @@ allmulti:
 	udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
 }
 
-Static int
-udav_openpipes(struct udav_softc *sc)
-{
-	usbd_status err;
-	int error = 0;
-
-	if (sc->sc_dying)
-		return EIO;
-
-	sc->sc_refcnt++;
-
-	/* Open RX pipe */
-	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
-			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
-	if (err) {
-		printf("%s: open rx pipe failed: %s\n",
-		       device_xname(sc->sc_dev), usbd_errstr(err));
-		error = EIO;
-		goto done;
-	}
-
-	/* Open TX pipe */
-	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
-			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
-	if (err) {
-		printf("%s: open tx pipe failed: %s\n",
-		       device_xname(sc->sc_dev), usbd_errstr(err));
-		error = EIO;
-		goto done;
-	}
-
-#if 0
-	/* XXX: interrupt endpoint is not yet supported */
-	/* Open Interrupt pipe */
-	err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
-				  USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
-				  &sc->sc_cdata.udav_ibuf, UDAV_INTR_PKGLEN,
-				  udav_intr, USBD_DEFAULT_INTERVAL);
-	if (err) {
-		printf("%s: open intr pipe failed: %s\n",
-		       device_xname(sc->sc_dev), usbd_errstr(err));
-		error = EIO;
-		goto done;
-	}
-#endif
- done:
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
-
-	return error;
-}
-
-Static int
-udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m)
-{
-	struct mbuf *m_new = NULL;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (m == NULL) {
-		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
-		if (m_new == NULL) {
-			printf("%s: no memory for rx list "
-			       "-- packet dropped!\n", device_xname(sc->sc_dev));
-			return ENOBUFS;
-		}
-		MCLGET(m_new, M_DONTWAIT);
-		if (!(m_new->m_flags & M_EXT)) {
-			printf("%s: no memory for rx list "
-			       "-- packet dropped!\n", device_xname(sc->sc_dev));
-			m_freem(m_new);
-			return ENOBUFS;
-		}
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-	} else {
-		m_new = m;
-		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-		m_new->m_data = m_new->m_ext.ext_buf;
-	}
-
-	m_adj(m_new, ETHER_ALIGN);
-	c->udav_mbuf = m_new;
-
-	return 0;
-}
-
-
-Static int
-udav_rx_list_init(struct udav_softc *sc)
+static void
+udav_setiff(struct usbnet *un)
 {
-	struct udav_cdata *cd;
-	struct udav_chain *c;
-	int i;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	cd = &sc->sc_cdata;
-	for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
-		c = &cd->udav_rx_chain[i];
-		c->udav_sc = sc;
-		if (udav_newbuf(sc, c, NULL) == ENOBUFS)
-			return ENOBUFS;
-		if (c->udav_xfer == NULL) {
-			int error = usbd_create_xfer(sc->sc_pipe_rx,
-			    UDAV_BUFSZ, 0, 0, &c->udav_xfer);
-			if (error)
-				return error;
-			c->udav_buf = usbd_get_buffer(c->udav_xfer);
-		}
-	}
-
-	return 0;
+	usbnet_lock_mii(un);
+	udav_setiff_locked(un);
+	usbnet_unlock_mii(un);
 }
 
-Static int
-udav_tx_list_init(struct udav_softc *sc)
-{
-	struct udav_cdata *cd;
-	struct udav_chain *c;
-	int i;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	cd = &sc->sc_cdata;
-	for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
-		c = &cd->udav_tx_chain[i];
-		c->udav_sc = sc;
-		c->udav_mbuf = NULL;
-		if (c->udav_xfer == NULL) {
-			int error = usbd_create_xfer(sc->sc_pipe_tx, UDAV_BUFSZ,
-			    USBD_FORCE_SHORT_XFER, 0, &c->udav_xfer);
-			if (error)
-				return error;
-			c->udav_buf = usbd_get_buffer(c->udav_xfer);
-		}
-	}
-
-	return 0;
-}
 
-Static void
-udav_start(struct ifnet *ifp)
-{
-	struct udav_softc *sc = ifp->if_softc;
-	struct mbuf *m_head = NULL;
-
-	DPRINTF(("%s: %s: enter, link=%d\n", device_xname(sc->sc_dev),
-		 __func__, sc->sc_link));
-
-	if (sc->sc_dying)
-		return;
-
-	if (!sc->sc_link)
-		return;
-
-	if (ifp->if_flags & IFF_OACTIVE)
-		return;
-
-	IFQ_POLL(&ifp->if_snd, m_head);
-	if (m_head == NULL)
-		return;
-
-	if (udav_send(sc, m_head, 0)) {
-		ifp->if_flags |= IFF_OACTIVE;
-		return;
-	}
-
-	IFQ_DEQUEUE(&ifp->if_snd, m_head);
-
-	bpf_mtap(ifp, m_head, BPF_D_OUT);
-
-	ifp->if_flags |= IFF_OACTIVE;
-
-	/* Set a timeout in case the chip goes out to lunch. */
-	ifp->if_timer = 5;
-}
-
-Static int
-udav_send(struct udav_softc *sc, struct mbuf *m, int idx)
+static unsigned
+udav_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
 {
 	int total_len;
-	struct udav_chain *c;
-	usbd_status err;
+	uint8_t *buf = c->unc_buf;
 
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
+	usbnet_isowned_tx(un);
 
-	c = &sc->sc_cdata.udav_tx_chain[idx];
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
+
+	if (m->m_pkthdr.len > UDAV_BUFSZ - 2)
+		return 0;
 
 	/* Copy the mbuf data into a contiguous buffer */
-	/*  first 2 bytes are packet length */
-	m_copydata(m, 0, m->m_pkthdr.len, c->udav_buf + 2);
-	c->udav_mbuf = m;
+	m_copydata(m, 0, m->m_pkthdr.len, buf + 2);
 	total_len = m->m_pkthdr.len;
 	if (total_len < UDAV_MIN_FRAME_LEN) {
-		memset(c->udav_buf + 2 + total_len, 0,
+		memset(buf + 2 + total_len, 0,
 		    UDAV_MIN_FRAME_LEN - total_len);
 		total_len = UDAV_MIN_FRAME_LEN;
 	}
 
 	/* Frame length is specified in the first 2bytes of the buffer */
-	c->udav_buf[0] = (uint8_t)total_len;
-	c->udav_buf[1] = (uint8_t)(total_len >> 8);
+	buf[0] = (uint8_t)total_len;
+	buf[1] = (uint8_t)(total_len >> 8);
 	total_len += 2;
 
-	usbd_setup_xfer(c->udav_xfer, c, c->udav_buf, total_len,
-	    USBD_FORCE_SHORT_XFER, UDAV_TX_TIMEOUT, udav_txeof);
-
-	/* Transmit */
-	sc->sc_refcnt++;
-	err = usbd_transfer(c->udav_xfer);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
-	if (err != USBD_IN_PROGRESS) {
-		printf("%s: udav_send error=%s\n", device_xname(sc->sc_dev),
-		       usbd_errstr(err));
-		/* Stop the interface */
-		usb_add_task(sc->sc_udev, &sc->sc_stop_task,
-		    USB_TASKQ_DRIVER);
-		return EIO;
-	}
-
-	DPRINTF(("%s: %s: send %d bytes\n", device_xname(sc->sc_dev),
-		 __func__, total_len));
-
-	sc->sc_cdata.udav_tx_cnt++;
-
-	return 0;
-}
-
-Static void
-udav_txeof(struct usbd_xfer *xfer, void *priv,
-    usbd_status status)
-{
-	struct udav_chain *c = priv;
-	struct udav_softc *sc = c->udav_sc;
-	struct ifnet *ifp = GET_IFP(sc);
-	int s;
-
-	if (sc->sc_dying)
-		return;
-
-	s = splnet();
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	ifp->if_timer = 0;
-	ifp->if_flags &= ~IFF_OACTIVE;
-
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
-			splx(s);
-			return;
-		}
-		ifp->if_oerrors++;
-		printf("%s: usb error on tx: %s\n", device_xname(sc->sc_dev),
-		       usbd_errstr(status));
-		if (status == USBD_STALLED) {
-			sc->sc_refcnt++;
-			usbd_clear_endpoint_stall_async(sc->sc_pipe_tx);
-			if (--sc->sc_refcnt < 0)
-				usb_detach_wakeupold(sc->sc_dev);
-		}
-		splx(s);
-		return;
-	}
+	DPRINTF(("%s: %s: send %d bytes\n", device_xname(un->un_dev),
+	    __func__, total_len));
 
-	ifp->if_opackets++;
-
-	m_freem(c->udav_mbuf);
-	c->udav_mbuf = NULL;
-
-	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-		udav_start(ifp);
-
-	splx(s);
+	return total_len;
 }
 
-Static void
-udav_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
+static void
+udav_rxeof_loop(struct usbnet *un, struct usbd_xfer *xfer,
+	        struct usbnet_chain *c, uint32_t total_len)
 {
-	struct udav_chain *c = priv;
-	struct udav_softc *sc = c->udav_sc;
-	struct ifnet *ifp = GET_IFP(sc);
-	struct mbuf *m;
-	uint32_t total_len;
-	uint8_t *pktstat;
-	int s;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev),__func__));
-
-	if (sc->sc_dying)
-		return;
+	struct ifnet *ifp = usbnet_ifp(un);
+	uint8_t *buf = c->unc_buf;
+	uint16_t pkt_len;
+	uint8_t pktstat;
 
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
-			return;
-		sc->sc_rx_errs++;
-		if (usbd_ratecheck(&sc->sc_rx_notice)) {
-			printf("%s: %u usb errors on rx: %s\n",
-			       device_xname(sc->sc_dev), sc->sc_rx_errs,
-			       usbd_errstr(status));
-			sc->sc_rx_errs = 0;
-		}
-		if (status == USBD_STALLED) {
-			sc->sc_refcnt++;
-			usbd_clear_endpoint_stall_async(sc->sc_pipe_rx);
-			if (--sc->sc_refcnt < 0)
-				usb_detach_wakeupold(sc->sc_dev);
-		}
-		goto done;
-	}
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
+	/* first byte in received data */
+	pktstat = *buf;
+	total_len -= sizeof(pktstat);
+	buf += sizeof(pktstat);
 
-	/* copy data to mbuf */
-	m = c->udav_mbuf;
-	memcpy(mtod(m, char *), c->udav_buf, total_len);
+	DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(un->un_dev), pktstat));
 
-	/* first byte in received data */
-	pktstat = mtod(m, uint8_t *);
-	m_adj(m, sizeof(uint8_t));
-	DPRINTF(("%s: RX Status: 0x%02x\n", device_xname(sc->sc_dev),
-				*pktstat));
+	pkt_len = UGETW(buf);
+ 	total_len -= sizeof(pkt_len);
+	buf += sizeof(pkt_len);
 
-	total_len = UGETW(mtod(m, uint8_t *));
-	m_adj(m, sizeof(uint16_t));
+	DPRINTF(("%s: RX Length: 0x%02x\n", device_xname(un->un_dev), pkt_len));
 
-	if (*pktstat & UDAV_RSR_LCS) {
+	if (pktstat & UDAV_RSR_LCS) {
 		ifp->if_collisions++;
-		goto done;
-	}
-
-	if (total_len < sizeof(struct ether_header) ||
-	    *pktstat & UDAV_RSR_ERR) {
-		ifp->if_ierrors++;
-		goto done;
+		return;
 	}
 
-	total_len -= ETHER_CRC_LEN;
-
-	m->m_pkthdr.len = m->m_len = total_len;
-	m_set_rcvif(m, ifp);
-
-	s = splnet();
-
-	if (udav_newbuf(sc, c, NULL) == ENOBUFS) {
+	if (pkt_len < sizeof(struct ether_header) ||
+	    pkt_len > total_len ||
+	    (pktstat & UDAV_RSR_ERR)) {
 		ifp->if_ierrors++;
-		goto done1;
+		return;
 	}
 
-	DPRINTF(("%s: %s: deliver %d\n", device_xname(sc->sc_dev),
-		 __func__, m->m_len));
-	if_percpuq_enqueue((ifp)->if_percpuq, (m));
-
- done1:
-	splx(s);
-
- done:
-	/* Setup new transfer */
-	usbd_setup_xfer(xfer, c, c->udav_buf, UDAV_BUFSZ, USBD_SHORT_XFER_OK,
-	    USBD_NO_TIMEOUT, udav_rxeof);
-	sc->sc_refcnt++;
-	usbd_transfer(xfer);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+	pkt_len -= ETHER_CRC_LEN;
 
-	DPRINTF(("%s: %s: start rx\n", device_xname(sc->sc_dev), __func__));
-}
+	DPRINTF(("%s: Rx deliver: 0x%02x\n", device_xname(un->un_dev), pkt_len));
 
-#if 0
-Static void udav_intr(void)
-{
+	usbnet_enqueue(un, buf, pkt_len, 0, 0, 0);
 }
-#endif
 
-Static int
-udav_ioctl(struct ifnet *ifp, u_long cmd, void *data)
+static int
+udav_ioctl_cb(struct ifnet *ifp, u_long cmd, void *data)
 {
-	struct udav_softc *sc = ifp->if_softc;
-	int s, error = 0;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
+	struct usbnet * const un = ifp->if_softc;
 
-	if (sc->sc_dying)
-		return EIO;
-
-	s = splnet();
-
-	error = ether_ioctl(ifp, cmd, data);
-	if (error == ENETRESET) {
-		if (ifp->if_flags & IFF_RUNNING)
-			udav_setmulti(sc);
-		error = 0;
+	switch (cmd) {
+	case SIOCADDMULTI:
+	case SIOCDELMULTI:
+		udav_setiff(un);
+		break;
+	default:
+		break;
 	}
 
-	splx(s);
-
-	return error;
-}
-
-Static void
-udav_watchdog(struct ifnet *ifp)
-{
-	struct udav_softc *sc = ifp->if_softc;
-	struct udav_chain *c;
-	usbd_status stat;
-	int s;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	ifp->if_oerrors++;
-	printf("%s: watchdog timeout\n", device_xname(sc->sc_dev));
 
-	s = splusb();
-	c = &sc->sc_cdata.udav_tx_chain[0];
-	usbd_get_xfer_status(c->udav_xfer, NULL, NULL, NULL, &stat);
-	udav_txeof(c->udav_xfer, c, stat);
-
-	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-		udav_start(ifp);
-	splx(s);
-}
-
-Static void
-udav_stop_task(struct udav_softc *sc)
-{
-	udav_stop(GET_IFP(sc), 1);
+	return 0;
 }
 
 /* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
-Static void
-udav_stop(struct ifnet *ifp, int disable)
+static void
+udav_stop_cb(struct ifnet *ifp, int disable)
 {
-	struct udav_softc *sc = ifp->if_softc;
-	usbd_status err;
-	int i;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	ifp->if_timer = 0;
-
-	udav_reset(sc);
+	struct usbnet * const un = ifp->if_softc;
 
-	callout_stop(&sc->sc_stat_ch);
+	DPRINTF(("%s: %s: enter\n", device_xname(un->un_dev), __func__));
 
-	/* Stop transfers */
-	/* RX endpoint */
-	if (sc->sc_pipe_rx != NULL) {
-		err = usbd_abort_pipe(sc->sc_pipe_rx);
-		if (err)
-			printf("%s: abort rx pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-	}
-
-	/* TX endpoint */
-	if (sc->sc_pipe_tx != NULL) {
-		err = usbd_abort_pipe(sc->sc_pipe_tx);
-		if (err)
-			printf("%s: abort tx pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-	}
-
-#if 0
-	/* XXX: Interrupt endpoint is not yet supported!! */
-	/* Interrupt endpoint */
-	if (sc->sc_pipe_intr != NULL) {
-		err = usbd_abort_pipe(sc->sc_pipe_intr);
-		if (err)
-			printf("%s: abort intr pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-		err = usbd_close_pipe(sc->sc_pipe_intr);
-		if (err)
-			printf("%s: close intr pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-		sc->sc_pipe_intr = NULL;
-	}
-#endif
-
-	/* Free RX resources. */
-	for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
-		if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
-			m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
-			sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
-		}
-		if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
-			sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
-		}
-	}
-
-	/* Free TX resources. */
-	for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
-		if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
-			m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
-			sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
-		}
-		if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
-			sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
-		}
-	}
-
-	/* Close pipes */
-	/* RX endpoint */
-	if (sc->sc_pipe_rx != NULL) {
-		err = usbd_close_pipe(sc->sc_pipe_rx);
-		if (err)
-			printf("%s: close rx pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-		sc->sc_pipe_rx = NULL;
-	}
-
-	/* TX endpoint */
-	if (sc->sc_pipe_tx != NULL) {
-		err = usbd_close_pipe(sc->sc_pipe_tx);
-		if (err)
-			printf("%s: close tx pipe failed: %s\n",
-			       device_xname(sc->sc_dev), usbd_errstr(err));
-		sc->sc_pipe_tx = NULL;
-	}
-
-	if (!ISSET(sc->sc_flags, UDAV_NO_PHY))
-		sc->sc_link = 0;
-	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+	udav_reset(un);
 }
 
-/* Set media options */
-Static int
-udav_ifmedia_change(struct ifnet *ifp)
+static usbd_status
+udav_mii_read_reg(struct usbnet *un, int phy, int reg, uint16_t *val)
 {
-	struct udav_softc *sc = ifp->if_softc;
-
-	DPRINTF(("%s: %s: enter\n", device_xname(sc->sc_dev), __func__));
-
-	if (sc->sc_dying)
-		return 0;
-
-	return ether_mediachange(ifp);
-}
-
-Static void
-udav_tick(void *xsc)
-{
-	struct udav_softc *sc = xsc;
-
-	if (sc == NULL)
-		return;
-
-	DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev),
-			__func__));
-
-	if (sc->sc_dying)
-		return;
-
-	/* Perform periodic stuff in process context */
-	usb_add_task(sc->sc_udev, &sc->sc_tick_task,
-	    USB_TASKQ_DRIVER);
-}
-
-Static void
-udav_tick_task(void *xsc)
-{
-	struct udav_softc *sc = xsc;
-	struct ifnet *ifp;
-	struct mii_data *mii;
-	int s;
-
-	if (sc == NULL)
-		return;
-
-	DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev),
-			__func__));
-
-	if (sc->sc_dying)
-		return;
-
-	ifp = GET_IFP(sc);
-	mii = GET_MII(sc);
-
-	if (mii == NULL)
-		return;
-
-	s = splnet();
-
-	mii_tick(mii);
-	if (!sc->sc_link) {
-		mii_pollstat(mii);
-		if (mii->mii_media_status & IFM_ACTIVE &&
-		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
-			DPRINTF(("%s: %s: got link\n",
-				 device_xname(sc->sc_dev), __func__));
-			sc->sc_link++;
-			if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-				   udav_start(ifp);
-		}
-	}
-
-	callout_reset(&sc->sc_stat_ch, hz, udav_tick, sc);
-
-	splx(s);
-}
-
-/* Get exclusive access to the MII registers */
-Static void
-udav_lock_mii(struct udav_softc *sc)
-{
-	DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev),
-			__func__));
-
-	sc->sc_refcnt++;
-	mutex_enter(&sc->sc_mii_lock);
-}
-
-Static void
-udav_unlock_mii(struct udav_softc *sc)
-{
-	DPRINTFN(0xff, ("%s: %s: enter\n", device_xname(sc->sc_dev),
-		       __func__));
-
-	mutex_exit(&sc->sc_mii_lock);
-	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
-}
-
-Static int
-udav_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val)
-{
-	struct udav_softc *sc;
+	struct udav_softc *sc = usbnet_softc(un);
 	uint8_t data[2];
 
-	if (dev == NULL)
-		return -1;
-
-	sc = device_private(dev);
+	usbnet_isowned_mii(un);
 
 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
-		 device_xname(sc->sc_dev), __func__, phy, reg));
+		 device_xname(un->un_dev), __func__, phy, reg));
 
-	if (sc->sc_dying) {
+	if (un->un_dying) {
 #ifdef DIAGNOSTIC
-		printf("%s: %s: dying\n", device_xname(sc->sc_dev),
+		printf("%s: %s: dying\n", device_xname(un->un_dev),
 		       __func__);
 #endif
-		return -1;
+		return USBD_INVAL;
 	}
 
 	/* XXX: one PHY only for the internal PHY */
 	if (phy != 0) {
 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
-			 device_xname(sc->sc_dev), __func__, phy));
-		return -1;
+			 device_xname(un->un_dev), __func__, phy));
+		return USBD_INVAL;
 	}
 
-	udav_lock_mii(sc);
-
 	/* select internal PHY and set PHY register address */
 	udav_csr_write1(sc, UDAV_EPAR,
 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
@@ -1512,33 +829,28 @@ udav_miibus_readreg(device_t dev, int ph
 	/* retrieve the result from data registers */
 	udav_csr_read(sc, UDAV_EPDRL, data, 2);
 
-	udav_unlock_mii(sc);
-
 	*val = data[0] | (data[1] << 8);
 
 	DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04hx\n",
-		device_xname(sc->sc_dev), __func__, phy, reg, *val));
+		device_xname(un->un_dev), __func__, phy, reg, *val));
 
-	return 0;
+	return USBD_NORMAL_COMPLETION;
 }
 
-Static int
-udav_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
+static usbd_status
+udav_mii_write_reg(struct usbnet *un, int phy, int reg, uint16_t val)
 {
-	struct udav_softc *sc;
+	struct udav_softc *sc = usbnet_softc(un);
 	uint8_t data[2];
 
-	if (dev == NULL)
-		return -1;
-
-	sc = device_private(dev);
+	usbnet_isowned_mii(un);
 
 	DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x val=0x%04hx\n",
-		 device_xname(sc->sc_dev), __func__, phy, reg, val));
+		 device_xname(un->un_dev), __func__, phy, reg, val));
 
-	if (sc->sc_dying) {
+	if (un->un_dying) {
 #ifdef DIAGNOSTIC
-		printf("%s: %s: dying\n", device_xname(sc->sc_dev),
+		printf("%s: %s: dying\n", device_xname(un->un_dev),
 		       __func__);
 #endif
 		return -1;
@@ -1547,12 +859,10 @@ udav_miibus_writereg(device_t dev, int p
 	/* XXX: one PHY only for the internal PHY */
 	if (phy != 0) {
 		DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
-			 device_xname(sc->sc_dev), __func__, phy));
+			 device_xname(un->un_dev), __func__, phy));
 		return -1;
 	}
 
-	udav_lock_mii(sc);
-
 	/* select internal PHY and set PHY register address */
 	udav_csr_write1(sc, UDAV_EPAR,
 			UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
@@ -1570,20 +880,54 @@ udav_miibus_writereg(device_t dev, int p
 	/* end write command */
 	UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
 
-	udav_unlock_mii(sc);
-
-	return 0;
+	return USBD_NORMAL_COMPLETION;
 }
 
-Static void
-udav_miibus_statchg(struct ifnet *ifp)
+static void
+udav_mii_statchg(struct ifnet *ifp)
 {
-#ifdef UDAV_DEBUG
+	struct usbnet * const un = ifp->if_softc;
+	struct mii_data * const mii = usbnet_mii(un);
 
-	if (ifp == NULL)
+	DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__));
+
+	if (un->un_dying)
 		return;
 
-	DPRINTF(("%s: %s: enter\n", ifp->if_xname, __func__));
+	un->un_link = false;
+	if (mii->mii_media_status & IFM_ACTIVE &&
+	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
+		DPRINTF(("%s: %s: got link\n",
+			 device_xname(un->un_dev), __func__));
+		un->un_link = true;
+	}
+}
+
+MODULE(MODULE_CLASS_DRIVER, if_udav, "usbnet");
+
+#ifdef _MODULE
+#include "ioconf.c"
 #endif
-	/* Nothing to do */
+
+static int
+if_udav_modcmd(modcmd_t cmd, void *aux)
+{
+	int error = 0;
+
+	switch (cmd) {
+	case MODULE_CMD_INIT:
+#ifdef _MODULE
+		error = config_init_component(cfdriver_ioconf_udav,
+		    cfattach_ioconf_udav, cfdata_ioconf_udav);
+#endif
+		return error;
+	case MODULE_CMD_FINI:
+#ifdef _MODULE
+		error = config_fini_component(cfdriver_ioconf_udav,
+		    cfattach_ioconf_udav, cfdata_ioconf_udav);
+#endif
+		return error;
+	default:
+		return ENOTTY;
+	}
 }

Index: src/sys/dev/usb/if_udavreg.h
diff -u src/sys/dev/usb/if_udavreg.h:1.14 src/sys/dev/usb/if_udavreg.h:1.15
--- src/sys/dev/usb/if_udavreg.h:1.14	Thu Aug  1 00:10:22 2019
+++ src/sys/dev/usb/if_udavreg.h	Wed Aug  7 19:21:48 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_udavreg.h,v 1.14 2019/08/01 00:10:22 mrg Exp $	*/
+/*	$NetBSD: if_udavreg.h,v 1.15 2019/08/07 19:21:48 skrll Exp $	*/
 /*	$nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $	*/
 /*
  * Copyright (c) 2003
@@ -140,61 +140,3 @@
 #define	 UDAV_GPR_GEPIO2	(1<<2) /* General purpose 2 */
 #define	 UDAV_GPR_GEPIO1	(1<<1) /* General purpose 1 */
 #define	 UDAV_GPR_GEPIO0	(1<<0) /* General purpose 0 */
-
-#define	GET_IFP(sc)		(&(sc)->sc_ec.ec_if)
-#define	GET_MII(sc)		(&(sc)->sc_mii)
-
-struct udav_chain {
-	struct udav_softc	*udav_sc;
-	struct usbd_xfer	*udav_xfer;
-	char			*udav_buf;
-	struct mbuf		*udav_mbuf;
-};
-
-struct udav_cdata {
-	struct udav_chain	udav_tx_chain[UDAV_TX_LIST_CNT];
-	struct udav_chain	udav_rx_chain[UDAV_TX_LIST_CNT];
-#if 0
-	/* XXX: Interrupt Endpoint is not yet supported! */
-	struct udav_intrpkg	udav_ibuf;
-#endif
-	int			udav_tx_prod;
-	int			udav_tx_cnt;
-};
-
-struct udav_softc {
-	device_t		sc_dev;	/* base device */
-	struct usbd_device *	sc_udev;
-
-	/* USB */
-	struct usbd_interface *	sc_ctl_iface;
-	/* int			sc_ctl_iface_no; */
-	int			sc_bulkin_no; /* bulk in endpoint */
-	int			sc_bulkout_no; /* bulk out endpoint */
-	int			sc_intrin_no; /* intr in endpoint */
-	struct usbd_pipe *	sc_pipe_rx;
-	struct usbd_pipe *	sc_pipe_tx;
-	struct usbd_pipe *	sc_pipe_intr;
-	struct callout		sc_stat_ch;
-	u_int			sc_rx_errs;
-	/* u_int		sc_intr_errs; */
-	struct timeval		sc_rx_notice;
-
-	/* Ethernet */
-	struct ethercom		sc_ec; /* ethernet common */
-	struct mii_data		sc_mii;
-	kmutex_t		sc_mii_lock;
-	int			sc_link;
-#define	sc_media udav_mii.mii_media
-	krndsource_t	rnd_source;
-	struct udav_cdata	sc_cdata;
-
-	int                     sc_attached;
-	int			sc_dying;
-	int                     sc_refcnt;
-
-	struct usb_task		sc_tick_task;
-	struct usb_task		sc_stop_task;
-
-	uint16_t		sc_flags;
-};

Reply via email to