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