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