root/dev/usb/if_upl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. upl_match
  2. upl_attach
  3. upl_detach
  4. upl_activate
  5. upl_newbuf
  6. upl_rx_list_init
  7. upl_tx_list_init
  8. upl_rxeof
  9. upl_txeof
  10. upl_send
  11. upl_start
  12. upl_init
  13. upl_openpipes
  14. upl_intr
  15. upl_ioctl
  16. upl_watchdog
  17. upl_stop
  18. upl_output
  19. upl_input

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

/* [<][>][^][v][top][bottom][index][help] */