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