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