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

Cache object: 1f7d2441c961f9b3d590e585f4a43605


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