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