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