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