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