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