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