Home | History | Annotate | Line # | Download | only in usb
if_cdce.c revision 1.12.10.4
      1 /*	$NetBSD: if_cdce.c,v 1.12.10.4 2007/06/12 13:58:24 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.4 2007/06/12 13:58:24 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, caddr_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 
    367 		crc = cdce_crc32(m);
    368 		crcle = htole32(crc);
    369 		m_copyback(m, m->m_pkthdr.len, 4, &crcle);
    370 	}
    371 
    372 	ret = usb_ether_map_tx_buffer_mbuf(c, m);
    373 	if (ret) {
    374 		c->ue_mbuf = NULL;
    375 		m_freem(m);
    376 		return (ret);
    377 	}
    378 
    379 	usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkout_pipe, c, NULL /* XXX buf */,
    380 	    m->m_pkthdr.len, USBD_NO_COPY, 10000, cdce_txeof);
    381 	err = usbd_transfer(c->ue_xfer);
    382 	if (err != USBD_IN_PROGRESS) {
    383 		c->ue_mbuf = NULL;
    384 		m_freem(m);
    385 		cdce_stop(GET_IFP(sc), 0);
    386 		return (EIO);
    387 	}
    388 
    389 	sc->cdce_cdata.cdce_tx_cnt++;
    390 
    391 	return (0);
    392 }
    393 
    394 Static void
    395 cdce_stop(struct ifnet *ifp, int disable)
    396 {
    397 	struct cdce_softc	*sc = ifp->if_softc;
    398 	usbd_status	 err;
    399 
    400 	ifp->if_timer = 0;
    401 
    402 	/* Stop transfers. */
    403 	if (sc->cdce_bulkin_pipe != NULL) {
    404 		err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
    405 		if (err)
    406 			printf("%s: abort rx pipe failed: %s\n",
    407 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    408 	}
    409 
    410 	if (sc->cdce_bulkout_pipe != NULL) {
    411 		err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
    412 		if (err)
    413 			printf("%s: abort tx pipe failed: %s\n",
    414 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    415 	}
    416 
    417 	/* Free RX/TX list resources. */
    418 	usb_ether_rx_list_free(sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT);
    419 	usb_ether_tx_list_free(sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT);
    420 
    421 	/* Close pipes. */
    422 	if (sc->cdce_bulkin_pipe != NULL) {
    423 		err = usbd_close_pipe(sc->cdce_bulkin_pipe);
    424 		if (err)
    425 			printf("%s: close rx pipe failed: %s\n",
    426 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    427 		sc->cdce_bulkin_pipe = NULL;
    428 	}
    429 
    430 	if (sc->cdce_bulkout_pipe != NULL) {
    431 		err = usbd_close_pipe(sc->cdce_bulkout_pipe);
    432 		if (err)
    433 			printf("%s: close tx pipe failed: %s\n",
    434 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    435 		sc->cdce_bulkout_pipe = NULL;
    436 	}
    437 
    438 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    439 }
    440 
    441 Static int
    442 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
    443 {
    444 	struct cdce_softc	*sc = ifp->if_softc;
    445 	int			 s, error;
    446 
    447 	if (sc->cdce_dying)
    448 		return (EIO);
    449 
    450 	s = splnet();
    451 
    452 	switch(command) {
    453 #if 0	/* no media support */
    454 	case SIOCGIFMEDIA:
    455 	case SIOCSIFMEDIA:
    456 		error = EINVAL;
    457 		break;
    458 #endif
    459 
    460 	default:
    461 		error = ether_ioctl(ifp, command, data);
    462 		if (error == ENETRESET) {
    463 #if 0	/* XXX not yet */
    464 			if (ifp->if_flags & IFF_RUNNING)
    465 				cdce_setmulti(sc);
    466 #endif
    467 			error = 0;
    468 		}
    469 		break;
    470 	}
    471 
    472 	splx(s);
    473 
    474 	return (error);
    475 }
    476 
    477 Static void
    478 cdce_watchdog(struct ifnet *ifp)
    479 {
    480 	struct cdce_softc	*sc = ifp->if_softc;
    481 
    482 	if (sc->cdce_dying)
    483 		return;
    484 
    485 	ifp->if_oerrors++;
    486 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
    487 }
    488 
    489 Static int
    490 cdce_init(struct ifnet *ifp)
    491 {
    492 	struct cdce_softc	*sc = ifp->if_softc;
    493 	struct ue_chain		*c;
    494 	usbd_status		 err;
    495 	int			 s, i;
    496 
    497 	if (ifp->if_flags & IFF_RUNNING)
    498 		return (EIO);
    499 
    500 	s = splnet();
    501 
    502 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
    503 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    504 	if (err) {
    505 		printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    506 		    usbd_errstr(err));
    507 		splx(s);
    508 		return (EIO);
    509 	}
    510 
    511 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
    512 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    513 	if (err) {
    514 		printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    515 		    usbd_errstr(err));
    516 		splx(s);
    517 		return (EIO);
    518 	}
    519 
    520 	if (usb_ether_tx_list_init(USBDEV(sc->cdce_dev),
    521 	    sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT,
    522 	    sc->cdce_udev, sc->cdce_bulkout_pipe, NULL)) {
    523 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
    524 		splx(s);
    525 		return (EIO);
    526 	}
    527 
    528 	if (usb_ether_rx_list_init(USBDEV(sc->cdce_dev),
    529 	    sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT,
    530 	    sc->cdce_udev, sc->cdce_bulkin_pipe)) {
    531 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
    532 		splx(s);
    533 		return (ENOMEM);
    534 	}
    535 
    536 	/* Maybe set multicast / broadcast here??? */
    537 
    538 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    539 		c = &sc->cdce_cdata.cdce_rx_chain[i];
    540 		(void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
    541 		usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
    542 		    NULL /* XXX buf */, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    543 		    USBD_NO_TIMEOUT, cdce_rxeof);
    544 		usbd_transfer(c->ue_xfer);
    545 	}
    546 
    547 	ifp->if_flags |= IFF_RUNNING;
    548 	ifp->if_flags &= ~IFF_OACTIVE;
    549 
    550 	splx(s);
    551 
    552 	return (0);
    553 }
    554 
    555 Static void
    556 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    557 {
    558 	struct ue_chain		*c = priv;
    559 	struct cdce_softc	*sc = (void *)c->ue_dev;
    560 	struct ifnet		*ifp = GET_IFP(sc);
    561 	struct mbuf		*m;
    562 	int			 total_len = 0;
    563 	int			 s;
    564 
    565 	if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
    566 		return;
    567 
    568 	usbd_unmap_buffer(xfer);
    569 
    570 	if (status != USBD_NORMAL_COMPLETION) {
    571 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    572 			return;
    573 		if (sc->cdce_rxeof_errors == 0)
    574 			printf("%s: usb error on rx: %s\n",
    575 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
    576 		if (status == USBD_STALLED)
    577 			usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
    578 		DELAY(sc->cdce_rxeof_errors * 10000);
    579 		sc->cdce_rxeof_errors++;
    580 		goto done;
    581 	}
    582 
    583 	sc->cdce_rxeof_errors = 0;
    584 
    585 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    586 	if (sc->cdce_flags & CDCE_ZAURUS)
    587 		total_len -= 4;	/* Strip off CRC added by Zaurus */
    588 
    589 	if (total_len < sizeof(struct ether_header)) {
    590 		ifp->if_ierrors++;
    591 		goto done;
    592 	}
    593 
    594 	m = c->ue_mbuf;
    595 
    596 	/*
    597 	 * Allocate new mbuf cluster for the next transfer.
    598 	 * If that failed, discard current packet and recycle the mbuf.
    599 	 */
    600 	if ((c->ue_mbuf = usb_ether_newbuf(NULL)) == NULL) {
    601 		printf("%s: no memory for rx list -- packet dropped!\n",
    602 		    USBDEVNAME(sc->cdce_dev));
    603 		ifp->if_ierrors++;
    604 		c->ue_mbuf = usb_ether_newbuf(m);
    605 		goto done;
    606 	}
    607 
    608 	ifp->if_ipackets++;
    609 	m->m_pkthdr.len = m->m_len = total_len;
    610 	m->m_pkthdr.rcvif = ifp;
    611 
    612 	s = splnet();
    613 
    614 #if NBPFILTER > 0
    615 	if (ifp->if_bpf)
    616 		BPF_MTAP(ifp, m);
    617 #endif
    618 
    619 	IF_INPUT(ifp, m);
    620 
    621 	splx(s);
    622 
    623 done:
    624 	/* Setup new transfer. */
    625 	(void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
    626 	usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
    627 	    CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    628 	    cdce_rxeof);
    629 	usbd_transfer(c->ue_xfer);
    630 }
    631 
    632 Static void
    633 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
    634     usbd_status status)
    635 {
    636 	struct ue_chain		*c = priv;
    637 	struct cdce_softc	*sc = (void *)c->ue_dev;
    638 	struct ifnet		*ifp = GET_IFP(sc);
    639 	usbd_status		 err;
    640 	int			 s;
    641 
    642 	if (sc->cdce_dying)
    643 		return;
    644 
    645 	usbd_unmap_buffer(xfer);
    646 
    647 	s = splnet();
    648 
    649 	ifp->if_timer = 0;
    650 	ifp->if_flags &= ~IFF_OACTIVE;
    651 
    652 	if (status != USBD_NORMAL_COMPLETION) {
    653 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    654 			splx(s);
    655 			return;
    656 		}
    657 		ifp->if_oerrors++;
    658 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
    659 		    usbd_errstr(status));
    660 		if (status == USBD_STALLED)
    661 			usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
    662 		splx(s);
    663 		return;
    664 	}
    665 
    666 	usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
    667 
    668 	if (c->ue_mbuf != NULL) {
    669 		m_freem(c->ue_mbuf);
    670 		c->ue_mbuf = NULL;
    671 	}
    672 
    673 	if (err)
    674 		ifp->if_oerrors++;
    675 	else
    676 		ifp->if_opackets++;
    677 
    678 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    679 		cdce_start(ifp);
    680 
    681 	splx(s);
    682 }
    683 
    684 int
    685 cdce_activate(device_ptr_t self, enum devact act)
    686 {
    687 	struct cdce_softc *sc = (struct cdce_softc *)self;
    688 
    689 	switch (act) {
    690 	case DVACT_ACTIVATE:
    691 		return (EOPNOTSUPP);
    692 		break;
    693 
    694 	case DVACT_DEACTIVATE:
    695 		if_deactivate(GET_IFP(sc));
    696 		sc->cdce_dying = 1;
    697 		break;
    698 	}
    699 	return (0);
    700 }
    701 
    702 
    703 /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
    704  *  code or tables extracted from it, as desired without restriction.
    705  */
    706 
    707 static const uint32_t cdce_crc32_tab[] = {
    708 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    709 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    710 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    711 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    712 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
    713 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    714 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
    715 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    716 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    717 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    718 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
    719 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    720 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    721 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    722 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    723 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    724 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    725 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    726 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    727 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    728 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    729 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    730 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    731 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    732 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    733 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    734 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    735 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    736 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    737 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    738 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    739 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    740 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    741 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    742 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    743 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    744 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    745 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    746 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    747 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    748 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    749 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    750 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    751 };
    752 
    753 Static uint32_t
    754 cdce_crc32(struct mbuf *m)
    755 {
    756 	const uint8_t *p;
    757 	uint32_t crc;
    758 	int len;
    759 
    760 	crc = ~0U;
    761 
    762 	for ( ; m; m = m->m_next) {
    763 		for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
    764 			crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    765 		}
    766 	}
    767 
    768 	return (crc ^ ~0U);
    769 }
    770