Module Name:    src
Committed By:   mrg
Date:           Fri Aug  9 06:38:39 UTC 2019

Modified Files:
        src/sys/dev/usb: TODO files.usb if_urndis.c

Log Message:
switch urndis(4) to usbnet.  thanks to maya@ for testing and helping
fix the few issues in the conversion.


To generate a diff of this commit:
cvs rdiff -u -r1.49 -r1.50 src/sys/dev/usb/TODO
cvs rdiff -u -r1.161 -r1.162 src/sys/dev/usb/files.usb
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/usb/if_urndis.c

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/TODO
diff -u src/sys/dev/usb/TODO:1.49 src/sys/dev/usb/TODO:1.50
--- src/sys/dev/usb/TODO:1.49	Fri Aug  9 02:56:51 2019
+++ src/sys/dev/usb/TODO	Fri Aug  9 06:38:39 2019
@@ -73,7 +73,7 @@ Factor out the common code from the Ethe
 	if_upl - patch available
 	if_ure - done
 	if_url - patch available
-	if_urndis - patch available, probably works
+	if_urndis - done
 
 Get rid of hcpriv.
 

Index: src/sys/dev/usb/files.usb
diff -u src/sys/dev/usb/files.usb:1.161 src/sys/dev/usb/files.usb:1.162
--- src/sys/dev/usb/files.usb:1.161	Wed Aug  7 19:21:48 2019
+++ src/sys/dev/usb/files.usb	Fri Aug  9 06:38:39 2019
@@ -1,4 +1,4 @@
-#	$NetBSD: files.usb,v 1.161 2019/08/07 19:21:48 skrll Exp $
+#	$NetBSD: files.usb,v 1.162 2019/08/09 06:38:39 mrg Exp $
 #
 # Config file and device description for machine-independent USB code.
 # Included by ports that need it.  Ports that use it must provide
@@ -528,7 +528,7 @@ attach	uyurex at uhidbus
 file	dev/usb/uyurex.c		uyurex
 
 # Microsoft RNDIS
-device	urndis: arp, ether, ifnet
+device	urndis: arp, ether, ifnet, usbnet
 attach	urndis at usbifif
 file	dev/usb/if_urndis.c		urndis
 

Index: src/sys/dev/usb/if_urndis.c
diff -u src/sys/dev/usb/if_urndis.c:1.25 src/sys/dev/usb/if_urndis.c:1.26
--- src/sys/dev/usb/if_urndis.c:1.25	Thu Aug  8 18:03:40 2019
+++ src/sys/dev/usb/if_urndis.c	Fri Aug  9 06:38:39 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urndis.c,v 1.25 2019/08/08 18:03:40 mrg Exp $ */
+/*	$NetBSD: if_urndis.c,v 1.26 2019/08/09 06:38:39 mrg Exp $ */
 /*	$OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */
 
 /*
@@ -21,7 +21,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.25 2019/08/08 18:03:40 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.26 2019/08/09 06:38:39 mrg Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -29,28 +29,10 @@ __KERNEL_RCSID(0, "$NetBSD: if_urndis.c,
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/sockio.h>
-#include <sys/rwlock.h>
-#include <sys/mbuf.h>
 #include <sys/kmem.h>
 #include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/device.h>
-#include <sys/endian.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_ether.h>
-
-#include <net/bpf.h>
-
-#include <sys/bus.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdi_util.h>
-#include <dev/usb/usbdivar.h>
+
+#include <dev/usb/usbnet.h>
 #include <dev/usb/usbdevs.h>
 #include <dev/usb/usbcdc.h>
 
@@ -60,48 +42,16 @@ __KERNEL_RCSID(0, "$NetBSD: if_urndis.c,
 #define RNDIS_TX_LIST_CNT	1
 #define RNDIS_BUFSZ		1562
 
-struct urndis_softc;
-
-struct urndis_chain {
-	struct urndis_softc	*sc_softc;
-	struct usbd_xfer	*sc_xfer;
-	char			*sc_buf;
-	struct mbuf		*sc_mbuf;
-};
-
-struct urndis_cdata {
-	struct urndis_chain	sc_rx_chain[RNDIS_RX_LIST_CNT];
-	struct urndis_chain	sc_tx_chain[RNDIS_TX_LIST_CNT];
-	int			sc_tx_cnt;
-};
-
-#define GET_IFP(sc) (&(sc)->sc_ec.ec_if)
 struct urndis_softc {
-	device_t			sc_dev;
+	struct usbnet			sc_un;
 
-	char				sc_attached;
-	int				sc_dying;
-	struct ethercom			sc_ec;
+	int				sc_ifaceno_ctl;
 
 	/* RNDIS device info */
 	uint32_t			sc_filter;
 	uint32_t			sc_maxppt;
 	uint32_t			sc_maxtsz;
 	uint32_t			sc_palign;
-
-	/* USB goo */
-	struct usbd_device *		sc_udev;
-	int				sc_ifaceno_ctl;
-	struct usbd_interface *		sc_iface_ctl;
-	struct usbd_interface *		sc_iface_data;
-
-	struct timeval			sc_rx_notice;
-	int				sc_bulkin_no;
-	struct usbd_pipe *		sc_bulkin_pipe;
-	int				sc_bulkout_no;
-	struct usbd_pipe *		sc_bulkout_pipe;
-
-	struct urndis_cdata		sc_data;
 };
 
 #ifdef URNDIS_DEBUG
@@ -110,69 +60,45 @@ struct urndis_softc {
 #define DPRINTF(x)
 #endif
 
-#define DEVNAME(sc)	(device_xname(sc->sc_dev))
+#define DEVNAME(un)	(device_xname(un->un_dev))
 
 #define URNDIS_RESPONSE_LEN 0x400
 
-
-static int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
-
-static int urndis_ioctl(struct ifnet *, unsigned long, void *);
 #if 0
 static void urndis_watchdog(struct ifnet *);
 #endif
 
-static void urndis_start(struct ifnet *);
-static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status);
-static void urndis_txeof(struct usbd_xfer *, void *, usbd_status);
-static int urndis_rx_list_init(struct urndis_softc *);
-static int urndis_tx_list_init(struct urndis_softc *);
-
 static int urndis_init(struct ifnet *);
-static void urndis_stop(struct ifnet *);
+static void urndis_rx_loop(struct usbnet *, struct usbd_xfer *,
+			   struct usbnet_chain *, uint32_t);
+static unsigned urndis_tx_prepare(struct usbnet *, struct mbuf *,
+				  struct usbnet_chain *);
+
+static int urndis_init_un(struct ifnet *, struct usbnet *);
 
