The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/if_upl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 74d58cf382c513f4036ad727db8f29ab


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.