This source file includes following definitions.
- cdce_match
- cdce_attach
- cdce_detach
- cdce_start
- cdce_encap
- cdce_stop
- cdce_ioctl
- cdce_watchdog
- cdce_init
- cdce_newbuf
- cdce_rx_list_init
- cdce_tx_list_init
- cdce_rxeof
- cdce_txeof
- cdce_activate
- cdce_intr
- cdce_crc32
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <bpfilter.h>
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/sockio.h>
48 #include <sys/mbuf.h>
49 #include <sys/malloc.h>
50 #include <sys/kernel.h>
51 #include <sys/socket.h>
52 #include <sys/device.h>
53 #include <sys/proc.h>
54
55 #include <net/if.h>
56 #include <net/if_dl.h>
57
58 #include <net/bpf.h>
59 #if NBPFILTER > 0
60 #endif
61
62 #include <netinet/in.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/in_var.h>
65 #include <netinet/ip.h>
66 #include <netinet/if_ether.h>
67
68 #include <dev/usb/usb.h>
69 #include <dev/usb/usbdi.h>
70 #include <dev/usb/usbdi_util.h>
71 #include <dev/usb/usbdevs.h>
72 #include <dev/usb/usbcdc.h>
73
74 #include <dev/usb/if_cdcereg.h>
75
76 #ifdef CDCE_DEBUG
77 #define DPRINTFN(n, x) do { if (cdcedebug > (n)) printf x; } while (0)
78 int cdcedebug = 0;
79 #else
80 #define DPRINTFN(n, x)
81 #endif
82 #define DPRINTF(x) DPRINTFN(0, x)
83
84 int cdce_tx_list_init(struct cdce_softc *);
85 int cdce_rx_list_init(struct cdce_softc *);
86 int cdce_newbuf(struct cdce_softc *, struct cdce_chain *,
87 struct mbuf *);
88 int cdce_encap(struct cdce_softc *, struct mbuf *, int);
89 void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
90 void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
91 void cdce_start(struct ifnet *);
92 int cdce_ioctl(struct ifnet *, u_long, caddr_t);
93 void cdce_init(void *);
94 void cdce_watchdog(struct ifnet *);
95 void cdce_stop(struct cdce_softc *);
96 void cdce_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
97 static uint32_t cdce_crc32(const void *, size_t);
98
99 const struct cdce_type cdce_devs[] = {
100 {{ USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632 }, 0 },
101 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, 0 },
102 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS },
103 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS },
104 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS },
105 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS },
106 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS },
107 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_ZAURUS },
108 {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_ZAURUS },
109 {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 },
110 {{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, 0 },
111 {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 },
112 {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION },
113 };
114 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p))
115
116 int cdce_match(struct device *, void *, void *);
117 void cdce_attach(struct device *, struct device *, void *);
118 int cdce_detach(struct device *, int);
119 int cdce_activate(struct device *, enum devact);
120
121 struct cfdriver cdce_cd = {
122 NULL, "cdce", DV_IFNET
123 };
124
125 const struct cfattach cdce_ca = {
126 sizeof(struct cdce_softc),
127 cdce_match,
128 cdce_attach,
129 cdce_detach,
130 cdce_activate,
131 };
132
133 int
134 cdce_match(struct device *parent, void *match, void *aux)
135 {
136 struct usb_attach_arg *uaa = aux;
137 usb_interface_descriptor_t *id;
138
139 if (uaa->iface == NULL)
140 return (UMATCH_NONE);
141
142 id = usbd_get_interface_descriptor(uaa->iface);
143 if (id == NULL)
144 return (UMATCH_NONE);
145
146 if (cdce_lookup(uaa->vendor, uaa->product) != NULL)
147 return (UMATCH_VENDOR_PRODUCT);
148
149 if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass ==
150 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL)
151 return (UMATCH_IFACECLASS_GENERIC);
152
153 return (UMATCH_NONE);
154 }
155
156 void
157 cdce_attach(struct device *parent, struct device *self, void *aux)
158 {
159 struct cdce_softc *sc = (struct cdce_softc *)self;
160 struct usb_attach_arg *uaa = aux;
161 char *devinfop;
162 int s;
163 struct ifnet *ifp;
164 usbd_device_handle dev = uaa->device;
165 const struct cdce_type *t;
166 usb_interface_descriptor_t *id;
167 usb_endpoint_descriptor_t *ed;
168 usb_cdc_union_descriptor_t *ud;
169 usb_cdc_ethernet_descriptor_t *ethd;
170 usb_config_descriptor_t *cd;
171 const usb_descriptor_t *desc;
172 usbd_desc_iter_t iter;
173 usb_string_descriptor_t eaddr_str;
174 u_int16_t macaddr_hi;
175 int i, j, numalts, len;
176 int ctl_ifcno = -1;
177 int data_ifcno = -1;
178
179 devinfop = usbd_devinfo_alloc(dev, 0);
180 printf("\n%s: %s\n", sc->cdce_dev.dv_xname, devinfop);
181 usbd_devinfo_free(devinfop);
182
183 sc->cdce_udev = uaa->device;
184 sc->cdce_ctl_iface = uaa->iface;
185 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface);
186 ctl_ifcno = id->bInterfaceNumber;
187
188 t = cdce_lookup(uaa->vendor, uaa->product);
189 if (t)
190 sc->cdce_flags = t->cdce_flags;
191
192
193 ethd = NULL;
194 usb_desc_iter_init(dev, &iter);
195 desc = usb_desc_iter_next(&iter);
196 while (desc) {
197 if (desc->bDescriptorType != UDESC_CS_INTERFACE) {
198 desc = usb_desc_iter_next(&iter);
199 continue;
200 }
201 switch(desc->bDescriptorSubtype) {
202 case UDESCSUB_CDC_UNION:
203 ud = (usb_cdc_union_descriptor_t *)desc;
204 if ((sc->cdce_flags & CDCE_SWAPUNION) == 0 &&
205 ud->bMasterInterface == ctl_ifcno)
206 data_ifcno = ud->bSlaveInterface[0];
207 if ((sc->cdce_flags & CDCE_SWAPUNION) &&
208 ud->bSlaveInterface[0] == ctl_ifcno)
209 data_ifcno = ud->bMasterInterface;
210 break;
211 case UDESCSUB_CDC_ENF:
212 if (ethd) {
213 printf("%s: ", sc->cdce_dev.dv_xname);
214 printf("extra ethernet descriptor\n");
215 return;
216 }
217 ethd = (usb_cdc_ethernet_descriptor_t *)desc;
218 break;
219 }
220 desc = usb_desc_iter_next(&iter);
221 }
222
223 if (data_ifcno == -1) {
224 DPRINTF(("cdce_attach: no union interface\n"));
225 sc->cdce_data_iface = sc->cdce_ctl_iface;
226 } else {
227 DPRINTF(("cdce_attach: union interface: ctl=%d, data=%d\n",
228 ctl_ifcno, data_ifcno));
229 for (i = 0; i < uaa->nifaces; i++) {
230 if (uaa->ifaces[i] != NULL) {
231 id = usbd_get_interface_descriptor(
232 uaa->ifaces[i]);
233 if (id != NULL && id->bInterfaceNumber ==
234 data_ifcno) {
235 sc->cdce_data_iface = uaa->ifaces[i];
236 uaa->ifaces[i] = NULL;
237 }
238 }
239 }
240 }
241
242 if (sc->cdce_data_iface == NULL) {
243 printf("%s: no data interface\n", sc->cdce_dev.dv_xname);
244 return;
245 }
246
247 id = usbd_get_interface_descriptor(sc->cdce_ctl_iface);
248 sc->cdce_intr_no = -1;
249 for (i = 0; i < id->bNumEndpoints && sc->cdce_intr_no == -1; i++) {
250 ed = usbd_interface2endpoint_descriptor(sc->cdce_ctl_iface, i);
251 if (!ed) {
252 printf("%s: no descriptor for interrupt endpoint %d\n",
253 sc->cdce_dev.dv_xname, i);
254 return;
255 }
256 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
257 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
258 sc->cdce_intr_no = ed->bEndpointAddress;
259 sc->cdce_intr_size = sizeof(sc->cdce_intr_buf);
260 }
261 }
262
263 id = usbd_get_interface_descriptor(sc->cdce_data_iface);
264 cd = usbd_get_config_descriptor(sc->cdce_udev);
265 numalts = usbd_get_no_alts(cd, id->bInterfaceNumber);
266
267 for (j = 0; j < numalts; j++) {
268 if (usbd_set_interface(sc->cdce_data_iface, j)) {
269 printf("%s: interface alternate setting %d failed\n",
270 sc->cdce_dev.dv_xname, j);
271 return;
272 }
273
274 id = usbd_get_interface_descriptor(sc->cdce_data_iface);
275 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1;
276 for (i = 0; i < id->bNumEndpoints; i++) {
277 ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i);
278 if (!ed) {
279 printf("%s: no descriptor for bulk endpoint %d\n",
280 sc->cdce_dev.dv_xname, i);
281 return;
282 }
283 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
284 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
285 sc->cdce_bulkin_no = ed->bEndpointAddress;
286 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
287 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
288 sc->cdce_bulkout_no = ed->bEndpointAddress;
289 }
290 #ifdef CDCE_DEBUG
291 else if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_IN &&
292 UE_GET_XFERTYPE(ed->bmAttributes) != UE_INTERRUPT) {
293 printf("%s: unexpected endpoint, ep=%x attr=%x\n",
294 sc->cdce_dev.dv_xname, ed->bEndpointAddress,
295 ed->bmAttributes);
296 }
297 #endif
298 }
299 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) {
300 DPRINTF(("cdce_attach: intr=0x%x, in=0x%x, out=0x%x\n",
301 sc->cdce_intr_no, sc->cdce_bulkin_no, sc->cdce_bulkout_no));
302 goto found;
303 }
304 }
305
306 if (sc->cdce_bulkin_no == -1) {
307 printf("%s: could not find data bulk in\n",
308 sc->cdce_dev.dv_xname);
309 return;
310 }
311 if (sc->cdce_bulkout_no == -1 ) {
312 printf("%s: could not find data bulk out\n",
313 sc->cdce_dev.dv_xname);
314 return;
315 }
316
317 found:
318 s = splnet();
319
320 if (!ethd || usbd_get_string_desc(sc->cdce_udev, ethd->iMacAddress, 0,
321 &eaddr_str, &len)) {
322 macaddr_hi = htons(0x2acb);
323 bcopy(&macaddr_hi, &sc->cdce_arpcom.ac_enaddr[0],
324 sizeof(u_int16_t));
325 bcopy(&ticks, &sc->cdce_arpcom.ac_enaddr[2], sizeof(u_int32_t));
326 sc->cdce_arpcom.ac_enaddr[5] = (u_int8_t)(sc->cdce_unit);
327 } else {
328 for (i = 0; i < ETHER_ADDR_LEN * 2; i++) {
329 int c = UGETW(eaddr_str.bString[i]);
330
331 if ('0' <= c && c <= '9')
332 c -= '0';
333 else if ('A' <= c && c <= 'F')
334 c -= 'A' - 10;
335 else if ('a' <= c && c <= 'f')
336 c -= 'a' - 10;
337 c &= 0xf;
338 if (i % 2 == 0)
339 c <<= 4;
340 sc->cdce_arpcom.ac_enaddr[i / 2] |= c;
341 }
342 }
343
344 printf("%s: address %s\n", sc->cdce_dev.dv_xname,
345 ether_sprintf(sc->cdce_arpcom.ac_enaddr));
346
347 ifp = GET_IFP(sc);
348 ifp->if_softc = sc;
349 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
350 ifp->if_ioctl = cdce_ioctl;
351 ifp->if_start = cdce_start;
352 ifp->if_watchdog = cdce_watchdog;
353 strlcpy(ifp->if_xname, sc->cdce_dev.dv_xname, IFNAMSIZ);
354
355 IFQ_SET_READY(&ifp->if_snd);
356
357 if_attach(ifp);
358 ether_ifattach(ifp);
359
360 sc->cdce_attached = 1;
361 splx(s);
362
363 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev,
364 &sc->cdce_dev);
365 }
366
367 int
368 cdce_detach(struct device *self, int flags)
369 {
370 struct cdce_softc *sc = (struct cdce_softc *)self;
371 struct ifnet *ifp = GET_IFP(sc);
372 int s;
373
374 s = splusb();
375
376 if (!sc->cdce_attached) {
377 splx(s);
378 return (0);
379 }
380
381 if (ifp->if_flags & IFF_RUNNING)
382 cdce_stop(sc);
383
384 ether_ifdetach(ifp);
385
386 if_detach(ifp);
387
388 sc->cdce_attached = 0;
389 splx(s);
390
391 return (0);
392 }
393
394 void
395 cdce_start(struct ifnet *ifp)
396 {
397 struct cdce_softc *sc = ifp->if_softc;
398 struct mbuf *m_head = NULL;
399
400 if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE))
401 return;
402
403 IFQ_POLL(&ifp->if_snd, m_head);
404 if (m_head == NULL)
405 return;
406
407 if (cdce_encap(sc, m_head, 0)) {
408 ifp->if_flags |= IFF_OACTIVE;
409 return;
410 }
411
412 IFQ_DEQUEUE(&ifp->if_snd, m_head);
413
414 #if NBPFILTER > 0
415 if (ifp->if_bpf)
416 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
417 #endif
418
419 ifp->if_flags |= IFF_OACTIVE;
420
421 ifp->if_timer = 6;
422 }
423
424 int
425 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx)
426 {
427 struct cdce_chain *c;
428 usbd_status err;
429 int extra = 0;
430
431 c = &sc->cdce_cdata.cdce_tx_chain[idx];
432
433 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf);
434 if (sc->cdce_flags & CDCE_ZAURUS) {
435
436 u_int32_t crc;
437
438 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len);
439 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4);
440 extra = 4;
441 }
442 c->cdce_mbuf = m;
443
444 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf,
445 m->m_pkthdr.len + extra, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
446 10000, cdce_txeof);
447 err = usbd_transfer(c->cdce_xfer);
448 if (err != USBD_IN_PROGRESS) {
449 cdce_stop(sc);
450 return (EIO);
451 }
452
453 sc->cdce_cdata.cdce_tx_cnt++;
454
455 return (0);
456 }
457
458 void
459 cdce_stop(struct cdce_softc *sc)
460 {
461 usbd_status err;
462 struct ifnet *ifp = GET_IFP(sc);
463 int i;
464
465 ifp->if_timer = 0;
466 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
467
468 if (sc->cdce_bulkin_pipe != NULL) {
469 err = usbd_abort_pipe(sc->cdce_bulkin_pipe);
470 if (err)
471 printf("%s: abort rx pipe failed: %s\n",
472 sc->cdce_dev.dv_xname, usbd_errstr(err));
473 err = usbd_close_pipe(sc->cdce_bulkin_pipe);
474 if (err)
475 printf("%s: close rx pipe failed: %s\n",
476 sc->cdce_dev.dv_xname, usbd_errstr(err));
477 sc->cdce_bulkin_pipe = NULL;
478 }
479
480 if (sc->cdce_bulkout_pipe != NULL) {
481 err = usbd_abort_pipe(sc->cdce_bulkout_pipe);
482 if (err)
483 printf("%s: abort tx pipe failed: %s\n",
484 sc->cdce_dev.dv_xname, usbd_errstr(err));
485 err = usbd_close_pipe(sc->cdce_bulkout_pipe);
486 if (err)
487 printf("%s: close tx pipe failed: %s\n",
488 sc->cdce_dev.dv_xname, usbd_errstr(err));
489 sc->cdce_bulkout_pipe = NULL;
490 }
491
492 if (sc->cdce_intr_pipe != NULL) {
493 err = usbd_abort_pipe(sc->cdce_intr_pipe);
494 if (err)
495 printf("%s: abort interrupt pipe failed: %s\n",
496 sc->cdce_dev.dv_xname, usbd_errstr(err));
497 err = usbd_close_pipe(sc->cdce_intr_pipe);
498 if (err)
499 printf("%s: close interrupt pipe failed: %s\n",
500 sc->cdce_dev.dv_xname, usbd_errstr(err));
501 sc->cdce_intr_pipe = NULL;
502 }
503
504 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
505 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) {
506 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf);
507 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL;
508 }
509 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) {
510 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer);
511 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL;
512 }
513 }
514
515 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
516 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) {
517 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf);
518 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL;
519 }
520 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) {
521 usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer);
522 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL;
523 }
524 }
525 }
526
527 int
528 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
529 {
530 struct cdce_softc *sc = ifp->if_softc;
531 struct ifaddr *ifa = (struct ifaddr *)data;
532 struct ifreq *ifr = (struct ifreq *)data;
533 int s, error = 0;
534
535 if (sc->cdce_dying)
536 return (EIO);
537
538 s = splnet();
539
540 switch(command) {
541 case SIOCSIFADDR:
542 ifp->if_flags |= IFF_UP;
543 cdce_init(sc);
544 switch (ifa->ifa_addr->sa_family) {
545 case AF_INET:
546 arp_ifinit(&sc->cdce_arpcom, ifa);
547 break;
548 }
549 break;
550
551 case SIOCSIFMTU:
552 if (ifr->ifr_mtu > ETHERMTU)
553 error = EINVAL;
554 else
555 ifp->if_mtu = ifr->ifr_mtu;
556 break;
557
558 case SIOCSIFFLAGS:
559 if (ifp->if_flags & IFF_UP) {
560 if (!(ifp->if_flags & IFF_RUNNING))
561 cdce_init(sc);
562 } else {
563 if (ifp->if_flags & IFF_RUNNING)
564 cdce_stop(sc);
565 }
566 error = 0;
567 break;
568
569 case SIOCADDMULTI:
570 case SIOCDELMULTI:
571 error = (command == SIOCADDMULTI) ?
572 ether_addmulti(ifr, &sc->cdce_arpcom) :
573 ether_delmulti(ifr, &sc->cdce_arpcom);
574
575 if (error == ENETRESET)
576 error = 0;
577 break;
578
579 default:
580 error = EINVAL;
581 break;
582 }
583
584 splx(s);
585
586 return (error);
587 }
588
589 void
590 cdce_watchdog(struct ifnet *ifp)
591 {
592 struct cdce_softc *sc = ifp->if_softc;
593
594 if (sc->cdce_dying)
595 return;
596
597 ifp->if_oerrors++;
598 printf("%s: watchdog timeout\n", sc->cdce_dev.dv_xname);
599 }
600
601 void
602 cdce_init(void *xsc)
603 {
604 struct cdce_softc *sc = xsc;
605 struct ifnet *ifp = GET_IFP(sc);
606 struct cdce_chain *c;
607 usbd_status err;
608 int s, i;
609
610 if (ifp->if_flags & IFF_RUNNING)
611 return;
612
613 s = splnet();
614
615 if (sc->cdce_intr_no != -1 && sc->cdce_intr_pipe == NULL) {
616 DPRINTFN(1, ("cdce_init: establish interrupt pipe\n"));
617 err = usbd_open_pipe_intr(sc->cdce_ctl_iface, sc->cdce_intr_no,
618 USBD_SHORT_XFER_OK, &sc->cdce_intr_pipe, sc,
619 &sc->cdce_intr_buf, sc->cdce_intr_size, cdce_intr,
620 USBD_DEFAULT_INTERVAL);
621 if (err) {
622 printf("%s: open interrupt pipe failed: %s\n",
623 sc->cdce_dev.dv_xname, usbd_errstr(err));
624 splx(s);
625 return;
626 }
627 }
628
629 if (cdce_tx_list_init(sc) == ENOBUFS) {
630 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname);
631 splx(s);
632 return;
633 }
634
635 if (cdce_rx_list_init(sc) == ENOBUFS) {
636 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname);
637 splx(s);
638 return;
639 }
640
641
642
643 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
644 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
645 if (err) {
646 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname,
647 usbd_errstr(err));
648 splx(s);
649 return;
650 }
651
652 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
653 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
654 if (err) {
655 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname,
656 usbd_errstr(err));
657 splx(s);
658 return;
659 }
660
661 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
662 c = &sc->cdce_cdata.cdce_rx_chain[i];
663 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c,
664 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
665 USBD_NO_TIMEOUT, cdce_rxeof);
666 usbd_transfer(c->cdce_xfer);
667 }
668
669 ifp->if_flags |= IFF_RUNNING;
670 ifp->if_flags &= ~IFF_OACTIVE;
671
672 splx(s);
673 }
674
675 int
676 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m)
677 {
678 struct mbuf *m_new = NULL;
679
680 if (m == NULL) {
681 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
682 if (m_new == NULL) {
683 printf("%s: no memory for rx list "
684 "-- packet dropped!\n", sc->cdce_dev.dv_xname);
685 return (ENOBUFS);
686 }
687 MCLGET(m_new, M_DONTWAIT);
688 if (!(m_new->m_flags & M_EXT)) {
689 printf("%s: no memory for rx list "
690 "-- packet dropped!\n", sc->cdce_dev.dv_xname);
691 m_freem(m_new);
692 return (ENOBUFS);
693 }
694 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
695 } else {
696 m_new = m;
697 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
698 m_new->m_data = m_new->m_ext.ext_buf;
699 }
700
701 m_adj(m_new, ETHER_ALIGN);
702 c->cdce_mbuf = m_new;
703 return (0);
704 }
705
706 int
707 cdce_rx_list_init(struct cdce_softc *sc)
708 {
709 struct cdce_cdata *cd;
710 struct cdce_chain *c;
711 int i;
712
713 cd = &sc->cdce_cdata;
714 for (i = 0; i < CDCE_RX_LIST_CNT; i++) {
715 c = &cd->cdce_rx_chain[i];
716 c->cdce_sc = sc;
717 c->cdce_idx = i;
718 if (cdce_newbuf(sc, c, NULL) == ENOBUFS)
719 return (ENOBUFS);
720 if (c->cdce_xfer == NULL) {
721 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
722 if (c->cdce_xfer == NULL)
723 return (ENOBUFS);
724 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
725 if (c->cdce_buf == NULL)
726 return (ENOBUFS);
727 }
728 }
729
730 return (0);
731 }
732
733 int
734 cdce_tx_list_init(struct cdce_softc *sc)
735 {
736 struct cdce_cdata *cd;
737 struct cdce_chain *c;
738 int i;
739
740 cd = &sc->cdce_cdata;
741 for (i = 0; i < CDCE_TX_LIST_CNT; i++) {
742 c = &cd->cdce_tx_chain[i];
743 c->cdce_sc = sc;
744 c->cdce_idx = i;
745 c->cdce_mbuf = NULL;
746 if (c->cdce_xfer == NULL) {
747 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev);
748 if (c->cdce_xfer == NULL)
749 return (ENOBUFS);
750 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ);
751 if (c->cdce_buf == NULL)
752 return (ENOBUFS);
753 }
754 }
755
756 return (0);
757 }
758
759 void
760 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
761 {
762 struct cdce_chain *c = priv;
763 struct cdce_softc *sc = c->cdce_sc;
764 struct ifnet *ifp = GET_IFP(sc);
765 struct mbuf *m;
766 int total_len = 0;
767 int s;
768
769 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING))
770 return;
771
772 if (status != USBD_NORMAL_COMPLETION) {
773 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
774 return;
775 if (sc->cdce_rxeof_errors == 0)
776 printf("%s: usb error on rx: %s\n",
777 sc->cdce_dev.dv_xname, usbd_errstr(status));
778 if (status == USBD_STALLED)
779 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe);
780 DELAY(sc->cdce_rxeof_errors * 10000);
781 if (sc->cdce_rxeof_errors++ > 10) {
782 printf("%s: too many errors, disabling\n",
783 sc->cdce_dev.dv_xname);
784 sc->cdce_dying = 1;
785 return;
786 }
787 goto done;
788 }
789
790 sc->cdce_rxeof_errors = 0;
791
792 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
793 if (sc->cdce_flags & CDCE_ZAURUS)
794 total_len -= 4;
795 if (total_len <= 1)
796 goto done;
797
798 m = c->cdce_mbuf;
799 memcpy(mtod(m, char *), c->cdce_buf, total_len);
800
801 if (total_len < sizeof(struct ether_header)) {
802 ifp->if_ierrors++;
803 goto done;
804 }
805
806 ifp->if_ipackets++;
807
808 m->m_pkthdr.len = m->m_len = total_len;
809 m->m_pkthdr.rcvif = ifp;
810
811 s = splnet();
812
813 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) {
814 ifp->if_ierrors++;
815 goto done1;
816 }
817
818 #if NBPFILTER > 0
819 if (ifp->if_bpf)
820 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
821 #endif
822
823 ether_input_mbuf(ifp, m);
824
825 done1:
826 splx(s);
827
828 done:
829
830 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf,
831 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
832 cdce_rxeof);
833 usbd_transfer(c->cdce_xfer);
834 }
835
836 void
837 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
838 {
839 struct cdce_chain *c = priv;
840 struct cdce_softc *sc = c->cdce_sc;
841 struct ifnet *ifp = GET_IFP(sc);
842 usbd_status err;
843 int s;
844
845 if (sc->cdce_dying)
846 return;
847
848 s = splnet();
849
850 ifp->if_timer = 0;
851 ifp->if_flags &= ~IFF_OACTIVE;
852
853 if (status != USBD_NORMAL_COMPLETION) {
854 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
855 splx(s);
856 return;
857 }
858 ifp->if_oerrors++;
859 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname,
860 usbd_errstr(status));
861 if (status == USBD_STALLED)
862 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe);
863 splx(s);
864 return;
865 }
866
867 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err);
868
869 if (c->cdce_mbuf != NULL) {
870 m_freem(c->cdce_mbuf);
871 c->cdce_mbuf = NULL;
872 }
873
874 if (err)
875 ifp->if_oerrors++;
876 else
877 ifp->if_opackets++;
878
879 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
880 cdce_start(ifp);
881
882 splx(s);
883 }
884
885 int
886 cdce_activate(struct device *self, enum devact act)
887 {
888 struct cdce_softc *sc = (struct cdce_softc *)self;
889
890 switch (act) {
891 case DVACT_ACTIVATE:
892 break;
893
894 case DVACT_DEACTIVATE:
895 sc->cdce_dying = 1;
896 break;
897 }
898 return (0);
899 }
900
901 void
902 cdce_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
903 {
904 struct cdce_softc *sc = addr;
905 usb_cdc_notification_t *buf = &sc->cdce_intr_buf;
906 usb_cdc_connection_speed_t *speed;
907 u_int32_t count;
908
909 if (status == USBD_CANCELLED)
910 return;
911
912 if (status != USBD_NORMAL_COMPLETION) {
913 DPRINTFN(2, ("cdce_intr: status=%d\n", status));
914 if (status == USBD_STALLED)
915 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe);
916 return;
917 }
918
919 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
920
921 if (buf->bmRequestType == UCDC_NOTIFICATION) {
922 switch (buf->bNotification) {
923 case UCDC_N_NETWORK_CONNECTION:
924 DPRINTFN(1, ("cdce_intr: network %s\n",
925 UGETW(buf->wValue) ? "connected" : "disconnected"));
926 break;
927 case UCDC_N_CONNECTION_SPEED_CHANGE:
928 speed = (usb_cdc_connection_speed_t *)&buf->data;
929 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n",
930 UGETDW(speed->dwUSBitRate),
931 UGETDW(speed->dwDSBitRate)));
932 break;
933 default:
934 DPRINTF(("cdce_intr: bNotification 0x%x\n",
935 buf->bNotification));
936 }
937 }
938 #ifdef CDCE_DEBUG
939 else {
940 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType);
941 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue),
942 UGETW(buf->wIndex), UGETW(buf->wLength));
943 }
944 #endif
945 }
946
947
948
949
950
951
952 static uint32_t cdce_crc32_tab[] = {
953 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
954 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
955 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
956 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
957 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
958 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
959 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
960 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
961 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
962 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
963 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
964 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
965 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
966 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
967 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
968 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
969 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
970 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
971 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
972 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
973 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
974 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
975 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
976 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
977 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
978 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
979 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
980 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
981 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
982 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
983 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
984 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
985 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
986 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
987 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
988 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
989 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
990 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
991 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
992 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
993 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
994 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
995 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
996 };
997
998 uint32_t
999 cdce_crc32(const void *buf, size_t size)
1000 {
1001 const uint8_t *p;
1002 uint32_t crc;
1003
1004 p = buf;
1005 crc = ~0U;
1006
1007 while (size--)
1008 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
1009
1010 return (htole32(crc) ^ ~0U);
1011 }