-static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
-    uint16_t, uint16_t, void *, size_t);
-static usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
-static struct rndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
-
-static uint32_t urndis_ctrl_handle(struct urndis_softc *,
-    struct rndis_comp_hdr *, void **, size_t *);
-static uint32_t urndis_ctrl_handle_init(struct urndis_softc *,
+static uint32_t urndis_ctrl_handle_init(struct usbnet *,
     const struct rndis_comp_hdr *);
-static uint32_t urndis_ctrl_handle_query(struct urndis_softc *,
+static uint32_t urndis_ctrl_handle_query(struct usbnet *,
     const struct rndis_comp_hdr *, void **, size_t *);
-static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *,
+static uint32_t urndis_ctrl_handle_reset(struct usbnet *,
     const struct rndis_comp_hdr *);
-static uint32_t urndis_ctrl_handle_status(struct urndis_softc *,
+static uint32_t urndis_ctrl_handle_status(struct usbnet *,
     const struct rndis_comp_hdr *);
 
-static uint32_t urndis_ctrl_init(struct urndis_softc *);
-#if 0
-static uint32_t urndis_ctrl_halt(struct urndis_softc *);
-#endif
-static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, void *,
-    size_t, void **, size_t *);
-static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, void *,
+static uint32_t urndis_ctrl_set(struct usbnet *, uint32_t, void *,
     size_t);
-#if 0
-static uint32_t urndis_ctrl_set_param(struct urndis_softc *, const char *,
-    uint32_t, void *, size_t);
-static uint32_t urndis_ctrl_reset(struct urndis_softc *);
-static uint32_t urndis_ctrl_keepalive(struct urndis_softc *);
-#endif
-
-static int urndis_encap(struct urndis_softc *, struct mbuf *, int);
-static void urndis_decap(struct urndis_softc *, struct urndis_chain *,
-    uint32_t);
 
 static int urndis_match(device_t, cfdata_t, void *);
 static void urndis_attach(device_t, device_t, void *);
-static int urndis_detach(device_t, int);
-static int urndis_activate(device_t, enum devact);
+
+static struct usbnet_ops urndis_ops = {
+	.uno_init = urndis_init,
+	.uno_tx_prepare = urndis_tx_prepare,
+	.uno_rx_loop = urndis_rx_loop,
+};
 
 CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc),
-    urndis_match, urndis_attach, urndis_detach, urndis_activate);
+    urndis_match, urndis_attach, usbnet_detach, usbnet_activate);
 
 /*
  * Supported devices that we can't match by class IDs.
@@ -184,7 +110,7 @@ static const struct usb_devno urndis_dev
 };
 
 static usbd_status
-urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
+urndis_ctrl_msg(struct usbnet *un, uint8_t rt, uint8_t r,
     uint16_t index, uint16_t value, void *buf, size_t buflen)
 {
 	usb_device_request_t req;
@@ -195,52 +121,57 @@ urndis_ctrl_msg(struct urndis_softc *sc,
 	USETW(req.wIndex, index);
 	USETW(req.wLength, buflen);
 
-	return usbd_do_request(sc->sc_udev, &req, buf);
+	return usbd_do_request(un->un_udev, &req, buf);
 }
 
 static usbd_status
-urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
+urndis_ctrl_send(struct usbnet *un, void *buf, size_t len)
 {
+	struct urndis_softc	*sc = usbnet_softc(un);
 	usbd_status err;
 
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return(0);
 
-	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
+	err = urndis_ctrl_msg(un, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
 	    sc->sc_ifaceno_ctl, 0, buf, len);
 
 	if (err != USBD_NORMAL_COMPLETION)
-		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
+		printf("%s: %s\n", DEVNAME(un), usbd_errstr(err));
 
 	return err;
 }
 
 static struct rndis_comp_hdr *
-urndis_ctrl_recv(struct urndis_softc *sc)
+urndis_ctrl_recv(struct usbnet *un)
 {
+	struct urndis_softc	*sc = usbnet_softc(un);
 	struct rndis_comp_hdr	*hdr;
 	char			*buf;
 	usbd_status		 err;
 
+	if (un->un_dying)
+		return(0);
+
 	buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP);
-	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
+	err = urndis_ctrl_msg(un, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
 	    sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN);
 
 	if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
-		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
+		printf("%s: %s\n", DEVNAME(un), usbd_errstr(err));
 		kmem_free(buf, URNDIS_RESPONSE_LEN);
 		return NULL;
 	}
 
 	hdr = (struct rndis_comp_hdr *)buf;
 	DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(hdr->rm_type),
 	    le32toh(hdr->rm_len)));
 
 	if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) {
 		printf("%s: ctrl message error: wrong size %u > %u\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(hdr->rm_len),
 		    URNDIS_RESPONSE_LEN);
 		kmem_free(buf, URNDIS_RESPONSE_LEN);
@@ -251,12 +182,12 @@ urndis_ctrl_recv(struct urndis_softc *sc
 }
 
 static uint32_t
-urndis_ctrl_handle(struct urndis_softc *sc, struct rndis_comp_hdr *hdr,
+urndis_ctrl_handle(struct usbnet *un, struct rndis_comp_hdr *hdr,
     void **buf, size_t *bufsz)
 {
 	uint32_t rval;
 
-	DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
+	DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(un)));
 
 	if (buf && bufsz) {
 		*buf = NULL;
@@ -265,15 +196,15 @@ urndis_ctrl_handle(struct urndis_softc *
 
 	switch (le32toh(hdr->rm_type)) {
 		case REMOTE_NDIS_INITIALIZE_CMPLT:
-			rval = urndis_ctrl_handle_init(sc, hdr);
+			rval = urndis_ctrl_handle_init(un, hdr);
 			break;
 
 		case REMOTE_NDIS_QUERY_CMPLT:
-			rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
+			rval = urndis_ctrl_handle_query(un, hdr, buf, bufsz);
 			break;
 
 		case REMOTE_NDIS_RESET_CMPLT:
-			rval = urndis_ctrl_handle_reset(sc, hdr);
+			rval = urndis_ctrl_handle_reset(un, hdr);
 			break;
 
 		case REMOTE_NDIS_KEEPALIVE_CMPLT:
@@ -282,12 +213,12 @@ urndis_ctrl_handle(struct urndis_softc *
 			break;
 
 		case REMOTE_NDIS_INDICATE_STATUS_MSG:
-			rval = urndis_ctrl_handle_status(sc, hdr);
+			rval = urndis_ctrl_handle_status(un, hdr);
 			break;
 
 		default:
 			printf("%s: ctrl message error: unknown event 0x%x\n",
-			    DEVNAME(sc), le32toh(hdr->rm_type));
+			    DEVNAME(un), le32toh(hdr->rm_type));
 			rval = RNDIS_STATUS_FAILURE;
 	}
 
@@ -297,9 +228,9 @@ urndis_ctrl_handle(struct urndis_softc *
 }
 
 static uint32_t
-urndis_ctrl_handle_init(struct urndis_softc *sc,
-    const struct rndis_comp_hdr *hdr)
+urndis_ctrl_handle_init(struct usbnet *un, const struct rndis_comp_hdr *hdr)
 {
+	struct urndis_softc		*sc = usbnet_softc(un);
 	const struct rndis_init_comp	*msg;
 
 	msg = (const struct rndis_init_comp *) hdr;
@@ -307,7 +238,7 @@ urndis_ctrl_handle_init(struct urndis_so
 	DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
 	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
 	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid),
 	    le32toh(msg->rm_status),
@@ -323,7 +254,7 @@ urndis_ctrl_handle_init(struct urndis_so
 
 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
 		printf("%s: init failed 0x%x\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(msg->rm_status));
 
 		return le32toh(msg->rm_status);
@@ -331,7 +262,7 @@ urndis_ctrl_handle_init(struct urndis_so
 
 	if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
 		printf("%s: wrong device type (current type: 0x%x)\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(msg->rm_devflags));
 
 		return RNDIS_STATUS_FAILURE;
@@ -339,7 +270,7 @@ urndis_ctrl_handle_init(struct urndis_so
 
 	if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
 		printf("%s: medium not 802.3 (current medium: 0x%x)\n",
-		    DEVNAME(sc), le32toh(msg->rm_medium));
+		    DEVNAME(un), le32toh(msg->rm_medium));
 
 		return RNDIS_STATUS_FAILURE;
 	}
@@ -347,7 +278,7 @@ urndis_ctrl_handle_init(struct urndis_so
 	if (le32toh(msg->rm_ver_major) != RNDIS_MAJOR_VERSION ||
 	    le32toh(msg->rm_ver_minor) != RNDIS_MINOR_VERSION) {
 		printf("%s: version not %u.%u (current version: %u.%u)\n",
-		    DEVNAME(sc), RNDIS_MAJOR_VERSION, RNDIS_MINOR_VERSION,
+		    DEVNAME(un), RNDIS_MAJOR_VERSION, RNDIS_MINOR_VERSION,
 		    le32toh(msg->rm_ver_major), le32toh(msg->rm_ver_minor));
 
 		return RNDIS_STATUS_FAILURE;
@@ -361,7 +292,7 @@ urndis_ctrl_handle_init(struct urndis_so
 }
 
 static uint32_t
-urndis_ctrl_handle_query(struct urndis_softc *sc,
+urndis_ctrl_handle_query(struct usbnet *un,
     const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz)
 {
 	const struct rndis_query_comp	*msg;
@@ -370,7 +301,7 @@ urndis_ctrl_handle_query(struct urndis_s
 
 	DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
 	    "buflen %u bufoff %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid),
 	    le32toh(msg->rm_status),
@@ -384,7 +315,7 @@ urndis_ctrl_handle_query(struct urndis_s
 
 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
 		printf("%s: query failed 0x%x\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(msg->rm_status));
 
 		return le32toh(msg->rm_status);
@@ -395,7 +326,7 @@ urndis_ctrl_handle_query(struct urndis_s
 		printf("%s: ctrl message error: invalid query info "
 		    "len/offset/end_position(%u/%u/%u) -> "
 		    "go out of buffer limit %u\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(msg->rm_infobuflen),
 		    le32toh(msg->rm_infobufoffset),
 		    le32toh(msg->rm_infobuflen) +
@@ -419,9 +350,9 @@ urndis_ctrl_handle_query(struct urndis_s
 }
 
 static uint32_t
-urndis_ctrl_handle_reset(struct urndis_softc *sc,
-    const struct rndis_comp_hdr *hdr)
+urndis_ctrl_handle_reset(struct usbnet *un, const struct rndis_comp_hdr *hdr)
 {
+	struct urndis_softc		*sc = usbnet_softc(un);
 	const struct rndis_reset_comp	*msg;
 	uint32_t			 rval;
 
@@ -431,13 +362,13 @@ urndis_ctrl_handle_reset(struct urndis_s
 
 	DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
 	    "adrreset %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_len),
 	    rval,
 	    le32toh(msg->rm_adrreset)));
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval);
+		printf("%s: reset failed 0x%x\n", DEVNAME(un), rval);
 		return rval;
 	}
 
@@ -445,11 +376,11 @@ urndis_ctrl_handle_reset(struct urndis_s
 		uint32_t filter;
 
 		filter = htole32(sc->sc_filter);
-		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+		rval = urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER,
 		    &filter, sizeof(filter));
 		if (rval != RNDIS_STATUS_SUCCESS) {
 			printf("%s: unable to reset data filters\n",
-			    DEVNAME(sc));
+			    DEVNAME(un));
 			return rval;
 		}
 	}
@@ -458,7 +389,7 @@ urndis_ctrl_handle_reset(struct urndis_s
 }
 
 static uint32_t
-urndis_ctrl_handle_status(struct urndis_softc *sc,
+urndis_ctrl_handle_status(struct usbnet *un,
     const struct rndis_comp_hdr *hdr)
 {
 	const struct rndis_status_msg	*msg;
@@ -470,7 +401,7 @@ urndis_ctrl_handle_status(struct urndis_
 
 	DPRINTF(("%s: urndis_ctrl_handle_status: len %u status 0x%x "
 	    "stbuflen %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_len),
 	    rval,
 	    le32toh(msg->rm_stbuflen)));
@@ -483,14 +414,14 @@ urndis_ctrl_handle_status(struct urndis_
 			break;
 
 		default:
-		        printf("%s: status 0x%x\n", DEVNAME(sc), rval);
+		        printf("%s: status 0x%x\n", DEVNAME(un), rval);
 	}
 
 	return rval;
 }
 
 static uint32_t
-urndis_ctrl_init(struct urndis_softc *sc)
+urndis_ctrl_init(struct usbnet *un)
 {
 	struct rndis_init_req	*msg;
 	uint32_t		 rval;
@@ -506,7 +437,7 @@ urndis_ctrl_init(struct urndis_softc *sc
 
 	DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
 	    "ver_minor %u max_xfersz %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_type),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid),
@@ -514,26 +445,26 @@ urndis_ctrl_init(struct urndis_softc *sc
 	    le32toh(msg->rm_ver_minor),
 	    le32toh(msg->rm_max_xfersz)));
 
-	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
+	rval = urndis_ctrl_send(un, msg, sizeof(*msg));
 	kmem_free(msg, sizeof(*msg));
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: init failed\n", DEVNAME(sc));
+		printf("%s: init failed\n", DEVNAME(un));
 		return rval;
 	}
 
-	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
-		printf("%s: unable to get init response\n", DEVNAME(sc));
+	if ((hdr = urndis_ctrl_recv(un)) == NULL) {
+		printf("%s: unable to get init response\n", DEVNAME(un));
 		return RNDIS_STATUS_FAILURE;
 	}
-	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+	rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
 
 	return rval;
 }
 
 #if 0
 static uint32_t
-urndis_ctrl_halt(struct urndis_softc *sc)
+urndis_ctrl_halt(struct usbnet *un)
 {
 	struct rndis_halt_req	*msg;
 	uint32_t		 rval;
@@ -544,23 +475,23 @@ urndis_ctrl_halt(struct urndis_softc *sc
 	msg->rm_rid = 0;
 
 	DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_type),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid)));
 
-	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
+	rval = urndis_ctrl_send(un, msg, sizeof(*msg));
 	kmem_free(msg, sizeof(*msg));
 
 	if (rval != RNDIS_STATUS_SUCCESS)
-		printf("%s: halt failed\n", DEVNAME(sc));
+		printf("%s: halt failed\n", DEVNAME(un));
 
 	return rval;
 }
 #endif
 
 static uint32_t
-urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
+urndis_ctrl_query(struct usbnet *un, uint32_t oid,
     void *qbuf, size_t qlen,
     void **rbuf, size_t *rbufsz)
 {
@@ -583,7 +514,7 @@ urndis_ctrl_query(struct urndis_softc *s
 
 	DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_type),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid),
@@ -592,25 +523,25 @@ urndis_ctrl_query(struct urndis_softc *s
 	    le32toh(msg->rm_infobufoffset),
 	    le32toh(msg->rm_devicevchdl)));
 
-	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
+	rval = urndis_ctrl_send(un, msg, sizeof(*msg));
 	kmem_free(msg, sizeof(*msg) + qlen);
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: query failed\n", DEVNAME(sc));
+		printf("%s: query failed\n", DEVNAME(un));
 		return rval;
 	}
 
-	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
-		printf("%s: unable to get query response\n", DEVNAME(sc));
+	if ((hdr = urndis_ctrl_recv(un)) == NULL) {
+		printf("%s: unable to get query response\n", DEVNAME(un));
 		return RNDIS_STATUS_FAILURE;
 	}
-	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
+	rval = urndis_ctrl_handle(un, hdr, rbuf, rbufsz);
 
 	return rval;
 }
 
 static uint32_t
-urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, void *buf, size_t len)
+urndis_ctrl_set(struct usbnet *un, uint32_t oid, void *buf, size_t len)
 {
 	struct rndis_set_req	*msg;
 	uint32_t		 rval;
@@ -631,7 +562,7 @@ urndis_ctrl_set(struct urndis_softc *sc,
 
 	DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(msg->rm_type),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_rid),
@@ -640,28 +571,28 @@ urndis_ctrl_set(struct urndis_softc *sc,
 	    le32toh(msg->rm_infobufoffset),
 	    le32toh(msg->rm_devicevchdl)));
 
-	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
+	rval = urndis_ctrl_send(un, msg, sizeof(*msg));
 	kmem_free(msg, sizeof(*msg) + len);
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: set failed\n", DEVNAME(sc));
+		printf("%s: set failed\n", DEVNAME(un));
 		return rval;
 	}
 
-	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
-		printf("%s: unable to get set response\n", DEVNAME(sc));
+	if ((hdr = urndis_ctrl_recv(un)) == NULL) {
+		printf("%s: unable to get set response\n", DEVNAME(un));
 		return RNDIS_STATUS_FAILURE;
 	}
-	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+	rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
 	if (rval != RNDIS_STATUS_SUCCESS)
-		printf("%s: set failed 0x%x\n", DEVNAME(sc), rval);
+		printf("%s: set failed 0x%x\n", DEVNAME(un), rval);
 
 	return rval;
 }
 
 #if 0
 static uint32_t
-urndis_ctrl_set_param(struct urndis_softc *sc,
+urndis_ctrl_set_param(struct urndis_softc *un,
     const char *name,
     uint32_t type,
     void *buf,
@@ -693,24 +624,24 @@ urndis_ctrl_set_param(struct urndis_soft
 
 	DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
 	    "type 0x%x valueoffset %u valuelen %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(param->rm_nameoffset),
 	    le32toh(param->rm_namelen),
 	    le32toh(param->rm_type),
 	    le32toh(param->rm_valueoffset),
 	    le32toh(param->rm_valuelen)));
 
-	rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
+	rval = urndis_ctrl_set(un, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
 	kmem_free(param, tlen);
 	if (rval != RNDIS_STATUS_SUCCESS)
-		printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval);
+		printf("%s: set param failed 0x%x\n", DEVNAME(un), rval);
 
 	return rval;
 }
 
 /* XXX : adrreset, get it from response */
 static uint32_t
