1 /* $NetBSD: if_cdce.c,v 1.28 2010/04/05 07:21:48 joerg 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.28 2010/04/05 07:21:48 joerg Exp $"); 45 #ifdef __NetBSD__ 46 #include "opt_inet.h" 47 #endif 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/sockio.h> 52 #include <sys/mbuf.h> 53 #include <sys/malloc.h> 54 #include <sys/kernel.h> 55 #include <sys/socket.h> 56 #include <sys/device.h> 57 58 #if NRND > 0 59 #include <sys/rnd.h> 60 #endif 61 62 #include <net/if.h> 63 #include <net/if_arp.h> 64 #include <net/if_dl.h> 65 #include <net/if_media.h> 66 67 #include <net/bpf.h> 68 69 #include <net/if_ether.h> 70 #ifdef INET 71 #include <netinet/in.h> 72 #include <netinet/if_inarp.h> 73 #endif 74 75 76 77 #include <dev/usb/usb.h> 78 #include <dev/usb/usbdi.h> 79 #include <dev/usb/usbdi_util.h> 80 #include <dev/usb/usbdevs.h> 81 #include <dev/usb/usbcdc.h> 82 83 #include <dev/usb/if_cdcereg.h> 84 85 Static int cdce_tx_list_init(struct cdce_softc *); 86 Static int cdce_rx_list_init(struct cdce_softc *); 87 Static int cdce_newbuf(struct cdce_softc *, struct cdce_chain *, 88 struct mbuf *); 89 Static int cdce_encap(struct cdce_softc *, struct mbuf *, int); 90 Static void cdce_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 91 Static void cdce_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 92 Static void cdce_start(struct ifnet *); 93 Static int cdce_ioctl(struct ifnet *, u_long, void *); 94 Static void cdce_init(void *); 95 Static void cdce_watchdog(struct ifnet *); 96 Static void cdce_stop(struct cdce_softc *); 97 Static uint32_t cdce_crc32(const void *, size_t); 98 99 Static const struct cdce_type cdce_devs[] = { 100 {{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501 }, CDCE_NO_UNION }, 101 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500 }, CDCE_ZAURUS }, 102 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_A300 }, CDCE_ZAURUS | CDCE_NO_UNION }, 103 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600 }, CDCE_ZAURUS | CDCE_NO_UNION }, 104 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C700 }, CDCE_ZAURUS | CDCE_NO_UNION }, 105 {{ USB_VENDOR_SHARP, USB_PRODUCT_SHARP_C750 }, CDCE_ZAURUS | CDCE_NO_UNION }, 106 }; 107 #define cdce_lookup(v, p) ((const struct cdce_type *)usb_lookup(cdce_devs, v, p)) 108 109 int cdce_match(device_t, cfdata_t, void *); 110 void cdce_attach(device_t, device_t, void *); 111 int cdce_detach(device_t, int); 112 int cdce_activate(device_t, enum devact); 113 extern struct cfdriver cdce_cd; 114 CFATTACH_DECL_NEW(cdce, sizeof(struct cdce_softc), cdce_match, cdce_attach, 115 cdce_detach, cdce_activate); 116 117 int 118 cdce_match(device_t parent, cfdata_t match, void *aux) 119 { 120 struct usbif_attach_arg *uaa = aux; 121 122 if (cdce_lookup(uaa->vendor, uaa->product) != NULL) 123 return (UMATCH_VENDOR_PRODUCT); 124 125 if (uaa->class == UICLASS_CDC && uaa->subclass == 126 UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL) 127 return (UMATCH_IFACECLASS_GENERIC); 128 129 return (UMATCH_NONE); 130 } 131 132 void 133 cdce_attach(device_t parent, device_t self, void *aux) 134 { 135 struct cdce_softc *sc = device_private(self); 136 struct usbif_attach_arg *uaa = aux; 137 char *devinfop; 138 int s; 139 struct ifnet *ifp; 140 usbd_device_handle dev = uaa->device; 141 const struct cdce_type *t; 142 usb_interface_descriptor_t *id; 143 usb_endpoint_descriptor_t *ed; 144 const usb_cdc_union_descriptor_t *ud; 145 usb_config_descriptor_t *cd; 146 int data_ifcno; 147 int i, j, numalts; 148 u_char eaddr[ETHER_ADDR_LEN]; 149 const usb_cdc_ethernet_descriptor_t *ue; 150 char eaddr_str[USB_MAX_ENCODED_STRING_LEN]; 151 152 sc->cdce_dev = self; 153 154 aprint_naive("\n"); 155 aprint_normal("\n"); 156 157 devinfop = usbd_devinfo_alloc(dev, 0); 158 aprint_normal_dev(self, "%s\n", devinfop); 159 usbd_devinfo_free(devinfop); 160 161 sc->cdce_udev = uaa->device; 162 sc->cdce_ctl_iface = uaa->iface; 163 164 t = cdce_lookup(uaa->vendor, uaa->product); 165 if (t) 166 sc->cdce_flags = t->cdce_flags; 167 168 if (sc->cdce_flags & CDCE_NO_UNION) 169 sc->cdce_data_iface = sc->cdce_ctl_iface; 170 else { 171 ud = (const usb_cdc_union_descriptor_t *)usb_find_desc(sc->cdce_udev, 172 UDESC_CS_INTERFACE, UDESCSUB_CDC_UNION); 173 if (ud == NULL) { 174 aprint_error_dev(self, "no union descriptor\n"); 175 return; 176 } 177 data_ifcno = ud->bSlaveInterface[0]; 178 179 for (i = 0; i < uaa->nifaces; i++) { 180 if (uaa->ifaces[i] != NULL) { 181 id = usbd_get_interface_descriptor( 182 uaa->ifaces[i]); 183 if (id != NULL && id->bInterfaceNumber == 184 data_ifcno) { 185 sc->cdce_data_iface = uaa->ifaces[i]; 186 uaa->ifaces[i] = NULL; 187 } 188 } 189 } 190 } 191 192 if (sc->cdce_data_iface == NULL) { 193 aprint_error_dev(self, "no data interface\n"); 194 return; 195 } 196 197 /* 198 * <quote> 199 * The Data Class interface of a networking device shall have a minimum 200 * of two interface settings. The first setting (the default interface 201 * setting) includes no endpoints and therefore no networking traffic is 202 * exchanged whenever the default interface setting is selected. One or 203 * more additional interface settings are used for normal operation, and 204 * therefore each includes a pair of endpoints (one IN, and one OUT) to 205 * exchange network traffic. Select an alternate interface setting to 206 * initialize the network aspects of the device and to enable the 207 * exchange of network traffic. 208 * </quote> 209 * 210 * Some devices, most notably cable modems, include interface settings 211 * that have no IN or OUT endpoint, therefore loop through the list of all 212 * available interface settings looking for one with both IN and OUT 213 * endpoints. 214 */ 215 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 216 cd = usbd_get_config_descriptor(sc->cdce_udev); 217 numalts = usbd_get_no_alts(cd, id->bInterfaceNumber); 218 219 for (j = 0; j < numalts; j++) { 220 if (usbd_set_interface(sc->cdce_data_iface, j)) { 221 aprint_error_dev(sc->cdce_dev, 222 "setting alternate interface failed\n"); 223 return; 224 } 225 /* Find endpoints. */ 226 id = usbd_get_interface_descriptor(sc->cdce_data_iface); 227 sc->cdce_bulkin_no = sc->cdce_bulkout_no = -1; 228 for (i = 0; i < id->bNumEndpoints; i++) { 229 ed = usbd_interface2endpoint_descriptor(sc->cdce_data_iface, i); 230 if (!ed) { 231 aprint_error_dev(self, 232 "could not read endpoint descriptor\n"); 233 return; 234 } 235 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 236 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 237 sc->cdce_bulkin_no = ed->bEndpointAddress; 238 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 239 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 240 sc->cdce_bulkout_no = ed->bEndpointAddress; 241 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 242 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 243 /* XXX: CDC spec defines an interrupt pipe, but it is not 244 * needed for simple host-to-host applications. */ 245 } else { 246 aprint_error_dev(self, "unexpected endpoint\n"); 247 } 248 } 249 /* If we found something, try and use it... */ 250 if ((sc->cdce_bulkin_no != -1) && (sc->cdce_bulkout_no != -1)) 251 break; 252 } 253 254 if (sc->cdce_bulkin_no == -1) { 255 aprint_error_dev(self, "could not find data bulk in\n"); 256 return; 257 } 258 if (sc->cdce_bulkout_no == -1 ) { 259 aprint_error_dev(self, "could not find data bulk out\n"); 260 return; 261 } 262 263 ue = (const usb_cdc_ethernet_descriptor_t *)usb_find_desc(dev, 264 UDESC_INTERFACE, UDESCSUB_CDC_ENF); 265 if (!ue || usbd_get_string(dev, ue->iMacAddress, eaddr_str)) { 266 aprint_normal_dev(self, "faking address\n"); 267 eaddr[0]= 0x2a; 268 memcpy(&eaddr[1], &hardclock_ticks, sizeof(u_int32_t)); 269 eaddr[5] = (u_int8_t)(device_unit(sc->cdce_dev)); 270 } else { 271 (void)ether_nonstatic_aton(eaddr, eaddr_str); 272 } 273 274 s = splnet(); 275 276 aprint_normal_dev(self, "address %s\n", ether_sprintf(eaddr)); 277 278 ifp = GET_IFP(sc); 279 ifp->if_softc = sc; 280 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 281 ifp->if_ioctl = cdce_ioctl; 282 ifp->if_start = cdce_start; 283 ifp->if_watchdog = cdce_watchdog; 284 strncpy(ifp->if_xname, device_xname(sc->cdce_dev), IFNAMSIZ); 285 286 IFQ_SET_READY(&ifp->if_snd); 287 288 if_attach(ifp); 289 ether_ifattach(ifp, eaddr); 290 291 sc->cdce_attached = 1; 292 splx(s); 293 294 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->cdce_udev, 295 sc->cdce_dev); 296 297 return; 298 } 299 300 int 301 cdce_detach(device_t self, int flags) 302 { 303 struct cdce_softc *sc = device_private(self); 304 struct ifnet *ifp = GET_IFP(sc); 305 int s; 306 307 s = splusb(); 308 309 if (!sc->cdce_attached) { 310 splx(s); 311 return (0); 312 } 313 314 if (ifp->if_flags & IFF_RUNNING) 315 cdce_stop(sc); 316 317 ether_ifdetach(ifp); 318 319 if_detach(ifp); 320 321 sc->cdce_attached = 0; 322 splx(s); 323 324 return (0); 325 } 326 327 Static void 328 cdce_start(struct ifnet *ifp) 329 { 330 struct cdce_softc *sc = ifp->if_softc; 331 struct mbuf *m_head = NULL; 332 333 if (sc->cdce_dying || (ifp->if_flags & IFF_OACTIVE)) 334 return; 335 336 IFQ_POLL(&ifp->if_snd, m_head); 337 if (m_head == NULL) 338 return; 339 340 if (cdce_encap(sc, m_head, 0)) { 341 ifp->if_flags |= IFF_OACTIVE; 342 return; 343 } 344 345 IFQ_DEQUEUE(&ifp->if_snd, m_head); 346 347 bpf_mtap(ifp, m_head); 348 349 ifp->if_flags |= IFF_OACTIVE; 350 351 ifp->if_timer = 6; 352 } 353 354 Static int 355 cdce_encap(struct cdce_softc *sc, struct mbuf *m, int idx) 356 { 357 struct cdce_chain *c; 358 usbd_status err; 359 int extra = 0; 360 361 c = &sc->cdce_cdata.cdce_tx_chain[idx]; 362 363 m_copydata(m, 0, m->m_pkthdr.len, c->cdce_buf); 364 if (sc->cdce_flags & CDCE_ZAURUS) { 365 /* Zaurus wants a 32-bit CRC appended to every frame */ 366 u_int32_t crc; 367 368 crc = cdce_crc32(c->cdce_buf, m->m_pkthdr.len); 369 memcpy(c->cdce_buf + m->m_pkthdr.len, &crc, 4); 370 extra = 4; 371 } 372 c->cdce_mbuf = m; 373 374 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkout_pipe, c, c->cdce_buf, 375 m->m_pkthdr.len + extra, USBD_NO_COPY, 10000, cdce_txeof); 376 err = usbd_transfer(c->cdce_xfer); 377 if (err != USBD_IN_PROGRESS) { 378 cdce_stop(sc); 379 return (EIO); 380 } 381 382 sc->cdce_cdata.cdce_tx_cnt++; 383 384 return (0); 385 } 386 387 Static void 388 cdce_stop(struct cdce_softc *sc) 389 { 390 usbd_status err; 391 struct ifnet *ifp = GET_IFP(sc); 392 int i; 393 394 ifp->if_timer = 0; 395 396 if (sc->cdce_bulkin_pipe != NULL) { 397 err = usbd_abort_pipe(sc->cdce_bulkin_pipe); 398 if (err) 399 printf("%s: abort rx pipe failed: %s\n", 400 device_xname(sc->cdce_dev), usbd_errstr(err)); 401 err = usbd_close_pipe(sc->cdce_bulkin_pipe); 402 if (err) 403 printf("%s: close rx pipe failed: %s\n", 404 device_xname(sc->cdce_dev), usbd_errstr(err)); 405 sc->cdce_bulkin_pipe = NULL; 406 } 407 408 if (sc->cdce_bulkout_pipe != NULL) { 409 err = usbd_abort_pipe(sc->cdce_bulkout_pipe); 410 if (err) 411 printf("%s: abort tx pipe failed: %s\n", 412 device_xname(sc->cdce_dev), usbd_errstr(err)); 413 err = usbd_close_pipe(sc->cdce_bulkout_pipe); 414 if (err) 415 printf("%s: close tx pipe failed: %s\n", 416 device_xname(sc->cdce_dev), usbd_errstr(err)); 417 sc->cdce_bulkout_pipe = NULL; 418 } 419 420 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 421 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf != NULL) { 422 m_freem(sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf); 423 sc->cdce_cdata.cdce_rx_chain[i].cdce_mbuf = NULL; 424 } 425 if (sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer != NULL) { 426 usbd_free_xfer(sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer); 427 sc->cdce_cdata.cdce_rx_chain[i].cdce_xfer = NULL; 428 } 429 } 430 431 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 432 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf != NULL) { 433 m_freem(sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf); 434 sc->cdce_cdata.cdce_tx_chain[i].cdce_mbuf = NULL; 435 } 436 if (sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer != NULL) { 437 usbd_free_xfer(sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer); 438 sc->cdce_cdata.cdce_tx_chain[i].cdce_xfer = NULL; 439 } 440 } 441 442 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 443 } 444 445 Static int 446 cdce_ioctl(struct ifnet *ifp, u_long command, void *data) 447 { 448 struct cdce_softc *sc = ifp->if_softc; 449 struct ifaddr *ifa = (struct ifaddr *)data; 450 struct ifreq *ifr = (struct ifreq *)data; 451 int s, error = 0; 452 453 if (sc->cdce_dying) 454 return (EIO); 455 456 s = splnet(); 457 458 switch(command) { 459 case SIOCINITIFADDR: 460 ifp->if_flags |= IFF_UP; 461 cdce_init(sc); 462 switch (ifa->ifa_addr->sa_family) { 463 #ifdef INET 464 case AF_INET: 465 arp_ifinit(ifp, ifa); 466 break; 467 #endif /* INET */ 468 } 469 break; 470 471 case SIOCSIFMTU: 472 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU) 473 error = EINVAL; 474 else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET) 475 error = 0; 476 break; 477 478 case SIOCSIFFLAGS: 479 if ((error = ifioctl_common(ifp, command, data)) != 0) 480 break; 481 /* XXX re-use ether_ioctl() */ 482 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 483 case IFF_UP: 484 cdce_init(sc); 485 break; 486 case IFF_RUNNING: 487 cdce_stop(sc); 488 break; 489 default: 490 break; 491 } 492 break; 493 494 default: 495 error = ether_ioctl(ifp, command, data); 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", device_xname(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", device_xname(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", device_xname(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", device_xname(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", 557 device_xname(sc->cdce_dev), 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", device_xname(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", device_xname(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 device_xname(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 bpf_mtap(ifp, m); 712 713 (*(ifp)->if_input)((ifp), (m)); 714 715 done1: 716 splx(s); 717 718 done: 719 /* Setup new transfer. */ 720 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 721 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 722 cdce_rxeof); 723 usbd_transfer(c->cdce_xfer); 724 } 725 726 Static void 727 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 728 usbd_status status) 729 { 730 struct cdce_chain *c = priv; 731 struct cdce_softc *sc = c->cdce_sc; 732 struct ifnet *ifp = GET_IFP(sc); 733 usbd_status err; 734 int s; 735 736 if (sc->cdce_dying) 737 return; 738 739 s = splnet(); 740 741 ifp->if_timer = 0; 742 ifp->if_flags &= ~IFF_OACTIVE; 743 744 if (status != USBD_NORMAL_COMPLETION) { 745 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 746 splx(s); 747 return; 748 } 749 ifp->if_oerrors++; 750 printf("%s: usb error on tx: %s\n", device_xname(sc->cdce_dev), 751 usbd_errstr(status)); 752 if (status == USBD_STALLED) 753 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 754 splx(s); 755 return; 756 } 757 758 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 759 760 if (c->cdce_mbuf != NULL) { 761 m_freem(c->cdce_mbuf); 762 c->cdce_mbuf = NULL; 763 } 764 765 if (err) 766 ifp->if_oerrors++; 767 else 768 ifp->if_opackets++; 769 770 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 771 cdce_start(ifp); 772 773 splx(s); 774 } 775 776 int 777 cdce_activate(device_t self, enum devact act) 778 { 779 struct cdce_softc *sc = device_private(self); 780 781 switch (act) { 782 case DVACT_DEACTIVATE: 783 if_deactivate(GET_IFP(sc)); 784 sc->cdce_dying = 1; 785 return 0; 786 default: 787 return EOPNOTSUPP; 788 } 789 } 790 791 792 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 793 * code or tables extracted from it, as desired without restriction. 794 */ 795 796 static uint32_t cdce_crc32_tab[] = { 797 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 798 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 799 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 800 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 801 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 802 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 803 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 804 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 805 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 806 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 807 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 808 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 809 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 810 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 811 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 812 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 813 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 814 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 815 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 816 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 817 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 818 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 819 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 820 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 821 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 822 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 823 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 824 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 825 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 826 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 827 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 828 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 829 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 830 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 831 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 832 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 833 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 834 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 835 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 836 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 837 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 838 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 839 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 840 }; 841 842 Static uint32_t 843 cdce_crc32(const void *buf, size_t size) 844 { 845 const uint8_t *p; 846 uint32_t crc; 847 848 p = buf; 849 crc = ~0U; 850 851 while (size--) 852 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 853 854 return (crc ^ ~0U); 855 } 856