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/vx/if_vx.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 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Herb Peyerl.
   18  * 4. The name of Herb Peyerl may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  *
   32  *
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 /*
   39  * Created from if_ep.c driver by Fred Gray (fgray@rice.edu) to support
   40  * the 3c590 family.
   41  */
   42 
   43 /*
   44  *      Modified from the FreeBSD 1.1.5.1 version by:
   45  *                      Andres Vega Garcia
   46  *                      INRIA - Sophia Antipolis, France
   47  *                      avega@sophia.inria.fr
   48  */
   49 
   50 /*
   51  *  Promiscuous mode added and interrupt logic slightly changed
   52  *  to reduce the number of adapter failures. Transceiver select
   53  *  logic changed to use value from EEPROM. Autoconfiguration
   54  *  features added.
   55  *  Done by:
   56  *          Serge Babkin
   57  *          Chelindbank (Chelyabinsk, Russia)
   58  *          babkin@hq.icb.chel.su
   59  */
   60 
   61 
   62 #include <sys/param.h>
   63 #include <sys/systm.h>
   64 #include <sys/sockio.h>
   65 #include <sys/kernel.h>
   66 #include <sys/malloc.h>
   67 #include <sys/mbuf.h>
   68 #include <sys/socket.h>
   69 
   70 #include <net/if.h>
   71 #include <net/if_var.h>
   72 
   73 #include <net/ethernet.h>
   74 #include <net/if_dl.h>
   75 #include <net/if_types.h>
   76 
   77 #include <machine/bus.h>
   78 
   79 #include <sys/bus.h>
   80 
   81 #include <net/bpf.h>
   82 
   83 #include <dev/vx/if_vxreg.h>
   84 #include <dev/vx/if_vxvar.h>
   85 
   86 #define ETHER_MAX_LEN   1518
   87 #define ETHER_ADDR_LEN  6
   88 #define ETHER_ALIGN     2
   89 
   90 static struct connector_entry {
   91         int bit;
   92         char *name;
   93 } conn_tab[VX_CONNECTORS] = {
   94 
   95 #define CONNECTOR_UTP   0
   96         {
   97                 0x08, "utp"
   98         },
   99 #define CONNECTOR_AUI   1
  100         {
  101                 0x20, "aui"
  102         },
  103 /* dummy */
  104         {
  105                 0, "???"
  106         },
  107 #define CONNECTOR_BNC   3
  108         {
  109                 0x10, "bnc"
  110         },
  111 #define CONNECTOR_TX    4
  112         {
  113                 0x02, "tx"
  114         },
  115 #define CONNECTOR_FX    5
  116         {
  117                 0x04, "fx"
  118         },
  119 #define CONNECTOR_MII   6
  120         {
  121                 0x40, "mii"
  122         },
  123         {
  124                 0, "???"
  125         }
  126 };
  127 
  128 static void vx_txstat(struct vx_softc *);
  129 static int vx_status(struct vx_softc *);
  130 static void vx_init(void *);
  131 static void vx_init_locked(struct vx_softc *);
  132 static int vx_ioctl(struct ifnet *, u_long, caddr_t);
  133 static void vx_start(struct ifnet *);
  134 static void vx_start_locked(struct ifnet *);
  135 static void vx_watchdog(void *);
  136 static void vx_reset(struct vx_softc *);
  137 static void vx_read(struct vx_softc *);
  138 static struct mbuf *vx_get(struct vx_softc *, u_int);
  139 static void vx_mbuf_fill(void *);
  140 static void vx_mbuf_empty(struct vx_softc *);
  141 static void vx_setfilter(struct vx_softc *);
  142 static void vx_getlink(struct vx_softc *);
  143 static void vx_setlink(struct vx_softc *);
  144 
  145 int
  146 vx_attach(device_t dev)
  147 {
  148         struct vx_softc *sc = device_get_softc(dev);
  149         struct ifnet *ifp;
  150         int i;
  151         u_char eaddr[6];
  152 
  153         ifp = sc->vx_ifp = if_alloc(IFT_ETHER);
  154         if (ifp == NULL) {
  155                 device_printf(dev, "can not if_alloc()\n");
  156                 return 0;
  157         }
  158         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  159 
  160         mtx_init(&sc->vx_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  161             MTX_DEF);
  162         callout_init_mtx(&sc->vx_callout, &sc->vx_mtx, 0);
  163         callout_init_mtx(&sc->vx_watchdog, &sc->vx_mtx, 0);
  164         GO_WINDOW(0);
  165         CSR_WRITE_2(sc, VX_COMMAND, GLOBAL_RESET);
  166         VX_BUSY_WAIT;
  167 
  168         vx_getlink(sc);
  169 
  170         /*
  171          * Read the station address from the eeprom
  172          */
  173         GO_WINDOW(0);
  174         for (i = 0; i < 3; i++) {
  175                 int x;
  176 
  177                 if (vx_busy_eeprom(sc)) {
  178                         mtx_destroy(&sc->vx_mtx);
  179                         if_free(ifp);
  180                         return 0;
  181                 }
  182                 CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD
  183                     | (EEPROM_OEM_ADDR0 + i));
  184                 if (vx_busy_eeprom(sc)) {
  185                         mtx_destroy(&sc->vx_mtx);
  186                         if_free(ifp);
  187                         return 0;
  188                 }
  189                 x = CSR_READ_2(sc, VX_W0_EEPROM_DATA);
  190                 eaddr[(i << 1)] = x >> 8;
  191                 eaddr[(i << 1) + 1] = x;
  192         }
  193 
  194         ifp->if_snd.ifq_maxlen = ifqmaxlen;
  195         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  196         ifp->if_start = vx_start;
  197         ifp->if_ioctl = vx_ioctl;
  198         ifp->if_init = vx_init;
  199         ifp->if_softc = sc;
  200 
  201         ether_ifattach(ifp, eaddr);
  202 
  203         sc->vx_tx_start_thresh = 20;    /* probably a good starting point. */
  204 
  205         VX_LOCK(sc);
  206         vx_stop(sc);
  207         VX_UNLOCK(sc);
  208 
  209         gone_by_fcp101_dev(dev);
  210 
  211         return 1;
  212 }
  213 
  214 /*
  215  * The order in here seems important. Otherwise we may not receive
  216  * interrupts. ?!
  217  */
  218 static void
  219 vx_init(void *xsc)
  220 {
  221         struct vx_softc *sc = (struct vx_softc *)xsc;
  222 
  223         VX_LOCK(sc);
  224         vx_init_locked(sc);
  225         VX_UNLOCK(sc);
  226 }
  227 
  228 static void
  229 vx_init_locked(struct vx_softc *sc)
  230 {
  231         struct ifnet *ifp = sc->vx_ifp;
  232         int i;
  233 
  234         VX_LOCK_ASSERT(sc);
  235 
  236         VX_BUSY_WAIT;
  237 
  238         GO_WINDOW(2);
  239 
  240         for (i = 0; i < 6; i++) /* Reload the ether_addr. */
  241                 CSR_WRITE_1(sc, VX_W2_ADDR_0 + i, IF_LLADDR(sc->vx_ifp)[i]);
  242 
  243         CSR_WRITE_2(sc, VX_COMMAND, RX_RESET);
  244         VX_BUSY_WAIT;
  245         CSR_WRITE_2(sc, VX_COMMAND, TX_RESET);
  246         VX_BUSY_WAIT;
  247 
  248         GO_WINDOW(1);           /* Window 1 is operating window */
  249         for (i = 0; i < 31; i++)
  250                 CSR_READ_1(sc, VX_W1_TX_STATUS);
  251 
  252         CSR_WRITE_2(sc, VX_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
  253             S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
  254         CSR_WRITE_2(sc, VX_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
  255             S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
  256 
  257         /*
  258          * Attempt to get rid of any stray interrupts that occurred during
  259          * configuration.  On the i386 this isn't possible because one may
  260          * already be queued.  However, a single stray interrupt is
  261          * unimportant.
  262          */
  263         CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | 0xff);
  264 
  265         vx_setfilter(sc);
  266         vx_setlink(sc);
  267 
  268         CSR_WRITE_2(sc, VX_COMMAND, RX_ENABLE);
  269         CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE);
  270 
  271         vx_mbuf_fill(sc);
  272 
  273         /* Interface is now `running', with no output active. */
  274         ifp->if_drv_flags |= IFF_DRV_RUNNING;
  275         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  276         callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
  277 
  278         /* Attempt to start output, if any. */
  279         vx_start_locked(ifp);
  280 }
  281 
  282 static void
  283 vx_setfilter(struct vx_softc *sc)
  284 {
  285         struct ifnet *ifp = sc->vx_ifp;
  286 
  287         VX_LOCK_ASSERT(sc);
  288         GO_WINDOW(1);           /* Window 1 is operating window */
  289         CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER |
  290             FIL_INDIVIDUAL | FIL_BRDCST | FIL_MULTICAST |
  291             ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0));
  292 }
  293 
  294 static void
  295 vx_getlink(struct vx_softc *sc)
  296 {
  297         int n, k;
  298 
  299         GO_WINDOW(3);
  300         sc->vx_connectors = CSR_READ_2(sc, VX_W3_RESET_OPT) & 0x7f;
  301         for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
  302                 if (sc->vx_connectors & conn_tab[k].bit) {
  303                         if (n > 0)
  304                                 printf("/");
  305                         printf("%s", conn_tab[k].name);
  306                         n++;
  307                 }
  308         }
  309         if (sc->vx_connectors == 0) {
  310                 printf("no connectors!\n");
  311                 return;
  312         }
  313         GO_WINDOW(3);
  314         sc->vx_connector =
  315             (CSR_READ_4(sc, VX_W3_INTERNAL_CFG) & INTERNAL_CONNECTOR_MASK)
  316             >> INTERNAL_CONNECTOR_BITS;
  317         if (sc->vx_connector & 0x10) {
  318                 sc->vx_connector &= 0x0f;
  319                 printf("[*%s*]", conn_tab[(int)sc->vx_connector].name);
  320                 printf(": disable 'auto select' with DOS util!\n");
  321         } else {
  322                 printf("[*%s*]\n", conn_tab[(int)sc->vx_connector].name);
  323         }
  324 }
  325 
  326 static void
  327 vx_setlink(struct vx_softc *sc)
  328 {
  329         struct ifnet *ifp = sc->vx_ifp;
  330         int i, j, k;
  331         char *reason, *warning;
  332         static int prev_flags;
  333         static signed char prev_conn = -1;
  334 
  335         VX_LOCK_ASSERT(sc);
  336         if (prev_conn == -1)
  337                 prev_conn = sc->vx_connector;
  338 
  339         /*
  340          * S.B.
  341          *
  342          * Now behavior was slightly changed:
  343          *
  344          * if any of flags link[0-2] is used and its connector is
  345          * physically present the following connectors are used:
  346          *
  347          *   link0 - AUI * highest precedence
  348          *   link1 - BNC
  349          *   link2 - UTP * lowest precedence
  350          *
  351          * If none of them is specified then
  352          * connector specified in the EEPROM is used
  353          * (if present on card or UTP if not).
  354          */
  355         i = sc->vx_connector;   /* default in EEPROM */
  356         reason = "default";
  357         warning = NULL;
  358 
  359         if (ifp->if_flags & IFF_LINK0) {
  360                 if (sc->vx_connectors & conn_tab[CONNECTOR_AUI].bit) {
  361                         i = CONNECTOR_AUI;
  362                         reason = "link0";
  363                 } else {
  364                         warning = "aui not present! (link0)";
  365                 }
  366         } else if (ifp->if_flags & IFF_LINK1) {
  367                 if (sc->vx_connectors & conn_tab[CONNECTOR_BNC].bit) {
  368                         i = CONNECTOR_BNC;
  369                         reason = "link1";
  370                 } else {
  371                         warning = "bnc not present! (link1)";
  372                 }
  373         } else if (ifp->if_flags & IFF_LINK2) {
  374                 if (sc->vx_connectors & conn_tab[CONNECTOR_UTP].bit) {
  375                         i = CONNECTOR_UTP;
  376                         reason = "link2";
  377                 } else {
  378                         warning = "utp not present! (link2)";
  379                 }
  380         } else if ((sc->vx_connectors & conn_tab[(int)sc->vx_connector].bit) == 0) {
  381                 warning = "strange connector type in EEPROM.";
  382                 reason = "forced";
  383                 i = CONNECTOR_UTP;
  384         }
  385         /* Avoid unnecessary message. */
  386         k = (prev_flags ^ ifp->if_flags) & (IFF_LINK0 | IFF_LINK1 | IFF_LINK2);
  387         if ((k != 0) || (prev_conn != i)) {
  388                 if (warning != NULL)
  389                         if_printf(ifp, "warning: %s\n", warning);
  390                 if_printf(ifp, "selected %s. (%s)\n", conn_tab[i].name, reason);
  391         }
  392         /* Set the selected connector. */
  393         GO_WINDOW(3);
  394         j = CSR_READ_4(sc, VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
  395         CSR_WRITE_4(sc, VX_W3_INTERNAL_CFG, j | (i << INTERNAL_CONNECTOR_BITS));
  396 
  397         /* First, disable all. */
  398         CSR_WRITE_2(sc, VX_COMMAND, STOP_TRANSCEIVER);
  399         DELAY(800);
  400         GO_WINDOW(4);
  401         CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, 0);
  402 
  403         /* Second, enable the selected one. */
  404         switch (i) {
  405         case CONNECTOR_UTP:
  406                 GO_WINDOW(4);
  407                 CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, ENABLE_UTP);
  408                 break;
  409         case CONNECTOR_BNC:
  410                 CSR_WRITE_2(sc, VX_COMMAND, START_TRANSCEIVER);
  411                 DELAY(800);
  412                 break;
  413         case CONNECTOR_TX:
  414         case CONNECTOR_FX:
  415                 GO_WINDOW(4);
  416                 CSR_WRITE_2(sc, VX_W4_MEDIA_TYPE, LINKBEAT_ENABLE);
  417                 break;
  418         default:                /* AUI and MII fall here */
  419                 break;
  420         }
  421         GO_WINDOW(1);
  422 
  423         prev_flags = ifp->if_flags;
  424         prev_conn = i;
  425 }
  426 
  427 static void
  428 vx_start(struct ifnet *ifp)
  429 {
  430         struct vx_softc *sc = ifp->if_softc;
  431 
  432         VX_LOCK(sc);
  433         vx_start_locked(ifp);
  434         VX_UNLOCK(sc);
  435 }
  436 
  437 static void
  438 vx_start_locked(struct ifnet *ifp)
  439 {
  440         struct vx_softc *sc = ifp->if_softc;
  441         struct mbuf *m;
  442         int len, pad;
  443 
  444         VX_LOCK_ASSERT(sc);
  445 
  446         /* Don't transmit if interface is busy or not running */
  447         if ((sc->vx_ifp->if_drv_flags &
  448             (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING)
  449                 return;
  450 
  451 startagain:
  452         /* Sneak a peek at the next packet */
  453         m = ifp->if_snd.ifq_head;
  454         if (m == NULL) {
  455                 return;
  456         }
  457         /* We need to use m->m_pkthdr.len, so require the header */
  458         M_ASSERTPKTHDR(m);
  459         len = m->m_pkthdr.len;
  460 
  461         pad = (4 - len) & 3;
  462 
  463         /*
  464          * The 3c509 automatically pads short packets to minimum ethernet
  465          * length, but we drop packets that are too large. Perhaps we should
  466          * truncate them instead?
  467          */
  468         if (len + pad > ETHER_MAX_LEN) {
  469                 /* packet is obviously too large: toss it */
  470                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  471                 IF_DEQUEUE(&ifp->if_snd, m);
  472                 m_freem(m);
  473                 goto readcheck;
  474         }
  475         VX_BUSY_WAIT;
  476         if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) {
  477                 CSR_WRITE_2(sc, VX_COMMAND,
  478                     SET_TX_AVAIL_THRESH | ((len + pad + 4) >> 2));
  479                 /* not enough room in FIFO - make sure */
  480                 if (CSR_READ_2(sc, VX_W1_FREE_TX) < len + pad + 4) {
  481                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  482                         sc->vx_timer = 1;
  483                         return;
  484                 }
  485         }
  486         CSR_WRITE_2(sc, VX_COMMAND, SET_TX_AVAIL_THRESH | (8188 >> 2));
  487         IF_DEQUEUE(&ifp->if_snd, m);
  488         if (m == NULL)          /* not really needed */
  489                 return;
  490 
  491         VX_BUSY_WAIT;
  492         CSR_WRITE_2(sc, VX_COMMAND, SET_TX_START_THRESH |
  493             ((len / 4 + sc->vx_tx_start_thresh) >> 2));
  494 
  495         BPF_MTAP(sc->vx_ifp, m);
  496 
  497         /*
  498          * Do the output at splhigh() so that an interrupt from another device
  499          * won't cause a FIFO underrun.
  500          *
  501          * XXX: Can't enforce that anymore.
  502          */
  503 
  504         CSR_WRITE_4(sc, VX_W1_TX_PIO_WR_1, len | TX_INDICATE);
  505 
  506         while (m) {
  507                 if (m->m_len > 3)
  508                         bus_space_write_multi_4(sc->vx_bst, sc->vx_bsh,
  509                             VX_W1_TX_PIO_WR_1, (u_int32_t *)mtod(m, caddr_t),
  510                             m->m_len / 4);
  511                 if (m->m_len & 3)
  512                         bus_space_write_multi_1(sc->vx_bst, sc->vx_bsh,
  513                             VX_W1_TX_PIO_WR_1,
  514                             mtod(m, caddr_t) + (m->m_len & ~3), m->m_len & 3);
  515                 m = m_free(m);
  516         }
  517         while (pad--)
  518                 CSR_WRITE_1(sc, VX_W1_TX_PIO_WR_1, 0);  /* Padding */
  519 
  520         if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
  521         sc->vx_timer = 1;
  522 
  523 readcheck:
  524         if ((CSR_READ_2(sc, VX_W1_RX_STATUS) & ERR_INCOMPLETE) == 0) {
  525                 /* We received a complete packet. */
  526 
  527                 if ((CSR_READ_2(sc, VX_STATUS) & S_INTR_LATCH) == 0) {
  528                         /*
  529                          * No interrupt, read the packet and continue
  530                          * Is this supposed to happen?  Is my motherboard
  531                          * completely busted?
  532                          */
  533                         vx_read(sc);
  534                 } else
  535                         /*
  536                          * Got an interrupt, return so that it gets
  537                          * serviced.
  538                          */
  539                         return;
  540         } else {
  541                 /* Check if we are stuck and reset [see XXX comment] */
  542                 if (vx_status(sc)) {
  543                         if (ifp->if_flags & IFF_DEBUG)
  544                                 if_printf(ifp, "adapter reset\n");
  545                         vx_reset(sc);
  546                 }
  547         }
  548 
  549         goto startagain;
  550 }
  551 
  552 /*
  553  * XXX: The 3c509 card can get in a mode where both the fifo status bit
  554  *      FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
  555  *      We detect this situation and we reset the adapter.
  556  *      It happens at times when there is a lot of broadcast traffic
  557  *      on the cable (once in a blue moon).
  558  */
  559 static int
  560 vx_status(struct vx_softc *sc)
  561 {
  562         struct ifnet *ifp;
  563         int fifost;
  564 
  565         VX_LOCK_ASSERT(sc);
  566 
  567         /*
  568          * Check the FIFO status and act accordingly
  569          */
  570         GO_WINDOW(4);
  571         fifost = CSR_READ_2(sc, VX_W4_FIFO_DIAG);
  572         GO_WINDOW(1);
  573 
  574         ifp = sc->vx_ifp;
  575         if (fifost & FIFOS_RX_UNDERRUN) {
  576                 if (ifp->if_flags & IFF_DEBUG)
  577                         if_printf(ifp, "RX underrun\n");
  578                 vx_reset(sc);
  579                 return 0;
  580         }
  581         if (fifost & FIFOS_RX_STATUS_OVERRUN) {
  582                 if (ifp->if_flags & IFF_DEBUG)
  583                         if_printf(ifp, "RX Status overrun\n");
  584                 return 1;
  585         }
  586         if (fifost & FIFOS_RX_OVERRUN) {
  587                 if (ifp->if_flags & IFF_DEBUG)
  588                         if_printf(ifp, "RX overrun\n");
  589                 return 1;
  590         }
  591         if (fifost & FIFOS_TX_OVERRUN) {
  592                 if (ifp->if_flags & IFF_DEBUG)
  593                         if_printf(ifp, "TX overrun\n");
  594                 vx_reset(sc);
  595                 return 0;
  596         }
  597         return 0;
  598 }
  599 
  600 static void
  601 vx_txstat(struct vx_softc *sc)
  602 {
  603         struct ifnet *ifp;
  604         int i;
  605 
  606         VX_LOCK_ASSERT(sc);
  607 
  608         /*
  609         * We need to read+write TX_STATUS until we get a 0 status
  610         * in order to turn off the interrupt flag.
  611         */
  612         ifp = sc->vx_ifp;
  613         while ((i = CSR_READ_1(sc, VX_W1_TX_STATUS)) & TXS_COMPLETE) {
  614                 CSR_WRITE_1(sc, VX_W1_TX_STATUS, 0x0);
  615 
  616                 if (i & TXS_JABBER) {
  617                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  618                         if (ifp->if_flags & IFF_DEBUG)
  619                                 if_printf(ifp, "jabber (%x)\n", i);
  620                         vx_reset(sc);
  621                 } else if (i & TXS_UNDERRUN) {
  622                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  623                         if (ifp->if_flags & IFF_DEBUG)
  624                                 if_printf(ifp, "fifo underrun (%x) @%d\n", i,
  625                                     sc->vx_tx_start_thresh);
  626                         if (sc->vx_tx_succ_ok < 100)
  627                                 sc->vx_tx_start_thresh =
  628                                     min(ETHER_MAX_LEN,
  629                                         sc->vx_tx_start_thresh + 20);
  630                         sc->vx_tx_succ_ok = 0;
  631                         vx_reset(sc);
  632                 } else if (i & TXS_MAX_COLLISION) {
  633                         if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
  634                         CSR_WRITE_2(sc, VX_COMMAND, TX_ENABLE);
  635                         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  636                 } else
  637                         sc->vx_tx_succ_ok = (sc->vx_tx_succ_ok + 1) & 127;
  638         }
  639 }
  640 
  641 void
  642 vx_intr(void *voidsc)
  643 {
  644         short status;
  645         struct vx_softc *sc = voidsc;
  646         struct ifnet *ifp = sc->vx_ifp;
  647 
  648         VX_LOCK(sc);
  649         for (;;) {
  650                 CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH);
  651 
  652                 status = CSR_READ_2(sc, VX_STATUS);
  653 
  654                 if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
  655                     S_RX_COMPLETE | S_CARD_FAILURE)) == 0)
  656                         break;
  657 
  658                 /*
  659                  * Acknowledge any interrupts.  It's important that we do this
  660                  * first, since there would otherwise be a race condition.
  661                  * Due to the i386 interrupt queueing, we may get spurious
  662                  * interrupts occasionally.
  663                  */
  664                 CSR_WRITE_2(sc, VX_COMMAND, ACK_INTR | status);
  665 
  666                 if (status & S_RX_COMPLETE)
  667                         vx_read(sc);
  668                 if (status & S_TX_AVAIL) {
  669                         sc->vx_timer = 0;
  670                         sc->vx_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  671                         vx_start_locked(sc->vx_ifp);
  672                 }
  673                 if (status & S_CARD_FAILURE) {
  674                         if_printf(ifp, "adapter failure (%x)\n", status);
  675                         sc->vx_timer = 0;
  676                         vx_reset(sc);
  677                         break;
  678                 }
  679                 if (status & S_TX_COMPLETE) {
  680                         sc->vx_timer = 0;
  681                         vx_txstat(sc);
  682                         vx_start_locked(ifp);
  683                 }
  684         }
  685         VX_UNLOCK(sc);
  686 
  687         /* no more interrupts */
  688         return;
  689 }
  690 
  691 static void
  692 vx_read(struct vx_softc *sc)
  693 {
  694         struct ifnet *ifp = sc->vx_ifp;
  695         struct mbuf *m;
  696         struct ether_header *eh;
  697         u_int len;
  698 
  699         VX_LOCK_ASSERT(sc);
  700         len = CSR_READ_2(sc, VX_W1_RX_STATUS);
  701 again:
  702 
  703         if (ifp->if_flags & IFF_DEBUG) {
  704                 int err = len & ERR_MASK;
  705                 char *s = NULL;
  706 
  707                 if (len & ERR_INCOMPLETE)
  708                         s = "incomplete packet";
  709                 else if (err == ERR_OVERRUN)
  710                         s = "packet overrun";
  711                 else if (err == ERR_RUNT)
  712                         s = "runt packet";
  713                 else if (err == ERR_ALIGNMENT)
  714                         s = "bad alignment";
  715                 else if (err == ERR_CRC)
  716                         s = "bad crc";
  717                 else if (err == ERR_OVERSIZE)
  718                         s = "oversized packet";
  719                 else if (err == ERR_DRIBBLE)
  720                         s = "dribble bits";
  721 
  722                 if (s)
  723                         if_printf(ifp, "%s\n", s);
  724         }
  725         if (len & ERR_INCOMPLETE)
  726                 return;
  727 
  728         if (len & ERR_RX) {
  729                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  730                 goto abort;
  731         }
  732         len &= RX_BYTES_MASK;   /* Lower 11 bits = RX bytes. */
  733 
  734         /* Pull packet off interface. */
  735         m = vx_get(sc, len);
  736         if (m == NULL) {
  737                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  738                 goto abort;
  739         }
  740         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
  741 
  742         {
  743                 struct mbuf *m0;
  744 
  745                 m0 = m_devget(mtod(m, char *), m->m_pkthdr.len, ETHER_ALIGN,
  746                     ifp, NULL);
  747                 if (m0 == NULL) {
  748                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  749                         goto abort;
  750                 }
  751                 m_freem(m);
  752                 m = m0;
  753         }
  754 
  755         /* We assume the header fit entirely in one mbuf. */
  756         eh = mtod(m, struct ether_header *);
  757 
  758         /*
  759          * XXX: Some cards seem to be in promiscuous mode all the time.
  760          * we need to make sure we only get our own stuff always.
  761          * bleah!
  762          */
  763 
  764         if (!(ifp->if_flags & IFF_PROMISC)
  765             && (eh->ether_dhost[0] & 1) == 0    /* !mcast and !bcast */
  766             && bcmp(eh->ether_dhost, IF_LLADDR(sc->vx_ifp),
  767             ETHER_ADDR_LEN) != 0) {
  768                 m_freem(m);
  769                 return;
  770         }
  771         VX_UNLOCK(sc);
  772         (*ifp->if_input)(ifp, m);
  773         VX_LOCK(sc);
  774 
  775         /*
  776         * In periods of high traffic we can actually receive enough
  777         * packets so that the fifo overrun bit will be set at this point,
  778         * even though we just read a packet. In this case we
  779         * are not going to receive any more interrupts. We check for
  780         * this condition and read again until the fifo is not full.
  781         * We could simplify this test by not using vx_status(), but
  782         * rechecking the RX_STATUS register directly. This test could
  783         * result in unnecessary looping in cases where there is a new
  784         * packet but the fifo is not full, but it will not fix the
  785         * stuck behavior.
  786         *
  787         * Even with this improvement, we still get packet overrun errors
  788         * which are hurting performance. Maybe when I get some more time
  789         * I'll modify vx_read() so that it can handle RX_EARLY interrupts.
  790         */
  791         if (vx_status(sc)) {
  792                 len = CSR_READ_2(sc, VX_W1_RX_STATUS);
  793                 /* Check if we are stuck and reset [see XXX comment] */
  794                 if (len & ERR_INCOMPLETE) {
  795                         if (ifp->if_flags & IFF_DEBUG)
  796                                 if_printf(ifp, "adapter reset\n");
  797                         vx_reset(sc);
  798                         return;
  799                 }
  800                 goto again;
  801         }
  802         return;
  803 
  804 abort:
  805         CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK);
  806 }
  807 
  808 static struct mbuf *
  809 vx_get(struct vx_softc *sc, u_int totlen)
  810 {
  811         struct ifnet *ifp = sc->vx_ifp;
  812         struct mbuf *top, **mp, *m;
  813         int len;
  814 
  815         VX_LOCK_ASSERT(sc);
  816         m = sc->vx_mb[sc->vx_next_mb];
  817         sc->vx_mb[sc->vx_next_mb] = NULL;
  818         if (m == NULL) {
  819                 MGETHDR(m, M_NOWAIT, MT_DATA);
  820                 if (m == NULL)
  821                         return NULL;
  822         } else {
  823                 /* If the queue is no longer full, refill. */
  824                 if (sc->vx_last_mb == sc->vx_next_mb &&
  825                     sc->vx_buffill_pending == 0) {
  826                         callout_reset(&sc->vx_callout, hz / 100, vx_mbuf_fill,
  827                             sc);
  828                         sc->vx_buffill_pending = 1;
  829                 }
  830                 /* Convert one of our saved mbuf's. */
  831                 sc->vx_next_mb = (sc->vx_next_mb + 1) % MAX_MBS;
  832                 m->m_data = m->m_pktdat;
  833                 m->m_flags = M_PKTHDR;
  834                 bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
  835         }
  836         m->m_pkthdr.rcvif = ifp;
  837         m->m_pkthdr.len = totlen;
  838         len = MHLEN;
  839         top = NULL;
  840         mp = &top;
  841 
  842         /*
  843          * We read the packet at splhigh() so that an interrupt from another
  844          * device doesn't cause the card's buffer to overflow while we're
  845          * reading it.  We may still lose packets at other times.
  846          *
  847          * XXX: Can't enforce this anymore.
  848          */
  849 
  850         /*
  851          * Since we don't set allowLargePackets bit in MacControl register,
  852          * we can assume that totlen <= 1500bytes.
  853          * The while loop will be performed iff we have a packet with
  854          * MLEN < m_len < MINCLSIZE.
  855          */
  856         while (totlen > 0) {
  857                 if (top) {
  858                         m = sc->vx_mb[sc->vx_next_mb];
  859                         sc->vx_mb[sc->vx_next_mb] = NULL;
  860                         if (m == NULL) {
  861                                 MGET(m, M_NOWAIT, MT_DATA);
  862                                 if (m == NULL) {
  863                                         m_freem(top);
  864                                         return NULL;
  865                                 }
  866                         } else {
  867                                 sc->vx_next_mb = (sc->vx_next_mb + 1) % MAX_MBS;
  868                         }
  869                         len = MLEN;
  870                 }
  871                 if (totlen >= MINCLSIZE) {
  872                         if (MCLGET(m, M_NOWAIT))
  873                                 len = MCLBYTES;
  874                 }
  875                 len = min(totlen, len);
  876                 if (len > 3)
  877                         bus_space_read_multi_4(sc->vx_bst, sc->vx_bsh,
  878                             VX_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), len / 4);
  879                 if (len & 3) {
  880                         bus_space_read_multi_1(sc->vx_bst, sc->vx_bsh,
  881                             VX_W1_RX_PIO_RD_1, mtod(m, u_int8_t *) + (len & ~3),
  882                             len & 3);
  883                 }
  884                 m->m_len = len;
  885                 totlen -= len;
  886                 *mp = m;
  887                 mp = &m->m_next;
  888         }
  889 
  890         CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK);
  891 
  892         return top;
  893 }
  894 
  895 
  896 static int
  897 vx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  898 {
  899         struct vx_softc *sc = ifp->if_softc;
  900         struct ifreq *ifr = (struct ifreq *) data;
  901         int error = 0;
  902 
  903         switch (cmd) {
  904         case SIOCSIFFLAGS:
  905                 VX_LOCK(sc);
  906                 if ((ifp->if_flags & IFF_UP) == 0 &&
  907                     (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
  908                         /*
  909                          * If interface is marked up and it is stopped, then
  910                          * start it.
  911                          */
  912                         vx_stop(sc);
  913                         ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
  914                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  915                     (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
  916                         /*
  917                          * If interface is marked up and it is stopped, then
  918                          * start it.
  919                          */
  920                         vx_init_locked(sc);
  921                 } else {
  922                         /*
  923                          * deal with flags changes:
  924                          * IFF_MULTICAST, IFF_PROMISC,
  925                          * IFF_LINK0, IFF_LINK1,
  926                          */
  927                         vx_setfilter(sc);
  928                         vx_setlink(sc);
  929                 }
  930                 VX_UNLOCK(sc);
  931                 break;
  932 
  933         case SIOCSIFMTU:
  934                 /*
  935                  * Set the interface MTU.
  936                  */
  937                 VX_LOCK(sc);
  938                 if (ifr->ifr_mtu > ETHERMTU) {
  939                         error = EINVAL;
  940                 } else {
  941                         ifp->if_mtu = ifr->ifr_mtu;
  942                 }
  943                 VX_UNLOCK(sc);
  944                 break;
  945 
  946         case SIOCADDMULTI:
  947         case SIOCDELMULTI:
  948                 /*
  949                  * Multicast list has changed; set the hardware filter
  950                  * accordingly.
  951                  */
  952                 VX_LOCK(sc);
  953                 vx_reset(sc);
  954                 VX_UNLOCK(sc);
  955                 error = 0;
  956                 break;
  957 
  958 
  959         default:
  960                 error = ether_ioctl(ifp, cmd, data);
  961                 break;
  962         }
  963 
  964         return (error);
  965 }
  966 
  967 static void
  968 vx_reset(struct vx_softc *sc)
  969 {
  970 
  971         VX_LOCK_ASSERT(sc);
  972         vx_stop(sc);
  973         vx_init_locked(sc);
  974 }
  975 
  976 static void
  977 vx_watchdog(void *arg)
  978 {
  979         struct vx_softc *sc;
  980         struct ifnet *ifp;
  981 
  982         sc = arg;
  983         VX_LOCK_ASSERT(sc);
  984         callout_reset(&sc->vx_watchdog, hz, vx_watchdog, sc);
  985         if (sc->vx_timer == 0 || --sc->vx_timer > 0)
  986                 return;
  987 
  988         ifp = sc->vx_ifp;
  989         if (ifp->if_flags & IFF_DEBUG)
  990                 if_printf(ifp, "device timeout\n");
  991         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  992         vx_start_locked(ifp);
  993         vx_intr(sc);
  994 }
  995 
  996 void
  997 vx_stop(struct vx_softc *sc)
  998 {
  999 
 1000         VX_LOCK_ASSERT(sc);
 1001         sc->vx_timer = 0;
 1002         callout_stop(&sc->vx_watchdog);
 1003 
 1004         CSR_WRITE_2(sc, VX_COMMAND, RX_DISABLE);
 1005         CSR_WRITE_2(sc, VX_COMMAND, RX_DISCARD_TOP_PACK);
 1006         VX_BUSY_WAIT;
 1007         CSR_WRITE_2(sc, VX_COMMAND, TX_DISABLE);
 1008         CSR_WRITE_2(sc, VX_COMMAND, STOP_TRANSCEIVER);
 1009         DELAY(800);
 1010         CSR_WRITE_2(sc, VX_COMMAND, RX_RESET);
 1011         VX_BUSY_WAIT;
 1012         CSR_WRITE_2(sc, VX_COMMAND, TX_RESET);
 1013         VX_BUSY_WAIT;
 1014         CSR_WRITE_2(sc, VX_COMMAND, C_INTR_LATCH);
 1015         CSR_WRITE_2(sc, VX_COMMAND, SET_RD_0_MASK);
 1016         CSR_WRITE_2(sc, VX_COMMAND, SET_INTR_MASK);
 1017         CSR_WRITE_2(sc, VX_COMMAND, SET_RX_FILTER);
 1018 
 1019         vx_mbuf_empty(sc);
 1020 }
 1021 
 1022 int
 1023 vx_busy_eeprom(struct vx_softc *sc)
 1024 {
 1025         int j, i = 100;
 1026 
 1027         while (i--) {
 1028                 j = CSR_READ_2(sc, VX_W0_EEPROM_COMMAND);
 1029                 if (j & EEPROM_BUSY)
 1030                         DELAY(100);
 1031                 else
 1032                         break;
 1033         }
 1034         if (!i) {
 1035                 if_printf(sc->vx_ifp, "eeprom failed to come ready\n");
 1036                 return (1);
 1037         }
 1038         return (0);
 1039 }
 1040 
 1041 static void
 1042 vx_mbuf_fill(void *sp)
 1043 {
 1044         struct vx_softc *sc = (struct vx_softc *)sp;
 1045         int i;
 1046 
 1047         VX_LOCK_ASSERT(sc);
 1048         i = sc->vx_last_mb;
 1049         do {
 1050                 if (sc->vx_mb[i] == NULL)
 1051                         MGET(sc->vx_mb[i], M_NOWAIT, MT_DATA);
 1052                 if (sc->vx_mb[i] == NULL)
 1053                         break;
 1054                 i = (i + 1) % MAX_MBS;
 1055         } while (i != sc->vx_next_mb);
 1056         sc->vx_last_mb = i;
 1057         /* If the queue was not filled, try again. */
 1058         if (sc->vx_last_mb != sc->vx_next_mb) {
 1059                 callout_reset(&sc->vx_callout, hz / 100, vx_mbuf_fill, sc);
 1060                 sc->vx_buffill_pending = 1;
 1061         } else {
 1062                 sc->vx_buffill_pending = 0;
 1063         }
 1064 }
 1065 
 1066 static void
 1067 vx_mbuf_empty(struct vx_softc *sc)
 1068 {
 1069         int i;
 1070 
 1071         VX_LOCK_ASSERT(sc);
 1072         for (i = 0; i < MAX_MBS; i++) {
 1073                 if (sc->vx_mb[i]) {
 1074                         m_freem(sc->vx_mb[i]);
 1075                         sc->vx_mb[i] = NULL;
 1076                 }
 1077         }
 1078         sc->vx_last_mb = sc->vx_next_mb = 0;
 1079         if (sc->vx_buffill_pending != 0)
 1080                 callout_stop(&sc->vx_callout);
 1081 }

Cache object: 8a4c78c02bff8180b78d03086a519546


[ 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.