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