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