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

Cache object: 8ffb84cd826ecb2f5bbbc559d6cb5436


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