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