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