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