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