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