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