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