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