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