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