1 /* $NetBSD: if_upl.c,v 1.37 2010/04/05 07:21:48 joerg Exp $ */ 2 /* 3 * Copyright (c) 2000 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Lennart Augustsson (lennart@augustsson.net) at 8 * Carlstedt Research & Technology. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Prolific PL2301/PL2302 driver 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.37 2010/04/05 07:21:48 joerg Exp $"); 38 39 #include "opt_inet.h" 40 #include "rnd.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/callout.h> 45 #include <sys/sockio.h> 46 #include <sys/mbuf.h> 47 #include <sys/malloc.h> 48 #include <sys/kernel.h> 49 #include <sys/socket.h> 50 51 #include <sys/device.h> 52 #if NRND > 0 53 #include <sys/rnd.h> 54 #endif 55 56 #include <net/if.h> 57 #include <net/if_types.h> 58 #include <net/if_dl.h> 59 #include <net/netisr.h> 60 61 #include <net/bpf.h> 62 63 #ifdef INET 64 #include <netinet/in.h> 65 #include <netinet/in_var.h> 66 #include <netinet/if_inarp.h> 67 #endif 68 69 70 #include <dev/usb/usb.h> 71 #include <dev/usb/usbdi.h> 72 #include <dev/usb/usbdi_util.h> 73 #include <dev/usb/usbdevs.h> 74 75 /* 76 * 7 6 5 4 3 2 1 0 77 * tx rx 1 0 78 * 1110 0000 rxdata 79 * 1010 0000 idle 80 * 0010 0000 tx over 81 * 0110 tx over + rxd 82 */ 83 84 #define UPL_RXDATA 0x40 85 #define UPL_TXOK 0x80 86 87 #define UPL_INTR_PKTLEN 1 88 89 #define UPL_CONFIG_NO 1 90 #define UPL_IFACE_IDX 0 91 92 /***/ 93 94 #define UPL_INTR_INTERVAL 20 95 96 #define UPL_BUFSZ 1024 97 98 #define UPL_RX_FRAMES 1 99 #define UPL_TX_FRAMES 1 100 101 #define UPL_RX_LIST_CNT 1 102 #define UPL_TX_LIST_CNT 1 103 104 #define UPL_ENDPT_RX 0x0 105 #define UPL_ENDPT_TX 0x1 106 #define UPL_ENDPT_INTR 0x2 107 #define UPL_ENDPT_MAX 0x3 108 109 struct upl_type { 110 u_int16_t upl_vid; 111 u_int16_t upl_did; 112 }; 113 114 struct upl_softc; 115 116 struct upl_chain { 117 struct upl_softc *upl_sc; 118 usbd_xfer_handle upl_xfer; 119 char *upl_buf; 120 struct mbuf *upl_mbuf; 121 int upl_idx; 122 }; 123 124 struct upl_cdata { 125 struct upl_chain upl_tx_chain[UPL_TX_LIST_CNT]; 126 struct upl_chain upl_rx_chain[UPL_RX_LIST_CNT]; 127 int upl_tx_prod; 128 int upl_tx_cons; 129 int upl_tx_cnt; 130 int upl_rx_prod; 131 }; 132 133 struct upl_softc { 134 USBBASEDEVICE sc_dev; 135 136 struct ifnet sc_if; 137 #if NRND > 0 138 rndsource_element_t sc_rnd_source; 139 #endif 140 141 usb_callout_t sc_stat_ch; 142 143 usbd_device_handle sc_udev; 144 usbd_interface_handle sc_iface; 145 u_int16_t sc_vendor; 146 u_int16_t sc_product; 147 int sc_ed[UPL_ENDPT_MAX]; 148 usbd_pipe_handle sc_ep[UPL_ENDPT_MAX]; 149 struct upl_cdata sc_cdata; 150 151 uByte sc_ibuf; 152 153 char sc_dying; 154 char sc_attached; 155 u_int sc_rx_errs; 156 struct timeval sc_rx_notice; 157 u_int sc_intr_errs; 158 }; 159 160 #ifdef UPL_DEBUG 161 #define DPRINTF(x) if (upldebug) logprintf x 162 #define DPRINTFN(n,x) if (upldebug >= (n)) logprintf x 163 int upldebug = 0; 164 #else 165 #define DPRINTF(x) 166 #define DPRINTFN(n,x) 167 #endif 168 169 /* 170 * Various supported device vendors/products. 171 */ 172 Static struct upl_type sc_devs[] = { 173 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 }, 174 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 }, 175 { 0, 0 } 176 }; 177 178 USB_DECLARE_DRIVER(upl); 179 180 Static int upl_openpipes(struct upl_softc *); 181 Static int upl_tx_list_init(struct upl_softc *); 182 Static int upl_rx_list_init(struct upl_softc *); 183 Static int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *); 184 Static int upl_send(struct upl_softc *, struct mbuf *, int); 185 Static void upl_intr(usbd_xfer_handle, usbd_private_handle, usbd_status); 186 Static void upl_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 187 Static void upl_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status); 188 Static void upl_start(struct ifnet *); 189 Static int upl_ioctl(struct ifnet *, u_long, void *); 190 Static void upl_init(void *); 191 Static void upl_stop(struct upl_softc *); 192 Static void upl_watchdog(struct ifnet *); 193 194 Static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *, 195 struct rtentry *); 196 Static void upl_input(struct ifnet *, struct mbuf *); 197 198 /* 199 * Probe for a Prolific chip. 200 */ 201 USB_MATCH(upl) 202 { 203 USB_MATCH_START(upl, uaa); 204 struct upl_type *t; 205 206 for (t = sc_devs; t->upl_vid != 0; t++) 207 if (uaa->vendor == t->upl_vid && uaa->product == t->upl_did) 208 return (UMATCH_VENDOR_PRODUCT); 209 210 return (UMATCH_NONE); 211 } 212 213 USB_ATTACH(upl) 214 { 215 USB_ATTACH_START(upl, sc, uaa); 216 char *devinfop; 217 int s; 218 usbd_device_handle dev = uaa->device; 219 usbd_interface_handle iface; 220 usbd_status err; 221 struct ifnet *ifp; 222 usb_interface_descriptor_t *id; 223 usb_endpoint_descriptor_t *ed; 224 int i; 225 226 DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev)); 227 228 sc->sc_dev = self; 229 230 aprint_naive("\n"); 231 aprint_normal("\n"); 232 233 devinfop = usbd_devinfo_alloc(dev, 0); 234 aprint_normal_dev(self, "%s\n", devinfop); 235 usbd_devinfo_free(devinfop); 236 237 err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1); 238 if (err) { 239 aprint_error_dev(self, "setting config no failed\n"); 240 USB_ATTACH_ERROR_RETURN; 241 } 242 243 sc->sc_udev = dev; 244 sc->sc_product = uaa->product; 245 sc->sc_vendor = uaa->vendor; 246 247 err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface); 248 if (err) { 249 aprint_error_dev(self, "getting interface handle failed\n"); 250 USB_ATTACH_ERROR_RETURN; 251 } 252 253 sc->sc_iface = iface; 254 id = usbd_get_interface_descriptor(iface); 255 256 /* Find endpoints. */ 257 for (i = 0; i < id->bNumEndpoints; i++) { 258 ed = usbd_interface2endpoint_descriptor(iface, i); 259 if (ed == NULL) { 260 aprint_error_dev(self, "couldn't get ep %d\n", i); 261 USB_ATTACH_ERROR_RETURN; 262 } 263 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 264 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 265 sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress; 266 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 267 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 268 sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress; 269 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 270 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 271 sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress; 272 } 273 } 274 275 if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 || 276 sc->sc_ed[UPL_ENDPT_INTR] == 0) { 277 aprint_error_dev(self, "missing endpoint\n"); 278 USB_ATTACH_ERROR_RETURN; 279 } 280 281 s = splnet(); 282 283 /* Initialize interface info.*/ 284 ifp = &sc->sc_if; 285 ifp->if_softc = sc; 286 ifp->if_mtu = UPL_BUFSZ; 287 ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX; 288 ifp->if_ioctl = upl_ioctl; 289 ifp->if_start = upl_start; 290 ifp->if_watchdog = upl_watchdog; 291 strncpy(ifp->if_xname, USBDEVNAME(sc->sc_dev), IFNAMSIZ); 292 293 ifp->if_type = IFT_OTHER; 294 ifp->if_addrlen = 0; 295 ifp->if_hdrlen = 0; 296 ifp->if_output = upl_output; 297 ifp->if_input = upl_input; 298 ifp->if_baudrate = 12000000; 299 ifp->if_dlt = DLT_RAW; 300 IFQ_SET_READY(&ifp->if_snd); 301 302 /* Attach the interface. */ 303 if_attach(ifp); 304 if_alloc_sadl(ifp); 305 306 bpf_attach(ifp, DLT_RAW, 0); 307 #if NRND > 0 308 rnd_attach_source(&sc->sc_rnd_source, USBDEVNAME(sc->sc_dev), 309 RND_TYPE_NET, 0); 310 #endif 311 312 sc->sc_attached = 1; 313 splx(s); 314 315 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, 316 USBDEV(sc->sc_dev)); 317 318 USB_ATTACH_SUCCESS_RETURN; 319 } 320 321 USB_DETACH(upl) 322 { 323 USB_DETACH_START(upl, sc); 324 struct ifnet *ifp = &sc->sc_if; 325 int s; 326 327 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); 328 329 s = splusb(); 330 331 if (!sc->sc_attached) { 332 /* Detached before attached finished, so just bail out. */ 333 splx(s); 334 return (0); 335 } 336 337 if (ifp->if_flags & IFF_RUNNING) 338 upl_stop(sc); 339 340 #if NRND > 0 341 rnd_detach_source(&sc->sc_rnd_source); 342 #endif 343 bpf_detach(ifp); 344 345 if_detach(ifp); 346 347 #ifdef DIAGNOSTIC 348 if (sc->sc_ep[UPL_ENDPT_TX] != NULL || 349 sc->sc_ep[UPL_ENDPT_RX] != NULL || 350 sc->sc_ep[UPL_ENDPT_INTR] != NULL) 351 aprint_debug_dev(self, "detach has active endpoints\n"); 352 #endif 353 354 sc->sc_attached = 0; 355 splx(s); 356 357 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, 358 USBDEV(sc->sc_dev)); 359 360 return (0); 361 } 362 363 int 364 upl_activate(device_ptr_t self, enum devact act) 365 { 366 struct upl_softc *sc = device_private(self); 367 368 DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); 369 370 switch (act) { 371 case DVACT_DEACTIVATE: 372 /* Deactivate the interface. */ 373 if_deactivate(&sc->sc_if); 374 sc->sc_dying = 1; 375 return 0; 376 default: 377 return EOPNOTSUPP; 378 } 379 } 380 381 /* 382 * Initialize an RX descriptor and attach an MBUF cluster. 383 */ 384 Static int 385 upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m) 386 { 387 struct mbuf *m_new = NULL; 388 389 DPRINTFN(8,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); 390 391 if (m == NULL) { 392 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 393 if (m_new == NULL) { 394 printf("%s: no memory for rx list " 395 "-- packet dropped!\n", USBDEVNAME(sc->sc_dev)); 396 return (ENOBUFS); 397 } 398 399 MCLGET(m_new, M_DONTWAIT); 400 if (!(m_new->m_flags & M_EXT)) { 401 printf("%s: no memory for rx list " 402 "-- packet dropped!\n", USBDEVNAME(sc->sc_dev)); 403 m_freem(m_new); 404 return (ENOBUFS); 405 } 406 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 407 } else { 408 m_new = m; 409 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 410 m_new->m_data = m_new->m_ext.ext_buf; 411 } 412 413 c->upl_mbuf = m_new; 414 415 return (0); 416 } 417 418 Static int 419 upl_rx_list_init(struct upl_softc *sc) 420 { 421 struct upl_cdata *cd; 422 struct upl_chain *c; 423 int i; 424 425 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); 426 427 cd = &sc->sc_cdata; 428 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 429 c = &cd->upl_rx_chain[i]; 430 c->upl_sc = sc; 431 c->upl_idx = i; 432 if (upl_newbuf(sc, c, NULL) == ENOBUFS) 433 return (ENOBUFS); 434 if (c->upl_xfer == NULL) { 435 c->upl_xfer = usbd_alloc_xfer(sc->sc_udev); 436 if (c->upl_xfer == NULL) 437 return (ENOBUFS); 438 c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ); 439 if (c->upl_buf == NULL) { 440 usbd_free_xfer(c->upl_xfer); 441 return (ENOBUFS); 442 } 443 } 444 } 445 446 return (0); 447 } 448 449 Static int 450 upl_tx_list_init(struct upl_softc *sc) 451 { 452 struct upl_cdata *cd; 453 struct upl_chain *c; 454 int i; 455 456 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__)); 457 458 cd = &sc->sc_cdata; 459 for (i = 0; i < UPL_TX_LIST_CNT; i++) { 460 c = &cd->upl_tx_chain[i]; 461 c->upl_sc = sc; 462 c->upl_idx = i; 463 c->upl_mbuf = NULL; 464 if (c->upl_xfer == NULL) { 465 c->upl_xfer = usbd_alloc_xfer(sc->sc_udev); 466 if (c->upl_xfer == NULL) 467 return (ENOBUFS); 468 c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ); 469 if (c->upl_buf == NULL) { 470 usbd_free_xfer(c->upl_xfer); 471 return (ENOBUFS); 472 } 473 } 474 } 475 476 return (0); 477 } 478 479 /* 480 * A frame has been uploaded: pass the resulting mbuf chain up to 481 * the higher level protocols. 482 */ 483 Static void 484 upl_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status) 485 { 486 struct upl_chain *c = priv; 487 struct upl_softc *sc = c->upl_sc; 488 struct ifnet *ifp = &sc->sc_if; 489 struct mbuf *m; 490 int total_len = 0; 491 int s; 492 493 if (sc->sc_dying) 494 return; 495 496 if (!(ifp->if_flags & IFF_RUNNING)) 497 return; 498 499 if (status != USBD_NORMAL_COMPLETION) { 500 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 501 return; 502 sc->sc_rx_errs++; 503 if (usbd_ratecheck(&sc->sc_rx_notice)) { 504 printf("%s: %u usb errors on rx: %s\n", 505 USBDEVNAME(sc->sc_dev), sc->sc_rx_errs, 506 usbd_errstr(status)); 507 sc->sc_rx_errs = 0; 508 } 509 if (status == USBD_STALLED) 510 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 511 goto done; 512 } 513 514 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 515 516 DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", 517 USBDEVNAME(sc->sc_dev), __func__, status, total_len)); 518 519 m = c->upl_mbuf; 520 memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len); 521 522 ifp->if_ipackets++; 523 m->m_pkthdr.len = m->m_len = total_len; 524 525 m->m_pkthdr.rcvif = ifp; 526 527 s = splnet(); 528 529 /* XXX ugly */ 530 if (upl_newbuf(sc, c, NULL) == ENOBUFS) { 531 ifp->if_ierrors++; 532 goto done1; 533 } 534 535 /* 536 * Handle BPF listeners. Let the BPF user see the packet, but 537 * don't pass it up to the ether_input() layer unless it's 538 * a broadcast packet, multicast packet, matches our ethernet 539 * address or the interface is in promiscuous mode. 540 */ 541 bpf_mtap(ifp, m); 542 543 DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev), 544 __func__, m->m_len)); 545 546 IF_INPUT(ifp, m); 547 548 done1: 549 splx(s); 550 551 done: 552 #if 1 553 /* Setup new transfer. */ 554 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 555 c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 556 USBD_NO_TIMEOUT, upl_rxeof); 557 usbd_transfer(c->upl_xfer); 558 559 DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev), 560 __func__)); 561 #endif 562 } 563 564 /* 565 * A frame was downloaded to the chip. It's safe for us to clean up 566 * the list buffers. 567 */ 568 Static void 569 upl_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, 570 usbd_status status) 571 { 572 struct upl_chain *c = priv; 573 struct upl_softc *sc = c->upl_sc; 574 struct ifnet *ifp = &sc->sc_if; 575 int s; 576 577 if (sc->sc_dying) 578 return; 579 580 s = splnet(); 581 582 DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->sc_dev), 583 __func__, status)); 584 585 ifp->if_timer = 0; 586 ifp->if_flags &= ~IFF_OACTIVE; 587 588 if (status != USBD_NORMAL_COMPLETION) { 589 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 590 splx(s); 591 return; 592 } 593 ifp->if_oerrors++; 594 printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev), 595 usbd_errstr(status)); 596 if (status == USBD_STALLED) 597 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]); 598 splx(s); 599 return; 600 } 601 602 ifp->if_opackets++; 603 604 m_freem(c->upl_mbuf); 605 c->upl_mbuf = NULL; 606 607 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 608 upl_start(ifp); 609 610 splx(s); 611 } 612 613 Static int 614 upl_send(struct upl_softc *sc, struct mbuf *m, int idx) 615 { 616 int total_len; 617 struct upl_chain *c; 618 usbd_status err; 619 620 c = &sc->sc_cdata.upl_tx_chain[idx]; 621 622 /* 623 * Copy the mbuf data into a contiguous buffer, leaving two 624 * bytes at the beginning to hold the frame length. 625 */ 626 m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf); 627 c->upl_mbuf = m; 628 629 total_len = m->m_pkthdr.len; 630 631 DPRINTFN(10,("%s: %s: total_len=%d\n", 632 USBDEVNAME(sc->sc_dev), __func__, total_len)); 633 634 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX], 635 c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT, 636 upl_txeof); 637 638 /* Transmit */ 639 err = usbd_transfer(c->upl_xfer); 640 if (err != USBD_IN_PROGRESS) { 641 printf("%s: upl_send error=%s\n", USBDEVNAME(sc->sc_dev), 642 usbd_errstr(err)); 643 upl_stop(sc); 644 return (EIO); 645 } 646 647 sc->sc_cdata.upl_tx_cnt++; 648 649 return (0); 650 } 651 652 Static void 653 upl_start(struct ifnet *ifp) 654 { 655 struct upl_softc *sc = ifp->if_softc; 656 struct mbuf *m_head = NULL; 657 658 if (sc->sc_dying) 659 return; 660 661 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__)); 662 663 if (ifp->if_flags & IFF_OACTIVE) 664 return; 665 666 IFQ_POLL(&ifp->if_snd, m_head); 667 if (m_head == NULL) 668 return; 669 670 if (upl_send(sc, m_head, 0)) { 671 ifp->if_flags |= IFF_OACTIVE; 672 return; 673 } 674 675 IFQ_DEQUEUE(&ifp->if_snd, m_head); 676 677 /* 678 * If there's a BPF listener, bounce a copy of this frame 679 * to him. 680 */ 681 bpf_mtap(ifp, m_head); 682 683 ifp->if_flags |= IFF_OACTIVE; 684 685 /* 686 * Set a timeout in case the chip goes out to lunch. 687 */ 688 ifp->if_timer = 5; 689 } 690 691 Static void 692 upl_init(void *xsc) 693 { 694 struct upl_softc *sc = xsc; 695 struct ifnet *ifp = &sc->sc_if; 696 int s; 697 698 if (sc->sc_dying) 699 return; 700 701 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__)); 702 703 if (ifp->if_flags & IFF_RUNNING) 704 return; 705 706 s = splnet(); 707 708 /* Init TX ring. */ 709 if (upl_tx_list_init(sc) == ENOBUFS) { 710 printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev)); 711 splx(s); 712 return; 713 } 714 715 /* Init RX ring. */ 716 if (upl_rx_list_init(sc) == ENOBUFS) { 717 printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev)); 718 splx(s); 719 return; 720 } 721 722 if (sc->sc_ep[UPL_ENDPT_RX] == NULL) { 723 if (upl_openpipes(sc)) { 724 splx(s); 725 return; 726 } 727 } 728 729 ifp->if_flags |= IFF_RUNNING; 730 ifp->if_flags &= ~IFF_OACTIVE; 731 732 splx(s); 733 } 734 735 Static int 736 upl_openpipes(struct upl_softc *sc) 737 { 738 struct upl_chain *c; 739 usbd_status err; 740 int i; 741 742 /* Open RX and TX pipes. */ 743 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX], 744 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]); 745 if (err) { 746 printf("%s: open rx pipe failed: %s\n", 747 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 748 return (EIO); 749 } 750 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX], 751 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]); 752 if (err) { 753 printf("%s: open tx pipe failed: %s\n", 754 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 755 return (EIO); 756 } 757 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR], 758 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc, 759 &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr, 760 UPL_INTR_INTERVAL); 761 if (err) { 762 printf("%s: open intr pipe failed: %s\n", 763 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 764 return (EIO); 765 } 766 767 768 #if 1 769 /* Start up the receive pipe. */ 770 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 771 c = &sc->sc_cdata.upl_rx_chain[i]; 772 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 773 c, c->upl_buf, UPL_BUFSZ, 774 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 775 upl_rxeof); 776 usbd_transfer(c->upl_xfer); 777 } 778 #endif 779 780 return (0); 781 } 782 783 Static void 784 upl_intr(usbd_xfer_handle xfer, usbd_private_handle priv, 785 usbd_status status) 786 { 787 struct upl_softc *sc = priv; 788 struct ifnet *ifp = &sc->sc_if; 789 uByte stat; 790 791 DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__)); 792 793 if (sc->sc_dying) 794 return; 795 796 if (!(ifp->if_flags & IFF_RUNNING)) 797 return; 798 799 if (status != USBD_NORMAL_COMPLETION) { 800 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 801 return; 802 } 803 sc->sc_intr_errs++; 804 if (usbd_ratecheck(&sc->sc_rx_notice)) { 805 printf("%s: %u usb errors on intr: %s\n", 806 USBDEVNAME(sc->sc_dev), sc->sc_rx_errs, 807 usbd_errstr(status)); 808 sc->sc_intr_errs = 0; 809 } 810 if (status == USBD_STALLED) 811 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 812 return; 813 } 814 815 stat = sc->sc_ibuf; 816 817 if (stat == 0) 818 return; 819 820 DPRINTFN(10,("%s: %s: stat=0x%02x\n", USBDEVNAME(sc->sc_dev), 821 __func__, stat)); 822 823 } 824 825 Static int 826 upl_ioctl(struct ifnet *ifp, u_long command, void *data) 827 { 828 struct upl_softc *sc = ifp->if_softc; 829 struct ifaddr *ifa = (struct ifaddr *)data; 830 struct ifreq *ifr = (struct ifreq *)data; 831 int s, error = 0; 832 833 if (sc->sc_dying) 834 return (EIO); 835 836 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n", 837 USBDEVNAME(sc->sc_dev), __func__, command)); 838 839 s = splnet(); 840 841 switch(command) { 842 case SIOCINITIFADDR: 843 ifp->if_flags |= IFF_UP; 844 upl_init(sc); 845 846 switch (ifa->ifa_addr->sa_family) { 847 #ifdef INET 848 case AF_INET: 849 break; 850 #endif /* INET */ 851 } 852 break; 853 854 case SIOCSIFMTU: 855 if (ifr->ifr_mtu > UPL_BUFSZ) 856 error = EINVAL; 857 else if ((error = ifioctl_common(ifp, command, data)) == ENETRESET) 858 error = 0; 859 break; 860 861 case SIOCSIFFLAGS: 862 if ((error = ifioctl_common(ifp, command, data)) != 0) 863 break; 864 /* XXX re-use ether_ioctl() */ 865 switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { 866 case IFF_UP: 867 upl_init(sc); 868 break; 869 case IFF_RUNNING: 870 upl_stop(sc); 871 break; 872 default: 873 break; 874 } 875 break; 876 default: 877 error = ifioctl_common(ifp, command, data); 878 break; 879 } 880 881 splx(s); 882 883 return (error); 884 } 885 886 Static void 887 upl_watchdog(struct ifnet *ifp) 888 { 889 struct upl_softc *sc = ifp->if_softc; 890 891 DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__)); 892 893 if (sc->sc_dying) 894 return; 895 896 ifp->if_oerrors++; 897 printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev)); 898 899 upl_stop(sc); 900 upl_init(sc); 901 902 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 903 upl_start(ifp); 904 } 905 906 /* 907 * Stop the adapter and free any mbufs allocated to the 908 * RX and TX lists. 909 */ 910 Static void 911 upl_stop(struct upl_softc *sc) 912 { 913 usbd_status err; 914 struct ifnet *ifp; 915 int i; 916 917 DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__)); 918 919 ifp = &sc->sc_if; 920 ifp->if_timer = 0; 921 922 /* Stop transfers. */ 923 if (sc->sc_ep[UPL_ENDPT_RX] != NULL) { 924 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]); 925 if (err) { 926 printf("%s: abort rx pipe failed: %s\n", 927 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 928 } 929 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]); 930 if (err) { 931 printf("%s: close rx pipe failed: %s\n", 932 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 933 } 934 sc->sc_ep[UPL_ENDPT_RX] = NULL; 935 } 936 937 if (sc->sc_ep[UPL_ENDPT_TX] != NULL) { 938 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]); 939 if (err) { 940 printf("%s: abort tx pipe failed: %s\n", 941 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 942 } 943 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]); 944 if (err) { 945 printf("%s: close tx pipe failed: %s\n", 946 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 947 } 948 sc->sc_ep[UPL_ENDPT_TX] = NULL; 949 } 950 951 if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) { 952 err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 953 if (err) { 954 printf("%s: abort intr pipe failed: %s\n", 955 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 956 } 957 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 958 if (err) { 959 printf("%s: close intr pipe failed: %s\n", 960 USBDEVNAME(sc->sc_dev), usbd_errstr(err)); 961 } 962 sc->sc_ep[UPL_ENDPT_INTR] = NULL; 963 } 964 965 /* Free RX resources. */ 966 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 967 if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) { 968 m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf); 969 sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL; 970 } 971 if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) { 972 usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer); 973 sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL; 974 } 975 } 976 977 /* Free TX resources. */ 978 for (i = 0; i < UPL_TX_LIST_CNT; i++) { 979 if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) { 980 m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf); 981 sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL; 982 } 983 if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) { 984 usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer); 985 sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL; 986 } 987 } 988 989 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 990 } 991 992 Static int 993 upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 994 struct rtentry *rt0) 995 { 996 int s, len, error; 997 ALTQ_DECL(struct altq_pktattr pktattr;) 998 999 DPRINTFN(10,("%s: %s: enter\n", 1000 USBDEVNAME(((struct upl_softc *)ifp->if_softc)->sc_dev), 1001 __func__)); 1002 1003 /* 1004 * if the queueing discipline needs packet classification, 1005 * do it now. 1006 */ 1007 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr); 1008 1009 len = m->m_pkthdr.len; 1010 s = splnet(); 1011 /* 1012 * Queue message on interface, and start output if interface 1013 * not yet active. 1014 */ 1015 IFQ_ENQUEUE(&ifp->if_snd, m, &pktattr, error); 1016 if (error) { 1017 /* mbuf is already freed */ 1018 splx(s); 1019 return (error); 1020 } 1021 ifp->if_obytes += len; 1022 if ((ifp->if_flags & IFF_OACTIVE) == 0) 1023 (*ifp->if_start)(ifp); 1024 splx(s); 1025 1026 return (0); 1027 } 1028 1029 Static void 1030 upl_input(struct ifnet *ifp, struct mbuf *m) 1031 { 1032 #ifdef INET 1033 struct ifqueue *inq; 1034 int s; 1035 1036 /* XXX Assume all traffic is IP */ 1037 1038 schednetisr(NETISR_IP); 1039 inq = &ipintrq; 1040 1041 s = splnet(); 1042 if (IF_QFULL(inq)) { 1043 IF_DROP(inq); 1044 splx(s); 1045 #if 0 1046 if (sc->sc_flags & SC_DEBUG) 1047 printf("%s: input queue full\n", ifp->if_xname); 1048 #endif 1049 ifp->if_iqdrops++; 1050 return; 1051 } 1052 IF_ENQUEUE(inq, m); 1053 splx(s); 1054 #endif 1055 ifp->if_ipackets++; 1056 ifp->if_ibytes += m->m_len; 1057 } 1058