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