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