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