-urndis_ctrl_reset(struct urndis_softc *sc)
+urndis_ctrl_reset(struct usbnet *un)
 {
 	struct rndis_reset_req		*reset;
 	uint32_t			 rval;
@@ -722,30 +653,30 @@ urndis_ctrl_reset(struct urndis_softc *s
 	reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
 
 	DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(reset->rm_type),
 	    le32toh(reset->rm_len),
 	    le32toh(reset->rm_rid)));
 
-	rval = urndis_ctrl_send(sc, reset, sizeof(*reset));
+	rval = urndis_ctrl_send(un, reset, sizeof(*reset));
 	kmem_free(reset, sizeof(*reset));
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: reset failed\n", DEVNAME(sc));
+		printf("%s: reset failed\n", DEVNAME(un));
 		return rval;
 	}
 
-	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
-		printf("%s: unable to get reset response\n", DEVNAME(sc));
+	if ((hdr = urndis_ctrl_recv(un)) == NULL) {
+		printf("%s: unable to get reset response\n", DEVNAME(un));
 		return RNDIS_STATUS_FAILURE;
 	}
-	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+	rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
 
 	return rval;
 }
 
 static uint32_t
-urndis_ctrl_keepalive(struct urndis_softc *sc)
+urndis_ctrl_keepalive(struct usbnet *un)
 {
 	struct rndis_keepalive_req	*keep;
 	uint32_t			 rval;
@@ -757,43 +688,39 @@ urndis_ctrl_keepalive(struct urndis_soft
 	keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
 
 	DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
-	    DEVNAME(sc),
+	    DEVNAME(un),
 	    le32toh(keep->rm_type),
 	    le32toh(keep->rm_len),
 	    le32toh(keep->rm_rid)));
 
