if_cdce.c revision 1.12.10.3 1 /* $NetBSD: if_cdce.c,v 1.12.10.3 2007/06/03 13:14:31 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.3 2007/06/03 13:14:31 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 int cdce_init(struct ifnet *);
113 Static void cdce_watchdog(struct ifnet *);
114 Static void cdce_stop(struct ifnet *, int);
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 ifp->if_init = cdce_init;
284 ifp->if_stop = cdce_stop;
285 strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ);
286
287 IFQ_SET_READY(&ifp->if_snd);
288
289 if_attach(ifp);
290 Ether_ifattach(ifp, eaddr);
291
292 sc->cdce_attached = 1;
293 splx(s);
294
295 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
296 USBDEV(sc->cdce_dev));
297
298 USB_ATTACH_SUCCESS_RETURN;
299 }
300
301 USB_DETACH(cdce)
302 {
303 USB_DETACH_START(cdce, sc);
304 struct ifnet *ifp = GET_IFP(sc);
305 int s;
306
307 s = splusb();
308
309 if (!sc->cdce_attached) {
310 splx(s);
311 return (0);
312 }
313
314 if (ifp->if_flags & IFF_RUNNING)
315 cdce_stop(ifp, 1);
316
317 ether_ifdetach(ifp);
318
319 if_detach(ifp);
320
321 sc->cdce_attached = 0;
322 splx(s);
323
324 return (0);
325 }
326
327 Static void
328 cdce_start(struct ifnet *ifp)
329 {
330 struct cdce_softc *sc = ifp->if_softc;
331 struct mbuf *m_head = NULL;
332
333 if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
334 return;
335
336 IFQ_POLL(&ifp->if_snd, m_head);
337 if (m_head == NULL)
338 return;
339
340 if (cdce_encap(sc, m_head, 0)) {
341 ifp->if_flags |= IFF_OACTIVE;
342 return;
343 }
344
345 IFQ_DEQUEUE(&ifp->if_snd, m_head);
346
347 #if NBPFILTER > 0
348 if (ifp->if_bpf)
349 BPF_MTAP(ifp, m_head);
350 #endif
351
352 ifp->if_flags |= IFF_OACTIVE;
353
354 ifp->if_timer = 6;
355 }
356
357 Static int
358 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
359 {
360 struct cdce_chain *c;
361 usbd_status err;
362 int extra = 0;
363
364 c = &sc->cdce_cdata.cdce_tx_chain[idx];
365
366 if (sc->cdce_flags & CDCE_ZAURUS) {
367 /* Zaurus wants a 32-bit CRC appended to every frame */
368 u_int32_t crc, crcle;
369
370 crc = cdce_crc32(m);
371 crcle = htole32(crc);
372 m_copyback(m, m->m_pkthdr.len, 4, &crcle);
373 extra = 4;
374 }
375
376 if (usbd_map_buffer_mbuf(c->cdce_xfer, m)) {
377 /* XXX should copy mbuf to contiguous memory and try again */
378 m_freem(m);
379 return (ENOMEM);
380 }
381 c->cdce_mbuf = m;
382
383 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, NULL /* XXX buf */,
384 m->m_pkthdr.len, USBD_NO_COPY, 10000, cdce_txeof);
385 err = usbd_transfer(c->cdce_xfer);
386 if (err != USBD_IN_PROGRESS) {
387 cdce_stop(GET_IFP(sc), 0);
388 return (EIO);
389 }
390
391 sc->cdce_cdata.cdce_tx_cnt++;
392
393 return (0);
394 }
395
396 Static void
397 cdce_stop(struct ifnet *ifp, int disable)
398 {
399 struct cdce_softc *sc = ifp->if_softc;
400 usbd_status err;
401 int i;
402
403 ifp->if_timer = 0;
404
405 /* Stop transfers. */
406 if (sc->cdce_bulkin_pipe != NULL) {
407 err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
408 if (err)
409 printf("%s: abort rx pipe failed: %s\n",
410 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
411 }
412
413 if (sc->cdce_bulkout_pipe != NULL) {
414 err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
415 if (err)
416 printf("%s: abort tx pipe failed: %s\n",
417 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
418 }
419
420 /* Free RX/TX list resources. */
421 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
422 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
423 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
424 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
425 }
426 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
427 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
428 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
429 }
430 }
431
432 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
433 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
434 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
435 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
436 }
437 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
438 usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
439 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
440 }
441 }
442
443 /* Close pipes. */
444 if (sc->cdce_bulkin_pipe != NULL) {
445 err = usbd_close_pipe(sc->cdce_bulkin_pipe);
446 if (err)
447 printf("%s: close rx pipe failed: %s\n",
448 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
449 sc->cdce_bulkin_pipe = NULL;
450 }
451
452 if (sc->cdce_bulkout_pipe != NULL) {
453 err = usbd_close_pipe(sc->cdce_bulkout_pipe);
454 if (err)
455 printf("%s: close tx pipe failed: %s\n",
456 USBDEVNAME(sc->cdce_dev), usbd_errstr(err));
457 sc->cdce_bulkout_pipe = NULL;
458 }
459
460 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
461 }
462
463 Static int
464 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
465 {
466 struct cdce_softc *sc = ifp->if_softc;
467 int s, error;
468
469 if (sc->cdce_dying)
470 return (EIO);
471
472 s = splnet();
473
474 switch(command) {
475 #if 0 /* no media support */
476 case SIOCGIFMEDIA:
477 case SIOCSIFMEDIA:
478 error = EINVAL;
479 break;
480 #endif
481
482 default:
483 error = ether_ioctl(ifp, command, data);
484 if (error == ENETRESET) {
485 #if 0 /* XXX not yet */
486 if (ifp->if_flags & IFF_RUNNING)
487 cdce_setmulti(sc);
488 #endif
489 error = 0;
490 }
491 break;
492 }
493
494 splx(s);
495
496 return (error);
497 }
498
499 Static void
500 cdce_watchdog(struct ifnet *ifp)
501 {
502 struct cdce_softc *sc = ifp->if_softc;
503
504 if (sc->cdce_dying)
505 return;
506
507 ifp->if_oerrors++;
508 printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev));
509 }
510
511 Static int
512 cdce_init(struct ifnet *ifp)
513 {
514 struct cdce_softc *sc = ifp->if_softc;
515 struct cdce_chain *c;
516 usbd_status err;
517 int s, i;
518
519 if (ifp->if_flags & IFF_RUNNING)
520 return (EIO);
521
522 s = splnet();
523
524 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
525 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
526 if (err) {
527 printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
528 usbd_errstr(err));
529 splx(s);
530 return (EIO);
531 }
532
533 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
534 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
535 if (err) {
536 printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
537 usbd_errstr(err));
538 splx(s);
539 return (EIO);
540 }
541
542 if (cdce_tx_list_init(sc)) {
543 printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
544 splx(s);
545 return (EIO);
546 }
547
548 if (cdce_rx_list_init(sc)) {
549 printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
550 splx(s);
551 return (ENOMEM);
552 }
553
554 /* Maybe set multicast / broadcast here??? */
555
556 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
557 c = &sc->cdce_cdata.cdce_rx_chain[i];
558 (void)usbd_map_buffer_mbuf(c->cdce_xfer, c->cdce_mbuf);
559 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
560 NULL /* XXX buf */, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
561 USBD_NO_TIMEOUT, cdce_rxeof);
562 usbd_transfer(c->cdce_xfer);
563 }
564
565 ifp->if_flags |= IFF_RUNNING;
566 ifp->if_flags &= ~IFF_OACTIVE;
567
568 splx(s);
569
570 return (0);
571 }
572
573 Static int
574 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
575 {
576 struct mbuf *m_new = NULL;
577
578 if (m == NULL) {
579 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
580 if (m_new == NULL) {
581 printf("%s: no memory for rx list "
582 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
583 return (ENOBUFS);
584 }
585 MCLGET(m_new, M_DONTWAIT);
586 if (!(m_new->m_flags & M_EXT)) {
587 printf("%s: no memory for rx list "
588 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev));
589 m_freem(m_new);
590 return (ENOBUFS);
591 }
592 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
593 } else {
594 m_new = m;
595 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
596 m_new->m_data = m_new->m_ext.ext_buf;
597 }
598 c->cdce_mbuf = m_new;
599 return (0);
600 }
601
602 Static int
603 cdce_rx_list_init(struct cdce_softc *sc)
604 {
605 struct cdce_cdata *cd;
606 struct cdce_chain *c;
607 int i, err;
608
609 cd = &sc->cdce_cdata;
610 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
611 c = &cd->cdce_rx_chain[i];
612 c->cdce_sc = sc;
613 c->cdce_idx = i;
614 if (c->cdce_xfer == NULL) {
615 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev,
616 sc->cdce_bulkin_pipe);
617 if (c->cdce_xfer == NULL)
618 return (ENOMEM);
619 if ((err = usbd_map_alloc(c->cdce_xfer) ? ENOMEM : 0) ||
620 (err = cdce_newbuf(sc, c, NULL))) {
621 usbd_free_xfer(c->cdce_xfer);
622 c->cdce_xfer = NULL;
623 return (err);
624 }
625 }
626 }
627
628 return (0);
629 }
630
631 Static int
632 cdce_tx_list_init(struct cdce_softc *sc)
633 {
634 struct cdce_cdata *cd;
635 struct cdce_chain *c;
636 int i;
637
638 cd = &sc->cdce_cdata;
639 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
640 c = &cd->cdce_tx_chain[i];
641 c->cdce_sc = sc;
642 c->cdce_idx = i;
643 c->cdce_mbuf = NULL;
644 if (c->cdce_xfer == NULL) {
645 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev,
646 sc->cdce_bulkout_pipe);
647 if (c->cdce_xfer == NULL)
648 return (ENOMEM);
649 if (usbd_map_alloc(c->cdce_xfer)) {
650 usbd_free_xfer(c->cdce_xfer);
651 c->cdce_xfer = NULL;
652 return (ENOMEM);
653 }
654 }
655 }
656
657 return (0);
658 }
659
660 Static void
661 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
662 {
663 struct cdce_chain *c = priv;
664 struct cdce_softc *sc = c->cdce_sc;
665 struct ifnet *ifp = GET_IFP(sc);
666 struct mbuf *m;
667 int total_len = 0;
668 int s;
669
670 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
671 return;
672
673 usbd_unmap_buffer(xfer);
674
675 if (status != USBD_NORMAL_COMPLETION) {
676 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
677 return;
678 if (sc->cdce_rxeof_errors == 0)
679 printf("%s: usb error on rx: %s\n",
680 USBDEVNAME(sc->cdce_dev), usbd_errstr(status));
681 if (status == USBD_STALLED)
682 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
683 DELAY(sc->cdce_rxeof_errors * 10000);
684 sc->cdce_rxeof_errors++;
685 goto done;
686 }
687
688 sc->cdce_rxeof_errors = 0;
689
690 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
691 if (sc->cdce_flags & CDCE_ZAURUS)
692 total_len -= 4; /* Strip off CRC added by Zaurus */
693
694 if (total_len < sizeof(struct ether_header)) {
695 ifp->if_ierrors++;
696 goto done;
697 }
698
699 m = c->cdce_mbuf;
700
701 /*
702 * Allocate new mbuf cluster for the next transfer.
703 * If that failed, discard current packet and recycle the mbuf.
704 */
705 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
706 ifp->if_ierrors++;
707 c->cdce_mbuf = m;
708 goto done;
709 }
710
711 ifp->if_ipackets++;
712 m->m_pkthdr.len = m->m_len = total_len;
713 m->m_pkthdr.rcvif = ifp;
714
715 s = splnet();
716
717 #if NBPFILTER > 0
718 if (ifp->if_bpf)
719 BPF_MTAP(ifp, m);
720 #endif
721
722 IF_INPUT(ifp, m);
723
724 splx(s);
725
726 done:
727 /* Setup new transfer. */
728 (void)usbd_map_buffer_mbuf(c->cdce_xfer, c->cdce_mbuf);
729 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, NULL /* XXX buf */,
730 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
731 cdce_rxeof);
732 usbd_transfer(c->cdce_xfer);
733 }
734
735 Static void
736 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv,
737 usbd_status status)
738 {
739 struct cdce_chain *c = priv;
740 struct cdce_softc *sc = c->cdce_sc;
741 struct ifnet *ifp = GET_IFP(sc);
742 usbd_status err;
743 int s;
744
745 if (sc->cdce_dying)
746 return;
747
748 usbd_unmap_buffer(xfer);
749
750 s = splnet();
751
752 ifp->if_timer = 0;
753 ifp->if_flags &= ~IFF_OACTIVE;
754
755 if (status != USBD_NORMAL_COMPLETION) {
756 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
757 splx(s);
758 return;
759 }
760 ifp->if_oerrors++;
761 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev),
762 usbd_errstr(status));
763 if (status == USBD_STALLED)
764 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
765 splx(s);
766 return;
767 }
768
769 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
770
771 if (c->cdce_mbuf != NULL) {
772 m_freem(c->cdce_mbuf);
773 c->cdce_mbuf = NULL;
774 }
775
776 if (err)
777 ifp->if_oerrors++;
778 else
779 ifp->if_opackets++;
780
781 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
782 cdce_start(ifp);
783
784 splx(s);
785 }
786
787 int
788 cdce_activate(device_ptr_t self, enum devact act)
789 {
790 struct cdce_softc *sc = (struct cdce_softc *)self;
791
792 switch (act) {
793 case DVACT_ACTIVATE:
794 return (EOPNOTSUPP);
795 break;
796
797 case DVACT_DEACTIVATE:
798 if_deactivate(GET_IFP(sc));
799 sc->cdce_dying = 1;
800 break;
801 }
802 return (0);
803 }
804
805
806 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
807 * code or tables extracted from it, as desired without restriction.
808 */
809
810 static const uint32_t cdce_crc32_tab[] = {
811 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
812 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
813 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
814 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
815 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
816 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
817 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
818 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
819 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
820 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
821 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
822 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
823 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
824 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
825 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
826 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
827 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
828 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
829 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
830 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
831 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
832 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
833 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
834 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
835 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
836 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
837 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
838 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
839 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
840 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
841 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
842 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
843 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
844 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
845 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
846 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
847 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
848 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
849 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
850 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
851 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
852 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
853 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
854 };
855
856 Static uint32_t
857 cdce_crc32(struct mbuf *m)
858 {
859 const uint8_t *p;
860 uint32_t crc;
861 int len;
862
863 crc = ~0U;
864
865 for ( ; m; m = m->m_next) {
866 for (p = mtod(m, uint8_t *), len = m->m_len; len > 0; len--) {
867 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
868 }
869 }
870
871 return (crc ^ ~0U);
872 }
873