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