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