Home | History | Annotate | Line # | Download | only in usb
if_cdce.c revision 1.24
      1 /*	$NetBSD: if_cdce.c,v 1.24 2009/09/04 18:10:08 dyoung Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul (at) windriver.com>
      5  * Copyright (c) 2003 Craig Boston
      6  * Copyright (c) 2004 Daniel Hartmeier
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by Bill Paul.
     20  * 4. Neither the name of the author nor the names of any co-contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR
     28  * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     31  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     33  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     34  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 
     37 /*
     38  * USB Communication Device Class (Ethernet Networking Control Model)
     39  * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf
     40  *
     41  */
     42 
     43 #include <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.24 2009/09/04 18:10:08 dyoung Exp $");
     45 #include "bpfilter.h"
     46 #ifdef	__NetBSD__
     47 #include "opt_inet.h"
     48 #endif
     49 
     50 #include <sys/param.h>
     51 #include <sys/systm.h>
     52 #include <sys/sockio.h>
     53 #include <sys/mbuf.h>
     54 #include <sys/malloc.h>
     55 #include <sys/kernel.h>
     56 #include <sys/socket.h>
     57 #include <sys/device.h>
     58 
     59 #if NRND > 0
     60 #include <sys/rnd.h>
     61 #endif
     62 
     63 #include <net/if.h>
     64 #include <net/if_arp.h>
     65 #include <net/if_dl.h>
     66 #include <net/if_media.h>
     67 
     68 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
     69 
     70 #if NBPFILTER > 0
     71 #include <net/bpf.h>
     72 #endif
     73 
     74 #include <net/if_ether.h>
     75 #ifdef INET
     76 #include <netinet/in.h>
     77 #include <netinet/if_inarp.h>
     78 #endif
     79 
     80 
     81 
     82 #include <dev/usb/usb.h>
     83 #include <dev/usb/usbdi.h>
     84 #include <dev/usb/usbdi_util.h>
     85 #include <dev/usb/usbdevs.h>
     86 #include <dev/usb/usbcdc.h>
     87 
     88 #include <dev/usb/if_cdcereg.h>
     89 
     90 Static int	 cdce_tx_list_init(struct cdce_softc *);
     91 Static int	 cdce_rx_list_init(struct cdce_softc *);
     92 Static int	 cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
     93 		    struct mbuf *);
     94 Static int	 cdce_encap(struct cdce_softc *, struct mbuf *, int);
     95 Static void	 cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
     96 Static void	 cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
     97 Static void	 cdce_start(struct ifnet *);
     98 Static int	 cdce_ioctl(struct ifnet *, u_long, void *);
     99 Static void	 cdce_init(void *);
    100 Static void	 cdce_watchdog(struct ifnet *);
    101 Static void	 cdce_stop(struct cdce_softc *);
    102 Static uint32_t	 cdce_crc32(const void *, size_t);
    103 
    104 Static const struct cdce_type cdce_devs[] = {
    105   {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
    106   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
    107   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
    108   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
    109   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
    110   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
    111 };
    112 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
    113 
    114 int cdce_match(device_t, cfdata_t, void *);
    115 void cdce_attach(device_t, device_t, void *);
    116 int cdce_detach(device_t, int);
    117 int cdce_activate(device_t, enum devact);
    118 extern struct cfdriver cdce_cd;
    119 CFATTACH_DECL_NEW(cdce, sizeof(struct cdce_softc), cdce_match, cdce_attach,
    120     cdce_detach, cdce_activate);
    121 
    122 int
    123 cdce_match(device_t parent, cfdata_t match, void *aux)
    124 {
    125 	struct usbif_attach_arg *uaa = aux;
    126 
    127 	if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
    128 		return (UMATCH_VENDOR_PRODUCT);
    129 
    130 	if (uaa->class == UICLASS_CDC && uaa->subclass ==
    131 	    UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
    132 		return (UMATCH_IFACECLASS_GENERIC);
    133 
    134 	return (UMATCH_NONE);
    135 }
    136 
    137 void
    138 cdce_attach(device_t parent, device_t self, void *aux)
    139 {
    140 	struct cdce_softc *sc = device_private(self);
    141 	struct usbif_attach_arg *uaa = aux;
    142 	char				 *devinfop;
    143 	int				 s;
    144 	struct ifnet			*ifp;
    145 	usbd_device_handle		 dev = uaa->device;
    146 	const struct cdce_type		*t;
    147 	usb_interface_descriptor_t	*id;
    148 	usb_endpoint_descriptor_t	*ed;
    149 	const usb_cdc_union_descriptor_t *ud;
    150 	usb_config_descriptor_t		*cd;
    151 	int				 data_ifcno;
    152 	int				 i, j, numalts;
    153 	u_char				 eaddr[ETHER_ADDR_LEN];
    154 	const usb_cdc_ethernet_descriptor_t *ue;
    155 	char				 eaddr_str[USB_MAX_ENCODED_STRING_LEN];
    156 
    157 	devinfop = usbd_devinfo_alloc(dev, 0);
    158 	aprint_naive("\n");
    159 	aprint_normal("\n");
    160 	sc->cdce_dev = self;
    161 	aprint_normal_dev(self, "%s\n", devinfop);
    162 	usbd_devinfo_free(devinfop);
    163 
    164 	sc->cdce_udev = uaa->device;
    165 	sc->cdce_ctl_iface = uaa->iface;
    166 
    167 	t = cdce_lookup(uaa->vendor, uaa->product);
    168 	if (t)
    169 		sc->cdce_flags = t->cdce_flags;
    170 
    171 	if (sc->cdce_flags & CDCE_NO_UNION)
    172 		sc->cdce_data_iface = sc->cdce_ctl_iface;
    173 	else {
    174 		ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
    175 		    UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
    176 		if (ud == NULL) {
    177 			aprint_error_dev(self, "no union descriptor\n");
    178 			return;
    179 		}
    180 		data_ifcno = ud->bSlaveInterface[0];
    181 
    182 		for (i = 0; i < uaa->nifaces; i++) {
    183 			if (uaa->ifaces[i] != NULL) {
    184 				id = usbd_get_interface_descriptor(
    185 				    uaa->ifaces[i]);
    186 				if (id != NULL && id->bInterfaceNumber ==
    187 				    data_ifcno) {
    188 					sc->cdce_data_iface = uaa->ifaces[i];
    189 					uaa->ifaces[i] = NULL;
    190 				}
    191 			}
    192 		}
    193 	}
    194 
    195 	if (sc->cdce_data_iface == NULL) {
    196 		aprint_error_dev(self, "no data interface\n");
    197 		return;
    198 	}
    199 
    200 	/*
    201 	 * <quote>
    202 	 *  The Data Class interface of a networking device shall have a minimum
    203 	 *  of two interface settings. The first setting (the default interface
    204 	 *  setting) includes no endpoints and therefore no networking traffic is
    205 	 *  exchanged whenever the default interface setting is selected. One or
    206 	 *  more additional interface settings are used for normal operation, and
    207 	 *  therefore each includes a pair of endpoints (one IN, and one OUT) to
    208 	 *  exchange network traffic. Select an alternate interface setting to
    209 	 *  initialize the network aspects of the device and to enable the
    210 	 *  exchange of network traffic.
    211 	 * </quote>
    212 	 *
    213 	 * Some devices, most notably cable modems, include interface settings
    214 	 * that have no IN or OUT endpoint, therefore loop through the list of all
    215 	 * available interface settings looking for one with both IN and OUT
    216 	 * endpoints.
    217 	 */
    218 	id = usbd_get_interface_descriptor(sc->cdce_data_iface);
    219 	cd = usbd_get_config_descriptor(sc->cdce_udev);
    220 	numalts = usbd_get_no_alts(cd, id->bInterfaceNumber);
    221 
    222 	for (j = 0; j < numalts; j++) {
    223 		if (usbd_set_interface(sc->cdce_data_iface, j)) {
    224 			aprint_error_dev(sc->cdce_dev,
    225 					"setting alternate interface failed\n");
    226 			return;
    227 		}
    228 		/* Find endpoints. */
    229 		id = usbd_get_interface_descriptor(sc->cdce_data_iface);
    230 		sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
    231 		for (i = 0; i < id->bNumEndpoints; i++) {
    232 			ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
    233 			if (!ed) {
    234 				aprint_error_dev(self,
    235 						"could not read endpoint descriptor\n");
    236 				return;
    237 			}
    238 			if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    239 					UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    240 				sc->cdce_bulkin_no = ed->bEndpointAddress;
    241 			} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    242 					UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    243 				sc->cdce_bulkout_no = ed->bEndpointAddress;
    244 			} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    245 					UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    246 				/* XXX: CDC spec defines an interrupt pipe, but it is not
    247 				 * needed for simple host-to-host applications. */
    248 			} else {
    249 				aprint_error_dev(self, "unexpected endpoint\n");
    250 			}
    251 		}
    252 		/* If we found something, try and use it... */
    253 		if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1))
    254 			break;
    255 	}
    256 
    257 	if (sc->cdce_bulkin_no == -1) {
    258 		aprint_error_dev(self, "could not find data bulk in\n");
    259 		return;
    260 	}
    261 	if (sc->cdce_bulkout_no == -1 ) {
    262 		aprint_error_dev(self, "could not find data bulk out\n");
    263 		return;
    264 	}
    265 
    266 	ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
    267 	    UDESC_INTERFACE, UDESCSUB_CDC_ENF);
    268 	if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
    269 		aprint_normal_dev(self, "faking address\n");
    270 		eaddr[0]= 0x2a;
    271 		memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t));
    272 		eaddr[5] = (u_int8_t)(device_unit(sc->cdce_dev));
    273 	} else {
    274 		(void)ether_nonstatic_aton(eaddr, eaddr_str);
    275 	}
    276 
    277 	s = splnet();
    278 
    279 	aprint_normal_dev(self, "address %s\n", ether_sprintf(eaddr));
    280 
    281 	ifp = GET_IFP(sc);
    282 	ifp->if_softc = sc;
    283 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    284 	ifp->if_ioctl = cdce_ioctl;
    285 	ifp->if_start = cdce_start;
    286 	ifp->if_watchdog = cdce_watchdog;
    287 	strncpy(ifp->if_xname, device_xname(sc->cdce_dev), IFNAMSIZ);
    288 
    289 	IFQ_SET_READY(&ifp->if_snd);
    290 
    291 	if_attach(ifp);
    292 	ether_ifattach(ifp, eaddr);
    293 
    294 	sc->cdce_attached = 1;
    295 	splx(s);
    296 
    297 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
    298 	    sc->cdce_dev);
    299 
    300 	return;
    301 }
    302 
    303 int
    304 cdce_detach(device_t self, int flags)
    305 {
    306 	struct cdce_softc *sc = device_private(self);
    307 	struct ifnet	*ifp = GET_IFP(sc);
    308 	int		 s;
    309 
    310 	s = splusb();
    311 
    312 	if (!sc->cdce_attached) {
    313 		splx(s);
    314 		return (0);
    315 	}
    316 
    317 	if (ifp->if_flags & IFF_RUNNING)
    318 		cdce_stop(sc);
    319 
    320 	ether_ifdetach(ifp);
    321 
    322 	if_detach(ifp);
    323 
    324 	sc->cdce_attached = 0;
    325 	splx(s);
    326 
    327 	return (0);
    328 }
    329 
    330 Static void
    331 cdce_start(struct ifnet *ifp)
    332 {
    333 	struct cdce_softc	*sc = ifp->if_softc;
    334 	struct mbuf		*m_head = NULL;
    335 
    336 	if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
    337 		return;
    338 
    339 	IFQ_POLL(&ifp->if_snd, m_head);
    340 	if (m_head == NULL)
    341 		return;
    342 
    343 	if (cdce_encap(sc, m_head, 0)) {
    344 		ifp->if_flags |= IFF_OACTIVE;
    345 		return;
    346 	}
    347 
    348 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
    349 
    350 #if NBPFILTER > 0
    351 	if (ifp->if_bpf)
    352 		BPF_MTAP(ifp, m_head);
    353 #endif
    354 
    355 	ifp->if_flags |= IFF_OACTIVE;
    356 
    357 	ifp->if_timer = 6;
    358 }
    359 
    360 Static int
    361 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
    362 {
    363 	struct cdce_chain	*c;
    364 	usbd_status		 err;
    365 	int			 extra = 0;
    366 
    367 	c = &sc->cdce_cdata.cdce_tx_chain[idx];
    368 
    369 	m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
    370 	if (sc->cdce_flags & CDCE_ZAURUS) {
    371 		/* Zaurus wants a 32-bit CRC appended to every frame */
    372 		u_int32_t crc;
    373 
    374 		crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
    375 		memcpy(c->cdce_buf + m->m_pkthdr.len, &crc, 4);
    376 		extra = 4;
    377 	}
    378 	c->cdce_mbuf = m;
    379 
    380 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
    381 	    m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof);
    382 	err = usbd_transfer(c->cdce_xfer);
    383 	if (err != USBD_IN_PROGRESS) {
    384 		cdce_stop(sc);
    385 		return (EIO);
    386 	}
    387 
    388 	sc->cdce_cdata.cdce_tx_cnt++;
    389 
    390 	return (0);
    391 }
    392 
    393 Static void
    394 cdce_stop(struct cdce_softc *sc)
    395 {
    396 	usbd_status	 err;
    397 	struct ifnet	*ifp = GET_IFP(sc);
    398 	int		 i;
    399 
    400 	ifp->if_timer = 0;
    401 
    402 	if (sc->cdce_bulkin_pipe != NULL) {
    403 		err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
    404 		if (err)
    405 			printf("%s: abort rx pipe failed: %s\n",
    406 			    device_xname(sc->cdce_dev), usbd_errstr(err));
    407 		err = usbd_close_pipe(sc->cdce_bulkin_pipe);
    408 		if (err)
    409 			printf("%s: close rx pipe failed: %s\n",
    410 			    device_xname(sc->cdce_dev), usbd_errstr(err));
    411 		sc->cdce_bulkin_pipe = NULL;
    412 	}
    413 
    414 	if (sc->cdce_bulkout_pipe != NULL) {
    415 		err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
    416 		if (err)
    417 			printf("%s: abort tx pipe failed: %s\n",
    418 			    device_xname(sc->cdce_dev), usbd_errstr(err));
    419 		err = usbd_close_pipe(sc->cdce_bulkout_pipe);
    420 		if (err)
    421 			printf("%s: close tx pipe failed: %s\n",
    422 			    device_xname(sc->cdce_dev), usbd_errstr(err));
    423 		sc->cdce_bulkout_pipe = NULL;
    424 	}
    425 
    426 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    427 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
    428 			m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
    429 			sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
    430 		}
    431 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
    432 			usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
    433 			sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
    434 		}
    435 	}
    436 
    437 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    438 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
    439 			m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
    440 			sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
    441 		}
    442 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
    443 			usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
    444 			sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
    445 		}
    446 	}
    447 
    448 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    449 }
    450 
    451 Static int
    452 cdce_ioctl(struct ifnet *ifp, u_long command, void *data)
    453 {
    454 	struct cdce_softc	*sc = ifp->if_softc;
    455 	struct ifaddr		*ifa = (struct ifaddr *)data;
    456 	struct ifreq		*ifr = (struct ifreq *)data;
    457 	int			 s, error = 0;
    458 
    459 	if (sc->cdce_dying)
    460 		return (EIO);
    461 
    462 	s = splnet();
    463 
    464 	switch(command) {
    465 	case SIOCINITIFADDR:
    466 		ifp->if_flags |= IFF_UP;
    467 		cdce_init(sc);
    468 		switch (ifa->ifa_addr->sa_family) {
    469 #ifdef INET
    470 		case AF_INET:
    471 			arp_ifinit(ifp, ifa);
    472 			break;
    473 #endif /* INET */
    474 		}
    475 		break;
    476 
    477 	case SIOCSIFMTU:
    478 		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
    479 			error = EINVAL;
    480 		else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET)
    481 			error = 0;
    482 		break;
    483 
    484 	case SIOCSIFFLAGS:
    485 		if ((error = ifioctl_common(ifp, command, data)) != 0)
    486 			break;
    487 		/* XXX re-use ether_ioctl() */
    488 		switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) {
    489 		case IFF_UP:
    490 			cdce_init(sc);
    491 			break;
    492 		case IFF_RUNNING:
    493 			cdce_stop(sc);
    494 			break;
    495 		default:
    496 			break;
    497 		}
    498 		break;
    499 
    500 	default:
    501 		error = ether_ioctl(ifp, command, data);
    502 		break;
    503 	}
    504 
    505 	splx(s);
    506 
    507 	return (error);
    508 }
    509 
    510 Static void
    511 cdce_watchdog(struct ifnet *ifp)
    512 {
    513 	struct cdce_softc	*sc = ifp->if_softc;
    514 
    515 	if (sc->cdce_dying)
    516 		return;
    517 
    518 	ifp->if_oerrors++;
    519 	printf("%s: watchdog timeout\n", device_xname(sc->cdce_dev));
    520 }
    521 
    522 Static void
    523 cdce_init(void *xsc)
    524 {
    525 	struct cdce_softc	*sc = xsc;
    526 	struct ifnet		*ifp = GET_IFP(sc);
    527 	struct cdce_chain	*c;
    528 	usbd_status		 err;
    529 	int			 s, i;
    530 
    531 	if (ifp->if_flags & IFF_RUNNING)
    532 		return;
    533 
    534 	s = splnet();
    535 
    536 	if (cdce_tx_list_init(sc) == ENOBUFS) {
    537 		printf("%s: tx list init failed\n", device_xname(sc->cdce_dev));
    538 		splx(s);
    539 		return;
    540 	}
    541 
    542 	if (cdce_rx_list_init(sc) == ENOBUFS) {
    543 		printf("%s: rx list init failed\n", device_xname(sc->cdce_dev));
    544 		splx(s);
    545 		return;
    546 	}
    547 
    548 	/* Maybe set multicast / broadcast here??? */
    549 
    550 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
    551 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    552 	if (err) {
    553 		printf("%s: open rx pipe failed: %s\n", device_xname(sc->cdce_dev),
    554 		    usbd_errstr(err));
    555 		splx(s);
    556 		return;
    557 	}
    558 
    559 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
    560 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    561 	if (err) {
    562 		printf("%s: open tx pipe failed: %s\n",
    563 		    device_xname(sc->cdce_dev), usbd_errstr(err));
    564 		splx(s);
    565 		return;
    566 	}
    567 
    568 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    569 		c = &sc->cdce_cdata.cdce_rx_chain[i];
    570 		usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
    571 		    c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    572 		    USBD_NO_TIMEOUT, cdce_rxeof);
    573 		usbd_transfer(c->cdce_xfer);
    574 	}
    575 
    576 	ifp->if_flags |= IFF_RUNNING;
    577 	ifp->if_flags &= ~IFF_OACTIVE;
    578 
    579 	splx(s);
    580 }
    581 
    582 Static int
    583 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
    584 {
    585 	struct mbuf	*m_new = NULL;
    586 
    587 	if (m == NULL) {
    588 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
    589 		if (m_new == NULL) {
    590 			printf("%s: no memory for rx list "
    591 			    "-- packet dropped!\n", device_xname(sc->cdce_dev));
    592 			return (ENOBUFS);
    593 		}
    594 		MCLGET(m_new, M_DONTWAIT);
    595 		if (!(m_new->m_flags & M_EXT)) {
    596 			printf("%s: no memory for rx list "
    597 			    "-- packet dropped!\n", device_xname(sc->cdce_dev));
    598 			m_freem(m_new);
    599 			return (ENOBUFS);
    600 		}
    601 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    602 	} else {
    603 		m_new = m;
    604 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    605 		m_new->m_data = m_new->m_ext.ext_buf;
    606 	}
    607 	c->cdce_mbuf = m_new;
    608 	return (0);
    609 }
    610 
    611 Static int
    612 cdce_rx_list_init(struct cdce_softc *sc)
    613 {
    614 	struct cdce_cdata	*cd;
    615 	struct cdce_chain	*c;
    616 	int			 i;
    617 
    618 	cd = &sc->cdce_cdata;
    619 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    620 		c = &cd->cdce_rx_chain[i];
    621 		c->cdce_sc = sc;
    622 		c->cdce_idx = i;
    623 		if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
    624 			return (ENOBUFS);
    625 		if (c->cdce_xfer == NULL) {
    626 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
    627 			if (c->cdce_xfer == NULL)
    628 				return (ENOBUFS);
    629 			c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
    630 			if (c->cdce_buf == NULL)
    631 				return (ENOBUFS);
    632 		}
    633 	}
    634 
    635 	return (0);
    636 }
    637 
    638 Static int
    639 cdce_tx_list_init(struct cdce_softc *sc)
    640 {
    641 	struct cdce_cdata	*cd;
    642 	struct cdce_chain	*c;
    643 	int			 i;
    644 
    645 	cd = &sc->cdce_cdata;
    646 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    647 		c = &cd->cdce_tx_chain[i];
    648 		c->cdce_sc = sc;
    649 		c->cdce_idx = i;
    650 		c->cdce_mbuf = NULL;
    651 		if (c->cdce_xfer == NULL) {
    652 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
    653 			if (c->cdce_xfer == NULL)
    654 				return (ENOBUFS);
    655 			c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
    656 			if (c->cdce_buf == NULL)
    657 				return (ENOBUFS);
    658 		}
    659 	}
    660 
    661 	return (0);
    662 }
    663 
    664 Static void
    665 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    666 {
    667 	struct cdce_chain	*c = priv;
    668 	struct cdce_softc	*sc = c->cdce_sc;
    669 	struct ifnet		*ifp = GET_IFP(sc);
    670 	struct mbuf		*m;
    671 	int			 total_len = 0;
    672 	int			 s;
    673 
    674 	if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
    675 		return;
    676 
    677 	if (status != USBD_NORMAL_COMPLETION) {
    678 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    679 			return;
    680 		if (sc->cdce_rxeof_errors == 0)
    681 			printf("%s: usb error on rx: %s\n",
    682 			    device_xname(sc->cdce_dev), usbd_errstr(status));
    683 		if (status == USBD_STALLED)
    684 			usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
    685 		DELAY(sc->cdce_rxeof_errors * 10000);
    686 		sc->cdce_rxeof_errors++;
    687 		goto done;
    688 	}
    689 
    690 	sc->cdce_rxeof_errors = 0;
    691 
    692 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    693 	if (sc->cdce_flags & CDCE_ZAURUS)
    694 		total_len -= 4;	/* Strip off CRC added by Zaurus */
    695 	if (total_len <= 1)
    696 		goto done;
    697 
    698 	m = c->cdce_mbuf;
    699 	memcpy(mtod(m, char *), c->cdce_buf, total_len);
    700 
    701 	if (total_len < sizeof(struct ether_header)) {
    702 		ifp->if_ierrors++;
    703 		goto done;
    704 	}
    705 
    706 	ifp->if_ipackets++;
    707 	m->m_pkthdr.len = m->m_len = total_len;
    708 	m->m_pkthdr.rcvif = ifp;
    709 
    710 	s = splnet();
    711 
    712 	if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
    713 		ifp->if_ierrors++;
    714 		goto done1;
    715 	}
    716 
    717 #if NBPFILTER > 0
    718 	if (ifp->if_bpf)
    719 		BPF_MTAP(ifp, m);
    720 #endif
    721 
    722 	(*(ifp)->if_input)((ifp), (m));
    723 
    724 done1:
    725 	splx(s);
    726 
    727 done:
    728 	/* Setup new transfer. */
    729 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
    730 	    CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    731 	    cdce_rxeof);
    732 	usbd_transfer(c->cdce_xfer);
    733 }
    734 
    735 Static void
    736 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
    737     usbd_status status)
    738 {
    739 	struct cdce_chain	*c = priv;
    740 	struct cdce_softc	*sc = c->cdce_sc;
    741 	struct ifnet		*ifp = GET_IFP(sc);
    742 	usbd_status		 err;
    743 	int			 s;
    744 
    745 	if (sc->cdce_dying)
    746 		return;
    747 
    748 	s = splnet();
    749 
    750 	ifp->if_timer = 0;
    751 	ifp->if_flags &= ~IFF_OACTIVE;
    752 
    753 	if (status != USBD_NORMAL_COMPLETION) {
    754 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    755 			splx(s);
    756 			return;
    757 		}
    758 		ifp->if_oerrors++;
    759 		printf("%s: usb error on tx: %s\n", device_xname(sc->cdce_dev),
    760 		    usbd_errstr(status));
    761 		if (status == USBD_STALLED)
    762 			usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
    763 		splx(s);
    764 		return;
    765 	}
    766 
    767 	usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
    768 
    769 	if (c->cdce_mbuf != NULL) {
    770 		m_freem(c->cdce_mbuf);
    771 		c->cdce_mbuf = NULL;
    772 	}
    773 
    774 	if (err)
    775 		ifp->if_oerrors++;
    776 	else
    777 		ifp->if_opackets++;
    778 
    779 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    780 		cdce_start(ifp);
    781 
    782 	splx(s);
    783 }
    784 
    785 int
    786 cdce_activate(device_t self, enum devact act)
    787 {
    788 	struct cdce_softc *sc = device_private(self);
    789 
    790 	switch (act) {
    791 	case DVACT_ACTIVATE:
    792 		return (EOPNOTSUPP);
    793 		break;
    794 
    795 	case DVACT_DEACTIVATE:
    796 		if_deactivate(GET_IFP(sc));
    797 		sc->cdce_dying = 1;
    798 		break;
    799 	}
    800 	return (0);
    801 }
    802 
    803 
    804 /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
    805  *  code or tables extracted from it, as desired without restriction.
    806  */
    807 
    808 static uint32_t cdce_crc32_tab[] = {
    809 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    810 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    811 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    812 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    813 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
    814 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    815 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
    816 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    817 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    818 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    819 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
    820 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    821 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    822 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    823 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    824 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    825 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    826 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    827 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    828 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    829 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    830 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    831 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    832 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    833 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    834 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    835 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    836 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    837 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    838 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    839 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    840 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    841 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    842 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    843 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    844 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    845 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    846 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    847 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    848 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    849 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    850 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    851 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    852 };
    853 
    854 Static uint32_t
    855 cdce_crc32(const void *buf, size_t size)
    856 {
    857 	const uint8_t *p;
    858 	uint32_t crc;
    859 
    860 	p = buf;
    861 	crc = ~0U;
    862 
    863 	while (size--)
    864 		crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    865 
    866 	return (crc ^ ~0U);
    867 }
    868