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