-	rval = urndis_ctrl_send(sc, keep, sizeof(*keep));
+	rval = urndis_ctrl_send(un, keep, sizeof(*keep));
 	kmem_free(keep, sizeof(*keep));
 
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: keepalive failed\n", DEVNAME(sc));
+		printf("%s: keepalive failed\n", DEVNAME(un));
 		return rval;
 	}
 
-	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
-		printf("%s: unable to get keepalive response\n", DEVNAME(sc));
+	if ((hdr = urndis_ctrl_recv(un)) == NULL) {
+		printf("%s: unable to get keepalive response\n", DEVNAME(un));
 		return RNDIS_STATUS_FAILURE;
 	}
-	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
+	rval = urndis_ctrl_handle(un, hdr, NULL, NULL);
 	if (rval != RNDIS_STATUS_SUCCESS) {
-		printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval);
-		urndis_ctrl_reset(sc);
+		printf("%s: keepalive failed 0x%x\n", DEVNAME(un), rval);
+		urndis_ctrl_reset(un);
 	}
 
 	return rval;
 }
 #endif
 
-static int
-urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx)
+static unsigned
+urndis_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
 {
-	struct urndis_chain		*c;
-	usbd_status			 err;
 	struct rndis_packet_msg		*msg;
 
-	c = &sc->sc_data.sc_tx_chain[idx];
-
-	msg = (struct rndis_packet_msg *)c->sc_buf;
+	msg = (struct rndis_packet_msg *)c->unc_buf;
 
 	memset(msg, 0, sizeof(*msg));
 	msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
@@ -805,61 +732,45 @@ urndis_encap(struct urndis_softc *sc, st
 	m_copydata(m, 0, m->m_pkthdr.len,
 	    ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
 
-	DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
-	    DEVNAME(sc),
+	DPRINTF(("%s: %s type 0x%x len %u data(off %u len %u)\n",
+	    __func__,
+	    DEVNAME(un),
 	    le32toh(msg->rm_type),
 	    le32toh(msg->rm_len),
 	    le32toh(msg->rm_dataoffset),
 	    le32toh(msg->rm_datalen)));
 
-	c->sc_mbuf = m;
-
-	usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, le32toh(msg->rm_len),
-	    USBD_FORCE_SHORT_XFER, 10000, urndis_txeof);
-
-	/* Transmit */
-	err = usbd_transfer(c->sc_xfer);
-	if (err != USBD_IN_PROGRESS) {
-		urndis_stop(GET_IFP(sc));
-		return(EIO);
-	}
-
-	sc->sc_data.sc_tx_cnt++;
-
-	return(0);
+	return le32toh(msg->rm_len);
 }
 
 static void
-urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, uint32_t len)
+urndis_rx_loop(struct usbnet * un, struct usbd_xfer *xfer,
+	       struct usbnet_chain *c, uint32_t total_len)
 {
-	struct mbuf		*m;
 	struct rndis_packet_msg	*msg;
-	struct ifnet		*ifp;
-	int			 s;
+	struct ifnet		*ifp = usbnet_ifp(un);
 	int			 offset;
 
-	ifp = GET_IFP(sc);
 	offset = 0;
 
-	while (len > 1) {
-		msg = (struct rndis_packet_msg *)((char*)c->sc_buf + offset);
-		m = c->sc_mbuf;
+	while (total_len > 1) {
+		msg = (struct rndis_packet_msg *)((char*)c->unc_buf + offset);
 
-		DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc),
-		    len));
+		DPRINTF(("%s: %s buffer size left %u\n", DEVNAME(un), __func__,
+		    total_len));
 
