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