Home | History | Annotate | Line # | Download | only in usb
if_cdce.c revision 1.12.10.2
      1 /*	$NetBSD: if_cdce.c,v 1.12.10.2 2007/06/01 03:18:03 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.2 2007/06/01 03:18:03 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(struct mbuf *);
    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 	if (sc->cdce_flags & CDCE_ZAURUS) {
    365 		/* Zaurus wants a 32-bit CRC appended to every frame */
    366 		u_int32_t crc, crcle;
    367 
    368 		crc = cdce_crc32(m);
    369 		crcle = htole32(crc);
    370 		m_copyback(m, m->m_pkthdr.len, 4, &crcle);
    371 		extra = 4;
    372 	}
    373 
    374 	if (usbd_map_buffer_mbuf(c->cdce_xfer, m)) {
    375 		/* XXX should copy mbuf to contiguous memory and try again */
    376 		m_freem(m);
    377 		return (ENOMEM);
    378 	}
    379 	c->cdce_mbuf = m;
    380 
    381 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, NULL /* XXX buf */,
    382 	    m->m_pkthdr.len, USBD_NO_COPY, 10000, cdce_txeof);
    383 	err = usbd_transfer(c->cdce_xfer);
    384 	if (err != USBD_IN_PROGRESS) {
    385 		cdce_stop(sc);
    386 		return (EIO);
    387 	}
    388 
    389 	sc->cdce_cdata.cdce_tx_cnt++;
    390 
    391 	return (0);
    392 }
    393 
    394 Static void
    395 cdce_stop(struct cdce_softc *sc)
    396 {
    397 	usbd_status	 err;
    398 	struct ifnet	*ifp = GET_IFP(sc);
    399 	int		 i;
    400 
    401 	ifp->if_timer = 0;
    402 
    403 	/* Stop transfers. */
    404 	if (sc->cdce_bulkin_pipe != NULL) {
    405 		err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
    406 		if (err)
    407 			printf("%s: abort rx pipe failed: %s\n",
    408 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    409 	}
    410 
    411 	if (sc->cdce_bulkout_pipe != NULL) {
    412 		err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
    413 		if (err)
    414 			printf("%s: abort tx pipe failed: %s\n",
    415 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    416 	}
    417 
    418 	/* Free RX/TX list resources. */
    419 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    420 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
    421 			m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
    422 			sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
    423 		}
    424 		if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
    425 			usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
    426 			sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
    427 		}
    428 	}
    429 
    430 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    431 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
    432 			m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
    433 			sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
    434 		}
    435 		if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
    436 			usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
    437 			sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
    438 		}
    439 	}
    440 
    441 	/* Close pipes. */
    442 	if (sc->cdce_bulkin_pipe != NULL) {
    443 		err = usbd_close_pipe(sc->cdce_bulkin_pipe);
    444 		if (err)
    445 			printf("%s: close rx pipe failed: %s\n",
    446 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    447 		sc->cdce_bulkin_pipe = NULL;
    448 	}
    449 
    450 	if (sc->cdce_bulkout_pipe != NULL) {
    451 		err = usbd_close_pipe(sc->cdce_bulkout_pipe);
    452 		if (err)
    453 			printf("%s: close tx pipe failed: %s\n",
    454 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
    455 		sc->cdce_bulkout_pipe = NULL;
    456 	}
    457 
    458 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    459 }
    460 
    461 Static int
    462 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
    463 {
    464 	struct cdce_softc	*sc = ifp->if_softc;
    465 	struct ifaddr		*ifa = (struct ifaddr *)data;
    466 	struct ifreq		*ifr = (struct ifreq *)data;
    467 	int			 s, error = 0;
    468 
    469 	if (sc->cdce_dying)
    470 		return (EIO);
    471 
    472 	s = splnet();
    473 
    474 	switch(command) {
    475 	case SIOCSIFADDR:
    476 		ifp->if_flags |= IFF_UP;
    477 		cdce_init(sc);
    478 		switch (ifa->ifa_addr->sa_family) {
    479 #ifdef INET
    480 		case AF_INET:
    481 #if defined(__NetBSD__)
    482 			arp_ifinit(ifp, ifa);
    483 #else
    484 			arp_ifinit(&sc->arpcom, ifa);
    485 #endif
    486 			break;
    487 #endif /* INET */
    488 		}
    489 		break;
    490 
    491 	case SIOCSIFMTU:
    492 		if (ifr->ifr_mtu > ETHERMTU)
    493 			error = EINVAL;
    494 		else
    495 			ifp->if_mtu = ifr->ifr_mtu;
    496 		break;
    497 
    498 	case SIOCSIFFLAGS:
    499 		if (ifp->if_flags & IFF_UP) {
    500 			if (!(ifp->if_flags & IFF_RUNNING))
    501 				cdce_init(sc);
    502 		} else {
    503 			if (ifp->if_flags & IFF_RUNNING)
    504 				cdce_stop(sc);
    505 		}
    506 		error = 0;
    507 		break;
    508 
    509 	default:
    510 		error = EINVAL;
    511 		break;
    512 	}
    513 
    514 	splx(s);
    515 
    516 	return (error);
    517 }
    518 
    519 Static void
    520 cdce_watchdog(struct ifnet *ifp)
    521 {
    522 	struct cdce_softc	*sc = ifp->if_softc;
    523 
    524 	if (sc->cdce_dying)
    525 		return;
    526 
    527 	ifp->if_oerrors++;
    528 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
    529 }
    530 
    531 Static void
    532 cdce_init(void *xsc)
    533 {
    534 	struct cdce_softc	*sc = xsc;
    535 	struct ifnet		*ifp = GET_IFP(sc);
    536 	struct cdce_chain	*c;
    537 	usbd_status		 err;
    538 	int			 s, i;
    539 
    540 	if (ifp->if_flags & IFF_RUNNING)
    541 		return;
    542 
    543 	s = splnet();
    544 
    545 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
    546 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    547 	if (err) {
    548 		printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    549 		    usbd_errstr(err));
    550 		splx(s);
    551 		return;
    552 	}
    553 
    554 	err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
    555 	    USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    556 	if (err) {
    557 		printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
    558 		    usbd_errstr(err));
    559 		splx(s);
    560 		return;
    561 	}
    562 
    563 	if (cdce_tx_list_init(sc)) {
    564 		printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
    565 		splx(s);
    566 		return;
    567 	}
    568 
    569 	if (cdce_rx_list_init(sc)) {
    570 		printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
    571 		splx(s);
    572 		return;
    573 	}
    574 
    575 	/* Maybe set multicast / broadcast here??? */
    576 
    577 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    578 		c = &sc->cdce_cdata.cdce_rx_chain[i];
    579 		(void)usbd_map_buffer_mbuf(c->cdce_xfer, c->cdce_mbuf);
    580 		usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
    581 		    NULL /* XXX buf */, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    582 		    USBD_NO_TIMEOUT, cdce_rxeof);
    583 		usbd_transfer(c->cdce_xfer);
    584 	}
    585 
    586 	ifp->if_flags |= IFF_RUNNING;
    587 	ifp->if_flags &= ~IFF_OACTIVE;
    588 
    589 	splx(s);
    590 }
    591 
    592 Static int
    593 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
    594 {
    595 	struct mbuf	*m_new = NULL;
    596 
    597 	if (m == NULL) {
    598 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
    599 		if (m_new == NULL) {
    600 			printf("%s: no memory for rx list "
    601 			    "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
    602 			return (ENOBUFS);
    603 		}
    604 		MCLGET(m_new, M_DONTWAIT);
    605 		if (!(m_new->m_flags & M_EXT)) {
    606 			printf("%s: no memory for rx list "
    607 			    "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
    608 			m_freem(m_new);
    609 			return (ENOBUFS);
    610 		}
    611 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    612 	} else {
    613 		m_new = m;
    614 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    615 		m_new->m_data = m_new->m_ext.ext_buf;
    616 	}
    617 	c->cdce_mbuf = m_new;
    618 	return (0);
    619 }
    620 
    621 Static int
    622 cdce_rx_list_init(struct cdce_softc *sc)
    623 {
    624 	struct cdce_cdata	*cd;
    625 	struct cdce_chain	*c;
    626 	int			 i, err;
    627 
    628 	cd = &sc->cdce_cdata;
    629 	for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
    630 		c = &cd->cdce_rx_chain[i];
    631 		c->cdce_sc = sc;
    632 		c->cdce_idx = i;
    633 		if (c->cdce_xfer == NULL) {
    634 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev,
    635 			    sc->cdce_bulkin_pipe);
    636 			if (c->cdce_xfer == NULL)
    637 				return (ENOMEM);
    638 			if ((err = usbd_map_alloc(c->cdce_xfer) ? ENOMEM : 0) ||
    639 			    (err = cdce_newbuf(sc, c, NULL))) {
    640 				usbd_free_xfer(c->cdce_xfer);
    641 				c->cdce_xfer = NULL;
    642 				return (err);
    643 			}
    644 		}
    645 	}
    646 
    647 	return (0);
    648 }
    649 
    650 Static int
    651 cdce_tx_list_init(struct cdce_softc *sc)
    652 {
    653 	struct cdce_cdata	*cd;
    654 	struct cdce_chain	*c;
    655 	int			 i;
    656 
    657 	cd = &sc->cdce_cdata;
    658 	for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
    659 		c = &cd->cdce_tx_chain[i];
    660 		c->cdce_sc = sc;
    661 		c->cdce_idx = i;
    662 		c->cdce_mbuf = NULL;
    663 		if (c->cdce_xfer == NULL) {
    664 			c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev,
    665 			    sc->cdce_bulkout_pipe);
    666 			if (c->cdce_xfer == NULL)
    667 				return (ENOMEM);
    668 			if (usbd_map_alloc(c->cdce_xfer)) {
    669 				usbd_free_xfer(c->cdce_xfer);
    670 				c->cdce_xfer = NULL;
    671 				return (ENOMEM);
    672 			}
    673 		}
    674 	}
    675 
    676 	return (0);
    677 }
    678 
    679 Static void
    680 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    681 {
    682 	struct cdce_chain	*c = priv;
    683 	struct cdce_softc	*sc = c->cdce_sc;
    684 	struct ifnet		*ifp = GET_IFP(sc);
    685 	struct mbuf		*m;
    686 	int			 total_len = 0;
    687 	int			 s;
    688 
    689 	if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
    690 		return;
    691 
    692 	usbd_unmap_buffer(xfer);
    693 
    694 	if (status != USBD_NORMAL_COMPLETION) {
    695 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    696 			return;
    697 		if (sc->cdce_rxeof_errors == 0)
    698 			printf("%s: usb error on rx: %s\n",
    699 			    USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
    700 		if (status == USBD_STALLED)
    701 			usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
    702 		DELAY(sc->cdce_rxeof_errors * 10000);
    703 		sc->cdce_rxeof_errors++;
    704 		goto done;
    705 	}
    706 
    707 	sc->cdce_rxeof_errors = 0;
    708 
    709 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    710 	if (sc->cdce_flags & CDCE_ZAURUS)
    711 		total_len -= 4;	/* Strip off CRC added by Zaurus */
    712 
    713 	if (total_len < sizeof(struct ether_header)) {
    714 		ifp->if_ierrors++;
    715 		goto done;
    716 	}
    717 
    718 	m = c->cdce_mbuf;
    719 
    720 	/*
    721 	 * Allocate new mbuf cluster for the next transfer.
    722 	 * If that failed, discard current packet and recycle the mbuf.
    723 	 */
    724 	if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
    725 		ifp->if_ierrors++;
    726 		c->cdce_mbuf = m;
    727 		goto done;
    728 	}
    729 
    730 	ifp->if_ipackets++;
    731 	m->m_pkthdr.len = m->m_len = total_len;
    732 	m->m_pkthdr.rcvif = ifp;
    733 
    734 	s = splnet();
    735 
    736 #if NBPFILTER > 0
    737 	if (ifp->if_bpf)
    738 		BPF_MTAP(ifp, m);
    739 #endif
    740 
    741 	IF_INPUT(ifp, m);
    742 
    743 	splx(s);
    744 
    745 done:
    746 	/* Setup new transfer. */
    747 	(void)usbd_map_buffer_mbuf(c->cdce_xfer, c->cdce_mbuf);
    748 	usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
    749 	    CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    750 	    cdce_rxeof);
    751 	usbd_transfer(c->cdce_xfer);
    752 }
    753 
    754 Static void
    755 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
    756     usbd_status status)
    757 {
    758 	struct cdce_chain	*c = priv;
    759 	struct cdce_softc	*sc = c->cdce_sc;
    760 	struct ifnet		*ifp = GET_IFP(sc);
    761 	usbd_status		 err;
    762 	int			 s;
    763 
    764 	if (sc->cdce_dying)
    765 		return;
    766 
    767 	usbd_unmap_buffer(xfer);
    768 
    769 	s = splnet();
    770 
    771 	ifp->if_timer = 0;
    772 	ifp->if_flags &= ~IFF_OACTIVE;
    773 
    774 	if (status != USBD_NORMAL_COMPLETION) {
    775 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    776 			splx(s);
    777 			return;
    778 		}
    779 		ifp->if_oerrors++;
    780 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
    781 		    usbd_errstr(status));
    782 		if (status == USBD_STALLED)
    783 			usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
    784 		splx(s);
    785 		return;
    786 	}
    787 
    788 	usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
    789 
    790 	if (c->cdce_mbuf != NULL) {
    791 		m_freem(c->cdce_mbuf);
    792 		c->cdce_mbuf = NULL;
    793 	}
    794 
    795 	if (err)
    796 		ifp->if_oerrors++;
    797 	else
    798 		ifp->if_opackets++;
    799 
    800 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    801 		cdce_start(ifp);
    802 
    803 	splx(s);
    804 }
    805 
    806 int
    807 cdce_activate(device_ptr_t self, enum devact act)
    808 {
    809 	struct cdce_softc *sc = (struct cdce_softc *)self;
    810 
    811 	switch (act) {
    812 	case DVACT_ACTIVATE:
    813 		return (EOPNOTSUPP);
    814 		break;
    815 
    816 	case DVACT_DEACTIVATE:
    817 		if_deactivate(GET_IFP(sc));
    818 		sc->cdce_dying = 1;
    819 		break;
    820 	}
    821 	return (0);
    822 }
    823 
    824 
    825 /*  COPYRIGHT (C) 1986 Gary S. Brown.  You may use this program, or
    826  *  code or tables extracted from it, as desired without restriction.
    827  */
    828 
    829 static const uint32_t cdce_crc32_tab[] = {
    830 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    831 	0xe963a535, 0x9e6495a3,	0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    832 	0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    833 	0xf3b97148, 0x84be41de,	0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    834 	0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,	0x14015c4f, 0x63066cd9,
    835 	0xfa0f3d63, 0x8d080df5,	0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    836 	0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,	0x35b5a8fa, 0x42b2986c,
    837 	0xdbbbc9d6, 0xacbcf940,	0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    838 	0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    839 	0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    840 	0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,	0x76dc4190, 0x01db7106,
    841 	0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    842 	0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    843 	0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    844 	0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    845 	0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    846 	0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    847 	0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    848 	0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    849 	0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    850 	0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    851 	0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    852 	0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    853 	0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    854 	0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    855 	0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    856 	0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    857 	0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    858 	0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    859 	0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    860 	0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    861 	0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    862 	0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    863 	0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    864 	0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    865 	0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    866 	0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    867 	0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    868 	0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    869 	0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    870 	0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    871 	0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    872 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    873 };
    874 
    875 Static uint32_t
    876 cdce_crc32(struct mbuf *m)
    877 {
    878 	const uint8_t *p;
    879 	uint32_t crc;
    880 	int len;
    881 
    882 	crc = ~0U;
    883 
    884 	for ( ; m; m = m->m_next) {
    885 		for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
    886 			crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
    887 		}
    888 	}
    889 
    890 	return (crc ^ ~0U);
    891 }
    892