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