1 /* $NetBSD: if_cdce.c,v 1.9 2006/03/28 17:38:35 thorpej 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 <sys/cdefs.h> 44 __KERNEL_RCSID(0, "$NetBSD: if_cdce.c,v 1.9 2006/03/28 17:38:35 thorpej Exp $"); 45 #include "bpfilter.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/sockio.h> 50 #include <sys/mbuf.h> 51 #include <sys/malloc.h> 52 #include <sys/kernel.h> 53 #include <sys/socket.h> 54 #include <sys/device.h> 55 #if defined(__OpenBSD__) 56 #include <sys/proc.h> 57 #endif 58 59 #if NRND > 0 60 #include <sys/rnd.h> 61 #endif 62 63 #include <net/if.h> 64 #if defined(__NetBSD__) 65 #include <net/if_arp.h> 66 #endif 67 #include <net/if_dl.h> 68 #include <net/if_media.h> 69 70 #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m)) 71 72 #if NBPFILTER > 0 73 #include <net/bpf.h> 74 #endif 75 76 #if defined(__NetBSD__) 77 #include <net/if_ether.h> 78 #ifdef INET 79 #include <netinet/in.h> 80 #include <netinet/if_inarp.h> 81 #endif 82 #endif /* defined(__NetBSD__) */ 83 84 #if defined(__OpenBSD__) 85 #ifdef INET 86 #include <netinet/in.h> 87 #include <netinet/in_systm.h> 88 #include <netinet/in_var.h> 89 #include <netinet/ip.h> 90 #include <netinet/if_ether.h> 91 #endif 92 #endif /* defined(__OpenBSD__) */ 93 94 #ifdef NS 95 #include <netns/ns.h> 96 #include <netns/ns_if.h> 97 #endif 98 99 #include <dev/usb/usb.h> 100 #include <dev/usb/usbdi.h> 101 #include <dev/usb/usbdi_util.h> 102 #include <dev/usb/usbdevs.h> 103 #include <dev/usb/usbcdc.h> 104 105 #include <dev/usb/if_cdcereg.h> 106 107 Static int cdce_tx_list_init(struct cdce_softc *); 108 Static int cdce_rx_list_init(struct cdce_softc *); 109 Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, 110 struct mbuf *); 111 Static int cdce_encap(struct cdce_softc *, struct mbuf *, int); 112 Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 113 Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 114 Static void cdce_start(struct ifnet *); 115 Static int cdce_ioctl(struct ifnet *, u_long, caddr_t); 116 Static void cdce_init(void *); 117 Static void cdce_watchdog(struct ifnet *); 118 Static void cdce_stop(struct cdce_softc *); 119 Static uint32_t cdce_crc32(const void *, size_t); 120 121 Static const struct cdce_type cdce_devs[] = { 122 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION }, 123 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS }, 124 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION }, 125 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION }, 126 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION }, 127 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION }, 128 }; 129 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) 130 131 USB_DECLARE_DRIVER(cdce); 132 133 USB_MATCH(cdce) 134 { 135 USB_MATCH_START(cdce, uaa); 136 usb_interface_descriptor_t *id; 137 138 if (uaa->iface == NULL) 139 return (UMATCH_NONE); 140 141 id = usbd_get_interface_descriptor(uaa->iface); 142 if (id == NULL) 143 return (UMATCH_NONE); 144 145 if (cdce_lookup(uaa->vendor, uaa->product) != NULL) 146 return (UMATCH_VENDOR_PRODUCT); 147 148 if (id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass == 149 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) 150 return (UMATCH_IFACECLASS_GENERIC); 151 152 return (UMATCH_NONE); 153 } 154 155 USB_ATTACH(cdce) 156 { 157 USB_ATTACH_START(cdce, sc, uaa); 158 char *devinfop; 159 int s; 160 struct ifnet *ifp; 161 usbd_device_handle dev = uaa->device; 162 const struct cdce_type *t; 163 usb_interface_descriptor_t *id; 164 usb_endpoint_descriptor_t *ed; 165 const usb_cdc_union_descriptor_t *ud; 166 int data_ifcno; 167 int i; 168 u_char eaddr[ETHER_ADDR_LEN]; 169 const usb_cdc_ethernet_descriptor_t *ue; 170 char eaddr_str[USB_MAX_ENCODED_STRING_LEN]; 171 172 devinfop = usbd_devinfo_alloc(dev, 0); 173 USB_ATTACH_SETUP; 174 printf("%s: %s\n", USBDEVNAME(sc->cdce_dev), devinfop); 175 usbd_devinfo_free(devinfop); 176 177 sc->cdce_udev = uaa->device; 178 sc->cdce_ctl_iface = uaa->iface; 179 180 t = cdce_lookup(uaa->vendor, uaa->product); 181 if (t) 182 sc->cdce_flags = t->cdce_flags; 183 184 if (sc->cdce_flags & CDCE_NO_UNION) 185 sc->cdce_data_iface = sc->cdce_ctl_iface; 186 else { 187 ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev, 188 UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION); 189 if (ud == NULL) { 190 printf("%s: no union descriptor\n", 191 USBDEVNAME(sc->cdce_dev)); 192 USB_ATTACH_ERROR_RETURN; 193 } 194 data_ifcno = ud->bSlaveInterface[0]; 195 196 for (i = 0; i < uaa->nifaces; i++) { 197 if (uaa->ifaces[i] != NULL) { 198 id = usbd_get_interface_descriptor( 199 uaa->ifaces[i]); 200 if (id != NULL && id->bInterfaceNumber == 201 data_ifcno) { 202 sc->cdce_data_iface = uaa->ifaces[i]; 203 uaa->ifaces[i] = NULL; 204 } 205 } 206 } 207 } 208 209 if (sc->cdce_data_iface == NULL) { 210 printf("%s: no data interface\n", USBDEVNAME(sc->cdce_dev)); 211 USB_ATTACH_ERROR_RETURN; 212 } 213 214 /* Find endpoints. */ 215 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 216 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; 217 for (i = 0; i < id->bNumEndpoints; i++) { 218 ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i); 219 if (!ed) { 220 printf("%s: could not read endpoint descriptor\n", 221 USBDEVNAME(sc->cdce_dev)); 222 USB_ATTACH_ERROR_RETURN; 223 } 224 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 225 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 226 sc->cdce_bulkin_no = ed->bEndpointAddress; 227 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 228 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 229 sc->cdce_bulkout_no = ed->bEndpointAddress; 230 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 231 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 232 /* XXX: CDC spec defines an interrupt pipe, but it is not 233 * needed for simple host-to-host applications. */ 234 } else { 235 printf("%s: unexpected endpoint\n", 236 USBDEVNAME(sc->cdce_dev)); 237 } 238 } 239 240 if (sc->cdce_bulkin_no == -1) { 241 printf("%s: could not find data bulk in\n", 242 USBDEVNAME(sc->cdce_dev)); 243 USB_ATTACH_ERROR_RETURN; 244 } 245 if (sc->cdce_bulkout_no == -1 ) { 246 printf("%s: could not find data bulk out\n", 247 USBDEVNAME(sc->cdce_dev)); 248 USB_ATTACH_ERROR_RETURN; 249 } 250 251 ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev, 252 UDESC_INTERFACE, UDESCSUB_CDC_ENF); 253 if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) { 254 printf("%s: faking address\n", USBDEVNAME(sc->cdce_dev)); 255 eaddr[0]= 0x2a; 256 memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t)); 257 eaddr[5] = (u_int8_t)(device_unit(&sc->cdce_dev)); 258 } else { 259 int j; 260 261 memset(eaddr, 0, ETHER_ADDR_LEN); 262 for (j = 0; j < ETHER_ADDR_LEN * 2; j++) { 263 int c = eaddr_str[j]; 264 265 if ('0' <= c && c <= '9') 266 c -= '0'; 267 else 268 c -= 'A' - 10; 269 c &= 0xf; 270 if (c%2 == 0) 271 c <<= 4; 272 eaddr[j / 2] |= c; 273 } 274 } 275 276 s = splnet(); 277 278 printf("%s: address %s\n", USBDEVNAME(sc->cdce_dev), 279 ether_sprintf(eaddr)); 280 281 ifp = GET_IFP(sc); 282 ifp->if_softc = sc; 283 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 284 ifp->if_ioctl = cdce_ioctl; 285 ifp->if_start = cdce_start; 286 ifp->if_watchdog = cdce_watchdog; 287 strncpy(ifp->if_xname, USBDEVNAME(sc->cdce_dev), IFNAMSIZ); 288 289 IFQ_SET_READY(&ifp->if_snd); 290 291 if_attach(ifp); 292 Ether_ifattach(ifp, eaddr); 293 294 sc->cdce_attached = 1; 295 splx(s); 296 297 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev, 298 USBDEV(sc->cdce_dev)); 299 300 USB_ATTACH_SUCCESS_RETURN; 301 } 302 303 USB_DETACH(cdce) 304 { 305 USB_DETACH_START(cdce, sc); 306 struct ifnet *ifp = GET_IFP(sc); 307 int s; 308 309 s = splusb(); 310 311 if (!sc->cdce_attached) { 312 splx(s); 313 return (0); 314 } 315 316 if (ifp->if_flags & IFF_RUNNING) 317 cdce_stop(sc); 318 319 ether_ifdetach(ifp); 320 321 if_detach(ifp); 322 323 sc->cdce_attached = 0; 324 splx(s); 325 326 return (0); 327 } 328 329 Static void 330 cdce_start(struct ifnet *ifp) 331 { 332 struct cdce_softc *sc = ifp->if_softc; 333 struct mbuf *m_head = NULL; 334 335 if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE)) 336 return; 337 338 IFQ_POLL(&ifp->if_snd, m_head); 339 if (m_head == NULL) 340 return; 341 342 if (cdce_encap(sc, m_head, 0)) { 343 ifp->if_flags |= IFF_OACTIVE; 344 return; 345 } 346 347 IFQ_DEQUEUE(&ifp->if_snd, m_head); 348 349 #if NBPFILTER > 0 350 if (ifp->if_bpf) 351 BPF_MTAP(ifp, m_head); 352 #endif 353 354 ifp->if_flags |= IFF_OACTIVE; 355 356 ifp->if_timer = 6; 357 } 358 359 Static int 360 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 361 { 362 struct cdce_chain *c; 363 usbd_status err; 364 int extra = 0; 365 366 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 367 368 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 369 if (sc->cdce_flags & CDCE_ZAURUS) { 370 /* Zaurus wants a 32-bit CRC appended to every frame */ 371 u_int32_t crc; 372 373 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len); 374 bcopy(&crc, c->cdce_buf + m->m_pkthdr.len, 4); 375 extra = 4; 376 } 377 c->cdce_mbuf = m; 378 379 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 380 m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof); 381 err = usbd_transfer(c->cdce_xfer); 382 if (err != USBD_IN_PROGRESS) { 383 cdce_stop(sc); 384 return (EIO); 385 } 386 387 sc->cdce_cdata.cdce_tx_cnt++; 388 389 return (0); 390 } 391 392 Static void 393 cdce_stop(struct cdce_softc *sc) 394 { 395 usbd_status err; 396 struct ifnet *ifp = GET_IFP(sc); 397 int i; 398 399 ifp->if_timer = 0; 400 401 if (sc->cdce_bulkin_pipe != NULL) { 402 err = usbd_abort_pipe(sc->cdce_bulkin_pipe); 403 if (err) 404 printf("%s: abort rx pipe failed: %s\n", 405 USBDEVNAME(sc->cdce_dev), usbd_errstr(err)); 406 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 407 if (err) 408 printf("%s: close rx pipe failed: %s\n", 409 USBDEVNAME(sc->cdce_dev), usbd_errstr(err)); 410 sc->cdce_bulkin_pipe = NULL; 411 } 412 413 if (sc->cdce_bulkout_pipe != NULL) { 414 err = usbd_abort_pipe(sc->cdce_bulkout_pipe); 415 if (err) 416 printf("%s: abort tx pipe failed: %s\n", 417 USBDEVNAME(sc->cdce_dev), usbd_errstr(err)); 418 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 419 if (err) 420 printf("%s: close tx pipe failed: %s\n", 421 USBDEVNAME(sc->cdce_dev), usbd_errstr(err)); 422 sc->cdce_bulkout_pipe = NULL; 423 } 424 425 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 426 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 427 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 428 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 429 } 430 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 431 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 432 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 433 } 434 } 435 436 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 437 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 438 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 439 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 440 } 441 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 442 usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 443 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 444 } 445 } 446 447 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 448 } 449 450 Static int 451 cdce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 452 { 453 struct cdce_softc *sc = ifp->if_softc; 454 struct ifaddr *ifa = (struct ifaddr *)data; 455 struct ifreq *ifr = (struct ifreq *)data; 456 int s, error = 0; 457 458 if (sc->cdce_dying) 459 return (EIO); 460 461 s = splnet(); 462 463 switch(command) { 464 case SIOCSIFADDR: 465 ifp->if_flags |= IFF_UP; 466 cdce_init(sc); 467 switch (ifa->ifa_addr->sa_family) { 468 #ifdef INET 469 case AF_INET: 470 #if defined(__NetBSD__) 471 arp_ifinit(ifp, ifa); 472 #else 473 arp_ifinit(&sc->arpcom, ifa); 474 #endif 475 break; 476 #endif /* INET */ 477 #ifdef NS 478 case AF_NS: 479 { 480 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 481 482 if (ns_nullhost(*ina)) 483 ina->x_host = *(union ns_host *) 484 LLADDR(ifp->if_sadl); 485 else 486 memcpy(LLADDR(ifp->if_sadl), 487 ina->x_host.c_host, 488 ifp->if_addrlen); 489 break; 490 } 491 #endif /* NS */ 492 } 493 break; 494 495 case SIOCSIFMTU: 496 if (ifr->ifr_mtu > ETHERMTU) 497 error = EINVAL; 498 else 499 ifp->if_mtu = ifr->ifr_mtu; 500 break; 501 502 case SIOCSIFFLAGS: 503 if (ifp->if_flags & IFF_UP) { 504 if (!(ifp->if_flags & IFF_RUNNING)) 505 cdce_init(sc); 506 } else { 507 if (ifp->if_flags & IFF_RUNNING) 508 cdce_stop(sc); 509 } 510 error = 0; 511 break; 512 513 default: 514 error = EINVAL; 515 break; 516 } 517 518 splx(s); 519 520 return (error); 521 } 522 523 Static void 524 cdce_watchdog(struct ifnet *ifp) 525 { 526 struct cdce_softc *sc = ifp->if_softc; 527 528 if (sc->cdce_dying) 529 return; 530 531 ifp->if_oerrors++; 532 printf("%s: watchdog timeout\n", USBDEVNAME(sc->cdce_dev)); 533 } 534 535 Static void 536 cdce_init(void *xsc) 537 { 538 struct cdce_softc *sc = xsc; 539 struct ifnet *ifp = GET_IFP(sc); 540 struct cdce_chain *c; 541 usbd_status err; 542 int s, i; 543 544 if (ifp->if_flags & IFF_RUNNING) 545 return; 546 547 s = splnet(); 548 549 if (cdce_tx_list_init(sc) == ENOBUFS) { 550 printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev)); 551 splx(s); 552 return; 553 } 554 555 if (cdce_rx_list_init(sc) == ENOBUFS) { 556 printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev)); 557 splx(s); 558 return; 559 } 560 561 /* Maybe set multicast / broadcast here??? */ 562 563 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 564 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 565 if (err) { 566 printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev), 567 usbd_errstr(err)); 568 splx(s); 569 return; 570 } 571 572 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 573 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 574 if (err) { 575 printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev), 576 usbd_errstr(err)); 577 splx(s); 578 return; 579 } 580 581 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 582 c = &sc->cdce_cdata.cdce_rx_chain[i]; 583 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 584 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 585 USBD_NO_TIMEOUT, cdce_rxeof); 586 usbd_transfer(c->cdce_xfer); 587 } 588 589 ifp->if_flags |= IFF_RUNNING; 590 ifp->if_flags &= ~IFF_OACTIVE; 591 592 splx(s); 593 } 594 595 Static int 596 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 597 { 598 struct mbuf *m_new = NULL; 599 600 if (m == NULL) { 601 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 602 if (m_new == NULL) { 603 printf("%s: no memory for rx list " 604 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev)); 605 return (ENOBUFS); 606 } 607 MCLGET(m_new, M_DONTWAIT); 608 if (!(m_new->m_flags & M_EXT)) { 609 printf("%s: no memory for rx list " 610 "-- packet dropped!\n", USBDEVNAME(sc->cdce_dev)); 611 m_freem(m_new); 612 return (ENOBUFS); 613 } 614 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 615 } else { 616 m_new = m; 617 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 618 m_new->m_data = m_new->m_ext.ext_buf; 619 } 620 c->cdce_mbuf = m_new; 621 return (0); 622 } 623 624 Static int 625 cdce_rx_list_init(struct cdce_softc *sc) 626 { 627 struct cdce_cdata *cd; 628 struct cdce_chain *c; 629 int i; 630 631 cd = &sc->cdce_cdata; 632 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 633 c = &cd->cdce_rx_chain[i]; 634 c->cdce_sc = sc; 635 c->cdce_idx = i; 636 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 637 return (ENOBUFS); 638 if (c->cdce_xfer == NULL) { 639 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 640 if (c->cdce_xfer == NULL) 641 return (ENOBUFS); 642 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 643 if (c->cdce_buf == NULL) 644 return (ENOBUFS); 645 } 646 } 647 648 return (0); 649 } 650 651 Static int 652 cdce_tx_list_init(struct cdce_softc *sc) 653 { 654 struct cdce_cdata *cd; 655 struct cdce_chain *c; 656 int i; 657 658 cd = &sc->cdce_cdata; 659 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 660 c = &cd->cdce_tx_chain[i]; 661 c->cdce_sc = sc; 662 c->cdce_idx = i; 663 c->cdce_mbuf = NULL; 664 if (c->cdce_xfer == NULL) { 665 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 666 if (c->cdce_xfer == NULL) 667 return (ENOBUFS); 668 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 669 if (c->cdce_buf == NULL) 670 return (ENOBUFS); 671 } 672 } 673 674 return (0); 675 } 676 677 Static void 678 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 679 { 680 struct cdce_chain *c = priv; 681 struct cdce_softc *sc = c->cdce_sc; 682 struct ifnet *ifp = GET_IFP(sc); 683 struct mbuf *m; 684 int total_len = 0; 685 int s; 686 687 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING)) 688 return; 689 690 if (status != USBD_NORMAL_COMPLETION) { 691 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 692 return; 693 if (sc->cdce_rxeof_errors == 0) 694 printf("%s: usb error on rx: %s\n", 695 USBDEVNAME(sc->cdce_dev), usbd_errstr(status)); 696 if (status == USBD_STALLED) 697 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 698 DELAY(sc->cdce_rxeof_errors * 10000); 699 sc->cdce_rxeof_errors++; 700 goto done; 701 } 702 703 sc->cdce_rxeof_errors = 0; 704 705 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 706 if (sc->cdce_flags & CDCE_ZAURUS) 707 total_len -= 4; /* Strip off CRC added by Zaurus */ 708 if (total_len <= 1) 709 goto done; 710 711 m = c->cdce_mbuf; 712 memcpy(mtod(m, char *), c->cdce_buf, total_len); 713 714 if (total_len < sizeof(struct ether_header)) { 715 ifp->if_ierrors++; 716 goto done; 717 } 718 719 ifp->if_ipackets++; 720 m->m_pkthdr.len = m->m_len = total_len; 721 m->m_pkthdr.rcvif = ifp; 722 723 s = splnet(); 724 725 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 726 ifp->if_ierrors++; 727 goto done1; 728 } 729 730 #if NBPFILTER > 0 731 if (ifp->if_bpf) 732 BPF_MTAP(ifp, m); 733 #endif 734 735 IF_INPUT(ifp, m); 736 737 done1: 738 splx(s); 739 740 done: 741 /* Setup new transfer. */ 742 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 743 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 744 cdce_rxeof); 745 usbd_transfer(c->cdce_xfer); 746 } 747 748 Static void 749 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 750 { 751 struct cdce_chain *c = priv; 752 struct cdce_softc *sc = c->cdce_sc; 753 struct ifnet *ifp = GET_IFP(sc); 754 usbd_status err; 755 int s; 756 757 if (sc->cdce_dying) 758 return; 759 760 s = splnet(); 761 762 ifp->if_timer = 0; 763 ifp->if_flags &= ~IFF_OACTIVE; 764 765 if (status != USBD_NORMAL_COMPLETION) { 766 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 767 splx(s); 768 return; 769 } 770 ifp->if_oerrors++; 771 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->cdce_dev), 772 usbd_errstr(status)); 773 if (status == USBD_STALLED) 774 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 775 splx(s); 776 return; 777 } 778 779 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 780 781 if (c->cdce_mbuf != NULL) { 782 m_freem(c->cdce_mbuf); 783 c->cdce_mbuf = NULL; 784 } 785 786 if (err) 787 ifp->if_oerrors++; 788 else 789 ifp->if_opackets++; 790 791 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 792 cdce_start(ifp); 793 794 splx(s); 795 } 796 797 int 798 cdce_activate(device_ptr_t self, enum devact act) 799 { 800 struct cdce_softc *sc = (struct cdce_softc *)self; 801 802 switch (act) { 803 case DVACT_ACTIVATE: 804 return (EOPNOTSUPP); 805 break; 806 807 case DVACT_DEACTIVATE: 808 if_deactivate(GET_IFP(sc)); 809 sc->cdce_dying = 1; 810 break; 811 } 812 return (0); 813 } 814 815 816 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 817 * code or tables extracted from it, as desired without restriction. 818 */ 819 820 static uint32_t cdce_crc32_tab[] = { 821 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 822 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 823 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 824 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 825 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 826 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 827 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 828 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 829 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 830 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 831 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 832 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 833 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 834 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 835 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 836 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 837 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 838 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 839 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 840 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 841 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 842 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 843 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 844 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 845 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 846 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 847 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 848 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 849 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 850 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 851 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 852 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 853 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 854 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 855 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 856 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 857 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 858 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 859 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 860 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 861 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 862 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 863 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 864 }; 865 866 Static uint32_t 867 cdce_crc32(const void *buf, size_t size) 868 { 869 const uint8_t *p; 870 uint32_t crc; 871 872 p = buf; 873 crc = ~0U; 874 875 while (size--) 876 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 877 878 return (crc ^ ~0U); 879 } 880