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