1 /* $OpenBSD: if_cdce.c,v 1.35 2007/07/25 16:42:24 mbalmer Exp $ */ 2 3 /* 4 * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@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 <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 /* Get the data interface no. and capabilities */ 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 /* Find endpoints. */ 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 /* Zaurus wants a 32-bit CRC appended to every frame */ 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("Failed to establish interrupt pipe: %s\n", 623 usbd_errstr(err)); 624 return; 625 } 626 } 627 628 if (cdce_tx_list_init(sc) == ENOBUFS) { 629 printf("%s: tx list init failed\n", sc->cdce_dev.dv_xname); 630 splx(s); 631 return; 632 } 633 634 if (cdce_rx_list_init(sc) == ENOBUFS) { 635 printf("%s: rx list init failed\n", sc->cdce_dev.dv_xname); 636 splx(s); 637 return; 638 } 639 640 /* Maybe set multicast / broadcast here??? */ 641 642 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 643 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 644 if (err) { 645 printf("%s: open rx pipe failed: %s\n", sc->cdce_dev.dv_xname, 646 usbd_errstr(err)); 647 splx(s); 648 return; 649 } 650 651 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 652 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 653 if (err) { 654 printf("%s: open tx pipe failed: %s\n", sc->cdce_dev.dv_xname, 655 usbd_errstr(err)); 656 splx(s); 657 return; 658 } 659 660 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 661 c = &sc->cdce_cdata.cdce_rx_chain[i]; 662 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 663 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 664 USBD_NO_TIMEOUT, cdce_rxeof); 665 usbd_transfer(c->cdce_xfer); 666 } 667 668 ifp->if_flags |= IFF_RUNNING; 669 ifp->if_flags &= ~IFF_OACTIVE; 670 671 splx(s); 672 } 673 674 int 675 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 676 { 677 struct mbuf *m_new = NULL; 678 679 if (m == NULL) { 680 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 681 if (m_new == NULL) { 682 printf("%s: no memory for rx list " 683 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 684 return (ENOBUFS); 685 } 686 MCLGET(m_new, M_DONTWAIT); 687 if (!(m_new->m_flags & M_EXT)) { 688 printf("%s: no memory for rx list " 689 "-- packet dropped!\n", sc->cdce_dev.dv_xname); 690 m_freem(m_new); 691 return (ENOBUFS); 692 } 693 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 694 } else { 695 m_new = m; 696 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 697 m_new->m_data = m_new->m_ext.ext_buf; 698 } 699 700 m_adj(m_new, ETHER_ALIGN); 701 c->cdce_mbuf = m_new; 702 return (0); 703 } 704 705 int 706 cdce_rx_list_init(struct cdce_softc *sc) 707 { 708 struct cdce_cdata *cd; 709 struct cdce_chain *c; 710 int i; 711 712 cd = &sc->cdce_cdata; 713 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 714 c = &cd->cdce_rx_chain[i]; 715 c->cdce_sc = sc; 716 c->cdce_idx = i; 717 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 718 return (ENOBUFS); 719 if (c->cdce_xfer == NULL) { 720 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 721 if (c->cdce_xfer == NULL) 722 return (ENOBUFS); 723 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 724 if (c->cdce_buf == NULL) 725 return (ENOBUFS); 726 } 727 } 728 729 return (0); 730 } 731 732 int 733 cdce_tx_list_init(struct cdce_softc *sc) 734 { 735 struct cdce_cdata *cd; 736 struct cdce_chain *c; 737 int i; 738 739 cd = &sc->cdce_cdata; 740 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 741 c = &cd->cdce_tx_chain[i]; 742 c->cdce_sc = sc; 743 c->cdce_idx = i; 744 c->cdce_mbuf = NULL; 745 if (c->cdce_xfer == NULL) { 746 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 747 if (c->cdce_xfer == NULL) 748 return (ENOBUFS); 749 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 750 if (c->cdce_buf == NULL) 751 return (ENOBUFS); 752 } 753 } 754 755 return (0); 756 } 757 758 void 759 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 760 { 761 struct cdce_chain *c = priv; 762 struct cdce_softc *sc = c->cdce_sc; 763 struct ifnet *ifp = GET_IFP(sc); 764 struct mbuf *m; 765 int total_len = 0; 766 int s; 767 768 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING)) 769 return; 770 771 if (status != USBD_NORMAL_COMPLETION) { 772 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 773 return; 774 if (sc->cdce_rxeof_errors == 0) 775 printf("%s: usb error on rx: %s\n", 776 sc->cdce_dev.dv_xname, usbd_errstr(status)); 777 if (status == USBD_STALLED) 778 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 779 DELAY(sc->cdce_rxeof_errors * 10000); 780 if (sc->cdce_rxeof_errors++ > 10) { 781 printf("%s: too many errors, disabling\n", 782 sc->cdce_dev.dv_xname); 783 sc->cdce_dying = 1; 784 return; 785 } 786 goto done; 787 } 788 789 sc->cdce_rxeof_errors = 0; 790 791 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 792 if (sc->cdce_flags & CDCE_ZAURUS) 793 total_len -= 4; /* Strip off CRC added by Zaurus */ 794 if (total_len <= 1) 795 goto done; 796 797 m = c->cdce_mbuf; 798 memcpy(mtod(m, char *), c->cdce_buf, total_len); 799 800 if (total_len < sizeof(struct ether_header)) { 801 ifp->if_ierrors++; 802 goto done; 803 } 804 805 ifp->if_ipackets++; 806 807 m->m_pkthdr.len = m->m_len = total_len; 808 m->m_pkthdr.rcvif = ifp; 809 810 s = splnet(); 811 812 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 813 ifp->if_ierrors++; 814 goto done1; 815 } 816 817 #if NBPFILTER > 0 818 if (ifp->if_bpf) 819 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 820 #endif 821 822 ether_input_mbuf(ifp, m); 823 824 done1: 825 splx(s); 826 827 done: 828 /* Setup new transfer. */ 829 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 830 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 831 cdce_rxeof); 832 usbd_transfer(c->cdce_xfer); 833 } 834 835 void 836 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 837 { 838 struct cdce_chain *c = priv; 839 struct cdce_softc *sc = c->cdce_sc; 840 struct ifnet *ifp = GET_IFP(sc); 841 usbd_status err; 842 int s; 843 844 if (sc->cdce_dying) 845 return; 846 847 s = splnet(); 848 849 ifp->if_timer = 0; 850 ifp->if_flags &= ~IFF_OACTIVE; 851 852 if (status != USBD_NORMAL_COMPLETION) { 853 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 854 splx(s); 855 return; 856 } 857 ifp->if_oerrors++; 858 printf("%s: usb error on tx: %s\n", sc->cdce_dev.dv_xname, 859 usbd_errstr(status)); 860 if (status == USBD_STALLED) 861 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 862 splx(s); 863 return; 864 } 865 866 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 867 868 if (c->cdce_mbuf != NULL) { 869 m_freem(c->cdce_mbuf); 870 c->cdce_mbuf = NULL; 871 } 872 873 if (err) 874 ifp->if_oerrors++; 875 else 876 ifp->if_opackets++; 877 878 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 879 cdce_start(ifp); 880 881 splx(s); 882 } 883 884 int 885 cdce_activate(struct device *self, enum devact act) 886 { 887 struct cdce_softc *sc = (struct cdce_softc *)self; 888 889 switch (act) { 890 case DVACT_ACTIVATE: 891 break; 892 893 case DVACT_DEACTIVATE: 894 sc->cdce_dying = 1; 895 break; 896 } 897 return (0); 898 } 899 900 void 901 cdce_intr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status) 902 { 903 struct cdce_softc *sc = addr; 904 usb_cdc_notification_t *buf = &sc->cdce_intr_buf; 905 usb_cdc_connection_speed_t *speed; 906 u_int32_t count; 907 908 if (status == USBD_CANCELLED) 909 return; 910 911 if (status != USBD_NORMAL_COMPLETION) { 912 DPRINTFN(2, ("cdce_intr: status=%d\n", status)); 913 if (status == USBD_STALLED) 914 usbd_clear_endpoint_stall_async(sc->cdce_intr_pipe); 915 return; 916 } 917 918 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 919 920 if (buf->bmRequestType == UCDC_NOTIFICATION) { 921 switch (buf->bNotification) { 922 case UCDC_N_NETWORK_CONNECTION: 923 DPRINTFN(1, ("cdce_intr: network %s\n", 924 UGETW(buf->wValue) ? "connected" : "disconnected")); 925 break; 926 case UCDC_N_CONNECTION_SPEED_CHANGE: 927 speed = (usb_cdc_connection_speed_t *)&buf->data; 928 DPRINTFN(1, ("cdce_intr: up=%d, down=%d\n", 929 UGETDW(speed->dwUSBitRate), 930 UGETDW(speed->dwDSBitRate))); 931 break; 932 default: 933 DPRINTF(("cdce_intr: bNotification 0x%x\n", 934 buf->bNotification)); 935 } 936 } 937 #ifdef CDCE_DEBUG 938 else { 939 printf("cdce_intr: bmRequestType=%d ", buf->bmRequestType); 940 printf("wValue=%d wIndex=%d wLength=%d\n", UGETW(buf->wValue), 941 UGETW(buf->wIndex), UGETW(buf->wLength)); 942 } 943 #endif 944 } 945 946 947 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 948 * code or tables extracted from it, as desired without restriction. 949 */ 950 951 static uint32_t cdce_crc32_tab[] = { 952 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 953 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 954 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 955 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 956 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 957 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 958 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 959 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 960 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 961 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 962 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 963 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 964 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 965 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 966 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 967 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 968 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 969 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 970 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 971 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 972 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 973 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 974 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 975 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 976 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 977 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 978 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 979 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 980 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 981 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 982 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 983 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 984 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 985 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 986 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 987 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 988 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 989 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 990 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 991 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 992 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 993 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 994 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 995 }; 996 997 uint32_t 998 cdce_crc32(const void *buf, size_t size) 999 { 1000 const uint8_t *p; 1001 uint32_t crc; 1002 1003 p = buf; 1004 crc = ~0U; 1005 1006 while (size--) 1007 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 1008 1009 return (htole32(crc) ^ ~0U); 1010 } 1011