1 /* $OpenBSD: if_upl.c,v 1.67 2015/06/30 13:54:42 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 m->m_pkthdr.len = m->m_len = total_len; 459 ml_enqueue(&ml, m); 460 461 if (upl_newbuf(sc, c, NULL) == ENOBUFS) { 462 ifp->if_ierrors++; 463 goto done; 464 } 465 466 s = splnet(); 467 if_input(ifp, &ml); 468 splx(s); 469 done: 470 #if 1 471 /* Setup new transfer. */ 472 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 473 c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 474 USBD_NO_TIMEOUT, upl_rxeof); 475 usbd_transfer(c->upl_xfer); 476 477 DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname, 478 __func__)); 479 #endif 480 } 481 482 /* 483 * A frame was downloaded to the chip. It's safe for us to clean up 484 * the list buffers. 485 */ 486 void 487 upl_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 488 { 489 struct upl_chain *c = priv; 490 struct upl_softc *sc = c->upl_sc; 491 struct ifnet *ifp = &sc->sc_if; 492 int s; 493 494 if (usbd_is_dying(sc->sc_udev)) 495 return; 496 497 s = splnet(); 498 499 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->sc_dev.dv_xname, 500 __func__, status)); 501 502 ifp->if_timer = 0; 503 ifp->if_flags &= ~IFF_OACTIVE; 504 505 if (status != USBD_NORMAL_COMPLETION) { 506 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 507 splx(s); 508 return; 509 } 510 ifp->if_oerrors++; 511 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname, 512 usbd_errstr(status)); 513 if (status == USBD_STALLED) 514 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]); 515 splx(s); 516 return; 517 } 518 519 ifp->if_opackets++; 520 521 m_freem(c->upl_mbuf); 522 c->upl_mbuf = NULL; 523 524 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 525 upl_start(ifp); 526 527 splx(s); 528 } 529 530 int 531 upl_send(struct upl_softc *sc, struct mbuf *m, int idx) 532 { 533 int total_len; 534 struct upl_chain *c; 535 usbd_status err; 536 537 c = &sc->sc_cdata.upl_tx_chain[idx]; 538 539 /* 540 * Copy the mbuf data into a contiguous buffer, leaving two 541 * bytes at the beginning to hold the frame length. 542 */ 543 m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf); 544 c->upl_mbuf = m; 545 546 total_len = m->m_pkthdr.len; 547 548 DPRINTFN(10,("%s: %s: total_len=%d\n", 549 sc->sc_dev.dv_xname, __func__, total_len)); 550 551 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX], 552 c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT, 553 upl_txeof); 554 555 /* Transmit */ 556 err = usbd_transfer(c->upl_xfer); 557 if (err != USBD_IN_PROGRESS) { 558 printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname, 559 usbd_errstr(err)); 560 upl_stop(sc); 561 return (EIO); 562 } 563 564 sc->sc_cdata.upl_tx_cnt++; 565 566 return (0); 567 } 568 569 void 570 upl_start(struct ifnet *ifp) 571 { 572 struct upl_softc *sc = ifp->if_softc; 573 struct mbuf *m_head = NULL; 574 575 if (usbd_is_dying(sc->sc_udev)) 576 return; 577 578 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 579 580 if (ifp->if_flags & IFF_OACTIVE) 581 return; 582 583 IFQ_POLL(&ifp->if_snd, m_head); 584 if (m_head == NULL) 585 return; 586 587 if (upl_send(sc, m_head, 0)) { 588 ifp->if_flags |= IFF_OACTIVE; 589 return; 590 } 591 592 IFQ_DEQUEUE(&ifp->if_snd, m_head); 593 594 #if NBPFILTER > 0 595 /* 596 * If there's a BPF listener, bounce a copy of this frame 597 * to him. 598 */ 599 if (ifp->if_bpf) 600 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 601 #endif 602 603 ifp->if_flags |= IFF_OACTIVE; 604 605 /* 606 * Set a timeout in case the chip goes out to lunch. 607 */ 608 ifp->if_timer = 5; 609 } 610 611 void 612 upl_init(void *xsc) 613 { 614 struct upl_softc *sc = xsc; 615 struct ifnet *ifp = &sc->sc_if; 616 int s; 617 618 if (usbd_is_dying(sc->sc_udev)) 619 return; 620 621 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 622 623 s = splnet(); 624 625 /* Init TX ring. */ 626 if (upl_tx_list_init(sc) == ENOBUFS) { 627 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); 628 splx(s); 629 return; 630 } 631 632 /* Init RX ring. */ 633 if (upl_rx_list_init(sc) == ENOBUFS) { 634 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); 635 splx(s); 636 return; 637 } 638 639 if (sc->sc_ep[UPL_ENDPT_RX] == NULL) { 640 if (upl_openpipes(sc)) { 641 splx(s); 642 return; 643 } 644 } 645 646 ifp->if_flags |= IFF_RUNNING; 647 ifp->if_flags &= ~IFF_OACTIVE; 648 649 splx(s); 650 } 651 652 int 653 upl_openpipes(struct upl_softc *sc) 654 { 655 struct upl_chain *c; 656 usbd_status err; 657 int i; 658 659 /* Open RX and TX pipes. */ 660 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX], 661 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]); 662 if (err) { 663 printf("%s: open rx pipe failed: %s\n", 664 sc->sc_dev.dv_xname, usbd_errstr(err)); 665 return (EIO); 666 } 667 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX], 668 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]); 669 if (err) { 670 printf("%s: open tx pipe failed: %s\n", 671 sc->sc_dev.dv_xname, usbd_errstr(err)); 672 return (EIO); 673 } 674 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR], 675 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc, 676 &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr, 677 UPL_INTR_INTERVAL); 678 if (err) { 679 printf("%s: open intr pipe failed: %s\n", 680 sc->sc_dev.dv_xname, usbd_errstr(err)); 681 return (EIO); 682 } 683 684 685 #if 1 686 /* Start up the receive pipe. */ 687 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 688 c = &sc->sc_cdata.upl_rx_chain[i]; 689 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 690 c, c->upl_buf, UPL_BUFSZ, 691 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 692 upl_rxeof); 693 usbd_transfer(c->upl_xfer); 694 } 695 #endif 696 697 return (0); 698 } 699 700 void 701 upl_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 702 { 703 struct upl_softc *sc = priv; 704 struct ifnet *ifp = &sc->sc_if; 705 uByte stat; 706 707 DPRINTFN(15,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 708 709 if (usbd_is_dying(sc->sc_udev)) 710 return; 711 712 if (!(ifp->if_flags & IFF_RUNNING)) 713 return; 714 715 if (status != USBD_NORMAL_COMPLETION) { 716 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 717 return; 718 } 719 sc->sc_intr_errs++; 720 if (usbd_ratecheck(&sc->sc_rx_notice)) { 721 printf("%s: %u usb errors on intr: %s\n", 722 sc->sc_dev.dv_xname, sc->sc_rx_errs, 723 usbd_errstr(status)); 724 sc->sc_intr_errs = 0; 725 } 726 if (status == USBD_STALLED) 727 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 728 return; 729 } 730 731 stat = sc->sc_ibuf; 732 733 if (stat == 0) 734 return; 735 736 DPRINTFN(10,("%s: %s: stat=0x%02x\n", sc->sc_dev.dv_xname, 737 __func__, stat)); 738 739 } 740 741 int 742 upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 743 { 744 struct upl_softc *sc = ifp->if_softc; 745 struct ifreq *ifr = (struct ifreq *)data; 746 int s, error = 0; 747 748 if (usbd_is_dying(sc->sc_udev)) 749 return (EIO); 750 751 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n", 752 sc->sc_dev.dv_xname, __func__, command)); 753 754 s = splnet(); 755 756 switch(command) { 757 case SIOCSIFADDR: 758 ifp->if_flags |= IFF_UP; 759 if (!(ifp->if_flags & IFF_RUNNING)) 760 upl_init(sc); 761 break; 762 763 case SIOCSIFFLAGS: 764 if (ifp->if_flags & IFF_UP) { 765 if (ifp->if_flags & IFF_RUNNING) 766 error = ENETRESET; 767 else 768 upl_init(sc); 769 } else { 770 if (ifp->if_flags & IFF_RUNNING) 771 upl_stop(sc); 772 } 773 break; 774 775 case SIOCSIFMTU: 776 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 777 error = EINVAL; 778 else 779 ifp->if_mtu = ifr->ifr_mtu; 780 break; 781 782 default: 783 error = ENOTTY; 784 } 785 786 if (error == ENETRESET) 787 error = 0; 788 789 splx(s); 790 return (error); 791 } 792 793 void 794 upl_watchdog(struct ifnet *ifp) 795 { 796 struct upl_softc *sc = ifp->if_softc; 797 798 DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 799 800 if (usbd_is_dying(sc->sc_udev)) 801 return; 802 803 ifp->if_oerrors++; 804 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); 805 806 upl_stop(sc); 807 upl_init(sc); 808 809 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 810 upl_start(ifp); 811 } 812 813 /* 814 * Stop the adapter and free any mbufs allocated to the 815 * RX and TX lists. 816 */ 817 void 818 upl_stop(struct upl_softc *sc) 819 { 820 usbd_status err; 821 struct ifnet *ifp; 822 int i; 823 824 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 825 826 ifp = &sc->sc_if; 827 ifp->if_timer = 0; 828 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 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