-		if (len < sizeof(*msg)) {
-			printf("%s: urndis_decap invalid buffer len %u < "
+		if (total_len < sizeof(*msg)) {
+			printf("%s: urndis_decap invalid buffer total_len %u < "
 			    "minimum header %zu\n",
-			    DEVNAME(sc),
-			    len,
+			    DEVNAME(un),
+			    total_len,
 			    sizeof(*msg));
 			return;
 		}
 
-		DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) "
+		DPRINTF(("%s: urndis_decap total_len %u data(off:%u len:%u) "
 		    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
-		    DEVNAME(sc),
+		    DEVNAME(un),
 		    le32toh(msg->rm_len),
 		    le32toh(msg->rm_dataoffset),
 		    le32toh(msg->rm_datalen),
@@ -871,24 +782,24 @@ urndis_decap(struct urndis_softc *sc, st
 
 		if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
 			printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
-			    DEVNAME(sc),
+			    DEVNAME(un),
 			    le32toh(msg->rm_type),
 			    REMOTE_NDIS_PACKET_MSG);
 			return;
 		}
 		if (le32toh(msg->rm_len) < sizeof(*msg)) {
 			printf("%s: urndis_decap invalid msg len %u < %zu\n",
-			    DEVNAME(sc),
+			    DEVNAME(un),
 			    le32toh(msg->rm_len),
 			    sizeof(*msg));
 			return;
 		}
-		if (le32toh(msg->rm_len) > len) {
+		if (le32toh(msg->rm_len) > total_len) {
 			printf("%s: urndis_decap invalid msg len %u > buffer "
-			    "len %u\n",
-			    DEVNAME(sc),
+			    "total_len %u\n",
+			    DEVNAME(un),
 			    le32toh(msg->rm_len),
-			    len);
+			    total_len);
 			return;
 		}
 
@@ -898,7 +809,7 @@ urndis_decap(struct urndis_softc *sc, st
 			printf("%s: urndis_decap invalid data "
 			    "len/offset/end_position(%u/%u/%u) -> "
 			    "go out of receive buffer limit %u\n",
-			    DEVNAME(sc),
+			    DEVNAME(un),
 			    le32toh(msg->rm_datalen),
 			    le32toh(msg->rm_dataoffset),
 			    le32toh(msg->rm_dataoffset) +
@@ -911,435 +822,69 @@ urndis_decap(struct urndis_softc *sc, st
 			ifp->if_ierrors++;
 			printf("%s: urndis_decap invalid ethernet size "
 			    "%d < %zu\n",
-			    DEVNAME(sc),
+			    DEVNAME(un),
 			    le32toh(msg->rm_datalen),
 			    sizeof(struct ether_header));
 			return;
 		}
 
-		memcpy(mtod(m, char*),
+		usbnet_enqueue(un,
 		    ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)),
-		    le32toh(msg->rm_datalen));
-		m->m_pkthdr.len = m->m_len = le32toh(msg->rm_datalen);
-
-		m_set_rcvif(m, ifp);
-
-		s = splnet();
-
-		if (urndis_newbuf(sc, c) == ENOBUFS) {
-			ifp->if_ierrors++;
-		} else {
-			if_percpuq_enqueue(ifp->if_percpuq, m);
-		}
-		splx(s);
+		    le32toh(msg->rm_datalen), 0, 0, 0);
 
 		offset += le32toh(msg->rm_len);
-		len -= le32toh(msg->rm_len);
-	}
-}
-
-static int
-urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c)
-{
-	struct mbuf *m_new = NULL;
-
-	MGETHDR(m_new, M_DONTWAIT, MT_DATA);
-	if (m_new == NULL) {
-		printf("%s: no memory for rx list -- packet dropped!\n",
-		    DEVNAME(sc));
-		return ENOBUFS;
-	}
-	MCLGET(m_new, M_DONTWAIT);
-	if (!(m_new->m_flags & M_EXT)) {
-		printf("%s: no memory for rx list -- packet dropped!\n",
-		    DEVNAME(sc));
-		m_freem(m_new);
-		return ENOBUFS;
-	}
-	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
-
-	m_adj(m_new, ETHER_ALIGN);
-	c->sc_mbuf = m_new;
-	return 0;
-}
-
-static int
-urndis_rx_list_init(struct urndis_softc *sc)
-{
-	struct urndis_cdata	*cd;
-	struct urndis_chain	*c;
-	int			 i;
-
-	cd = &sc->sc_data;
-	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
-		c = &cd->sc_rx_chain[i];
-		c->sc_softc = sc;
-
-		if (urndis_newbuf(sc, c) == ENOBUFS)
-			return ENOBUFS;
-
-		if (c->sc_xfer == NULL) {
-			int err = usbd_create_xfer(sc->sc_bulkin_pipe,
-			    RNDIS_BUFSZ, 0, 0, &c->sc_xfer);
-			if (err)
-				return err;
-			c->sc_buf = usbd_get_buffer(c->sc_xfer);
-		}
-	}
-
-	return 0;
-}
-
-static int
-urndis_tx_list_init(struct urndis_softc *sc)
-{
-	struct urndis_cdata	*cd;
-	struct urndis_chain	*c;
-	int			 i;
-
-	cd = &sc->sc_data;
-	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
-		c = &cd->sc_tx_chain[i];
-		c->sc_softc = sc;
-		c->sc_mbuf = NULL;
-		if (c->sc_xfer == NULL) {
-			int err = usbd_create_xfer(sc->sc_bulkout_pipe,
-			    RNDIS_BUFSZ, USBD_FORCE_SHORT_XFER, 0, &c->sc_xfer);
-			if (err)
-				return err;
-			c->sc_buf = usbd_get_buffer(c->sc_xfer);
-		}
-	}
-	return 0;
-}
-
-static int
-urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data)
-{
-	struct urndis_softc	*sc;
-	int			 s, error;
-
-	sc = ifp->if_softc;
-	error = 0;
-
-	if (sc->sc_dying)
-		return EIO;
-
-	s = splnet();
-
-	switch(command) {
-	case SIOCSIFFLAGS:
-		if ((error = ifioctl_common(ifp, command, data)) != 0)
-			break;
-		if (ifp->if_flags & IFF_UP) {
-			if (!(ifp->if_flags & IFF_RUNNING))
-				urndis_init(ifp);
-		} else {
-			if (ifp->if_flags & IFF_RUNNING)
-				urndis_stop(ifp);
-		}
-		error = 0;
-		break;
-
-	default:
-		error = ether_ioctl(ifp, command, data);
-		break;
+		total_len -= le32toh(msg->rm_len);
 	}
-
-	if (error == ENETRESET)
-		error = 0;
-
-	splx(s);
-	return error;
 }
 
 #if 0
 static void
 urndis_watchdog(struct ifnet *ifp)
 {
-	struct urndis_softc *sc;
+	struct urndis_softc	*sc = usbnet_softc(un);
 
-	sc = ifp->if_softc;
-
-	if (sc->sc_dying)
+	if (un->un_dying)
 		return;
 
 	ifp->if_oerrors++;
-	printf("%s: watchdog timeout\n", DEVNAME(sc));
+	printf("%s: watchdog timeout\n", DEVNAME(un));
 
-	urndis_ctrl_keepalive(sc);
+	urndis_ctrl_keepalive(un);
 }
 #endif
 
 static int
