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