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