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