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