1 /* $OpenBSD: if_upl.c,v 1.63 2015/03/14 03:38:49 jsg 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 *m; 425 int total_len = 0; 426 int s; 427 428 if (usbd_is_dying(sc->sc_udev)) 429 return; 430 431 if (!(ifp->if_flags & IFF_RUNNING)) 432 return; 433 434 if (status != USBD_NORMAL_COMPLETION) { 435 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 436 return; 437 sc->sc_rx_errs++; 438 if (usbd_ratecheck(&sc->sc_rx_notice)) { 439 printf("%s: %u usb errors on rx: %s\n", 440 sc->sc_dev.dv_xname, sc->sc_rx_errs, 441 usbd_errstr(status)); 442 sc->sc_rx_errs = 0; 443 } 444 if (status == USBD_STALLED) 445 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 446 goto done; 447 } 448 449 usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL); 450 451 DPRINTFN(9,("%s: %s: enter status=%d length=%d\n", 452 sc->sc_dev.dv_xname, __func__, status, total_len)); 453 454 m = c->upl_mbuf; 455 memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len); 456 457 ifp->if_ipackets++; 458 m->m_pkthdr.len = m->m_len = total_len; 459 460 m->m_pkthdr.rcvif = ifp; 461 462 s = splnet(); 463 464 /* XXX ugly */ 465 if (upl_newbuf(sc, c, NULL) == ENOBUFS) { 466 ifp->if_ierrors++; 467 goto done1; 468 } 469 470 #if NBPFILTER > 0 471 if (ifp->if_bpf) { 472 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN); 473 } 474 #endif 475 476 DPRINTFN(10,("%s: %s: deliver %d\n", sc->sc_dev.dv_xname, 477 __func__, m->m_len)); 478 479 ether_input_mbuf(ifp, m); 480 481 done1: 482 splx(s); 483 484 done: 485 #if 1 486 /* Setup new transfer. */ 487 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 488 c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY, 489 USBD_NO_TIMEOUT, upl_rxeof); 490 usbd_transfer(c->upl_xfer); 491 492 DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname, 493 __func__)); 494 #endif 495 } 496 497 /* 498 * A frame was downloaded to the chip. It's safe for us to clean up 499 * the list buffers. 500 */ 501 void 502 upl_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status) 503 { 504 struct upl_chain *c = priv; 505 struct upl_softc *sc = c->upl_sc; 506 struct ifnet *ifp = &sc->sc_if; 507 int s; 508 509 if (usbd_is_dying(sc->sc_udev)) 510 return; 511 512 s = splnet(); 513 514 DPRINTFN(10,("%s: %s: enter status=%d\n", sc->sc_dev.dv_xname, 515 __func__, status)); 516 517 ifp->if_timer = 0; 518 ifp->if_flags &= ~IFF_OACTIVE; 519 520 if (status != USBD_NORMAL_COMPLETION) { 521 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 522 splx(s); 523 return; 524 } 525 ifp->if_oerrors++; 526 printf("%s: usb error on tx: %s\n", sc->sc_dev.dv_xname, 527 usbd_errstr(status)); 528 if (status == USBD_STALLED) 529 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_TX]); 530 splx(s); 531 return; 532 } 533 534 ifp->if_opackets++; 535 536 m_freem(c->upl_mbuf); 537 c->upl_mbuf = NULL; 538 539 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 540 upl_start(ifp); 541 542 splx(s); 543 } 544 545 int 546 upl_send(struct upl_softc *sc, struct mbuf *m, int idx) 547 { 548 int total_len; 549 struct upl_chain *c; 550 usbd_status err; 551 552 c = &sc->sc_cdata.upl_tx_chain[idx]; 553 554 /* 555 * Copy the mbuf data into a contiguous buffer, leaving two 556 * bytes at the beginning to hold the frame length. 557 */ 558 m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf); 559 c->upl_mbuf = m; 560 561 total_len = m->m_pkthdr.len; 562 563 DPRINTFN(10,("%s: %s: total_len=%d\n", 564 sc->sc_dev.dv_xname, __func__, total_len)); 565 566 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX], 567 c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT, 568 upl_txeof); 569 570 /* Transmit */ 571 err = usbd_transfer(c->upl_xfer); 572 if (err != USBD_IN_PROGRESS) { 573 printf("%s: upl_send error=%s\n", sc->sc_dev.dv_xname, 574 usbd_errstr(err)); 575 upl_stop(sc); 576 return (EIO); 577 } 578 579 sc->sc_cdata.upl_tx_cnt++; 580 581 return (0); 582 } 583 584 void 585 upl_start(struct ifnet *ifp) 586 { 587 struct upl_softc *sc = ifp->if_softc; 588 struct mbuf *m_head = NULL; 589 590 if (usbd_is_dying(sc->sc_udev)) 591 return; 592 593 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 594 595 if (ifp->if_flags & IFF_OACTIVE) 596 return; 597 598 IFQ_POLL(&ifp->if_snd, m_head); 599 if (m_head == NULL) 600 return; 601 602 if (upl_send(sc, m_head, 0)) { 603 ifp->if_flags |= IFF_OACTIVE; 604 return; 605 } 606 607 IFQ_DEQUEUE(&ifp->if_snd, m_head); 608 609 #if NBPFILTER > 0 610 /* 611 * If there's a BPF listener, bounce a copy of this frame 612 * to him. 613 */ 614 if (ifp->if_bpf) 615 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT); 616 #endif 617 618 ifp->if_flags |= IFF_OACTIVE; 619 620 /* 621 * Set a timeout in case the chip goes out to lunch. 622 */ 623 ifp->if_timer = 5; 624 } 625 626 void 627 upl_init(void *xsc) 628 { 629 struct upl_softc *sc = xsc; 630 struct ifnet *ifp = &sc->sc_if; 631 int s; 632 633 if (usbd_is_dying(sc->sc_udev)) 634 return; 635 636 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 637 638 s = splnet(); 639 640 /* Init TX ring. */ 641 if (upl_tx_list_init(sc) == ENOBUFS) { 642 printf("%s: tx list init failed\n", sc->sc_dev.dv_xname); 643 splx(s); 644 return; 645 } 646 647 /* Init RX ring. */ 648 if (upl_rx_list_init(sc) == ENOBUFS) { 649 printf("%s: rx list init failed\n", sc->sc_dev.dv_xname); 650 splx(s); 651 return; 652 } 653 654 if (sc->sc_ep[UPL_ENDPT_RX] == NULL) { 655 if (upl_openpipes(sc)) { 656 splx(s); 657 return; 658 } 659 } 660 661 ifp->if_flags |= IFF_RUNNING; 662 ifp->if_flags &= ~IFF_OACTIVE; 663 664 splx(s); 665 } 666 667 int 668 upl_openpipes(struct upl_softc *sc) 669 { 670 struct upl_chain *c; 671 usbd_status err; 672 int i; 673 674 /* Open RX and TX pipes. */ 675 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX], 676 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]); 677 if (err) { 678 printf("%s: open rx pipe failed: %s\n", 679 sc->sc_dev.dv_xname, usbd_errstr(err)); 680 return (EIO); 681 } 682 err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX], 683 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]); 684 if (err) { 685 printf("%s: open tx pipe failed: %s\n", 686 sc->sc_dev.dv_xname, usbd_errstr(err)); 687 return (EIO); 688 } 689 err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR], 690 USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc, 691 &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr, 692 UPL_INTR_INTERVAL); 693 if (err) { 694 printf("%s: open intr pipe failed: %s\n", 695 sc->sc_dev.dv_xname, usbd_errstr(err)); 696 return (EIO); 697 } 698 699 700 #if 1 701 /* Start up the receive pipe. */ 702 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 703 c = &sc->sc_cdata.upl_rx_chain[i]; 704 usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX], 705 c, c->upl_buf, UPL_BUFSZ, 706 USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT, 707 upl_rxeof); 708 usbd_transfer(c->upl_xfer); 709 } 710 #endif 711 712 return (0); 713 } 714 715 void 716 upl_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 717 { 718 struct upl_softc *sc = priv; 719 struct ifnet *ifp = &sc->sc_if; 720 uByte stat; 721 722 DPRINTFN(15,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 723 724 if (usbd_is_dying(sc->sc_udev)) 725 return; 726 727 if (!(ifp->if_flags & IFF_RUNNING)) 728 return; 729 730 if (status != USBD_NORMAL_COMPLETION) { 731 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) { 732 return; 733 } 734 sc->sc_intr_errs++; 735 if (usbd_ratecheck(&sc->sc_rx_notice)) { 736 printf("%s: %u usb errors on intr: %s\n", 737 sc->sc_dev.dv_xname, sc->sc_rx_errs, 738 usbd_errstr(status)); 739 sc->sc_intr_errs = 0; 740 } 741 if (status == USBD_STALLED) 742 usbd_clear_endpoint_stall_async(sc->sc_ep[UPL_ENDPT_RX]); 743 return; 744 } 745 746 stat = sc->sc_ibuf; 747 748 if (stat == 0) 749 return; 750 751 DPRINTFN(10,("%s: %s: stat=0x%02x\n", sc->sc_dev.dv_xname, 752 __func__, stat)); 753 754 } 755 756 int 757 upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 758 { 759 struct upl_softc *sc = ifp->if_softc; 760 struct ifreq *ifr = (struct ifreq *)data; 761 int s, error = 0; 762 763 if (usbd_is_dying(sc->sc_udev)) 764 return (EIO); 765 766 DPRINTFN(5,("%s: %s: cmd=0x%08lx\n", 767 sc->sc_dev.dv_xname, __func__, command)); 768 769 s = splnet(); 770 771 switch(command) { 772 case SIOCSIFADDR: 773 ifp->if_flags |= IFF_UP; 774 if (!(ifp->if_flags & IFF_RUNNING)) 775 upl_init(sc); 776 break; 777 778 case SIOCSIFFLAGS: 779 if (ifp->if_flags & IFF_UP) { 780 if (ifp->if_flags & IFF_RUNNING) 781 error = ENETRESET; 782 else 783 upl_init(sc); 784 } else { 785 if (ifp->if_flags & IFF_RUNNING) 786 upl_stop(sc); 787 } 788 break; 789 790 case SIOCSIFMTU: 791 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 792 error = EINVAL; 793 else 794 ifp->if_mtu = ifr->ifr_mtu; 795 break; 796 797 default: 798 error = ENOTTY; 799 } 800 801 if (error == ENETRESET) 802 error = 0; 803 804 splx(s); 805 return (error); 806 } 807 808 void 809 upl_watchdog(struct ifnet *ifp) 810 { 811 struct upl_softc *sc = ifp->if_softc; 812 813 DPRINTFN(5,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 814 815 if (usbd_is_dying(sc->sc_udev)) 816 return; 817 818 ifp->if_oerrors++; 819 printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname); 820 821 upl_stop(sc); 822 upl_init(sc); 823 824 if (IFQ_IS_EMPTY(&ifp->if_snd) == 0) 825 upl_start(ifp); 826 } 827 828 /* 829 * Stop the adapter and free any mbufs allocated to the 830 * RX and TX lists. 831 */ 832 void 833 upl_stop(struct upl_softc *sc) 834 { 835 usbd_status err; 836 struct ifnet *ifp; 837 int i; 838 839 DPRINTFN(10,("%s: %s: enter\n", sc->sc_dev.dv_xname,__func__)); 840 841 ifp = &sc->sc_if; 842 ifp->if_timer = 0; 843 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 844 845 /* Stop transfers. */ 846 if (sc->sc_ep[UPL_ENDPT_RX] != NULL) { 847 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]); 848 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]); 849 if (err) { 850 printf("%s: close rx pipe failed: %s\n", 851 sc->sc_dev.dv_xname, usbd_errstr(err)); 852 } 853 sc->sc_ep[UPL_ENDPT_RX] = NULL; 854 } 855 856 if (sc->sc_ep[UPL_ENDPT_TX] != NULL) { 857 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]); 858 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]); 859 if (err) { 860 printf("%s: close tx pipe failed: %s\n", 861 sc->sc_dev.dv_xname, usbd_errstr(err)); 862 } 863 sc->sc_ep[UPL_ENDPT_TX] = NULL; 864 } 865 866 if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) { 867 usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 868 err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]); 869 if (err) { 870 printf("%s: close intr pipe failed: %s\n", 871 sc->sc_dev.dv_xname, usbd_errstr(err)); 872 } 873 sc->sc_ep[UPL_ENDPT_INTR] = NULL; 874 } 875 876 /* Free RX resources. */ 877 for (i = 0; i < UPL_RX_LIST_CNT; i++) { 878 if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) { 879 m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf); 880 sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL; 881 } 882 if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) { 883 usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer); 884 sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL; 885 } 886 } 887 888 /* Free TX resources. */ 889 for (i = 0; i < UPL_TX_LIST_CNT; i++) { 890 if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) { 891 m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf); 892 sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL; 893 } 894 if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) { 895 usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer); 896 sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL; 897 } 898 } 899 } 900 901 int 902 upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, 903 struct rtentry *rt0) 904 { 905 int s, len, error; 906 907 DPRINTFN(10,("%s: %s: enter\n", 908 ((struct upl_softc *)ifp->if_softc)->sc_dev.dv_xname, 909 __func__)); 910 911 len = m->m_pkthdr.len; 912 s = splnet(); 913 /* 914 * Queue message on interface, and start output if interface 915 * not yet active. 916 */ 917 IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error); 918 if (error) { 919 /* mbuf is already freed */ 920 splx(s); 921 return (error); 922 } 923 ifp->if_obytes += len; 924 if ((ifp->if_flags & IFF_OACTIVE) == 0) 925 (*ifp->if_start)(ifp); 926 splx(s); 927 928 return (0); 929 } 930