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

Cache object: 5732694e000582d3d06f4526ba905446


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