-urndis_init(struct ifnet *ifp)
+urndis_init_un(struct ifnet *ifp, struct usbnet *un)
 {
-	struct urndis_softc	*sc;
-	int			 i, s;
 	int 			 err;
-	usbd_status		 usberr;
-
-	sc = ifp->if_softc;
 
 	if (ifp->if_flags & IFF_RUNNING)
 		return 0;
 
-	err = urndis_ctrl_init(sc);
+	err = urndis_ctrl_init(un);
 	if (err != RNDIS_STATUS_SUCCESS)
 		return EIO;
 
-	s = splnet();
-
-	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
-	    USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
-	if (usberr) {
-		printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
-		    usbd_errstr(err));
-		splx(s);
-		return EIO;
-	}
-
-	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
-	    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
-	if (usberr) {
-		printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
-		    usbd_errstr(err));
-		splx(s);
-		return EIO;
-	}
-
-	err = urndis_tx_list_init(sc);
-	if (err) {
-		printf("%s: tx list init failed\n",
-		    DEVNAME(sc));
-		splx(s);
-		return err;
-	}
-
-	err = urndis_rx_list_init(sc);
-	if (err) {
-		printf("%s: rx list init failed\n",
-		    DEVNAME(sc));
-		splx(s);
-		return err;
-	}
-
-	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
-		struct urndis_chain *c;
-
-		c = &sc->sc_data.sc_rx_chain[i];
-
-		usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ,
-		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof);
-		usbd_transfer(c->sc_xfer);
-	}
-
-	ifp->if_flags |= IFF_RUNNING;
-	ifp->if_flags &= ~IFF_OACTIVE;
-
-	splx(s);
-	return 0;
-}
-
-static void
-urndis_stop(struct ifnet *ifp)
-{
-	struct urndis_softc	*sc;
-	usbd_status	 err;
-	int		 i;
-
-	sc = ifp->if_softc;
-
-	ifp->if_timer = 0;
-	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-
-	if (sc->sc_bulkin_pipe != NULL) {
-		err = usbd_abort_pipe(sc->sc_bulkin_pipe);
-		if (err)
-			printf("%s: abort rx pipe failed: %s\n",
-			    DEVNAME(sc), usbd_errstr(err));
-	}
-
-	if (sc->sc_bulkout_pipe != NULL) {
-		err = usbd_abort_pipe(sc->sc_bulkout_pipe);
-		if (err)
-			printf("%s: abort tx pipe failed: %s\n",
-			    DEVNAME(sc), usbd_errstr(err));
-	}
-
-	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
-		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
-			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
-			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
-		}
-	}
-
-	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
-		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
-			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
-			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
-		}
-	}
-
-	/* Close pipes. */
-	if (sc->sc_bulkin_pipe != NULL) {
-		err = usbd_close_pipe(sc->sc_bulkin_pipe);
-		if (err)
-			printf("%s: close rx pipe failed: %s\n",
-			    DEVNAME(sc), usbd_errstr(err));
-		sc->sc_bulkin_pipe = NULL;
+	usbnet_lock(un);
+	if (un->un_dying)
+		err = EIO;
+	else {
+		usbnet_stop(un, ifp, 1);
+		err = usbnet_init_rx_tx(un);
+		if (err == 0)
+			un->un_link = true;
 	}
+	usbnet_unlock(un);
 
-	if (sc->sc_bulkout_pipe != NULL) {
-		err = usbd_close_pipe(sc->sc_bulkout_pipe);
-		if (err)
-			printf("%s: close tx pipe failed: %s\n",
-			    DEVNAME(sc), usbd_errstr(err));
-		sc->sc_bulkout_pipe = NULL;
-	}
+	return err;
 }
 
