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