Home | History | Annotate | Line # | Download | only in usb
if_urndis.c revision 1.22
      1 /*	$NetBSD: if_urndis.c,v 1.22 2019/08/01 00:10:22 mrg Exp $ */
      2 /*	$OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2010 Jonathan Armani <armani (at) openbsd.org>
      6  * Copyright (c) 2010 Fabien Romano <fabien (at) openbsd.org>
      7  * Copyright (c) 2010 Michael Knudsen <mk (at) openbsd.org>
      8  * All rights reserved.
      9  *
     10  * Permission to use, copy, modify, and distribute this software for any
     11  * purpose with or without fee is hereby granted, provided that the above
     12  * copyright notice and this permission notice appear in all copies.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #include <sys/cdefs.h>
     24 __KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.22 2019/08/01 00:10:22 mrg Exp $");
     25 
     26 #ifdef _KERNEL_OPT
     27 #include "opt_usb.h"
     28 #endif
     29 
     30 #include <sys/param.h>
     31 #include <sys/systm.h>
     32 #include <sys/sockio.h>
     33 #include <sys/rwlock.h>
     34 #include <sys/mbuf.h>
     35 #include <sys/kmem.h>
     36 #include <sys/kernel.h>
     37 #include <sys/proc.h>
     38 #include <sys/socket.h>
     39 #include <sys/device.h>
     40 
     41 #include <net/if.h>
     42 #include <net/if_dl.h>
     43 #include <net/if_media.h>
     44 #include <net/if_ether.h>
     45 
     46 #include <net/bpf.h>
     47 
     48 #include <sys/bus.h>
     49 #include <dev/usb/usb.h>
     50 #include <dev/usb/usbdi.h>
     51 #include <dev/usb/usbdi_util.h>
     52 #include <dev/usb/usbdivar.h>
     53 #include <dev/usb/usbdevs.h>
     54 #include <dev/usb/usbcdc.h>
     55 
     56 #include <dev/ic/rndisreg.h>
     57 
     58 #define RNDIS_RX_LIST_CNT	1
     59 #define RNDIS_TX_LIST_CNT	1
     60 #define RNDIS_BUFSZ		1562
     61 
     62 struct urndis_softc;
     63 
     64 struct urndis_chain {
     65 	struct urndis_softc	*sc_softc;
     66 	struct usbd_xfer	*sc_xfer;
     67 	char			*sc_buf;
     68 	struct mbuf		*sc_mbuf;
     69 };
     70 
     71 struct urndis_cdata {
     72 	struct urndis_chain	sc_rx_chain[RNDIS_RX_LIST_CNT];
     73 	struct urndis_chain	sc_tx_chain[RNDIS_TX_LIST_CNT];
     74 	int			sc_tx_cnt;
     75 };
     76 
     77 #define GET_IFP(sc) (&(sc)->sc_ec.ec_if)
     78 struct urndis_softc {
     79 	device_t			sc_dev;
     80 
     81 	char				sc_attached;
     82 	int				sc_dying;
     83 	struct ethercom			sc_ec;
     84 
     85 	/* RNDIS device info */
     86 	uint32_t			sc_filter;
     87 	uint32_t			sc_maxppt;
     88 	uint32_t			sc_maxtsz;
     89 	uint32_t			sc_palign;
     90 
     91 	/* USB goo */
     92 	struct usbd_device *		sc_udev;
     93 	int				sc_ifaceno_ctl;
     94 	struct usbd_interface *		sc_iface_ctl;
     95 	struct usbd_interface *		sc_iface_data;
     96 
     97 	struct timeval			sc_rx_notice;
     98 	int				sc_bulkin_no;
     99 	struct usbd_pipe *		sc_bulkin_pipe;
    100 	int				sc_bulkout_no;
    101 	struct usbd_pipe *		sc_bulkout_pipe;
    102 
    103 	struct urndis_cdata		sc_data;
    104 };
    105 
    106 #ifdef URNDIS_DEBUG
    107 #define DPRINTF(x)      do { printf x; } while (0)
    108 #else
    109 #define DPRINTF(x)
    110 #endif
    111 
    112 #define DEVNAME(sc)	(device_xname(sc->sc_dev))
    113 
    114 #define URNDIS_RESPONSE_LEN 0x400
    115 
    116 
    117 static int urndis_newbuf(struct urndis_softc *, struct urndis_chain *);
    118 
    119 static int urndis_ioctl(struct ifnet *, unsigned long, void *);
    120 #if 0
    121 static void urndis_watchdog(struct ifnet *);
    122 #endif
    123 
    124 static void urndis_start(struct ifnet *);
    125 static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status);
    126 static void urndis_txeof(struct usbd_xfer *, void *, usbd_status);
    127 static int urndis_rx_list_init(struct urndis_softc *);
    128 static int urndis_tx_list_init(struct urndis_softc *);
    129 
    130 static int urndis_init(struct ifnet *);
    131 static void urndis_stop(struct ifnet *);
    132 
    133 static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
    134     uint16_t, uint16_t, void *, size_t);
    135 static usbd_status urndis_ctrl_send(struct urndis_softc *, void *, size_t);
    136 static struct rndis_comp_hdr *urndis_ctrl_recv(struct urndis_softc *);
    137 
    138 static uint32_t urndis_ctrl_handle(struct urndis_softc *,
    139     struct rndis_comp_hdr *, void **, size_t *);
    140 static uint32_t urndis_ctrl_handle_init(struct urndis_softc *,
    141     const struct rndis_comp_hdr *);
    142 static uint32_t urndis_ctrl_handle_query(struct urndis_softc *,
    143     const struct rndis_comp_hdr *, void **, size_t *);
    144 static uint32_t urndis_ctrl_handle_reset(struct urndis_softc *,
    145     const struct rndis_comp_hdr *);
    146 
    147 static uint32_t urndis_ctrl_init(struct urndis_softc *);
    148 #if 0
    149 static uint32_t urndis_ctrl_halt(struct urndis_softc *);
    150 #endif
    151 static uint32_t urndis_ctrl_query(struct urndis_softc *, uint32_t, void *,
    152     size_t, void **, size_t *);
    153 static uint32_t urndis_ctrl_set(struct urndis_softc *, uint32_t, void *,
    154     size_t);
    155 #if 0
    156 static uint32_t urndis_ctrl_set_param(struct urndis_softc *, const char *,
    157     uint32_t, void *, size_t);
    158 static uint32_t urndis_ctrl_reset(struct urndis_softc *);
    159 static uint32_t urndis_ctrl_keepalive(struct urndis_softc *);
    160 #endif
    161 
    162 static int urndis_encap(struct urndis_softc *, struct mbuf *, int);
    163 static void urndis_decap(struct urndis_softc *, struct urndis_chain *,
    164     uint32_t);
    165 
    166 static int urndis_match(device_t, cfdata_t, void *);
    167 static void urndis_attach(device_t, device_t, void *);
    168 static int urndis_detach(device_t, int);
    169 static int urndis_activate(device_t, enum devact);
    170 
    171 CFATTACH_DECL_NEW(urndis, sizeof(struct urndis_softc),
    172     urndis_match, urndis_attach, urndis_detach, urndis_activate);
    173 
    174 /*
    175  * Supported devices that we can't match by class IDs.
    176  */
    177 static const struct usb_devno urndis_devs[] = {
    178 	{ USB_VENDOR_HTC,	USB_PRODUCT_HTC_ANDROID },
    179 	{ USB_VENDOR_SAMSUNG,	USB_PRODUCT_SAMSUNG_ANDROID2 },
    180 };
    181 
    182 static usbd_status
    183 urndis_ctrl_msg(struct urndis_softc *sc, uint8_t rt, uint8_t r,
    184     uint16_t index, uint16_t value, void *buf, size_t buflen)
    185 {
    186 	usb_device_request_t req;
    187 
    188 	req.bmRequestType = rt;
    189 	req.bRequest = r;
    190 	USETW(req.wValue, value);
    191 	USETW(req.wIndex, index);
    192 	USETW(req.wLength, buflen);
    193 
    194 	return usbd_do_request(sc->sc_udev, &req, buf);
    195 }
    196 
    197 static usbd_status
    198 urndis_ctrl_send(struct urndis_softc *sc, void *buf, size_t len)
    199 {
    200 	usbd_status err;
    201 
    202 	if (sc->sc_dying)
    203 		return(0);
    204 
    205 	err = urndis_ctrl_msg(sc, UT_WRITE_CLASS_INTERFACE, UR_GET_STATUS,
    206 	    sc->sc_ifaceno_ctl, 0, buf, len);
    207 
    208 	if (err != USBD_NORMAL_COMPLETION)
    209 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
    210 
    211 	return err;
    212 }
    213 
    214 static struct rndis_comp_hdr *
    215 urndis_ctrl_recv(struct urndis_softc *sc)
    216 {
    217 	struct rndis_comp_hdr	*hdr;
    218 	char			*buf;
    219 	usbd_status		 err;
    220 
    221 	buf = kmem_alloc(URNDIS_RESPONSE_LEN, KM_SLEEP);
    222 	err = urndis_ctrl_msg(sc, UT_READ_CLASS_INTERFACE, UR_CLEAR_FEATURE,
    223 	    sc->sc_ifaceno_ctl, 0, buf, URNDIS_RESPONSE_LEN);
    224 
    225 	if (err != USBD_NORMAL_COMPLETION && err != USBD_SHORT_XFER) {
    226 		printf("%s: %s\n", DEVNAME(sc), usbd_errstr(err));
    227 		kmem_free(buf, URNDIS_RESPONSE_LEN);
    228 		return NULL;
    229 	}
    230 
    231 	hdr = (struct rndis_comp_hdr *)buf;
    232 	DPRINTF(("%s: urndis_ctrl_recv: type 0x%x len %u\n",
    233 	    DEVNAME(sc),
    234 	    le32toh(hdr->rm_type),
    235 	    le32toh(hdr->rm_len)));
    236 
    237 	if (le32toh(hdr->rm_len) > URNDIS_RESPONSE_LEN) {
    238 		printf("%s: ctrl message error: wrong size %u > %u\n",
    239 		    DEVNAME(sc),
    240 		    le32toh(hdr->rm_len),
    241 		    URNDIS_RESPONSE_LEN);
    242 		kmem_free(buf, URNDIS_RESPONSE_LEN);
    243 		return NULL;
    244 	}
    245 
    246 	return hdr;
    247 }
    248 
    249 static uint32_t
    250 urndis_ctrl_handle(struct urndis_softc *sc, struct rndis_comp_hdr *hdr,
    251     void **buf, size_t *bufsz)
    252 {
    253 	uint32_t rval;
    254 
    255 	DPRINTF(("%s: urndis_ctrl_handle\n", DEVNAME(sc)));
    256 
    257 	if (buf && bufsz) {
    258 		*buf = NULL;
    259 		*bufsz = 0;
    260 	}
    261 
    262 	switch (le32toh(hdr->rm_type)) {
    263 		case REMOTE_NDIS_INITIALIZE_CMPLT:
    264 			rval = urndis_ctrl_handle_init(sc, hdr);
    265 			break;
    266 
    267 		case REMOTE_NDIS_QUERY_CMPLT:
    268 			rval = urndis_ctrl_handle_query(sc, hdr, buf, bufsz);
    269 			break;
    270 
    271 		case REMOTE_NDIS_RESET_CMPLT:
    272 			rval = urndis_ctrl_handle_reset(sc, hdr);
    273 			break;
    274 
    275 		case REMOTE_NDIS_KEEPALIVE_CMPLT:
    276 		case REMOTE_NDIS_SET_CMPLT:
    277 			rval = le32toh(hdr->rm_status);
    278 			break;
    279 
    280 		default:
    281 			printf("%s: ctrl message error: unknown event 0x%x\n",
    282 			    DEVNAME(sc), le32toh(hdr->rm_type));
    283 			rval = RNDIS_STATUS_FAILURE;
    284 	}
    285 
    286 	kmem_free(hdr, URNDIS_RESPONSE_LEN);
    287 
    288 	return rval;
    289 }
    290 
    291 static uint32_t
    292 urndis_ctrl_handle_init(struct urndis_softc *sc,
    293     const struct rndis_comp_hdr *hdr)
    294 {
    295 	const struct rndis_init_comp	*msg;
    296 
    297 	msg = (const struct rndis_init_comp *) hdr;
    298 
    299 	DPRINTF(("%s: urndis_ctrl_handle_init: len %u rid %u status 0x%x "
    300 	    "ver_major %u ver_minor %u devflags 0x%x medium 0x%x pktmaxcnt %u "
    301 	    "pktmaxsz %u align %u aflistoffset %u aflistsz %u\n",
    302 	    DEVNAME(sc),
    303 	    le32toh(msg->rm_len),
    304 	    le32toh(msg->rm_rid),
    305 	    le32toh(msg->rm_status),
    306 	    le32toh(msg->rm_ver_major),
    307 	    le32toh(msg->rm_ver_minor),
    308 	    le32toh(msg->rm_devflags),
    309 	    le32toh(msg->rm_medium),
    310 	    le32toh(msg->rm_pktmaxcnt),
    311 	    le32toh(msg->rm_pktmaxsz),
    312 	    le32toh(msg->rm_align),
    313 	    le32toh(msg->rm_aflistoffset),
    314 	    le32toh(msg->rm_aflistsz)));
    315 
    316 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
    317 		printf("%s: init failed 0x%x\n",
    318 		    DEVNAME(sc),
    319 		    le32toh(msg->rm_status));
    320 
    321 		return le32toh(msg->rm_status);
    322 	}
    323 
    324 	if (le32toh(msg->rm_devflags) != RNDIS_DF_CONNECTIONLESS) {
    325 		printf("%s: wrong device type (current type: 0x%x)\n",
    326 		    DEVNAME(sc),
    327 		    le32toh(msg->rm_devflags));
    328 
    329 		return RNDIS_STATUS_FAILURE;
    330 	}
    331 
    332 	if (le32toh(msg->rm_medium) != RNDIS_MEDIUM_802_3) {
    333 		printf("%s: medium not 802.3 (current medium: 0x%x)\n",
    334 		    DEVNAME(sc), le32toh(msg->rm_medium));
    335 
    336 		return RNDIS_STATUS_FAILURE;
    337 	}
    338 
    339 	if (le32toh(msg->rm_ver_major) != RNDIS_MAJOR_VERSION ||
    340 	    le32toh(msg->rm_ver_minor) != RNDIS_MINOR_VERSION) {
    341 		printf("%s: version not %u.%u (current version: %u.%u)\n",
    342 		    DEVNAME(sc), RNDIS_MAJOR_VERSION, RNDIS_MINOR_VERSION,
    343 		    le32toh(msg->rm_ver_major), le32toh(msg->rm_ver_minor));
    344 
    345 		return RNDIS_STATUS_FAILURE;
    346 	}
    347 
    348 	sc->sc_maxppt = le32toh(msg->rm_pktmaxcnt);
    349 	sc->sc_maxtsz = le32toh(msg->rm_pktmaxsz);
    350 	sc->sc_palign = 1U << le32toh(msg->rm_align);
    351 
    352 	return le32toh(msg->rm_status);
    353 }
    354 
    355 static uint32_t
    356 urndis_ctrl_handle_query(struct urndis_softc *sc,
    357     const struct rndis_comp_hdr *hdr, void **buf, size_t *bufsz)
    358 {
    359 	const struct rndis_query_comp	*msg;
    360 
    361 	msg = (const struct rndis_query_comp *) hdr;
    362 
    363 	DPRINTF(("%s: urndis_ctrl_handle_query: len %u rid %u status 0x%x "
    364 	    "buflen %u bufoff %u\n",
    365 	    DEVNAME(sc),
    366 	    le32toh(msg->rm_len),
    367 	    le32toh(msg->rm_rid),
    368 	    le32toh(msg->rm_status),
    369 	    le32toh(msg->rm_infobuflen),
    370 	    le32toh(msg->rm_infobufoffset)));
    371 
    372 	if (buf && bufsz) {
    373 		*buf = NULL;
    374 		*bufsz = 0;
    375 	}
    376 
    377 	if (le32toh(msg->rm_status) != RNDIS_STATUS_SUCCESS) {
    378 		printf("%s: query failed 0x%x\n",
    379 		    DEVNAME(sc),
    380 		    le32toh(msg->rm_status));
    381 
    382 		return le32toh(msg->rm_status);
    383 	}
    384 
    385 	if (le32toh(msg->rm_infobuflen) + le32toh(msg->rm_infobufoffset) +
    386 	    RNDIS_HEADER_OFFSET > le32toh(msg->rm_len)) {
    387 		printf("%s: ctrl message error: invalid query info "
    388 		    "len/offset/end_position(%u/%u/%u) -> "
    389 		    "go out of buffer limit %u\n",
    390 		    DEVNAME(sc),
    391 		    le32toh(msg->rm_infobuflen),
    392 		    le32toh(msg->rm_infobufoffset),
    393 		    le32toh(msg->rm_infobuflen) +
    394 		    le32toh(msg->rm_infobufoffset) + (uint32_t)RNDIS_HEADER_OFFSET,
    395 		    le32toh(msg->rm_len));
    396 		return RNDIS_STATUS_FAILURE;
    397 	}
    398 
    399 	if (buf && bufsz) {
    400 		const char *p;
    401 
    402 		*buf = kmem_alloc(le32toh(msg->rm_infobuflen), KM_SLEEP);
    403 		*bufsz = le32toh(msg->rm_infobuflen);
    404 
    405 		p = (const char *)&msg->rm_rid;
    406 		p += le32toh(msg->rm_infobufoffset);
    407 		memcpy(*buf, p, le32toh(msg->rm_infobuflen));
    408 	}
    409 
    410 	return le32toh(msg->rm_status);
    411 }
    412 
    413 static uint32_t
    414 urndis_ctrl_handle_reset(struct urndis_softc *sc,
    415     const struct rndis_comp_hdr *hdr)
    416 {
    417 	const struct rndis_reset_comp	*msg;
    418 	uint32_t			 rval;
    419 
    420 	msg = (const struct rndis_reset_comp *) hdr;
    421 
    422 	rval = le32toh(msg->rm_status);
    423 
    424 	DPRINTF(("%s: urndis_ctrl_handle_reset: len %u status 0x%x "
    425 	    "adrreset %u\n",
    426 	    DEVNAME(sc),
    427 	    le32toh(msg->rm_len),
    428 	    rval,
    429 	    le32toh(msg->rm_adrreset)));
    430 
    431 	if (rval != RNDIS_STATUS_SUCCESS) {
    432 		printf("%s: reset failed 0x%x\n", DEVNAME(sc), rval);
    433 		return rval;
    434 	}
    435 
    436 	if (le32toh(msg->rm_adrreset) != 0) {
    437 		uint32_t filter;
    438 
    439 		filter = htole32(sc->sc_filter);
    440 		rval = urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
    441 		    &filter, sizeof(filter));
    442 		if (rval != RNDIS_STATUS_SUCCESS) {
    443 			printf("%s: unable to reset data filters\n",
    444 			    DEVNAME(sc));
    445 			return rval;
    446 		}
    447 	}
    448 
    449 	return rval;
    450 }
    451 
    452 static uint32_t
    453 urndis_ctrl_init(struct urndis_softc *sc)
    454 {
    455 	struct rndis_init_req	*msg;
    456 	uint32_t		 rval;
    457 	struct rndis_comp_hdr	*hdr;
    458 
    459 	msg = kmem_alloc(sizeof(*msg), KM_SLEEP);
    460 	msg->rm_type = htole32(REMOTE_NDIS_INITIALIZE_MSG);
    461 	msg->rm_len = htole32(sizeof(*msg));
    462 	msg->rm_rid = htole32(0);
    463 	msg->rm_ver_major = htole32(RNDIS_MAJOR_VERSION);
    464 	msg->rm_ver_minor = htole32(RNDIS_MINOR_VERSION);
    465 	msg->rm_max_xfersz = htole32(RNDIS_BUFSZ);
    466 
    467 	DPRINTF(("%s: urndis_ctrl_init send: type %u len %u rid %u ver_major %u "
    468 	    "ver_minor %u max_xfersz %u\n",
    469 	    DEVNAME(sc),
    470 	    le32toh(msg->rm_type),
    471 	    le32toh(msg->rm_len),
    472 	    le32toh(msg->rm_rid),
    473 	    le32toh(msg->rm_ver_major),
    474 	    le32toh(msg->rm_ver_minor),
    475 	    le32toh(msg->rm_max_xfersz)));
    476 
    477 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
    478 	kmem_free(msg, sizeof(*msg));
    479 
    480 	if (rval != RNDIS_STATUS_SUCCESS) {
    481 		printf("%s: init failed\n", DEVNAME(sc));
    482 		return rval;
    483 	}
    484 
    485 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
    486 		printf("%s: unable to get init response\n", DEVNAME(sc));
    487 		return RNDIS_STATUS_FAILURE;
    488 	}
    489 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
    490 
    491 	return rval;
    492 }
    493 
    494 #if 0
    495 static uint32_t
    496 urndis_ctrl_halt(struct urndis_softc *sc)
    497 {
    498 	struct rndis_halt_req	*msg;
    499 	uint32_t		 rval;
    500 
    501 	msg = kmem_alloc(sizeof(*msg), KM_SLEEP);
    502 	msg->rm_type = htole32(REMOTE_NDIS_HALT_MSG);
    503 	msg->rm_len = htole32(sizeof(*msg));
    504 	msg->rm_rid = 0;
    505 
    506 	DPRINTF(("%s: urndis_ctrl_halt send: type %u len %u rid %u\n",
    507 	    DEVNAME(sc),
    508 	    le32toh(msg->rm_type),
    509 	    le32toh(msg->rm_len),
    510 	    le32toh(msg->rm_rid)));
    511 
    512 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
    513 	kmem_free(msg, sizeof(*msg));
    514 
    515 	if (rval != RNDIS_STATUS_SUCCESS)
    516 		printf("%s: halt failed\n", DEVNAME(sc));
    517 
    518 	return rval;
    519 }
    520 #endif
    521 
    522 static uint32_t
    523 urndis_ctrl_query(struct urndis_softc *sc, uint32_t oid,
    524     void *qbuf, size_t qlen,
    525     void **rbuf, size_t *rbufsz)
    526 {
    527 	struct rndis_query_req	*msg;
    528 	uint32_t		 rval;
    529 	struct rndis_comp_hdr	*hdr;
    530 
    531 	msg = kmem_alloc(sizeof(*msg) + qlen, KM_SLEEP);
    532 	msg->rm_type = htole32(REMOTE_NDIS_QUERY_MSG);
    533 	msg->rm_len = htole32(sizeof(*msg) + qlen);
    534 	msg->rm_rid = 0; /* XXX */
    535 	msg->rm_oid = htole32(oid);
    536 	msg->rm_infobuflen = htole32(qlen);
    537 	if (qlen != 0) {
    538 		msg->rm_infobufoffset = htole32(20);
    539 		memcpy((char*)msg + 20, qbuf, qlen);
    540 	} else
    541 		msg->rm_infobufoffset = 0;
    542 	msg->rm_devicevchdl = 0;
    543 
    544 	DPRINTF(("%s: urndis_ctrl_query send: type %u len %u rid %u oid 0x%x "
    545 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
    546 	    DEVNAME(sc),
    547 	    le32toh(msg->rm_type),
    548 	    le32toh(msg->rm_len),
    549 	    le32toh(msg->rm_rid),
    550 	    le32toh(msg->rm_oid),
    551 	    le32toh(msg->rm_infobuflen),
    552 	    le32toh(msg->rm_infobufoffset),
    553 	    le32toh(msg->rm_devicevchdl)));
    554 
    555 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
    556 	kmem_free(msg, sizeof(*msg) + qlen);
    557 
    558 	if (rval != RNDIS_STATUS_SUCCESS) {
    559 		printf("%s: query failed\n", DEVNAME(sc));
    560 		return rval;
    561 	}
    562 
    563 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
    564 		printf("%s: unable to get query response\n", DEVNAME(sc));
    565 		return RNDIS_STATUS_FAILURE;
    566 	}
    567 	rval = urndis_ctrl_handle(sc, hdr, rbuf, rbufsz);
    568 
    569 	return rval;
    570 }
    571 
    572 static uint32_t
    573 urndis_ctrl_set(struct urndis_softc *sc, uint32_t oid, void *buf, size_t len)
    574 {
    575 	struct rndis_set_req	*msg;
    576 	uint32_t		 rval;
    577 	struct rndis_comp_hdr	*hdr;
    578 
    579 	msg = kmem_alloc(sizeof(*msg) + len, KM_SLEEP);
    580 	msg->rm_type = htole32(REMOTE_NDIS_SET_MSG);
    581 	msg->rm_len = htole32(sizeof(*msg) + len);
    582 	msg->rm_rid = 0; /* XXX */
    583 	msg->rm_oid = htole32(oid);
    584 	msg->rm_infobuflen = htole32(len);
    585 	if (len != 0) {
    586 		msg->rm_infobufoffset = htole32(20);
    587 		memcpy((char*)msg + 20, buf, len);
    588 	} else
    589 		msg->rm_infobufoffset = 0;
    590 	msg->rm_devicevchdl = 0;
    591 
    592 	DPRINTF(("%s: urndis_ctrl_set send: type %u len %u rid %u oid 0x%x "
    593 	    "infobuflen %u infobufoffset %u devicevchdl %u\n",
    594 	    DEVNAME(sc),
    595 	    le32toh(msg->rm_type),
    596 	    le32toh(msg->rm_len),
    597 	    le32toh(msg->rm_rid),
    598 	    le32toh(msg->rm_oid),
    599 	    le32toh(msg->rm_infobuflen),
    600 	    le32toh(msg->rm_infobufoffset),
    601 	    le32toh(msg->rm_devicevchdl)));
    602 
    603 	rval = urndis_ctrl_send(sc, msg, sizeof(*msg));
    604 	kmem_free(msg, sizeof(*msg) + len);
    605 
    606 	if (rval != RNDIS_STATUS_SUCCESS) {
    607 		printf("%s: set failed\n", DEVNAME(sc));
    608 		return rval;
    609 	}
    610 
    611 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
    612 		printf("%s: unable to get set response\n", DEVNAME(sc));
    613 		return RNDIS_STATUS_FAILURE;
    614 	}
    615 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
    616 	if (rval != RNDIS_STATUS_SUCCESS)
    617 		printf("%s: set failed 0x%x\n", DEVNAME(sc), rval);
    618 
    619 	return rval;
    620 }
    621 
    622 #if 0
    623 static uint32_t
    624 urndis_ctrl_set_param(struct urndis_softc *sc,
    625     const char *name,
    626     uint32_t type,
    627     void *buf,
    628     size_t len)
    629 {
    630 	struct rndis_set_parameter	*param;
    631 	uint32_t			 rval;
    632 	size_t				 namelen, tlen;
    633 
    634 	if (name)
    635 		namelen = strlen(name);
    636 	else
    637 		namelen = 0;
    638 	tlen = sizeof(*param) + len + namelen;
    639 	param = kmem_alloc(tlen, KM_SLEEP);
    640 	param->rm_namelen = htole32(namelen);
    641 	param->rm_valuelen = htole32(len);
    642 	param->rm_type = htole32(type);
    643 	if (namelen != 0) {
    644 		param->rm_nameoffset = htole32(20);
    645 		memcpy(param + 20, name, namelen);
    646 	} else
    647 		param->rm_nameoffset = 0;
    648 	if (len != 0) {
    649 		param->rm_valueoffset = htole32(20 + namelen);
    650 		memcpy(param + 20 + namelen, buf, len);
    651 	} else
    652 		param->rm_valueoffset = 0;
    653 
    654 	DPRINTF(("%s: urndis_ctrl_set_param send: nameoffset %u namelen %u "
    655 	    "type 0x%x valueoffset %u valuelen %u\n",
    656 	    DEVNAME(sc),
    657 	    le32toh(param->rm_nameoffset),
    658 	    le32toh(param->rm_namelen),
    659 	    le32toh(param->rm_type),
    660 	    le32toh(param->rm_valueoffset),
    661 	    le32toh(param->rm_valuelen)));
    662 
    663 	rval = urndis_ctrl_set(sc, OID_GEN_RNDIS_CONFIG_PARAMETER, param, tlen);
    664 	kmem_free(param, tlen);
    665 	if (rval != RNDIS_STATUS_SUCCESS)
    666 		printf("%s: set param failed 0x%x\n", DEVNAME(sc), rval);
    667 
    668 	return rval;
    669 }
    670 
    671 /* XXX : adrreset, get it from response */
    672 static uint32_t
    673 urndis_ctrl_reset(struct urndis_softc *sc)
    674 {
    675 	struct rndis_reset_req		*reset;
    676 	uint32_t			 rval;
    677 	struct rndis_comp_hdr		*hdr;
    678 
    679 	reset = kmem_alloc(sizeof(*reset), KM_SLEEP);
    680 	reset->rm_type = htole32(REMOTE_NDIS_RESET_MSG);
    681 	reset->rm_len = htole32(sizeof(*reset));
    682 	reset->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
    683 
    684 	DPRINTF(("%s: urndis_ctrl_reset send: type %u len %u rid %u\n",
    685 	    DEVNAME(sc),
    686 	    le32toh(reset->rm_type),
    687 	    le32toh(reset->rm_len),
    688 	    le32toh(reset->rm_rid)));
    689 
    690 	rval = urndis_ctrl_send(sc, reset, sizeof(*reset));
    691 	kmem_free(reset, sizeof(*reset));
    692 
    693 	if (rval != RNDIS_STATUS_SUCCESS) {
    694 		printf("%s: reset failed\n", DEVNAME(sc));
    695 		return rval;
    696 	}
    697 
    698 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
    699 		printf("%s: unable to get reset response\n", DEVNAME(sc));
    700 		return RNDIS_STATUS_FAILURE;
    701 	}
    702 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
    703 
    704 	return rval;
    705 }
    706 
    707 static uint32_t
    708 urndis_ctrl_keepalive(struct urndis_softc *sc)
    709 {
    710 	struct rndis_keepalive_req	*keep;
    711 	uint32_t			 rval;
    712 	struct rndis_comp_hdr		*hdr;
    713 
    714 	keep = kmem_alloc(sizeof(*keep), KM_SLEEP);
    715 	keep->rm_type = htole32(REMOTE_NDIS_KEEPALIVE_MSG);
    716 	keep->rm_len = htole32(sizeof(*keep));
    717 	keep->rm_rid = 0; /* XXX rm_rid == reserved ... remove ? */
    718 
    719 	DPRINTF(("%s: urndis_ctrl_keepalive: type %u len %u rid %u\n",
    720 	    DEVNAME(sc),
    721 	    le32toh(keep->rm_type),
    722 	    le32toh(keep->rm_len),
    723 	    le32toh(keep->rm_rid)));
    724 
    725 	rval = urndis_ctrl_send(sc, keep, sizeof(*keep));
    726 	kmem_free(keep, sizeof(*keep));
    727 
    728 	if (rval != RNDIS_STATUS_SUCCESS) {
    729 		printf("%s: keepalive failed\n", DEVNAME(sc));
    730 		return rval;
    731 	}
    732 
    733 	if ((hdr = urndis_ctrl_recv(sc)) == NULL) {
    734 		printf("%s: unable to get keepalive response\n", DEVNAME(sc));
    735 		return RNDIS_STATUS_FAILURE;
    736 	}
    737 	rval = urndis_ctrl_handle(sc, hdr, NULL, NULL);
    738 	if (rval != RNDIS_STATUS_SUCCESS) {
    739 		printf("%s: keepalive failed 0x%x\n", DEVNAME(sc), rval);
    740 		urndis_ctrl_reset(sc);
    741 	}
    742 
    743 	return rval;
    744 }
    745 #endif
    746 
    747 static int
    748 urndis_encap(struct urndis_softc *sc, struct mbuf *m, int idx)
    749 {
    750 	struct urndis_chain		*c;
    751 	usbd_status			 err;
    752 	struct rndis_packet_msg		*msg;
    753 
    754 	c = &sc->sc_data.sc_tx_chain[idx];
    755 
    756 	msg = (struct rndis_packet_msg *)c->sc_buf;
    757 
    758 	memset(msg, 0, sizeof(*msg));
    759 	msg->rm_type = htole32(REMOTE_NDIS_PACKET_MSG);
    760 	msg->rm_len = htole32(sizeof(*msg) + m->m_pkthdr.len);
    761 
    762 	msg->rm_dataoffset = htole32(RNDIS_DATA_OFFSET);
    763 	msg->rm_datalen = htole32(m->m_pkthdr.len);
    764 
    765 	m_copydata(m, 0, m->m_pkthdr.len,
    766 	    ((char*)msg + RNDIS_DATA_OFFSET + RNDIS_HEADER_OFFSET));
    767 
    768 	DPRINTF(("%s: urndis_encap type 0x%x len %u data(off %u len %u)\n",
    769 	    DEVNAME(sc),
    770 	    le32toh(msg->rm_type),
    771 	    le32toh(msg->rm_len),
    772 	    le32toh(msg->rm_dataoffset),
    773 	    le32toh(msg->rm_datalen)));
    774 
    775 	c->sc_mbuf = m;
    776 
    777 	usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, le32toh(msg->rm_len),
    778 	    USBD_FORCE_SHORT_XFER, 10000, urndis_txeof);
    779 
    780 	/* Transmit */
    781 	err = usbd_transfer(c->sc_xfer);
    782 	if (err != USBD_IN_PROGRESS) {
    783 		urndis_stop(GET_IFP(sc));
    784 		return(EIO);
    785 	}
    786 
    787 	sc->sc_data.sc_tx_cnt++;
    788 
    789 	return(0);
    790 }
    791 
    792 static void
    793 urndis_decap(struct urndis_softc *sc, struct urndis_chain *c, uint32_t len)
    794 {
    795 	struct mbuf		*m;
    796 	struct rndis_packet_msg	*msg;
    797 	struct ifnet		*ifp;
    798 	int			 s;
    799 	int			 offset;
    800 
    801 	ifp = GET_IFP(sc);
    802 	offset = 0;
    803 
    804 	while (len > 1) {
    805 		msg = (struct rndis_packet_msg *)((char*)c->sc_buf + offset);
    806 		m = c->sc_mbuf;
    807 
    808 		DPRINTF(("%s: urndis_decap buffer size left %u\n", DEVNAME(sc),
    809 		    len));
    810 
    811 		if (len < sizeof(*msg)) {
    812 			printf("%s: urndis_decap invalid buffer len %u < "
    813 			    "minimum header %zu\n",
    814 			    DEVNAME(sc),
    815 			    len,
    816 			    sizeof(*msg));
    817 			return;
    818 		}
    819 
    820 		DPRINTF(("%s: urndis_decap len %u data(off:%u len:%u) "
    821 		    "oobdata(off:%u len:%u nb:%u) perpacket(off:%u len:%u)\n",
    822 		    DEVNAME(sc),
    823 		    le32toh(msg->rm_len),
    824 		    le32toh(msg->rm_dataoffset),
    825 		    le32toh(msg->rm_datalen),
    826 		    le32toh(msg->rm_oobdataoffset),
    827 		    le32toh(msg->rm_oobdatalen),
    828 		    le32toh(msg->rm_oobdataelements),
    829 		    le32toh(msg->rm_pktinfooffset),
    830 		    le32toh(msg->rm_pktinfooffset)));
    831 
    832 		if (le32toh(msg->rm_type) != REMOTE_NDIS_PACKET_MSG) {
    833 			printf("%s: urndis_decap invalid type 0x%x != 0x%x\n",
    834 			    DEVNAME(sc),
    835 			    le32toh(msg->rm_type),
    836 			    REMOTE_NDIS_PACKET_MSG);
    837 			return;
    838 		}
    839 		if (le32toh(msg->rm_len) < sizeof(*msg)) {
    840 			printf("%s: urndis_decap invalid msg len %u < %zu\n",
    841 			    DEVNAME(sc),
    842 			    le32toh(msg->rm_len),
    843 			    sizeof(*msg));
    844 			return;
    845 		}
    846 		if (le32toh(msg->rm_len) > len) {
    847 			printf("%s: urndis_decap invalid msg len %u > buffer "
    848 			    "len %u\n",
    849 			    DEVNAME(sc),
    850 			    le32toh(msg->rm_len),
    851 			    len);
    852 			return;
    853 		}
    854 
    855 		if (le32toh(msg->rm_dataoffset) +
    856 		    le32toh(msg->rm_datalen) + RNDIS_HEADER_OFFSET
    857 		        > le32toh(msg->rm_len)) {
    858 			printf("%s: urndis_decap invalid data "
    859 			    "len/offset/end_position(%u/%u/%u) -> "
    860 			    "go out of receive buffer limit %u\n",
    861 			    DEVNAME(sc),
    862 			    le32toh(msg->rm_datalen),
    863 			    le32toh(msg->rm_dataoffset),
    864 			    le32toh(msg->rm_dataoffset) +
    865 			    le32toh(msg->rm_datalen) + (uint32_t)RNDIS_HEADER_OFFSET,
    866 			    le32toh(msg->rm_len));
    867 			return;
    868 		}
    869 
    870 		if (le32toh(msg->rm_datalen) < sizeof(struct ether_header)) {
    871 			ifp->if_ierrors++;
    872 			printf("%s: urndis_decap invalid ethernet size "
    873 			    "%d < %zu\n",
    874 			    DEVNAME(sc),
    875 			    le32toh(msg->rm_datalen),
    876 			    sizeof(struct ether_header));
    877 			return;
    878 		}
    879 
    880 		memcpy(mtod(m, char*),
    881 		    ((char*)&msg->rm_dataoffset + le32toh(msg->rm_dataoffset)),
    882 		    le32toh(msg->rm_datalen));
    883 		m->m_pkthdr.len = m->m_len = le32toh(msg->rm_datalen);
    884 
    885 		m_set_rcvif(m, ifp);
    886 
    887 		s = splnet();
    888 
    889 		if (urndis_newbuf(sc, c) == ENOBUFS) {
    890 			ifp->if_ierrors++;
    891 		} else {
    892 			if_percpuq_enqueue(ifp->if_percpuq, m);
    893 		}
    894 		splx(s);
    895 
    896 		offset += le32toh(msg->rm_len);
    897 		len -= le32toh(msg->rm_len);
    898 	}
    899 }
    900 
    901 static int
    902 urndis_newbuf(struct urndis_softc *sc, struct urndis_chain *c)
    903 {
    904 	struct mbuf *m_new = NULL;
    905 
    906 	MGETHDR(m_new, M_DONTWAIT, MT_DATA);
    907 	if (m_new == NULL) {
    908 		printf("%s: no memory for rx list -- packet dropped!\n",
    909 		    DEVNAME(sc));
    910 		return ENOBUFS;
    911 	}
    912 	MCLGET(m_new, M_DONTWAIT);
    913 	if (!(m_new->m_flags & M_EXT)) {
    914 		printf("%s: no memory for rx list -- packet dropped!\n",
    915 		    DEVNAME(sc));
    916 		m_freem(m_new);
    917 		return ENOBUFS;
    918 	}
    919 	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    920 
    921 	m_adj(m_new, ETHER_ALIGN);
    922 	c->sc_mbuf = m_new;
    923 	return 0;
    924 }
    925 
    926 static int
    927 urndis_rx_list_init(struct urndis_softc *sc)
    928 {
    929 	struct urndis_cdata	*cd;
    930 	struct urndis_chain	*c;
    931 	int			 i;
    932 
    933 	cd = &sc->sc_data;
    934 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
    935 		c = &cd->sc_rx_chain[i];
    936 		c->sc_softc = sc;
    937 
    938 		if (urndis_newbuf(sc, c) == ENOBUFS)
    939 			return ENOBUFS;
    940 
    941 		if (c->sc_xfer == NULL) {
    942 			int err = usbd_create_xfer(sc->sc_bulkin_pipe,
    943 			    RNDIS_BUFSZ, 0, 0, &c->sc_xfer);
    944 			if (err)
    945 				return err;
    946 			c->sc_buf = usbd_get_buffer(c->sc_xfer);
    947 		}
    948 	}
    949 
    950 	return 0;
    951 }
    952 
    953 static int
    954 urndis_tx_list_init(struct urndis_softc *sc)
    955 {
    956 	struct urndis_cdata	*cd;
    957 	struct urndis_chain	*c;
    958 	int			 i;
    959 
    960 	cd = &sc->sc_data;
    961 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
    962 		c = &cd->sc_tx_chain[i];
    963 		c->sc_softc = sc;
    964 		c->sc_mbuf = NULL;
    965 		if (c->sc_xfer == NULL) {
    966 			int err = usbd_create_xfer(sc->sc_bulkout_pipe,
    967 			    RNDIS_BUFSZ, USBD_FORCE_SHORT_XFER, 0, &c->sc_xfer);
    968 			if (err)
    969 				return err;
    970 			c->sc_buf = usbd_get_buffer(c->sc_xfer);
    971 		}
    972 	}
    973 	return 0;
    974 }
    975 
    976 static int
    977 urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data)
    978 {
    979 	struct urndis_softc	*sc;
    980 	int			 s, error;
    981 
    982 	sc = ifp->if_softc;
    983 	error = 0;
    984 
    985 	if (sc->sc_dying)
    986 		return EIO;
    987 
    988 	s = splnet();
    989 
    990 	switch(command) {
    991 	case SIOCSIFFLAGS:
    992 		if ((error = ifioctl_common(ifp, command, data)) != 0)
    993 			break;
    994 		if (ifp->if_flags & IFF_UP) {
    995 			if (!(ifp->if_flags & IFF_RUNNING))
    996 				urndis_init(ifp);
    997 		} else {
    998 			if (ifp->if_flags & IFF_RUNNING)
    999 				urndis_stop(ifp);
   1000 		}
   1001 		error = 0;
   1002 		break;
   1003 
   1004 	default:
   1005 		error = ether_ioctl(ifp, command, data);
   1006 		break;
   1007 	}
   1008 
   1009 	if (error == ENETRESET)
   1010 		error = 0;
   1011 
   1012 	splx(s);
   1013 	return error;
   1014 }
   1015 
   1016 #if 0
   1017 static void
   1018 urndis_watchdog(struct ifnet *ifp)
   1019 {
   1020 	struct urndis_softc *sc;
   1021 
   1022 	sc = ifp->if_softc;
   1023 
   1024 	if (sc->sc_dying)
   1025 		return;
   1026 
   1027 	ifp->if_oerrors++;
   1028 	printf("%s: watchdog timeout\n", DEVNAME(sc));
   1029 
   1030 	urndis_ctrl_keepalive(sc);
   1031 }
   1032 #endif
   1033 
   1034 static int
   1035 urndis_init(struct ifnet *ifp)
   1036 {
   1037 	struct urndis_softc	*sc;
   1038 	int			 i, s;
   1039 	int 			 err;
   1040 	usbd_status		 usberr;
   1041 
   1042 	sc = ifp->if_softc;
   1043 
   1044 	if (ifp->if_flags & IFF_RUNNING)
   1045 		return 0;
   1046 
   1047 	err = urndis_ctrl_init(sc);
   1048 	if (err != RNDIS_STATUS_SUCCESS)
   1049 		return EIO;
   1050 
   1051 	s = splnet();
   1052 
   1053 	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
   1054 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
   1055 	if (usberr) {
   1056 		printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
   1057 		    usbd_errstr(err));
   1058 		splx(s);
   1059 		return EIO;
   1060 	}
   1061 
   1062 	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
   1063 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
   1064 	if (usberr) {
   1065 		printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
   1066 		    usbd_errstr(err));
   1067 		splx(s);
   1068 		return EIO;
   1069 	}
   1070 
   1071 	err = urndis_tx_list_init(sc);
   1072 	if (err) {
   1073 		printf("%s: tx list init failed\n",
   1074 		    DEVNAME(sc));
   1075 		splx(s);
   1076 		return err;
   1077 	}
   1078 
   1079 	err = urndis_rx_list_init(sc);
   1080 	if (err) {
   1081 		printf("%s: rx list init failed\n",
   1082 		    DEVNAME(sc));
   1083 		splx(s);
   1084 		return err;
   1085 	}
   1086 
   1087 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
   1088 		struct urndis_chain *c;
   1089 
   1090 		c = &sc->sc_data.sc_rx_chain[i];
   1091 
   1092 		usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ,
   1093 		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof);
   1094 		usbd_transfer(c->sc_xfer);
   1095 	}
   1096 
   1097 	ifp->if_flags |= IFF_RUNNING;
   1098 	ifp->if_flags &= ~IFF_OACTIVE;
   1099 
   1100 	splx(s);
   1101 	return 0;
   1102 }
   1103 
   1104 static void
   1105 urndis_stop(struct ifnet *ifp)
   1106 {
   1107 	struct urndis_softc	*sc;
   1108 	usbd_status	 err;
   1109 	int		 i;
   1110 
   1111 	sc = ifp->if_softc;
   1112 
   1113 	ifp->if_timer = 0;
   1114 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1115 
   1116 	if (sc->sc_bulkin_pipe != NULL) {
   1117 		err = usbd_abort_pipe(sc->sc_bulkin_pipe);
   1118 		if (err)
   1119 			printf("%s: abort rx pipe failed: %s\n",
   1120 			    DEVNAME(sc), usbd_errstr(err));
   1121 	}
   1122 
   1123 	if (sc->sc_bulkout_pipe != NULL) {
   1124 		err = usbd_abort_pipe(sc->sc_bulkout_pipe);
   1125 		if (err)
   1126 			printf("%s: abort tx pipe failed: %s\n",
   1127 			    DEVNAME(sc), usbd_errstr(err));
   1128 	}
   1129 
   1130 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
   1131 		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
   1132 			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
   1133 			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
   1134 		}
   1135 		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
   1136 			usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
   1137 			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
   1138 		}
   1139 	}
   1140 
   1141 	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
   1142 		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
   1143 			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
   1144 			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
   1145 		}
   1146 		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
   1147 			usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
   1148 			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
   1149 		}
   1150 	}
   1151 
   1152 	/* Close pipes. */
   1153 	if (sc->sc_bulkin_pipe != NULL) {
   1154 		err = usbd_close_pipe(sc->sc_bulkin_pipe);
   1155 		if (err)
   1156 			printf("%s: close rx pipe failed: %s\n",
   1157 			    DEVNAME(sc), usbd_errstr(err));
   1158 		sc->sc_bulkin_pipe = NULL;
   1159 	}
   1160 
   1161 	if (sc->sc_bulkout_pipe != NULL) {
   1162 		err = usbd_close_pipe(sc->sc_bulkout_pipe);
   1163 		if (err)
   1164 			printf("%s: close tx pipe failed: %s\n",
   1165 			    DEVNAME(sc), usbd_errstr(err));
   1166 		sc->sc_bulkout_pipe = NULL;
   1167 	}
   1168 }
   1169 
   1170 static void
   1171 urndis_start(struct ifnet *ifp)
   1172 {
   1173 	struct urndis_softc	*sc;
   1174 	struct mbuf		*m_head = NULL;
   1175 
   1176 	sc = ifp->if_softc;
   1177 
   1178 	if (sc->sc_dying || (ifp->if_flags & IFF_OACTIVE))
   1179 		return;
   1180 
   1181 	IFQ_POLL(&ifp->if_snd, m_head);
   1182 	if (m_head == NULL)
   1183 		return;
   1184 
   1185 	if (urndis_encap(sc, m_head, 0)) {
   1186 		ifp->if_flags |= IFF_OACTIVE;
   1187 		return;
   1188 	}
   1189 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
   1190 
   1191 	/*
   1192 	 * If there's a BPF listener, bounce a copy of this frame
   1193 	 * to him.
   1194 	 */
   1195 	bpf_mtap(ifp, m_head, BPF_D_OUT);
   1196 
   1197 	ifp->if_flags |= IFF_OACTIVE;
   1198 
   1199 	/*
   1200 	 * Set a timeout in case the chip goes out to lunch.
   1201 	 */
   1202 	ifp->if_timer = 5;
   1203 
   1204 	return;
   1205 }
   1206 
   1207 static void
   1208 urndis_rxeof(struct usbd_xfer *xfer,
   1209     void *priv,
   1210     usbd_status status)
   1211 {
   1212 	struct urndis_chain	*c;
   1213 	struct urndis_softc	*sc;
   1214 	struct ifnet		*ifp;
   1215 	uint32_t		 total_len;
   1216 
   1217 	c = priv;
   1218 	sc = c->sc_softc;
   1219 	ifp = GET_IFP(sc);
   1220 	total_len = 0;
   1221 
   1222 	if (sc->sc_dying || !(ifp->if_flags & IFF_RUNNING))
   1223 		return;
   1224 
   1225 	if (status != USBD_NORMAL_COMPLETION) {
   1226 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
   1227 			return;
   1228 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
   1229 			printf("%s: usb errors on rx: %s\n",
   1230 			    DEVNAME(sc), usbd_errstr(status));
   1231 		}
   1232 		if (status == USBD_STALLED)
   1233 			usbd_clear_endpoint_stall_async(sc->sc_bulkin_pipe);
   1234 
   1235 		goto done;
   1236 	}
   1237 
   1238 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
   1239 	urndis_decap(sc, c, total_len);
   1240 
   1241 done:
   1242 	/* Setup new transfer. */
   1243 	usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, RNDIS_BUFSZ,
   1244 	    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, urndis_rxeof);
   1245 	usbd_transfer(c->sc_xfer);
   1246 }
   1247 
   1248 static void
   1249 urndis_txeof(struct usbd_xfer *xfer,
   1250     void *priv,
   1251     usbd_status status)
   1252 {
   1253 	struct urndis_chain	*c;
   1254 	struct urndis_softc	*sc;
   1255 	struct ifnet		*ifp;
   1256 	usbd_status		 err;
   1257 	int			 s;
   1258 
   1259 	c = priv;
   1260 	sc = c->sc_softc;
   1261 	ifp = GET_IFP(sc);
   1262 
   1263 	DPRINTF(("%s: urndis_txeof\n", DEVNAME(sc)));
   1264 
   1265 	if (sc->sc_dying)
   1266 		return;
   1267 
   1268 	s = splnet();
   1269 
   1270 	ifp->if_timer = 0;
   1271 	ifp->if_flags &= ~IFF_OACTIVE;
   1272 
   1273 	if (status != USBD_NORMAL_COMPLETION) {
   1274 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
   1275 			splx(s);
   1276 			return;
   1277 		}
   1278 		ifp->if_oerrors++;
   1279 		printf("%s: usb error on tx: %s\n", DEVNAME(sc),
   1280 		    usbd_errstr(status));
   1281 		if (status == USBD_STALLED)
   1282 			usbd_clear_endpoint_stall_async(sc->sc_bulkout_pipe);
   1283 		splx(s);
   1284 		return;
   1285 	}
   1286 
   1287 	usbd_get_xfer_status(c->sc_xfer, NULL, NULL, NULL, &err);
   1288 
   1289 	if (c->sc_mbuf != NULL) {
   1290 		m_freem(c->sc_mbuf);
   1291 		c->sc_mbuf = NULL;
   1292 	}
   1293 
   1294 	if (err)
   1295 		ifp->if_oerrors++;
   1296 	else
   1297 		ifp->if_opackets++;
   1298 
   1299 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
   1300 		urndis_start(ifp);
   1301 
   1302 	splx(s);
   1303 }
   1304 
   1305 static int
   1306 urndis_match(device_t parent, cfdata_t match, void *aux)
   1307 {
   1308 	struct usbif_attach_arg		*uiaa = aux;
   1309 	usb_interface_descriptor_t	*id;
   1310 
   1311 	if (!uiaa->uiaa_iface)
   1312 		return UMATCH_NONE;
   1313 
   1314 	id = usbd_get_interface_descriptor(uiaa->uiaa_iface);
   1315 	if (id == NULL)
   1316 		return UMATCH_NONE;
   1317 
   1318 	if (id->bInterfaceClass == UICLASS_WIRELESS &&
   1319 	    id->bInterfaceSubClass == UISUBCLASS_RF &&
   1320 	    id->bInterfaceProtocol == UIPROTO_RNDIS)
   1321 		return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
   1322 
   1323 	return usb_lookup(urndis_devs, uiaa->uiaa_vendor, uiaa->uiaa_product) != NULL ?
   1324 	    UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
   1325 }
   1326 
   1327 static void
   1328 urndis_attach(device_t parent, device_t self, void *aux)
   1329 {
   1330 	struct urndis_softc		*sc;
   1331 	struct usbif_attach_arg		*uiaa;
   1332 	struct ifnet			*ifp;
   1333 	usb_interface_descriptor_t	*id;
   1334 	usb_endpoint_descriptor_t	*ed;
   1335 	usb_config_descriptor_t		*cd;
   1336 	const usb_cdc_union_descriptor_t *ud;
   1337 	const usb_cdc_header_descriptor_t *desc;
   1338 	usbd_desc_iter_t		 iter;
   1339 	int				 if_ctl, if_data;
   1340 	int				 i, j, altcnt;
   1341 	int				 s;
   1342 	u_char				 eaddr[ETHER_ADDR_LEN];
   1343 	void				*buf;
   1344 	size_t				 bufsz;
   1345 	uint32_t			 filter;
   1346 	char				*devinfop;
   1347 
   1348 	sc = device_private(self);
   1349 	uiaa = aux;
   1350 	sc->sc_dev = self;
   1351 	sc->sc_udev = uiaa->uiaa_device;
   1352 
   1353 	aprint_naive("\n");
   1354 	aprint_normal("\n");
   1355 
   1356 	devinfop = usbd_devinfo_alloc(uiaa->uiaa_device, 0);
   1357 	aprint_normal_dev(self, "%s\n", devinfop);
   1358 	usbd_devinfo_free(devinfop);
   1359 
   1360 	sc->sc_iface_ctl = uiaa->uiaa_iface;
   1361 	id = usbd_get_interface_descriptor(sc->sc_iface_ctl);
   1362 	if_ctl = id->bInterfaceNumber;
   1363 	sc->sc_ifaceno_ctl = if_ctl;
   1364 	if_data = -1;
   1365 
   1366 	usb_desc_iter_init(sc->sc_udev, &iter);
   1367 	while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) {
   1368 
   1369 		if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
   1370 			continue;
   1371 		}
   1372 		switch (desc->bDescriptorSubtype) {
   1373 		case UDESCSUB_CDC_UNION:
   1374 			/* XXX bail out when found first? */
   1375 			ud = (const usb_cdc_union_descriptor_t *)desc;
   1376 			if (if_data == -1)
   1377 				if_data = ud->bSlaveInterface[0];
   1378 			break;
   1379 		}
   1380 	}
   1381 
   1382 	if (if_data == -1) {
   1383 		DPRINTF(("urndis_attach: no union interface\n"));
   1384 		sc->sc_iface_data = sc->sc_iface_ctl;
   1385 	} else {
   1386 		DPRINTF(("urndis_attach: union interface: ctl %u, data %u\n",
   1387 		    if_ctl, if_data));
   1388 		for (i = 0; i < uiaa->uiaa_nifaces; i++) {
   1389 			if (uiaa->uiaa_ifaces[i] != NULL) {
   1390 				id = usbd_get_interface_descriptor(
   1391 				    uiaa->uiaa_ifaces[i]);
   1392 				if (id != NULL && id->bInterfaceNumber ==
   1393 				    if_data) {
   1394 					sc->sc_iface_data = uiaa->uiaa_ifaces[i];
   1395 					uiaa->uiaa_ifaces[i] = NULL;
   1396 				}
   1397 			}
   1398 		}
   1399 	}
   1400 
   1401 	if (sc->sc_iface_data == NULL) {
   1402 		aprint_error("%s: no data interface\n", DEVNAME(sc));
   1403 		return;
   1404 	}
   1405 
   1406 	id = usbd_get_interface_descriptor(sc->sc_iface_data);
   1407 	cd = usbd_get_config_descriptor(sc->sc_udev);
   1408 	altcnt = usbd_get_no_alts(cd, id->bInterfaceNumber);
   1409 
   1410 	for (j = 0; j < altcnt; j++) {
   1411 		if (usbd_set_interface(sc->sc_iface_data, j)) {
   1412 			aprint_error("%s: interface alternate setting %u "
   1413 			    "failed\n", DEVNAME(sc), j);
   1414 			return;
   1415 		}
   1416 		/* Find endpoints. */
   1417 		id = usbd_get_interface_descriptor(sc->sc_iface_data);
   1418 		sc->sc_bulkin_no = sc->sc_bulkout_no = -1;
   1419 		for (i = 0; i < id->bNumEndpoints; i++) {
   1420 			ed = usbd_interface2endpoint_descriptor(
   1421 			    sc->sc_iface_data, i);
   1422 			if (!ed) {
   1423 				aprint_error("%s: no descriptor for bulk "
   1424 				    "endpoint %u\n", DEVNAME(sc), i);
   1425 				return;
   1426 			}
   1427 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
   1428 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
   1429 				sc->sc_bulkin_no = ed->bEndpointAddress;
   1430 			}
   1431 			else if (
   1432 			    UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
   1433 			    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
   1434 				sc->sc_bulkout_no = ed->bEndpointAddress;
   1435 			}
   1436 		}
   1437 
   1438 		if (sc->sc_bulkin_no != -1 && sc->sc_bulkout_no != -1) {
   1439 			DPRINTF(("%s: in=0x%x, out=0x%x\n",
   1440 			    DEVNAME(sc),
   1441 			    sc->sc_bulkin_no,
   1442 			    sc->sc_bulkout_no));
   1443 			goto found;
   1444 		}
   1445 	}
   1446 
   1447 	if (sc->sc_bulkin_no == -1)
   1448 		aprint_error("%s: could not find data bulk in\n", DEVNAME(sc));
   1449 	if (sc->sc_bulkout_no == -1 )
   1450 		aprint_error("%s: could not find data bulk out\n",DEVNAME(sc));
   1451 	return;
   1452 
   1453 	found:
   1454 
   1455 	ifp = GET_IFP(sc);
   1456 	ifp->if_softc = sc;
   1457 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
   1458 	ifp->if_start = urndis_start;
   1459 	ifp->if_ioctl = urndis_ioctl;
   1460 	ifp->if_init = urndis_init;
   1461 #if 0
   1462 	ifp->if_watchdog = urndis_watchdog;
   1463 #endif
   1464 
   1465 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
   1466 
   1467 	IFQ_SET_READY(&ifp->if_snd);
   1468 
   1469 	urndis_init(ifp);
   1470 
   1471 	s = splnet();
   1472 
   1473 	if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
   1474 	    &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
   1475 		aprint_error("%s: unable to get hardware address\n",
   1476 		    DEVNAME(sc));
   1477 		urndis_stop(ifp);
   1478 		splx(s);
   1479 		return;
   1480 	}
   1481 
   1482 	if (bufsz == ETHER_ADDR_LEN) {
   1483 		memcpy(eaddr, buf, ETHER_ADDR_LEN);
   1484 		aprint_normal("%s: address %s\n", DEVNAME(sc),
   1485 		    ether_sprintf(eaddr));
   1486 		kmem_free(buf, bufsz);
   1487 	} else {
   1488 		aprint_error("%s: invalid address\n", DEVNAME(sc));
   1489 		kmem_free(buf, bufsz);
   1490 		urndis_stop(ifp);
   1491 		splx(s);
   1492 		return;
   1493 	}
   1494 
   1495 	/* Initialize packet filter */
   1496 	sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST;
   1497 	sc->sc_filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST;
   1498 	filter = htole32(sc->sc_filter);
   1499 	if (urndis_ctrl_set(sc, OID_GEN_CURRENT_PACKET_FILTER, &filter,
   1500 	    sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
   1501 		aprint_error("%s: unable to set data filters\n", DEVNAME(sc));
   1502 		urndis_stop(ifp);
   1503 		splx(s);
   1504 		return;
   1505 	}
   1506 
   1507 	if_attach(ifp);
   1508 	ether_ifattach(ifp, eaddr);
   1509 	sc->sc_attached = 1;
   1510 
   1511 	splx(s);
   1512 }
   1513 
   1514 static int
   1515 urndis_detach(device_t self, int flags)
   1516 {
   1517 	struct urndis_softc	*sc;
   1518 	struct ifnet		*ifp;
   1519 	int			 s;
   1520 
   1521 	sc = device_private(self);
   1522 
   1523 	DPRINTF(("urndis_detach: %s flags %u\n", DEVNAME(sc),
   1524 	    flags));
   1525 
   1526 	if (!sc->sc_attached)
   1527 		return 0;
   1528 
   1529 	s = splusb();
   1530 
   1531 	ifp = GET_IFP(sc);
   1532 
   1533 	if (ifp->if_softc != NULL) {
   1534 		ether_ifdetach(ifp);
   1535 		if_detach(ifp);
   1536 	}
   1537 
   1538 	urndis_stop(ifp);
   1539 	sc->sc_attached = 0;
   1540 
   1541 	splx(s);
   1542 
   1543 	return 0;
   1544 }
   1545 
   1546 static int
   1547 urndis_activate(device_t self, enum devact act)
   1548 {
   1549 	struct urndis_softc *sc;
   1550 
   1551 	sc = device_private(self);
   1552 
   1553 	switch (act) {
   1554 	case DVACT_DEACTIVATE:
   1555 		sc->sc_dying = 1;
   1556 		return 0;
   1557 	}
   1558 
   1559 	return EOPNOTSUPP;
   1560 }
   1561