-static void
-urndis_start(struct ifnet *ifp)
+static int
+urndis_init(struct ifnet *ifp)
 {
-	struct urndis_softc	*sc;
-	struct mbuf		*m_head = NULL;
-
-	sc = ifp->if_softc;
-
-	if (sc->sc_dying || (ifp->if_flags & IFF_OACTIVE))
-		return;
-
-	IFQ_POLL(&ifp->if_snd, m_head);
-	if (m_head == NULL)
-		return;
-
-	if (urndis_encap(sc, m_head, 0)) {
-		ifp->if_flags |= IFF_OACTIVE;
-		return;
-	}
-	IFQ_DEQUEUE(&ifp->if_snd, m_head);
-
-	/*
-	 * If there's a BPF listener, bounce a copy of this frame
-	 * to him.
-	 */
-	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;
-
-	return;
-}
-
-static void
-urndis_rxeof(struct usbd_xfer *xfer,
-    void *priv,
-    usbd_status status)
-{
-	struct urndis_chain	*c;
-	struct urndis_softc	*sc;
-	struct ifnet		*ifp;
-	uint32_t		 total_len;
-
-	c = priv;
-	sc = c->sc_softc;
-	ifp = GET_IFP(sc);
-	total_len = 0;
-
-	if (sc->sc_dying || !(ifp->if_flags & IFF_RUNNING))
-		return;
-
-	if (status != USBD_NORMAL_COMPLETION) {
-		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
-			return;
-		if (usbd_ratecheck(&sc->sc_rx_notice)) {
-			printf("%s: usb errors on rx: %s\n",
-			    DEVNAME(sc), usbd_errstr(status));
-		}
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
-
-		goto done;
-	}
-
-	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
-	urndis_decap(sc, c, total_len);
-
-done:
-	/* Setup new transfer. */
-	usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ,
-	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof);
-	usbd_transfer(c->sc_xfer);
-}
-
-static void
-urndis_txeof(struct usbd_xfer *xfer,
-    void *priv,
-    usbd_status status)
-{
-	struct urndis_chain	*c;
-	struct urndis_softc	*sc;
-	struct ifnet		*ifp;
-	usbd_status		 err;
-	int			 s;
-
-	c = priv;
-	sc = c->sc_softc;
-	ifp = GET_IFP(sc);
+	struct usbnet *un = ifp->if_softc;
 
-	DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc)));
-
-	if (sc->sc_dying)
-		return;
-
-	s = splnet();
-
-	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", DEVNAME(sc),
-		    usbd_errstr(status));
-		if (status == USBD_STALLED)
-			usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe);
-		splx(s);
-		return;
-	}
-
-	usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err);
-
-	if (c->sc_mbuf != NULL) {
-		m_freem(c->sc_mbuf);
-		c->sc_mbuf = NULL;
-	}
-
-	if (err)
-		ifp->if_oerrors++;
-	else
-		ifp->if_opackets++;
-
-	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
-		urndis_start(ifp);
-
-	splx(s);
+	return urndis_init_un(ifp, un);
 }
 
 static int
@@ -1367,43 +912,46 @@ urndis_match(device_t parent, cfdata_t m
 static void
 urndis_attach(device_t parent, device_t self, void *aux)
 {
-	struct urndis_softc		*sc;
-	struct usbif_attach_arg		*uiaa;
-	struct ifnet			*ifp;
+	struct urndis_softc		*sc = device_private(self);
+	struct usbnet * const		 un = &sc->sc_un;
+	struct usbif_attach_arg		*uiaa = aux;
+	struct usbd_device	        *dev = uiaa->uiaa_device;
 	usb_interface_descriptor_t	*id;
 	usb_endpoint_descriptor_t	*ed;
 	usb_config_descriptor_t		*cd;
+	struct usbd_interface		*iface_ctl;
 	const usb_cdc_union_descriptor_t *ud;
 	const usb_cdc_header_descriptor_t *desc;
 	usbd_desc_iter_t		 iter;
 	int				 if_ctl, if_data;
 	int				 i, j, altcnt;
-	int				 s;
-	u_char				 eaddr[ETHER_ADDR_LEN];
 	void				*buf;
 	size_t				 bufsz;
 	uint32_t			 filter;
 	char				*devinfop;
 
-	sc = device_private(self);
-	uiaa = aux;
-	sc->sc_dev = self;
-	sc->sc_udev = uiaa->uiaa_device;
+	/* Switch to usbnet for device_private() */
+	self->dv_private = un;
 
 	aprint_naive("\n");
 	aprint_normal("\n");
-
-	devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0);
+	devinfop = usbd_devinfo_alloc(dev, 0);
 	aprint_normal_dev(self, "%s\n", devinfop);
 	usbd_devinfo_free(devinfop);
 
-	sc->sc_iface_ctl = uiaa->uiaa_iface;
-	id = usbd_get_interface_descriptor(sc->sc_iface_ctl);
+	un->un_dev = self;
+	un->un_udev = dev;
+	un->un_sc = sc;
+	un->un_ops = &urndis_ops;
+
+	iface_ctl = uiaa->uiaa_iface;
+	un->un_iface = uiaa->uiaa_iface;
+	id = usbd_get_interface_descriptor(iface_ctl);
 	if_ctl = id->bInterfaceNumber;
 	sc->sc_ifaceno_ctl = if_ctl;
 	if_data = -1;
 
-	usb_desc_iter_init(sc->sc_udev, &iter);
+	usb_desc_iter_init(un->un_udev, &iter);
 	while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) {
 
 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
@@ -1421,7 +969,7 @@ urndis_attach(device_t parent, device_t 
 
 	if (if_data == -1) {
 		DPRINTF(("urndis_attach: no union interface\n"));
-		sc->sc_iface_data = sc->sc_iface_ctl;
+		un->un_iface = iface_ctl;
 	} else {
 		DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n",
 		    if_ctl, if_data));
@@ -1431,104 +979,96 @@ urndis_attach(device_t parent, device_t 
 				    uiaa->uiaa_ifaces[i]);
 				if (id != NULL && id->bInterfaceNumber ==
 				    if_data) {
-					sc->sc_iface_data = uiaa->uiaa_ifaces[i];
+					un->un_iface = uiaa->uiaa_ifaces[i];
 					uiaa->uiaa_ifaces[i] = NULL;
 				}
 			}
 		}
 	}
 
