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