if_cdce.c revision 1.12.10.7 1 /* $NetBSD: if_cdce.c,v 1.12.10.7 2007/06/18 13:40:59 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.7 2007/06/18 13:40:59 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, 10000, cdce_txeof);
399 err = usbd_transfer(c->ue_xfer);
400 if (err != USBD_IN_PROGRESS) {
401 c->ue_mbuf = NULL;
402 m_freem(m);
403 cdce_stop(GET_IFP(sc), 0);
404 return (EIO);
405 }
406
407 sc->cdce_cdata.cdce_tx_cnt++;
408
409 return (0);
410 }
411
412 Static void
413 cdce_stop(struct ifnet *ifp, int disable)
414 {
415 struct cdce_softc *sc = ifp->if_softc;
416 usbd_status err;
417
418 ifp->if_timer = 0;
419
420 /* Stop transfers. */
421 if (sc->cdce_bulkin_pipe != NULL) {
422 err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
423 if (err)
424 printf("%s: abort rx pipe failed: %s\n",
425 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
426 }
427
428 if (sc->cdce_bulkout_pipe != NULL) {
429 err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
430 if (err)
431 printf("%s: abort tx pipe failed: %s\n",
432 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
433 }
434
435 /* Free RX/TX list resources. */
436 usb_ether_rx_list_free(sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT);
437 usb_ether_tx_list_free(sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT);
438
439 /* Close pipes. */
440 if (sc->cdce_bulkin_pipe != NULL) {
441 err = usbd_close_pipe(sc->cdce_bulkin_pipe);
442 if (err)
443 printf("%s: close rx pipe failed: %s\n",
444 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
445 sc->cdce_bulkin_pipe = NULL;
446 }
447
448 if (sc->cdce_bulkout_pipe != NULL) {
449 err = usbd_close_pipe(sc->cdce_bulkout_pipe);
450 if (err)
451 printf("%s: close tx pipe failed: %s\n",
452 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
453 sc->cdce_bulkout_pipe = NULL;
454 }
455
456 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
457 }
458
459 Static int
460 cdce_ioctl(struct ifnet *ifp, u_long command, usb_ioctlarg_t data)
461 {
462 struct cdce_softc *sc = ifp->if_softc;
463 int s, error;
464
465 if (sc->cdce_dying)
466 return (EIO);
467
468 s = splnet();
469
470 switch(command) {
471 #if 0 /* no media support */
472 case SIOCGIFMEDIA:
473 case SIOCSIFMEDIA:
474 error = EINVAL;
475 break;
476 #endif
477
478 default:
479 error = ether_ioctl(ifp, command, data);
480 if (error == ENETRESET) {
481 #if 0 /* XXX not yet */
482 if (ifp->if_flags & IFF_RUNNING)
483 cdce_setmulti(sc);
484 #endif
485 error = 0;
486 }
487 break;
488 }
489
490 splx(s);
491
492 return (error);
493 }
494
495 Static void
496 cdce_watchdog(struct ifnet *ifp)
497 {
498 struct cdce_softc *sc = ifp->if_softc;
499
500 if (sc->cdce_dying)
501 return;
502
503 ifp->if_oerrors++;
504 printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
505 }
506
507 Static int
508 cdce_init(struct ifnet *ifp)
509 {
510 struct cdce_softc *sc = ifp->if_softc;
511 struct ue_chain *c;
512 usbd_status err;
513 int s, i;
514
515 if (ifp->if_flags & IFF_RUNNING)
516 return (EIO);
517
518 s = splnet();
519
520 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
521 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
522 if (err) {
523 printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
524 usbd_errstr(err));
525 splx(s);
526 return (EIO);
527 }
528
529 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
530 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
531 if (err) {
532 printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
533 usbd_errstr(err));
534 splx(s);
535 return (EIO);
536 }
537
538 if (usb_ether_tx_list_init(USBDEV(sc->cdce_dev),
539 sc->cdce_cdata.cdce_tx_chain, CDCE_TX_LIST_CNT,
540 sc->cdce_udev, sc->cdce_bulkout_pipe, NULL)) {
541 printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
542 splx(s);
543 return (EIO);
544 }
545
546 if (usb_ether_rx_list_init(USBDEV(sc->cdce_dev),
547 sc->cdce_cdata.cdce_rx_chain, CDCE_RX_LIST_CNT,
548 sc->cdce_udev, sc->cdce_bulkin_pipe)) {
549 printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
550 splx(s);
551 return (ENOMEM);
552 }
553
554 /* Maybe set multicast / broadcast here??? */
555
556 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
557 c = &sc->cdce_cdata.cdce_rx_chain[i];
558 (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
559 usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
560 NULL /* XXX buf */, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
561 USBD_NO_TIMEOUT, cdce_rxeof);
562 usbd_transfer(c->ue_xfer);
563 }
564
565 ifp->if_flags |= IFF_RUNNING;
566 ifp->if_flags &= ~IFF_OACTIVE;
567
568 splx(s);
569
570 return (0);
571 }
572
573 Static void
574 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
575 {
576 struct ue_chain *c = priv;
577 struct cdce_softc *sc = (void *)c->ue_dev;
578 struct ifnet *ifp = GET_IFP(sc);
579 struct mbuf *m;
580 int total_len = 0;
581 int s;
582
583 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
584 return;
585
586 usbd_unmap_buffer(xfer);
587
588 if (status != USBD_NORMAL_COMPLETION) {
589 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
590 return;
591 if (sc->cdce_rxeof_errors == 0)
592 printf("%s: usb error on rx: %s\n",
593 USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
594 if (status == USBD_STALLED)
595 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
596 DELAY(sc->cdce_rxeof_errors * 10000);
597 sc->cdce_rxeof_errors++;
598 goto done;
599 }
600
601 sc->cdce_rxeof_errors = 0;
602
603 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
604 if (sc->cdce_flags & CDCE_ZAURUS)
605 total_len -= 4; /* Strip off CRC added by Zaurus */
606
607 if (total_len < sizeof(struct ether_header)) {
608 ifp->if_ierrors++;
609 goto done;
610 }
611
612 m = c->ue_mbuf;
613
614 /*
615 * Allocate new mbuf cluster for the next transfer.
616 * If that failed, discard current packet and recycle the mbuf.
617 */
618 if ((c->ue_mbuf = usb_ether_newbuf(NULL)) == NULL) {
619 printf("%s: no memory for rx list -- packet dropped!\n",
620 USBDEVNAME(sc->cdce_dev));
621 ifp->if_ierrors++;
622 c->ue_mbuf = usb_ether_newbuf(m);
623 goto done;
624 }
625
626 ifp->if_ipackets++;
627 m->m_pkthdr.len = m->m_len = total_len;
628 m->m_pkthdr.rcvif = ifp;
629
630 s = splnet();
631
632 #if NBPFILTER > 0
633 if (ifp->if_bpf)
634 BPF_MTAP(ifp, m);
635 #endif
636
637 IF_INPUT(ifp, m);
638
639 splx(s);
640
641 done:
642 /* Setup new transfer. */
643 (void)usbd_map_buffer_mbuf(c->ue_xfer, c->ue_mbuf);
644 usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
645 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
646 cdce_rxeof);
647 usbd_transfer(c->ue_xfer);
648 }
649
650 Static void
651 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
652 usbd_status status)
653 {
654 struct ue_chain *c = priv;
655 struct cdce_softc *sc = (void *)c->ue_dev;
656 struct ifnet *ifp = GET_IFP(sc);
657 usbd_status err;
658 int s;
659
660 if (sc->cdce_dying)
661 return;
662
663 usbd_unmap_buffer(xfer);
664
665 s = splnet();
666
667 ifp->if_timer = 0;
668 ifp->if_flags &= ~IFF_OACTIVE;
669
670 if (status != USBD_NORMAL_COMPLETION) {
671 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
672 splx(s);
673 return;
674 }
675 ifp->if_oerrors++;
676 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
677 usbd_errstr(status));
678 if (status == USBD_STALLED)
679 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
680 splx(s);
681 return;
682 }
683
684 usbd_get_xfer_status(c->ue_xfer, NULL, NULL, NULL, &err);
685
686 if (c->ue_mbuf != NULL) {
687 m_freem(c->ue_mbuf);
688 c->ue_mbuf = NULL;
689 }
690
691 if (err)
692 ifp->if_oerrors++;
693 else
694 ifp->if_opackets++;
695
696 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
697 cdce_start(ifp);
698
699 splx(s);
700 }
701
702 int
703 cdce_activate(device_ptr_t self, enum devact act)
704 {
705 struct cdce_softc *sc = (struct cdce_softc *)self;
706
707 switch (act) {
708 case DVACT_ACTIVATE:
709 return (EOPNOTSUPP);
710 break;
711
712 case DVACT_DEACTIVATE:
713 if_deactivate(GET_IFP(sc));
714 sc->cdce_dying = 1;
715 break;
716 }
717 return (0);
718 }
719
720
721 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
722 * code or tables extracted from it, as desired without restriction.
723 */
724
725 static const uint32_t cdce_crc32_tab[] = {
726 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
727 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
728 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
729 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
730 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
731 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
732 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
733 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
734 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
735 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
736 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
737 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
738 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
739 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
740 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
741 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
742 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
743 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
744 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
745 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
746 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
747 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
748 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
749 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
750 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
751 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
752 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
753 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
754 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
755 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
756 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
757 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
758 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
759 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
760 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
761 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
762 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
763 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
764 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
765 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
766 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
767 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
768 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
769 };
770
771 Static uint32_t
772 cdce_crc32(struct mbuf *m)
773 {
774 const uint8_t *p;
775 uint32_t crc;
776 int len;
777
778 crc = ~0U;
779
780 for ( ; m; m = m->m_next) {
781 for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
782 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
783 }
784 }
785
786 return (crc ^ ~0U);
787 }
788