-	if (sc->sc_iface_data == NULL) {
-		aprint_error("%s: no data interface\n", DEVNAME(sc));
+	if (un->un_iface == NULL) {
+		aprint_error("%s: no data interface\n", DEVNAME(un));
 		return;
 	}
 
-	id = usbd_get_interface_descriptor(sc->sc_iface_data);
-	cd = usbd_get_config_descriptor(sc->sc_udev);
+	id = usbd_get_interface_descriptor(un->un_iface);
+	cd = usbd_get_config_descriptor(un->un_udev);
 	altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
 
 	for (j = 0; j < altcnt; j++) {
-		if (usbd_set_interface(sc->sc_iface_data, j)) {
+		if (usbd_set_interface(un->un_iface, j)) {
 			aprint_error("%s: interface alternate setting %u "
-			    "failed\n", DEVNAME(sc), j);
+			    "failed\n", DEVNAME(un), j);
 			return;
 		}
 		/* Find endpoints. */
-		id = usbd_get_interface_descriptor(sc->sc_iface_data);
-		sc->sc_bulkin_no = sc->sc_bulkout_no = -1;
+		id = usbd_get_interface_descriptor(un->un_iface);
+		un->un_ed[USBNET_ENDPT_RX] = un->un_ed[USBNET_ENDPT_TX] = 0;
 		for (i = 0; i < id->bNumEndpoints; i++) {
 			ed = usbd_interface2endpoint_descriptor(
-			    sc->sc_iface_data, i);
+			    un->un_iface, i);
 			if (!ed) {
 				aprint_error("%s: no descriptor for bulk "
-				    "endpoint %u\n", DEVNAME(sc), i);
+				    "endpoint %u\n", DEVNAME(un), i);
 				return;
 			}
 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-				sc->sc_bulkin_no = ed->bEndpointAddress;
+				un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
 			}
 			else if (
 			    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
-				sc->sc_bulkout_no = ed->bEndpointAddress;
+				un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
 			}
 		}
 
-		if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) {
+		if (un->un_ed[USBNET_ENDPT_RX] != 0 && un->un_ed[USBNET_ENDPT_TX] != 0) {
 			DPRINTF(("%s: in=0x%x, out=0x%x\n",
-			    DEVNAME(sc),
-			    sc->sc_bulkin_no,
+			    DEVNAME(un),
+			    un->un_ed[USBNET_ENDPT_RX],
 			    sc->sc_bulkout_no));
-			goto found;
+			break;
 		}
 	}
 
-	if (sc->sc_bulkin_no == -1)
-		aprint_error("%s: could not find data bulk in\n", DEVNAME(sc));
-	if (sc->sc_bulkout_no == -1 )
-		aprint_error("%s: could not find data bulk out\n",DEVNAME(sc));
-	return;
-
-	found:
-
-	ifp = GET_IFP(sc);
-	ifp->if_softc = sc;
-	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_start = urndis_start;
-	ifp->if_ioctl = urndis_ioctl;
-	ifp->if_init = urndis_init;
+	if (un->un_ed[USBNET_ENDPT_RX] == 0)
+		aprint_error("%s: could not find data bulk in\n", DEVNAME(un));
+	if (un->un_ed[USBNET_ENDPT_TX] == 0)
+		aprint_error("%s: could not find data bulk out\n",DEVNAME(un));
+	if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0)
+		return;
+
+	struct ifnet *ifp = usbnet_ifp(un);
 #if 0
 	ifp->if_watchdog = urndis_watchdog;
 #endif
 
-	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
+	usbnet_attach(un, "urndisdet", RNDIS_RX_LIST_CNT, RNDIS_TX_LIST_CNT,
+		      USBD_SHORT_XFER_OK, USBD_FORCE_SHORT_XFER,
+		      RNDIS_BUFSZ, RNDIS_BUFSZ);
 
-	IFQ_SET_READY(&ifp->if_snd);
+	urndis_init_un(ifp, un);
 
-	urndis_init(ifp);
-
-	s = splnet();
-
-	if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
+	if (urndis_ctrl_query(un, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
 	    &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
 		aprint_error("%s: unable to get hardware address\n",
-		    DEVNAME(sc));
-		urndis_stop(ifp);
-		splx(s);
+		    DEVNAME(un));
+		usbnet_lock(un);
+		usbnet_stop(un, ifp, 1);
+		usbnet_unlock(un);
 		return;
 	}
 
 	if (bufsz == ETHER_ADDR_LEN) {
-		memcpy(eaddr, buf, ETHER_ADDR_LEN);
-		aprint_normal("%s: address %s\n", DEVNAME(sc),
-		    ether_sprintf(eaddr));
+		memcpy(un->un_eaddr, buf, ETHER_ADDR_LEN);
 		kmem_free(buf, bufsz);
 	} else {
-		aprint_error("%s: invalid address\n", DEVNAME(sc));
+		aprint_error("%s: invalid address\n", DEVNAME(un));
 		kmem_free(buf, bufsz);
-		urndis_stop(ifp);
-		splx(s);
+		usbnet_lock(un);
+		usbnet_stop(un, ifp, 1);
+		usbnet_unlock(un);
 		return;
 	}
 
@@ -1536,65 +1076,20 @@ urndis_attach(device_t parent, device_t 
 	sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST;
 	sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
 	filter = htole32(sc->sc_filter);
-	if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter,
+	if (urndis_ctrl_set(un, OID_GEN_CURRENT_PACKET_FILTER, &filter,
 	    sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
-		aprint_error("%s: unable to set data filters\n", DEVNAME(sc));
-		urndis_stop(ifp);
-		splx(s);
+		aprint_error("%s: unable to set data filters\n", DEVNAME(un));
+		usbnet_lock(un);
+		usbnet_stop(un, ifp, 1);
+		usbnet_unlock(un);
 		return;
 	}
 
-	if_attach(ifp);
-	ether_ifattach(ifp, eaddr);
-	sc->sc_attached = 1;
-
-	splx(s);
-}
-
-static int
-urndis_detach(device_t self, int flags)
-{
-	struct urndis_softc	*sc;
-	struct ifnet		*ifp;
-	int			 s;
-
-	sc = device_private(self);
-
-	DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc),
-	    flags));
-
-	if (!sc->sc_attached)
-		return 0;
-
-	s = splusb();
-
-	ifp = GET_IFP(sc);
-
-	if (ifp->if_softc != NULL) {
-		ether_ifdetach(ifp);
-		if_detach(ifp);
-	}
-
-	urndis_stop(ifp);
-	sc->sc_attached = 0;
-
-	splx(s);
-
-	return 0;
-}
-
-static int
-urndis_activate(device_t self, enum devact act)
-{
-	struct urndis_softc *sc;
-
-	sc = device_private(self);
-
-	switch (act) {
-	case DVACT_DEACTIVATE:
-		sc->sc_dying = 1;
-		return 0;
-	}
+	/* Turn off again now it has been identified. */
+	usbnet_lock(un);
+	usbnet_stop(un, ifp, 1);
+	usbnet_unlock(un);
 
-	return EOPNOTSUPP;
+	usbnet_attach_ifp(un, false, IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST,
+            0, 0);
 }

Reply via email to