1 /* $NetBSD: if_cdce.c,v 1.27 2010/01/19 22:07:43 pooka 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.27 2010/01/19 22:07:43 pooka 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 if (ifp->if_bpf) 348 bpf_ops->bpf_mtap(ifp->if_bpf, m_head); 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 memcpy(c->cdce_buf + m->m_pkthdr.len, &crc, 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 device_xname(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 device_xname(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 device_xname(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 device_xname(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, void *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 SIOCINITIFADDR: 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 arp_ifinit(ifp, ifa); 467 break; 468 #endif /* INET */ 469 } 470 break; 471 472 case SIOCSIFMTU: 473 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU) 474 error = EINVAL; 475 else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET) 476 error = 0; 477 break; 478 479 case SIOCSIFFLAGS: 480 if ((error = ifioctl_common(ifp, command, data)) != 0) 481 break; 482 /* XXX re-use ether_ioctl() */ 483 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 484 case IFF_UP: 485 cdce_init(sc); 486 break; 487 case IFF_RUNNING: 488 cdce_stop(sc); 489 break; 490 default: 491 break; 492 } 493 break; 494 495 default: 496 error = ether_ioctl(ifp, command, data); 497 break; 498 } 499 500 splx(s); 501 502 return (error); 503 } 504 505 Static void 506 cdce_watchdog(struct ifnet *ifp) 507 { 508 struct cdce_softc *sc = ifp->if_softc; 509 510 if (sc->cdce_dying) 511 return; 512 513 ifp->if_oerrors++; 514 printf("%s: watchdog timeout\n", device_xname(sc->cdce_dev)); 515 } 516 517 Static void 518 cdce_init(void *xsc) 519 { 520 struct cdce_softc *sc = xsc; 521 struct ifnet *ifp = GET_IFP(sc); 522 struct cdce_chain *c; 523 usbd_status err; 524 int s, i; 525 526 if (ifp->if_flags & IFF_RUNNING) 527 return; 528 529 s = splnet(); 530 531 if (cdce_tx_list_init(sc) == ENOBUFS) { 532 printf("%s: tx list init failed\n", device_xname(sc->cdce_dev)); 533 splx(s); 534 return; 535 } 536 537 if (cdce_rx_list_init(sc) == ENOBUFS) { 538 printf("%s: rx list init failed\n", device_xname(sc->cdce_dev)); 539 splx(s); 540 return; 541 } 542 543 /* Maybe set multicast / broadcast here??? */ 544 545 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no, 546 USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe); 547 if (err) { 548 printf("%s: open rx pipe failed: %s\n", device_xname(sc->cdce_dev), 549 usbd_errstr(err)); 550 splx(s); 551 return; 552 } 553 554 err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no, 555 USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe); 556 if (err) { 557 printf("%s: open tx pipe failed: %s\n", 558 device_xname(sc->cdce_dev), usbd_errstr(err)); 559 splx(s); 560 return; 561 } 562 563 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 564 c = &sc->cdce_cdata.cdce_rx_chain[i]; 565 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, 566 c->cdce_buf, CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 567 USBD_NO_TIMEOUT, cdce_rxeof); 568 usbd_transfer(c->cdce_xfer); 569 } 570 571 ifp->if_flags |= IFF_RUNNING; 572 ifp->if_flags &= ~IFF_OACTIVE; 573 574 splx(s); 575 } 576 577 Static int 578 cdce_newbuf(struct cdce_softc *sc, struct cdce_chain *c, struct mbuf *m) 579 { 580 struct mbuf *m_new = NULL; 581 582 if (m == NULL) { 583 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 584 if (m_new == NULL) { 585 printf("%s: no memory for rx list " 586 "-- packet dropped!\n", device_xname(sc->cdce_dev)); 587 return (ENOBUFS); 588 } 589 MCLGET(m_new, M_DONTWAIT); 590 if (!(m_new->m_flags & M_EXT)) { 591 printf("%s: no memory for rx list " 592 "-- packet dropped!\n", device_xname(sc->cdce_dev)); 593 m_freem(m_new); 594 return (ENOBUFS); 595 } 596 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 597 } else { 598 m_new = m; 599 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 600 m_new->m_data = m_new->m_ext.ext_buf; 601 } 602 c->cdce_mbuf = m_new; 603 return (0); 604 } 605 606 Static int 607 cdce_rx_list_init(struct cdce_softc *sc) 608 { 609 struct cdce_cdata *cd; 610 struct cdce_chain *c; 611 int i; 612 613 cd = &sc->cdce_cdata; 614 for (i = 0; i < CDCE_RX_LIST_CNT; i++) { 615 c = &cd->cdce_rx_chain[i]; 616 c->cdce_sc = sc; 617 c->cdce_idx = i; 618 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) 619 return (ENOBUFS); 620 if (c->cdce_xfer == NULL) { 621 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 622 if (c->cdce_xfer == NULL) 623 return (ENOBUFS); 624 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 625 if (c->cdce_buf == NULL) 626 return (ENOBUFS); 627 } 628 } 629 630 return (0); 631 } 632 633 Static int 634 cdce_tx_list_init(struct cdce_softc *sc) 635 { 636 struct cdce_cdata *cd; 637 struct cdce_chain *c; 638 int i; 639 640 cd = &sc->cdce_cdata; 641 for (i = 0; i < CDCE_TX_LIST_CNT; i++) { 642 c = &cd->cdce_tx_chain[i]; 643 c->cdce_sc = sc; 644 c->cdce_idx = i; 645 c->cdce_mbuf = NULL; 646 if (c->cdce_xfer == NULL) { 647 c->cdce_xfer = usbd_alloc_xfer(sc->cdce_udev); 648 if (c->cdce_xfer == NULL) 649 return (ENOBUFS); 650 c->cdce_buf = usbd_alloc_buffer(c->cdce_xfer, CDCE_BUFSZ); 651 if (c->cdce_buf == NULL) 652 return (ENOBUFS); 653 } 654 } 655 656 return (0); 657 } 658 659 Static void 660 cdce_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 661 { 662 struct cdce_chain *c = priv; 663 struct cdce_softc *sc = c->cdce_sc; 664 struct ifnet *ifp = GET_IFP(sc); 665 struct mbuf *m; 666 int total_len = 0; 667 int s; 668 669 if (sc->cdce_dying || !(ifp->if_flags & IFF_RUNNING)) 670 return; 671 672 if (status != USBD_NORMAL_COMPLETION) { 673 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 674 return; 675 if (sc->cdce_rxeof_errors == 0) 676 printf("%s: usb error on rx: %s\n", 677 device_xname(sc->cdce_dev), usbd_errstr(status)); 678 if (status == USBD_STALLED) 679 usbd_clear_endpoint_stall_async(sc->cdce_bulkin_pipe); 680 DELAY(sc->cdce_rxeof_errors * 10000); 681 sc->cdce_rxeof_errors++; 682 goto done; 683 } 684 685 sc->cdce_rxeof_errors = 0; 686 687 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 688 if (sc->cdce_flags & CDCE_ZAURUS) 689 total_len -= 4; /* Strip off CRC added by Zaurus */ 690 if (total_len <= 1) 691 goto done; 692 693 m = c->cdce_mbuf; 694 memcpy(mtod(m, char *), c->cdce_buf, total_len); 695 696 if (total_len < sizeof(struct ether_header)) { 697 ifp->if_ierrors++; 698 goto done; 699 } 700 701 ifp->if_ipackets++; 702 m->m_pkthdr.len = m->m_len = total_len; 703 m->m_pkthdr.rcvif = ifp; 704 705 s = splnet(); 706 707 if (cdce_newbuf(sc, c, NULL) == ENOBUFS) { 708 ifp->if_ierrors++; 709 goto done1; 710 } 711 712 if (ifp->if_bpf) 713 bpf_ops->bpf_mtap(ifp->if_bpf, m); 714 715 (*(ifp)->if_input)((ifp), (m)); 716 717 done1: 718 splx(s); 719 720 done: 721 /* Setup new transfer. */ 722 usbd_setup_xfer(c->cdce_xfer, sc->cdce_bulkin_pipe, c, c->cdce_buf, 723 CDCE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 724 cdce_rxeof); 725 usbd_transfer(c->cdce_xfer); 726 } 727 728 Static void 729 cdce_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 730 usbd_status status) 731 { 732 struct cdce_chain *c = priv; 733 struct cdce_softc *sc = c->cdce_sc; 734 struct ifnet *ifp = GET_IFP(sc); 735 usbd_status err; 736 int s; 737 738 if (sc->cdce_dying) 739 return; 740 741 s = splnet(); 742 743 ifp->if_timer = 0; 744 ifp->if_flags &= ~IFF_OACTIVE; 745 746 if (status != USBD_NORMAL_COMPLETION) { 747 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 748 splx(s); 749 return; 750 } 751 ifp->if_oerrors++; 752 printf("%s: usb error on tx: %s\n", device_xname(sc->cdce_dev), 753 usbd_errstr(status)); 754 if (status == USBD_STALLED) 755 usbd_clear_endpoint_stall_async(sc->cdce_bulkout_pipe); 756 splx(s); 757 return; 758 } 759 760 usbd_get_xfer_status(c->cdce_xfer, NULL, NULL, NULL, &err); 761 762 if (c->cdce_mbuf != NULL) { 763 m_freem(c->cdce_mbuf); 764 c->cdce_mbuf = NULL; 765 } 766 767 if (err) 768 ifp->if_oerrors++; 769 else 770 ifp->if_opackets++; 771 772 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 773 cdce_start(ifp); 774 775 splx(s); 776 } 777 778 int 779 cdce_activate(device_t self, enum devact act) 780 { 781 struct cdce_softc *sc = device_private(self); 782 783 switch (act) { 784 case DVACT_DEACTIVATE: 785 if_deactivate(GET_IFP(sc)); 786 sc->cdce_dying = 1; 787 return 0; 788 default: 789 return EOPNOTSUPP; 790 } 791 } 792 793 794 /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or 795 * code or tables extracted from it, as desired without restriction. 796 */ 797 798 static uint32_t cdce_crc32_tab[] = { 799 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 800 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 801 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 802 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 803 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 804 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 805 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 806 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 807 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 808 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 809 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 810 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 811 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 812 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 813 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 814 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 815 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 816 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 817 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 818 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 819 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 820 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 821 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 822 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 823 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 824 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 825 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 826 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 827 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 828 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 829 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 830 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 831 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 832 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 833 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 834 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 835 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 836 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 837 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 838 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 839 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 840 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 841 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d 842 }; 843 844 Static uint32_t 845 cdce_crc32(const void *buf, size_t size) 846 { 847 const uint8_t *p; 848 uint32_t crc; 849 850 p = buf; 851 crc = ~0U; 852 853 while (size--) 854 crc = cdce_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); 855 856 return (crc ^ ~0U); 857 } 858