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