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