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