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