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