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