1 /* $OpenBSD: if_upl.c,v 1.65 2015/05/21 09:22:39 mpi 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/netisr.h> 52 53 #if NBPFILTER > 0 54 #include <net/bpf.h> 55 #endif 56 57 #include <netinet/in.h> 58 #include <netinet/if_ether.h> 59 60 #include <dev/usb/usb.h> 61 #include <dev/usb/usbdi.h> 62 #include <dev/usb/usbdi_util.h> 63 #include <dev/usb/usbdevs.h> 64 65 /* 66 * 7 6 5 4 3 2 1 0 67 * tx rx 1 0 68 * 1110 0000 rxdata 69 * 1010 0000 idle 70 * 0010 0000 tx over 71 * 0110 tx over + rxd 72 */ 73 74 #define UPL_RXDATA 0x40 75 #define UPL_TXOK 0x80 76 77 #define UPL_INTR_PKTLEN 1 78 79 #define UPL_CONFIG_NO 1 80 #define UPL_IFACE_IDX 0 81 82 /***/ 83 84 #define UPL_INTR_INTERVAL 20 85 86 #define UPL_BUFSZ 1024 87 88 #define UPL_RX_FRAMES 1 89 #define UPL_TX_FRAMES 1 90 91 #define UPL_RX_LIST_CNT 1 92 #define UPL_TX_LIST_CNT 1 93 94 #define UPL_ENDPT_RX 0x0 95 #define UPL_ENDPT_TX 0x1 96 #define UPL_ENDPT_INTR 0x2 97 #define UPL_ENDPT_MAX 0x3 98 99 struct upl_softc; 100 101 struct upl_chain { 102 struct upl_softc *upl_sc; 103 struct usbd_xfer *upl_xfer; 104 char *upl_buf; 105 struct mbuf *upl_mbuf; 106 int upl_idx; 107 }; 108 109 struct upl_cdata { 110 struct upl_chain upl_tx_chain[UPL_TX_LIST_CNT]; 111 struct upl_chain upl_rx_chain[UPL_RX_LIST_CNT]; 112 int upl_tx_prod; 113 int upl_tx_cons; 114 int upl_tx_cnt; 115 int upl_rx_prod; 116 }; 117 118 struct upl_softc { 119 struct device sc_dev; 120 121 struct ifnet sc_if; 122 struct timeout sc_stat_ch; 123 124 struct usbd_device *sc_udev; 125 struct usbd_interface *sc_iface; 126 int sc_ed[UPL_ENDPT_MAX]; 127 struct usbd_pipe *sc_ep[UPL_ENDPT_MAX]; 128 struct upl_cdata sc_cdata; 129 130 uByte sc_ibuf; 131 132 u_int sc_rx_errs; 133 struct timeval sc_rx_notice; 134 u_int sc_intr_errs; 135 }; 136 137 #ifdef UPL_DEBUG 138 #define DPRINTF(x) do { if (upldebug) printf x; } while (0) 139 #define DPRINTFN(n,x) do { if (upldebug >= (n)) printf x; } while (0) 140 int upldebug = 0; 141 #else 142 #define DPRINTF(x) 143 #define DPRINTFN(n,x) 144 #endif 145 146 /* 147 * Various supported device vendors/products. 148 */ 149 struct usb_devno upl_devs[] = { 150 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 }, 151 { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 } 152 }; 153 154 int upl_match(struct device *, void *, void *); 155 void upl_attach(struct device *, struct device *, void *); 156 int upl_detach(struct device *, int); 157 158 struct cfdriver upl_cd = { 159 NULL, "upl", DV_IFNET 160 }; 161 162 const struct cfattach upl_ca = { 163 sizeof(struct upl_softc), upl_match, upl_attach, upl_detach 164 }; 165 166 int upl_openpipes(struct upl_softc *); 167 int upl_tx_list_init(struct upl_softc *); 168 int upl_rx_list_init(struct upl_softc *); 169 int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *); 170 int upl_send(struct upl_softc *, struct mbuf *, int); 171 void upl_intr(struct usbd_xfer *, void *, usbd_status); 172 void upl_rxeof(struct usbd_xfer *, void *, usbd_status); 173 void upl_txeof(struct usbd_xfer *, void *, usbd_status); 174 void upl_start(struct ifnet *); 175 int upl_ioctl(struct ifnet *, u_long, caddr_t); 176 void upl_init(void *); 177 void upl_stop(struct upl_softc *); 178 void upl_watchdog(struct ifnet *); 179 180 int upl_output(struct ifnet *, struct mbuf *, struct sockaddr *, 181 struct rtentry *); 182 183 /* 184 * Probe for a Prolific chip. 185 */ 186 int 187 upl_match(struct device *parent, void *match, void *aux) 188 { 189 struct usb_attach_arg *uaa = aux; 190 191 if (uaa->iface != NULL) 192 return (UMATCH_NONE); 193 194 return (usb_lookup(upl_devs, uaa->vendor, uaa->product) != NULL ? 195 UMATCH_VENDOR_PRODUCT : UMATCH_NONE); 196 } 197 198 void 199 upl_attach(struct device *parent, struct device *self, void *aux) 200 { 201 struct upl_softc *sc = (struct upl_softc *)self; 202 struct usb_attach_arg *uaa = aux; 203 int s; 204 struct usbd_device *dev = uaa->device; 205 struct usbd_interface *iface; 206 usbd_status err; 207 struct ifnet *ifp; 208 usb_interface_descriptor_t *id; 209 usb_endpoint_descriptor_t *ed; 210 int i; 211 212 DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev)); 213 214 err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1); 215 if (err) { 216 printf("%s: setting config no failed\n", 217 sc->sc_dev.dv_xname); 218 return; 219 } 220 221 sc->sc_udev = dev; 222 223 err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface); 224 if (err) { 225 printf("%s: getting interface handle failed\n", 226 sc->sc_dev.dv_xname); 227 return; 228 } 229 230 sc->sc_iface = iface; 231 id = usbd_get_interface_descriptor(iface); 232 233 /* Find endpoints. */ 234 for (i = 0; i < id->bNumEndpoints; i++) { 235 ed = usbd_interface2endpoint_descriptor(iface, i); 236 if (ed == NULL) { 237 printf("%s: couldn't get ep %d\n", 238 sc->sc_dev.dv_xname, i); 239 return; 240 } 241 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 242 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 243 sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress; 244 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 245 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { 246 sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress; 247 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 248 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { 249 sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress; 250 } 251 } 252 253 if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 || 254 sc->sc_ed[UPL_ENDPT_INTR] == 0) { 255 printf("%s: missing endpoint\n", sc->sc_dev.dv_xname); 256 return; 257 } 258 259 s = splnet(); 260 261 /* Initialize interface info.*/ 262 ifp = &sc->sc_if; 263 ifp->if_softc = sc; 264 ifp->if_mtu = UPL_BUFSZ; 265 ifp->if_hardmtu = UPL_BUFSZ; 266 ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX; 267 ifp->if_ioctl = upl_ioctl; 268 ifp->if_start = upl_start; 269 ifp->if_watchdog = upl_watchdog; 270 strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ); 271 272 ifp->if_type = IFT_OTHER; 273 ifp->if_addrlen = 0; 274 ifp->if_hdrlen = 0; 275 ifp->if_output = upl_output; 276 ifp->if_baudrate = IF_Mbps(12); 277 IFQ_SET_READY(&ifp->if_snd); 278 279 /* Attach the interface. */ 280 if_attach(ifp); 281 if_alloc_sadl(ifp); 282 283 splx(s); 284 } 285 286 int 287 upl_detach(struct device *self, int flags) 288 { 289 struct upl_softc *sc = (struct upl_softc *)self; 290 struct ifnet *ifp = &sc->sc_if; 291 int s; 292 293 DPRINTFN(2,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 294 295 s = splusb(); 296 297 if (ifp->if_flags & IFF_RUNNING) 298 upl_stop(sc); 299 300 if (ifp->if_softc != NULL) 301 if_detach(ifp); 302 303 #ifdef DIAGNOSTIC 304 if (sc->sc_ep[UPL_ENDPT_TX] != NULL || 305 sc->sc_ep[UPL_ENDPT_RX] != NULL || 306 sc->sc_ep[UPL_ENDPT_INTR] != NULL) 307 printf("%s: detach has active endpoints\n", 308 sc->sc_dev.dv_xname); 309 #endif 310 311 splx(s); 312 313 return (0); 314 } 315 316 /* 317 * Initialize an RX descriptor and attach an MBUF cluster. 318 */ 319 int 320 upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m) 321 { 322 struct mbuf *m_new = NULL; 323 324 DPRINTFN(8,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 325 326 if (m == NULL) { 327 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 328 if (m_new == NULL) { 329 printf("%s: no memory for rx list " 330 "-- packet dropped!\n", sc->sc_dev.dv_xname); 331 return (ENOBUFS); 332 } 333 334 MCLGET(m_new, M_DONTWAIT); 335 if (!(m_new->m_flags & M_EXT)) { 336 printf("%s: no memory for rx list " 337 "-- packet dropped!\n", sc->sc_dev.dv_xname); 338 m_freem(m_new); 339 return (ENOBUFS); 340 } 341 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 342 } else { 343 m_new = m; 344 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 345 m_new->m_data = m_new->m_ext.ext_buf; 346 } 347 348 c->upl_mbuf = m_new; 349 350 return (0); 351 } 352 353 int 354 upl_rx_list_init(struct upl_softc *sc) 355 { 356 struct upl_cdata *cd; 357 struct upl_chain *c; 358 int i; 359 360 DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 361 362 cd = &sc->sc_cdata; 363 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 364 c = &cd->upl_rx_chain[i]; 365 c->upl_sc = sc; 366 c->upl_idx = i; 367 if (upl_newbuf(sc, c, NULL) == ENOBUFS) 368 return (ENOBUFS); 369 if (c->upl_xfer == NULL) { 370 c->upl_xfer = usbd_alloc_xfer(sc->sc_udev); 371 if (c->upl_xfer == NULL) 372 return (ENOBUFS); 373 c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ); 374 if (c->upl_buf == NULL) { 375 usbd_free_xfer(c->upl_xfer); 376 return (ENOBUFS); 377 } 378 } 379 } 380 381 return (0); 382 } 383 384 int 385 upl_tx_list_init(struct upl_softc *sc) 386 { 387 struct upl_cdata *cd; 388 struct upl_chain *c; 389 int i; 390 391 DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname, __func__)); 392 393 cd = &sc->sc_cdata; 394 for (i = 0; i < UPL_TX_LIST_CNT; i++) { 395 c = &cd->upl_tx_chain[i]; 396 c->upl_sc = sc; 397 c->upl_idx = i; 398 c->upl_mbuf = NULL; 399 if (c->upl_xfer == NULL) { 400 c->upl_xfer = usbd_alloc_xfer(sc->sc_udev); 401 if (c->upl_xfer == NULL) 402 return (ENOBUFS); 403 c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ); 404 if (c->upl_buf == NULL) { 405 usbd_free_xfer(c->upl_xfer); 406 return (ENOBUFS); 407 } 408 } 409 } 410 411 return (0); 412 } 413 414 /* 415 * A frame has been uploaded: pass the resulting mbuf chain up to 416 * the higher level protocols. 417 */ 418 void 419 upl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 420 { 421 struct upl_chain *c = priv; 422 struct upl_softc *sc = c->upl_sc; 423 struct ifnet *ifp = &sc->sc_if; 424 struct mbuf_list ml = MBUF_LIST_INITIALIZER(); 425 struct mbuf *m; 426 int total_len = 0; 427 int s; 428 429 if (usbd_is_dying(sc->sc_udev)) 430 return; 431 432 if (!(ifp->if_flags & IFF_RUNNING)) 433 return; 434 435 if (status != USBD_NORMAL_COMPLETION) { 436 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 437 return; 438 sc->sc_rx_errs++; 439 if (usbd_ratecheck(&sc->sc_rx_notice)) { 440 printf("%s: %u usb errors on rx: %s\n", 441 sc->sc_dev.dv_xname, sc->sc_rx_errs, 442 usbd_errstr(status)); 443 sc->sc_rx_errs = 0; 444 } 445 if (status == USBD_STALLED) 446 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 447 goto done; 448 } 449 450 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 451 452 DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", 453 sc->sc_dev.dv_xname, __func__, status, total_len)); 454 455 m = c->upl_mbuf; 456 memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len); 457 458 ifp->if_ipackets++; 459 m->m_pkthdr.len = m->m_len = total_len; 460 ml_enqueue(&ml, m); 461 462 if (upl_newbuf(sc, c, NULL) == ENOBUFS) { 463 ifp->if_ierrors++; 464 goto done; 465 } 466 467 s = splnet(); 468 if_input(ifp, &ml); 469 splx(s); 470 done: 471 #if 1 472 /* Setup new transfer. */ 473 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 474 c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 475 USBD_NO_TIMEOUT, upl_rxeof); 476 usbd_transfer(c->upl_xfer); 477 478 DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname, 479 __func__)); 480 #endif 481 } 482 483 /* 484 * A frame was downloaded to the chip. It's safe for us to clean up 485 * the list buffers. 486 */ 487 void 488 upl_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 489 { 490 struct upl_chain *c = priv; 491 struct upl_softc *sc = c->upl_sc; 492 struct ifnet *ifp = &sc->sc_if; 493 int s; 494 495 if (usbd_is_dying(sc->sc_udev)) 496 return; 497 498 s = splnet(); 499 500 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->sc_dev.dv_xname, 501 __func__, status)); 502 503 ifp->if_timer = 0; 504 ifp->if_flags &= ~IFF_OACTIVE; 505 506 if (status != USBD_NORMAL_COMPLETION) { 507 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 508 splx(s); 509 return; 510 } 511 ifp->if_oerrors++; 512 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname, 513 usbd_errstr(status)); 514 if (status == USBD_STALLED) 515 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]); 516 splx(s); 517 return; 518 } 519 520 ifp->if_opackets++; 521 522 m_freem(c->upl_mbuf); 523 c->upl_mbuf = NULL; 524 525 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 526 upl_start(ifp); 527 528 splx(s); 529 } 530 531 int 532 upl_send(struct upl_softc *sc, struct mbuf *m, int idx) 533 { 534 int total_len; 535 struct upl_chain *c; 536 usbd_status err; 537 538 c = &sc->sc_cdata.upl_tx_chain[idx]; 539 540 /* 541 * Copy the mbuf data into a contiguous buffer, leaving two 542 * bytes at the beginning to hold the frame length. 543 */ 544 m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf); 545 c->upl_mbuf = m; 546 547 total_len = m->m_pkthdr.len; 548 549 DPRINTFN(10,("%s: %s: total_len=%d\n", 550 sc->sc_dev.dv_xname, __func__, total_len)); 551 552 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX], 553 c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT, 554 upl_txeof); 555 556 /* Transmit */ 557 err = usbd_transfer(c->upl_xfer); 558 if (err != USBD_IN_PROGRESS) { 559 printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname, 560 usbd_errstr(err)); 561 upl_stop(sc); 562 return (EIO); 563 } 564 565 sc->sc_cdata.upl_tx_cnt++; 566 567 return (0); 568 } 569 570 void 571 upl_start(struct ifnet *ifp) 572 { 573 struct upl_softc *sc = ifp->if_softc; 574 struct mbuf *m_head = NULL; 575 576 if (usbd_is_dying(sc->sc_udev)) 577 return; 578 579 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 580 581 if (ifp->if_flags & IFF_OACTIVE) 582 return; 583 584 IFQ_POLL(&ifp->if_snd, m_head); 585 if (m_head == NULL) 586 return; 587 588 if (upl_send(sc, m_head, 0)) { 589 ifp->if_flags |= IFF_OACTIVE; 590 return; 591 } 592 593 IFQ_DEQUEUE(&ifp->if_snd, m_head); 594 595 #if NBPFILTER > 0 596 /* 597 * If there's a BPF listener, bounce a copy of this frame 598 * to him. 599 */ 600 if (ifp->if_bpf) 601 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 602 #endif 603 604 ifp->if_flags |= IFF_OACTIVE; 605 606 /* 607 * Set a timeout in case the chip goes out to lunch. 608 */ 609 ifp->if_timer = 5; 610 } 611 612 void 613 upl_init(void *xsc) 614 { 615 struct upl_softc *sc = xsc; 616 struct ifnet *ifp = &sc->sc_if; 617 int s; 618 619 if (usbd_is_dying(sc->sc_udev)) 620 return; 621 622 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 623 624 s = splnet(); 625 626 /* Init TX ring. */ 627 if (upl_tx_list_init(sc) == ENOBUFS) { 628 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); 629 splx(s); 630 return; 631 } 632 633 /* Init RX ring. */ 634 if (upl_rx_list_init(sc) == ENOBUFS) { 635 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); 636 splx(s); 637 return; 638 } 639 640 if (sc->sc_ep[UPL_ENDPT_RX] == NULL) { 641 if (upl_openpipes(sc)) { 642 splx(s); 643 return; 644 } 645 } 646 647 ifp->if_flags |= IFF_RUNNING; 648 ifp->if_flags &= ~IFF_OACTIVE; 649 650 splx(s); 651 } 652 653 int 654 upl_openpipes(struct upl_softc *sc) 655 { 656 struct upl_chain *c; 657 usbd_status err; 658 int i; 659 660 /* Open RX and TX pipes. */ 661 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX], 662 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]); 663 if (err) { 664 printf("%s: open rx pipe failed: %s\n", 665 sc->sc_dev.dv_xname, usbd_errstr(err)); 666 return (EIO); 667 } 668 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX], 669 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]); 670 if (err) { 671 printf("%s: open tx pipe failed: %s\n", 672 sc->sc_dev.dv_xname, usbd_errstr(err)); 673 return (EIO); 674 } 675 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR], 676 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc, 677 &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr, 678 UPL_INTR_INTERVAL); 679 if (err) { 680 printf("%s: open intr pipe failed: %s\n", 681 sc->sc_dev.dv_xname, usbd_errstr(err)); 682 return (EIO); 683 } 684 685 686 #if 1 687 /* Start up the receive pipe. */ 688 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 689 c = &sc->sc_cdata.upl_rx_chain[i]; 690 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 691 c, c->upl_buf, UPL_BUFSZ, 692 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 693 upl_rxeof); 694 usbd_transfer(c->upl_xfer); 695 } 696 #endif 697 698 return (0); 699 } 700 701 void 702 upl_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 703 { 704 struct upl_softc *sc = priv; 705 struct ifnet *ifp = &sc->sc_if; 706 uByte stat; 707 708 DPRINTFN(15,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 709 710 if (usbd_is_dying(sc->sc_udev)) 711 return; 712 713 if (!(ifp->if_flags & IFF_RUNNING)) 714 return; 715 716 if (status != USBD_NORMAL_COMPLETION) { 717 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 718 return; 719 } 720 sc->sc_intr_errs++; 721 if (usbd_ratecheck(&sc->sc_rx_notice)) { 722 printf("%s: %u usb errors on intr: %s\n", 723 sc->sc_dev.dv_xname, sc->sc_rx_errs, 724 usbd_errstr(status)); 725 sc->sc_intr_errs = 0; 726 } 727 if (status == USBD_STALLED) 728 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 729 return; 730 } 731 732 stat = sc->sc_ibuf; 733 734 if (stat == 0) 735 return; 736 737 DPRINTFN(10,("%s: %s: stat=0x%02x\n", sc->sc_dev.dv_xname, 738 __func__, stat)); 739 740 } 741 742 int 743 upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 744 { 745 struct upl_softc *sc = ifp->if_softc; 746 struct ifreq *ifr = (struct ifreq *)data; 747 int s, error = 0; 748 749 if (usbd_is_dying(sc->sc_udev)) 750 return (EIO); 751 752 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n", 753 sc->sc_dev.dv_xname, __func__, command)); 754 755 s = splnet(); 756 757 switch(command) { 758 case SIOCSIFADDR: 759 ifp->if_flags |= IFF_UP; 760 if (!(ifp->if_flags & IFF_RUNNING)) 761 upl_init(sc); 762 break; 763 764 case SIOCSIFFLAGS: 765 if (ifp->if_flags & IFF_UP) { 766 if (ifp->if_flags & IFF_RUNNING) 767 error = ENETRESET; 768 else 769 upl_init(sc); 770 } else { 771 if (ifp->if_flags & IFF_RUNNING) 772 upl_stop(sc); 773 } 774 break; 775 776 case SIOCSIFMTU: 777 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 778 error = EINVAL; 779 else 780 ifp->if_mtu = ifr->ifr_mtu; 781 break; 782 783 default: 784 error = ENOTTY; 785 } 786 787 if (error == ENETRESET) 788 error = 0; 789 790 splx(s); 791 return (error); 792 } 793 794 void 795 upl_watchdog(struct ifnet *ifp) 796 { 797 struct upl_softc *sc = ifp->if_softc; 798 799 DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 800 801 if (usbd_is_dying(sc->sc_udev)) 802 return; 803 804 ifp->if_oerrors++; 805 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); 806 807 upl_stop(sc); 808 upl_init(sc); 809 810 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 811 upl_start(ifp); 812 } 813 814 /* 815 * Stop the adapter and free any mbufs allocated to the 816 * RX and TX lists. 817 */ 818 void 819 upl_stop(struct upl_softc *sc) 820 { 821 usbd_status err; 822 struct ifnet *ifp; 823 int i; 824 825 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 826 827 ifp = &sc->sc_if; 828 ifp->if_timer = 0; 829 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 830 831 /* Stop transfers. */ 832 if (sc->sc_ep[UPL_ENDPT_RX] != NULL) { 833 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]); 834 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]); 835 if (err) { 836 printf("%s: close rx pipe failed: %s\n", 837 sc->sc_dev.dv_xname, usbd_errstr(err)); 838 } 839 sc->sc_ep[UPL_ENDPT_RX] = NULL; 840 } 841 842 if (sc->sc_ep[UPL_ENDPT_TX] != NULL) { 843 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]); 844 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]); 845 if (err) { 846 printf("%s: close tx pipe failed: %s\n", 847 sc->sc_dev.dv_xname, usbd_errstr(err)); 848 } 849 sc->sc_ep[UPL_ENDPT_TX] = NULL; 850 } 851 852 if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) { 853 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 854 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 855 if (err) { 856 printf("%s: close intr pipe failed: %s\n", 857 sc->sc_dev.dv_xname, usbd_errstr(err)); 858 } 859 sc->sc_ep[UPL_ENDPT_INTR] = NULL; 860 } 861 862 /* Free RX resources. */ 863 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 864 if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) { 865 m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf); 866 sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL; 867 } 868 if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) { 869 usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer); 870 sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL; 871 } 872 } 873 874 /* Free TX resources. */ 875 for (i = 0; i < UPL_TX_LIST_CNT; i++) { 876 if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) { 877 m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf); 878 sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL; 879 } 880 if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) { 881 usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer); 882 sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL; 883 } 884 } 885 } 886 887 int 888 upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 889 struct rtentry *rt0) 890 { 891 return (if_output(ifp, m)); 892 } 893