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