Home | History | Annotate | Line # | Download | only in usb
if_cdce.c revision 1.12.10.7
      1 /*	$NetBSD: if_cdce.c,v 1.12.10.7 2007/06/18 13:40:59 itohy 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.12.10.7 2007/06/18 13:40:59 itohy Exp $");
     45 #include "bpfilter.h"
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/sockio.h>
     50 #include <sys/mbuf.h>
     51 #include <sys/malloc.h>
     52 #include <sys/kernel.h>
     53 #include <sys/socket.h>
     54 #include <sys/device.h>
     55 #if defined(__OpenBSD__)
     56 #include <sys/proc.h>
     57 #endif
     58 
     59 #if NRND > 0
     60 #include <sys/rnd.h>
     61 #endif
     62 
     63 #include <net/if.h>
     64 #if defined(__NetBSD__)
     65 #include <net/if_arp.h>
     66 #endif
     67 #include <net/if_dl.h>
     68 #include <net/if_media.h>
     69 
     70 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
     71 
     72 #if NBPFILTER > 0
     73 #include <net/bpf.h>
     74 #endif
     75 
     76 #if defined(__NetBSD__)
     77 #include <net/if_ether.h>
     78 #ifdef INET
     79 #include <netinet/in.h>
     80 #include <netinet/if_inarp.h>
     81 #endif
     82 #endif /* defined(__NetBSD__) */
     83 
     84 #if defined(__OpenBSD__)
     85 #ifdef INET
     86 #include <netinet/in.h>
     87 #include <netinet/in_systm.h>
     88 #include <netinet/in_var.h>
     89 #include <netinet/ip.h>
     90 #include <netinet/if_ether.h>
     91 #endif
     92 #endif /* defined(__OpenBSD__) */
     93 
     94 
     95 #include <dev/usb/usb.h>
     96 #include <dev/usb/usbdi.h>
     97 #include <dev/usb/usbdi_util.h>
     98 #include <dev/usb/usbdevs.h>
     99 #include <dev/usb/usbcdc.h>
    100 #include <dev/usb/usb_ethersubr.h>
    101 
    102 #include <dev/usb/if_cdcereg.h>
    103 
    104 Static int	 cdce_encap(struct cdce_softc *, struct mbuf *, int);
    105 Static void	 cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    106 Static void	 cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    107 Static void	 cdce_start(struct ifnet *);
    108 Static int	 cdce_ioctl(struct ifnet *, u_long, usb_ioctlarg_t);
    109 Static int	 cdce_init(struct ifnet *);
    110 Static void	 cdce_watchdog(struct ifnet *);
    111 Static void	 cdce_stop(struct ifnet *, int);
    112 Static uint32_t	 cdce_crc32(struct mbuf *);
    113 
    114 Static const struct cdce_type cdce_devs[] = {
    115   {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION },
    116   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
    117   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION },
    118   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION },
    119   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION },
    120   {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION },
    121 };
    122 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
    123 
    124 USB_DECLARE_DRIVER(cdce);
    125 
    126 USB_MATCH(cdce)
    127 {
    128 #ifndef USB_USE_IFATTACH
    129 	USB_MATCH_START(cdce, uaa);
    130 	usb_interface_descriptor_t *id;
    131 
    132 	if (uaa->iface == NULL)
    133 		return (UMATCH_NONE);
    134 
    135 	id = usbd_get_interface_descriptor(uaa->iface);
    136 	if (id == NULL)
    137 		return (UMATCH_NONE);
    138 #else
    139 	USB_IFMATCH_START(cdce, uaa);
    140 #endif /* USB_USE_IFATTACH */
    141 
    142 	if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
    143 		return (UMATCH_VENDOR_PRODUCT);
    144 
    145 	if (
    146 #ifndef USB_USE_IFATTACH
    147 	    id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
    148 #else
    149 	    uaa->class == UICLASS_CDC && uaa->subclass ==
    150 #endif /* USB_USE_IFATTACH */
    151 	    UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
    152 		return (UMATCH_IFACECLASS_GENERIC);
    153 
    154 	return (UMATCH_NONE);
    155 }
    156 
    157 USB_ATTACH(cdce)
    158 {
    159 #ifndef USB_USE_IFATTACH
    160 	USB_ATTACH_START(cdce, sc, uaa);
    161 #else
    162 	USB_IFATTACH_START(cdce, sc, uaa);
    163 #endif /* USB_USE_IFATTACH */
    164 	char				 *devinfop;
    165 	int				 s;
    166 	struct ifnet			*ifp;
    167 	usbd_device_handle		 dev = uaa->device;
    168 	const struct cdce_type		*t;
    169 	usb_interface_descriptor_t	*id;
    170 	usb_endpoint_descriptor_t	*ed;
    171 	const usb_cdc_union_descriptor_t *ud;
    172 	int				 data_ifcno;
    173 	int				 i;
    174 	u_char				 eaddr[ETHER_ADDR_LEN];
    175 	const usb_cdc_ethernet_descriptor_t *ue;
    176 	char				 eaddr_str[USB_MAX_ENCODED_STRING_LEN];
    177 
    178 	devinfop = usbd_devinfo_alloc(dev, 0);
    179 	USB_ATTACH_SETUP;
    180 	printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfop);
    181 	usbd_devinfo_free(devinfop);
    182 
    183 	sc->cdce_udev = uaa->device;
    184 	sc->cdce_ctl_iface = uaa->iface;
    185 
    186 	t = cdce_lookup(uaa->vendor, uaa->product);
    187 	if (t)
    188 		sc->cdce_flags = t->cdce_flags;
    189 
    190 	if (sc->cdce_flags & CDCE_NO_UNION)
    191 		sc->cdce_data_iface = sc->cdce_ctl_iface;
    192 	else {
    193 		ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev,
    194 		    UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION);
    195 		if (ud == NULL) {
    196 			printf("%s: no union descriptor\n",
    197 			    USBDEVNAME(sc->cdce_dev));
    198 			USB_ATTACH_ERROR_RETURN;
    199 		}
    200 		data_ifcno = ud->bSlaveInterface[0];
    201 
    202 		for (i = 0; i < uaa->nifaces; i++) {
    203 			if (uaa->ifaces[i] != NULL) {
    204 				id = usbd_get_interface_descriptor(
    205 				    uaa->ifaces[i]);
    206 				if (id != NULL && id->bInterfaceNumber ==
    207 				    data_ifcno) {
    208 					sc->cdce_data_iface = uaa->ifaces[i];
    209 					uaa->ifaces[i] = NULL;
    210 				}
    211 			}
    212 		}
    213 	}
    214 
    215 	if (sc->cdce_data_iface == NULL) {
    216 		printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev));
    217 		USB_ATTACH_ERROR_RETURN;
    218 	}
    219 
    220 	/* Find endpoints. */
    221 	id = usbd_get_interface_descriptor(sc->cdce_data_iface);
    222 	sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
    223 	for (i = 0; i < id->bNumEndpoints; i++) {
    224 		ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
    225 		if (!ed) {
    226 			printf("%s: could not read endpoint descriptor\n",
    227 			    USBDEVNAME(sc->cdce_dev));
    228 			USB_ATTACH_ERROR_RETURN;
    229 		}
    230 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    231 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    232 			sc->cdce_bulkin_no = ed->bEndpointAddress;
    233 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    234 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    235 			sc->cdce_bulkout_no = ed->bEndpointAddress;
    236 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    237 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    238 			/* XXX: CDC spec defines an interrupt pipe, but it is not
    239 			 * needed for simple host-to-host applications. */
    240 		} else {
    241 			printf("%s: unexpected endpoint\n",
    242 			    USBDEVNAME(sc->cdce_dev));
    243 		}
    244 	}
    245 
    246 	if (sc->cdce_bulkin_no == -1) {
    247 		printf("%s: could not find data bulk in\n",
    248 		    USBDEVNAME(sc->cdce_dev));
    249 		USB_ATTACH_ERROR_RETURN;
    250 	}
    251 	if (sc->cdce_bulkout_no == -1 ) {
    252 		printf("%s: could not find data bulk out\n",
    253 		    USBDEVNAME(sc->cdce_dev));
    254 		USB_ATTACH_ERROR_RETURN;
    255 	}
    256 
    257 	ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev,
    258             UDESC_INTERFACE, UDESCSUB_CDC_ENF);
    259 	if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) {
    260 		printf("%s: faking address\n", USBDEVNAME(sc->cdce_dev));
    261 		eaddr[0]= 0x2a;
    262 		memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t));
    263 		eaddr[5] = (u_int8_t)(device_unit(&sc->cdce_dev));
    264 	} else {
    265 		int j;
    266 
    267 		memset(eaddr, 0, ETHER_ADDR_LEN);
    268 		for (j = 0; j < ETHER_ADDR_LEN * 2; j++) {
    269 			int c = eaddr_str[j];
    270 
    271 			if ('0' <= c && c <= '9')
    272 				c -= '0';
    273 			else
    274 				c -= 'A' - 10;
    275 			c &= 0xf;
    276 			if (c%2 == 0)
    277 				c <<= 4;
    278 			eaddr[j / 2] |= c;
    279 		}
    280 	}
    281 
    282 	s = splnet();
    283 
    284 	printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev),
    285 	    ether_sprintf(eaddr));
    286 
    287 	ifp = GET_IFP(sc);
    288 	ifp->if_softc = sc;
    289 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    290 	ifp->if_ioctl = cdce_ioctl;
    291 	ifp->if_start = cdce_start;
    292 	ifp->if_init = cdce_init;
    293 	ifp->if_stop = cdce_stop;
    294 	ifp->if_watchdog = cdce_watchdog;
    295 	strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
    296 
    297 	IFQ_SET_READY(&ifp->if_snd);
    298 
    299 	if_attach(ifp);
    300 	Ether_ifattach(ifp, eaddr);
    301 
    302 	sc->cdce_attached = 1;
    303 	splx(s);
    304 
    305 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
    306 	    USBDEV(sc->cdce_dev));
    307 
    308 	USB_ATTACH_SUCCESS_RETURN;
    309 }
    310 
    311 USB_DETACH(cdce)
    312 {
    313 	USB_DETACH_START(cdce, sc);
    314 	struct ifnet	*ifp = GET_IFP(sc);
    315 	int		 s;
    316 
    317 	s = splusb();
    318 
    319 	if (!sc->cdce_attached) {
    320 		splx(s);
    321 		return (0);
    322 	}
    323 
    324 	if (ifp->if_flags & IFF_RUNNING)
    325 		cdce_stop(ifp, 1);
    326 
    327 	ether_ifdetach(ifp);
    328 
    329 	if_detach(ifp);
    330 
    331 	sc->cdce_attached = 0;
    332 	splx(s);
    333 
    334 	return (0);
    335 }
    336 
    337 Static void
    338 cdce_start(struct ifnet *ifp)
    339 {
    340 	struct cdce_softc	*sc = ifp->if_softc;
    341 	struct mbuf		*m_head = NULL;
    342 
    343 	if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
    344 		return;
    345 
    346 	IFQ_POLL(&ifp->if_snd, m_head);
    347 	if (m_head == NULL)
    348 		return;
    349 
    350 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
    351 
    352 #if NBPFILTER > 0
    353 	if (ifp->if_bpf)
    354 		BPF_MTAP(ifp, m_head);
    355 #endif
    356 
    357 	if (cdce_encap(sc, m_head, 0)) {
    358 		ifp->if_flags |= IFF_OACTIVE;
    359 		return;
    360 	}
    361 
    362 	ifp->if_flags |= IFF_OACTIVE;
    363 
    364 	ifp->if_timer = 6;
    365 }
    366 
    367 Static int
    368 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
    369 {
    370 	struct ue_chain		*c;
    371 	usbd_status		 err;
    372 	int			 ret;
    373 
    374 	c = &sc->cdce_cdata.cdce_tx_chain[idx];
    375 
    376 	if (sc->cdce_flags & CDCE_ZAURUS) {
    377 		/* Zaurus wants a 32-bit CRC appended to every frame */
    378 		u_int32_t crc, crcle;
    379 		int len;
    380 
    381 		crc = cdce_crc32(m);
    382 		crcle = htole32(crc);
    383 		len = m->m_pkthdr.len + 4;
    384 		m_copyback(m, m->m_pkthdr.len, 4, &crcle);
    385 		if (m->m_pkthdr.len != len) {
    386 			m_freem(m);
    387 			return (ENOBUFS);
    388 		}
    389 	}
    390 
    391 	ret = usb_ether_map_tx_buffer_mbuf(c, m);
    392 	if (ret) {
    393 		m_freem(m);
    394 		return (ret);
    395 	}
    396 
    397 	usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkout_pipe, c, NULL /* XXX buf */,
    398 	    m->m_pkthdr.len, USBD_NO_COPY, 10000, cdce_txeof);
    399 	err = usbd_transfer(c->ue_xfer);
    400 	if (err != USBD_IN_PROGRESS) {
    401 		c->ue_mbuf = NULL;
    402 		m_freem(m);
    403 		cdce_stop(GET_IFP(sc), 0);
    404 		return (EIO);
    405 	}
    406 
    407 	sc->cdce_cdata.cdce_tx_cnt++;
    408 
    409 	return (0);
    410 }
    411 
    412 Static void
    413 cdce_stop(struct ifnet *ifp, int disable)
    414 {
    415 	struct cdce_softc	*sc = ifp->if_softc;
    416 	usbd_status	 err;
    417 
    418 	ifp->if_timer = 0;
    419 
    420 	/* Stop transfers. */
    421 	if (sc->cdce_bulkin_pipe != NULL) {
    422 		err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
    423 		if (err)
    424 			printf("%s: abort rx pipe failed: %s\n",
    425 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    426 	}
    427 
    428 	if (sc->cdce_bulkout_pipe != NULL) {
    429 		err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
    430 		if (err)
    431 			printf("%s: abort tx pipe failed: %s\n",
    432 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    433 	}
    434 
    435 	/* Free RX/TX list resources. */
    436 	usb_ether_rx_list_free(sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT);
    437 	usb_ether_tx_list_free(sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT);
    438 
    439 	/* Close pipes. */
    440 	if (sc->cdce_bulkin_pipe != NULL) {
    441 		err = usbd_close_pipe(sc->cdce_bulkin_pipe);
    442 		if (err)
    443 			printf("%s: close rx pipe failed: %s\n",
    444 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    445 		sc->cdce_bulkin_pipe = NULL;
    446 	}
    447 
    448 	if (sc->cdce_bulkout_pipe != NULL) {
    449 		err = usbd_close_pipe(sc->cdce_bulkout_pipe);
    450 		if (err)
    451 			printf("%s: close tx pipe failed: %s\n",
    452 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    453 		sc->cdce_bulkout_pipe = NULL;
    454 	}
    455 
    456 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    457 }
    458 
    459 Static int
    460 cdce_ioctl(struct ifnet *ifp, u_long command, usb_ioctlarg_t data)
    461 {
    462 	struct cdce_softc	*sc = ifp->if_softc;
    463 	int			 s, error;
    464 
    465 	if (sc->cdce_dying)
    466 		return (EIO);
    467 
    468 	s = splnet();
    469 
    470 	switch(command) {
    471 #if 0	/* no media support */
    472 	case SIOCGIFMEDIA:
    473 	case SIOCSIFMEDIA:
    474 		error = EINVAL;
    475 		break;
    476 #endif
    477 
    478 	default:
    479 		error = ether_ioctl(ifp, command, data);
    480 		if (error == ENETRESET) {
    481 #if 0	/* XXX not yet */
    482 			if (ifp->if_flags & IFF_RUNNING)
    483 				cdce_setmulti(sc);
    484 #endif
    485 			error = 0;
    486 		}
    487 		break;
    488 	}
    489 
    490 	splx(s);
    491 
    492 	return (error);
    493 }
    494 
    495 Static void
    496 cdce_watchdog(struct ifnet *ifp)
    497 {
    498 	struct cdce_softc	*sc = ifp->if_softc;
    499 
    500 	if (sc->cdce_dying)
    501 		return;
    502 
    503 	ifp->if_oerrors++;
    504 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
    505 }
    506 
    507 Static int
    508 cdce_init(struct ifnet *ifp)
    509 {
    510 	struct cdce_softc	*sc = ifp->if_softc;
    511 	struct ue_chain		*c;
    512 	usbd_status		 err;
    513 	int			 s, i;
    514 
    515 	if (ifp->if_flags & IFF_RUNNING)
    516 		return (EIO);
    517 
    518 	s = splnet();
    519 
    520 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
    521 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    522 	if (err) {
    523 		printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    524 		    usbd_errstr(err));
    525 		splx(s);
    526 		return (EIO);
    527 	}
    528 
    529 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
    530 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    531 	if (err) {
    532 		printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    533 		    usbd_errstr(err));
    534 		splx(s);
    535 		return (EIO);
    536 	}
    537 
    538 	if (usb_ether_tx_list_init(USBDEV(sc->cdce_dev),
    539 	    sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT,
    540 	    sc->cdce_udev, sc->cdce_bulkout_pipe, NULL)) {
    541 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
    542 		splx(s);
    543 		return (EIO);
    544 	}
    545 
    546 	if (usb_ether_rx_list_init(USBDEV(sc->cdce_dev),
    547 	    sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT,
    548 	    sc->cdce_udev, sc->cdce_bulkin_pipe)) {
    549 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
    550 		splx(s);
    551 		return (ENOMEM);
    552 	}
    553 
    554 	/* Maybe set multicast / broadcast here??? */
    555 
    556 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    557 		c = &sc->cdce_cdata.cdce_rx_chain[i];
    558 		(void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
    559 		usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
    560 		    NULL /* XXX buf */, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    561 		    USBD_NO_TIMEOUT, cdce_rxeof);
    562 		usbd_transfer(c->ue_xfer);
    563 	}
    564 
    565 	ifp->if_flags |= IFF_RUNNING;
    566 	ifp->if_flags &= ~IFF_OACTIVE;
    567 
    568 	splx(s);
    569 
    570 	return (0);
    571 }
    572 
    573 Static void
    574 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    575 {
    576 	struct ue_chain		*c = priv;
    577 	struct cdce_softc	*sc = (void *)c->ue_dev;
    578 	struct ifnet		*ifp = GET_IFP(sc);
    579 	struct mbuf		*m;
    580 	int			 total_len = 0;
    581 	int			 s;
    582 
    583 	if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
    584 		return;
    585 
    586 	usbd_unmap_buffer(xfer);
    587 
    588 	if (status != USBD_NORMAL_COMPLETION) {
    589 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    590 			return;
    591 		if (sc->cdce_rxeof_errors == 0)
    592 			printf("%s: usb error on rx: %s\n",
    593 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
    594 		if (status == USBD_STALLED)
    595 			usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
    596 		DELAY(sc->cdce_rxeof_errors * 10000);
    597 		sc->cdce_rxeof_errors++;
    598 		goto done;
    599 	}
    600 
    601 	sc->cdce_rxeof_errors = 0;
    602 
    603 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    604 	if (sc->cdce_flags & CDCE_ZAURUS)
    605 		total_len -= 4;	/* Strip off CRC added by Zaurus */
    606 
    607 	if (total_len < sizeof(struct ether_header)) {
    608 		ifp->if_ierrors++;
    609 		goto done;
    610 	}
    611 
    612 	m = c->ue_mbuf;
    613 
    614 	/*
    615 	 * Allocate new mbuf cluster for the next transfer.
    616 	 * If that failed, discard current packet and recycle the mbuf.
    617 	 */
    618 	if ((c->ue_mbuf = usb_ether_newbuf(NULL)) == NULL) {
    619 		printf("%s: no memory for rx list -- packet dropped!\n",
    620 		    USBDEVNAME(sc->cdce_dev));
    621 		ifp->if_ierrors++;
    622 		c->ue_mbuf = usb_ether_newbuf(m);
    623 		goto done;
    624 	}
    625 
    626 	ifp->if_ipackets++;
    627 	m->m_pkthdr.len = m->m_len = total_len;
    628 	m->m_pkthdr.rcvif = ifp;
    629 
    630 	s = splnet();
    631 
    632 #if NBPFILTER > 0
    633 	if (ifp->if_bpf)
    634 		BPF_MTAP(ifp, m);
    635 #endif
    636 
    637 	IF_INPUT(ifp, m);
    638 
    639 	splx(s);
    640 
    641 done:
    642 	/* Setup new transfer. */
    643 	(void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
    644 	usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
    645 	    CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    646 	    cdce_rxeof);
    647 	usbd_transfer(c->ue_xfer);
    648 }
    649 
    650 Static void
    651 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
    652     usbd_status status)
    653 {
    654 	struct ue_chain		*c = priv;
    655 	struct cdce_softc	*sc = (void *)c->ue_dev;
    656 	struct ifnet		*ifp = GET_IFP(sc);
    657 	usbd_status		 err;
    658 	int			 s;
    659 
    660 	if (sc->cdce_dying)
    661 		return;
    662 
    663 	usbd_unmap_buffer(xfer);
    664 
    665 	s = splnet();
    666 
    667 	ifp->if_timer = 0;
    668 	ifp->if_flags &= ~IFF_OACTIVE;
    669 
    670 	if (status != USBD_NORMAL_COMPLETION) {
    671 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    672 			splx(s);
    673 			return;
    674 		}
    675 		ifp->if_oerrors++;
    676 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
    677 		    usbd_errstr(status));
    678 		if (status == USBD_STALLED)
    679 			usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
    680 		splx(s);
    681 		return;
    682 	}
    683 
    684 	usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
    685 
    686 	if (c->ue_mbuf != NULL) {
    687 		m_freem(c->ue_mbuf);
    688 		c->ue_mbuf = NULL;
    689 	}
    690 
    691 	if (err)
    692 		ifp->if_oerrors++;
    693 	else
    694 		ifp->if_opackets++;
    695 
    696 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    697 		cdce_start(ifp);
    698 
    699 	splx(s);
    700 }
    701 
    702 int
    703 cdce_activate(device_ptr_t self, enum devact act)
    704 {
    705 	struct cdce_softc *sc = (struct cdce_softc *)self;
    706 
    707 	switch (act) {
    708 	case DVACT_ACTIVATE:
    709 		return (EOPNOTSUPP);
    710 		break;
    711 
    712 	case DVACT_DEACTIVATE:
    713 		if_deactivate(GET_IFP(sc));
    714 		sc->cdce_dying = 1;
    715 		break;
    716 	}
    717 	return (0);
    718 }
    719 
    720 
    721 /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
    722  *  code or tables extracted from it, as desired without restriction.
    723  */
    724 
    725 static const uint32_t cdce_crc32_tab[] = {
    726 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    727 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    728 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    729 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    730 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
    731 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    732 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
    733 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    734 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    735 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    736 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
    737 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    738 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    739 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    740 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    741 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    742 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    743 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    744 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    745 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    746 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    747 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    748 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    749 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    750 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    751 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    752 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    753 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    754 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    755 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    756 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    757 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    758 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    759 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    760 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    761 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    762 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    763 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    764 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    765 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    766 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    767 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    768 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    769 };
    770 
    771 Static uint32_t
    772 cdce_crc32(struct mbuf *m)
    773 {
    774 	const uint8_t *p;
    775 	uint32_t crc;
    776 	int len;
    777 
    778 	crc = ~0U;
    779 
    780 	for ( ; m; m = m->m_next) {
    781 		for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
    782 			crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    783 		}
    784 	}
    785 
    786 	return (crc ^ ~0U);
    787 }
    788