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