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