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