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/qbus/if_il.c

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

    1 /*      $NetBSD: if_il.c,v 1.19 2008/04/05 19:16:49 cegger Exp $        */
    2 /*
    3  * Copyright (c) 1982, 1986 Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. Neither the name of the University nor the names of its contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  *      @(#)if_il.c     7.8 (Berkeley) 12/16/90
   31  */
   32 
   33 /*
   34  * Interlan Ethernet Communications Controller interface
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __KERNEL_RCSID(0, "$NetBSD: if_il.c,v 1.19 2008/04/05 19:16:49 cegger Exp $");
   39 
   40 #include "opt_inet.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/buf.h>
   46 #include <sys/protosw.h>
   47 #include <sys/socket.h>
   48 #include <sys/ioctl.h>
   49 #include <sys/errno.h>
   50 #include <sys/syslog.h>
   51 #include <sys/device.h>
   52 
   53 #include <net/if.h>
   54 #include <net/if_ether.h>
   55 #include <net/if_dl.h>
   56 
   57 #ifdef INET
   58 #include <netinet/in.h>
   59 #endif
   60 
   61 
   62 #include <sys/bus.h>
   63 
   64 #include <dev/qbus/ubareg.h>
   65 #include <dev/qbus/ubavar.h>
   66 #include <dev/qbus/if_uba.h>
   67 
   68 #include <dev/qbus/if_il.h>
   69 #include <dev/qbus/if_ilreg.h>
   70 
   71 /*
   72  * Ethernet software status per interface.
   73  *
   74  * Each interface is referenced by a network interface structure,
   75  * is_if, which the routing code uses to locate the interface.
   76  * This structure contains the output queue for the interface, its address, ...
   77  * We also have, for each interface, a UBA interface structure, which
   78  * contains information about the UNIBUS resources held by the interface:
   79  * map registers, buffered data paths, etc.  Information is cached in this
   80  * structure for use by the if_uba.c routines in running the interface
   81  * efficiently.
   82  */
   83 
   84 struct  il_softc {
   85         struct  device sc_dev;          /* Configuration common part */
   86         struct  ethercom sc_ec;         /* Ethernet common part */
   87 #define sc_if   sc_ec.ec_if             /* network-visible interface */
   88         struct  evcnt sc_cintrcnt;      /* Command interrupts */
   89         struct  evcnt sc_rintrcnt;      /* Receive interrupts */
   90         bus_space_tag_t sc_iot;
   91         bus_addr_t sc_ioh;
   92         bus_dma_tag_t sc_dmat;
   93         struct  ubinfo sc_ui;
   94 
   95         struct  ifuba sc_ifuba;         /* UNIBUS resources */
   96         int     sc_flags;
   97 #define ILF_RCVPENDING  0x2             /* start rcv in ilcint */
   98 #define ILF_STATPENDING 0x4             /* stat cmd pending */
   99 #define ILF_RUNNING     0x8             /* board is running */
  100 #define ILF_SETADDR     0x10            /* physical address is changed */
  101         short   sc_lastcmd;             /* can't read csr, so must save it */
  102         short   sc_scaninterval;        /* interval of stat collection */
  103 #define ILWATCHINTERVAL 60              /* once every 60 seconds */
  104         union {
  105             struct      il_stats isu_stats;     /* holds on-board statistics */
  106             struct      ether_addr isu_maddrs[63];      /* multicast addrs */
  107         }       sc_isu;
  108 #define sc_stats        sc_isu.isu_stats
  109 #define sc_maddrs       sc_isu.isu_maddrs
  110         struct  il_stats sc_sum;        /* summation over time */
  111         int     sc_ubaddr;              /* mapping registers of is_stats */
  112 };
  113 
  114 static  int ilmatch(struct device *, struct cfdata *, void *);
  115 static  void ilattach(struct device *, struct device *, void *);
  116 static  void ilcint(void *);
  117 static  void ilrint(void *);
  118 static  void ilreset(struct device *);
  119 static  int ilwait(struct il_softc *, char *);
  120 static  int ilinit(struct ifnet *);
  121 static  void ilstart(struct ifnet *);
  122 static  void ilwatch(struct ifnet *);
  123 static  void iltotal(struct il_softc *);
  124 static  void ilstop(struct ifnet *, int);
  125 
  126 CFATTACH_DECL(il, sizeof(struct il_softc),
  127     ilmatch, ilattach, NULL, NULL);
  128 
  129 #define IL_WCSR(csr, val) \
  130         bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
  131 #define IL_RCSR(csr) \
  132         bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
  133 #define LOWORD(x)       ((int)(x) & 0xffff)
  134 #define HIWORD(x)       (((int)(x) >> 16) & 0x3)
  135 
  136 int
  137 ilmatch(struct device *parent, struct cfdata *cf, void *aux)
  138 {
  139         struct uba_attach_args *ua = aux;
  140         volatile int i;
  141 
  142         bus_space_write_2(ua->ua_iot, ua->ua_ioh, IL_CSR, ILC_OFFLINE|IL_CIE);
  143         DELAY(100000);
  144         i = bus_space_read_2(ua->ua_iot, ua->ua_ioh, IL_CSR); /* clear CDONE */
  145 
  146         return 1;
  147 }
  148 
  149 /*
  150  * Interface exists: make available by filling in network interface
  151  * record.  System will initialize the interface when it is ready
  152  * to accept packets.  A STATUS command is done to get the ethernet
  153  * address and other interesting data.
  154  */
  155 void
  156 ilattach(struct device *parent, struct device *self, void *aux)
  157 {
  158         struct uba_attach_args *ua = aux;
  159         struct il_softc *sc = device_private(self);
  160         struct ifnet *ifp = &sc->sc_if;
  161         int error;
  162 
  163         sc->sc_iot = ua->ua_iot;
  164         sc->sc_ioh = ua->ua_ioh;
  165         sc->sc_dmat = ua->ua_dmat;
  166 
  167         /*
  168          * Map interrupt vectors and reset function.
  169          */
  170         uba_intr_establish(ua->ua_icookie, ua->ua_cvec, ilcint,
  171             sc, &sc->sc_cintrcnt);
  172         evcnt_attach_dynamic(&sc->sc_cintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  173             device_xname(&sc->sc_dev), "intr");
  174         uba_intr_establish(ua->ua_icookie, ua->ua_cvec-4, ilrint,
  175             sc, &sc->sc_rintrcnt);
  176         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  177             device_xname(&sc->sc_dev), "intr");
  178         uba_reset_establish(ilreset, &sc->sc_dev);
  179 
  180         /*
  181          * Reset the board and map the statistics
  182          * buffer onto the Unibus.
  183          */
  184         IL_WCSR(IL_CSR, ILC_RESET);
  185         (void)ilwait(sc, "reset");
  186         sc->sc_ui.ui_size = sizeof(struct il_stats);
  187         sc->sc_ui.ui_vaddr = (void *)&sc->sc_stats;
  188         if ((error = uballoc((struct uba_softc *)parent, &sc->sc_ui, 0)))
  189                 return printf(": failed uballoc, error = %d\n", error);
  190 
  191         IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  192         IL_WCSR(IL_BCR, sizeof(struct il_stats));
  193         IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_STAT);
  194         (void)ilwait(sc, "status");
  195         ubfree((struct uba_softc *)parent, &sc->sc_ui);
  196         printf("%s: module=%s firmware=%s\n", device_xname(&sc->sc_dev),
  197                 sc->sc_stats.ils_module, sc->sc_stats.ils_firmware);
  198         printf("%s: hardware address %s\n", device_xname(&sc->sc_dev),
  199                 ether_sprintf(sc->sc_stats.ils_addr));
  200 
  201         strlcpy(ifp->if_xname, device_xname(&sc->sc_dev), IFNAMSIZ);
  202         ifp->if_softc = sc;
  203         ifp->if_flags = IFF_BROADCAST;
  204         ifp->if_init = ilinit;
  205         ifp->if_stop = ilstop;
  206         ifp->if_ioctl = ether_ioctl;
  207         ifp->if_start = ilstart;
  208         ifp->if_watchdog = ilwatch;
  209         IFQ_SET_READY(&ifp->if_snd);
  210 
  211         if_attach(ifp);
  212         ether_ifattach(ifp, sc->sc_stats.ils_addr);
  213 }
  214 
  215 void
  216 ilstop(struct ifnet *ifp, int a)
  217 {
  218         struct il_softc *sc = ifp->if_softc;
  219 
  220         IL_WCSR(IL_CSR, ILC_RESET);
  221 }
  222 
  223 
  224 int
  225 ilwait(struct il_softc *sc, char *op)
  226 {
  227 
  228         while ((IL_RCSR(IL_CSR)&IL_CDONE) == 0)
  229                 ;
  230         if (IL_RCSR(IL_CSR)&IL_STATUS) {
  231                 char bits[64];
  232 
  233                 aprint_error_dev(&sc->sc_dev, "%s failed, csr=%s\n", op,
  234                     bitmask_snprintf(IL_RCSR(IL_CSR), IL_BITS, bits,
  235                     sizeof(bits)));
  236                 return (-1);
  237         }
  238         return (0);
  239 }
  240 
  241 /*
  242  * Reset of interface after UNIBUS reset.
  243  * If interface is on specified uba, reset its state.
  244  */
  245 void
  246 ilreset(struct device *dev)
  247 {
  248         struct il_softc *sc = (void *)dev;
  249 
  250         printf(" %s", device_xname(&sc->sc_dev));
  251         sc->sc_if.if_flags &= ~IFF_RUNNING;
  252         sc->sc_flags &= ~ILF_RUNNING;
  253         ilinit(&sc->sc_if);
  254 }
  255 
  256 /*
  257  * Initialization of interface; clear recorded pending
  258  * operations, and reinitialize UNIBUS usage.
  259  */
  260 int
  261 ilinit(struct ifnet *ifp)
  262 {
  263         struct il_softc *sc = ifp->if_softc;
  264         int s;
  265 
  266         if (sc->sc_flags & ILF_RUNNING)
  267                 return 0;
  268 
  269         if ((ifp->if_flags & IFF_RUNNING) == 0) {
  270                 if (if_ubainit(&sc->sc_ifuba,
  271                     (void *)device_parent(&sc->sc_dev),
  272                     ETHER_MAX_LEN)) {
  273                         aprint_error_dev(&sc->sc_dev, "can't initialize\n");
  274                         sc->sc_if.if_flags &= ~IFF_UP;
  275                         return 0;
  276                 }
  277                 sc->sc_ui.ui_size = sizeof(sc->sc_isu);
  278                 sc->sc_ui.ui_vaddr = (void *)&sc->sc_isu;
  279                 uballoc((void *)device_parent(&sc->sc_dev), &sc->sc_ui, 0);
  280         }
  281         sc->sc_scaninterval = ILWATCHINTERVAL;
  282         ifp->if_timer = sc->sc_scaninterval;
  283 
  284         /*
  285          * Turn off source address insertion (it's faster this way),
  286          * and set board online.  Former doesn't work if board is
  287          * already online (happens on ubareset), so we put it offline
  288          * first.
  289          */
  290         s = splnet();
  291         IL_WCSR(IL_CSR, ILC_RESET);
  292         if (ilwait(sc, "hardware diag")) {
  293                 sc->sc_if.if_flags &= ~IFF_UP;
  294                 splx(s);
  295                 return 0;
  296         }
  297         IL_WCSR(IL_CSR, ILC_CISA);
  298         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  299                 ;
  300         /*
  301          * If we must reprogram this board's physical ethernet
  302          * address (as for secondary XNS interfaces), we do so
  303          * before putting it on line, and starting receive requests.
  304          * If you try this on an older 1010 board, it will total
  305          * wedge the board.
  306          */
  307         if (sc->sc_flags & ILF_SETADDR) {
  308                 bcopy(CLLADDR(ifp->if_sadl), &sc->sc_isu, ETHER_ADDR_LEN);
  309                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  310                 IL_WCSR(IL_BCR, ETHER_ADDR_LEN);
  311                 IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_LDPA);
  312                 if (ilwait(sc, "setaddr"))
  313                         return 0;
  314                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  315                 IL_WCSR(IL_BCR, sizeof (struct il_stats));
  316                 IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_STAT);
  317                 if (ilwait(sc, "verifying setaddr"))
  318                         return 0;
  319                 if (memcmp(sc->sc_stats.ils_addr,
  320                     CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN) != 0) {
  321                         aprint_error_dev(&sc->sc_dev, "setaddr didn't work\n");
  322                         return 0;
  323                 }
  324         }
  325 #ifdef MULTICAST
  326         if (is->is_if.if_flags & IFF_PROMISC) {
  327                 addr->il_csr = ILC_PRMSC;
  328                 if (ilwait(ui, "all multi"))
  329                         return 0;
  330         } else if (is->is_if.if_flags & IFF_ALLMULTI) {
  331         too_many_multis:
  332                 addr->il_csr = ILC_ALLMC;
  333                 if (ilwait(ui, "all multi"))
  334                         return 0;
  335         else {
  336                 int i;
  337                 register struct ether_addr *ep = is->is_maddrs;
  338                 struct ether_multi *enm;
  339                 struct ether_multistep step;
  340                 /*
  341                  * Step through our list of multicast addresses.  If we have
  342                  * too many multicast addresses, or if we have to listen to
  343                  * a range of multicast addresses, turn on reception of all
  344                  * multicasts.
  345                  */
  346                 i = 0;
  347                 ETHER_FIRST_MULTI(step, &is->is_ac, enm);
  348                 while (enm != NULL) {
  349                         if (++i > 63 && k != 0) {
  350                                 break;
  351                         }
  352                         *ep++ = *(struct ether_addr *)enm->enm_addrlo;
  353                         ETHER_NEXT_MULTI(step, enm);
  354                 }
  355                 if (i = 0) {
  356                         /* no multicasts! */
  357                 } else if (i <= 63) {
  358                         addr->il_bar = is->is_ubaddr & 0xffff;
  359                         addr->il_bcr = i * sizeof (struct ether_addr);
  360                         addr->il_csr = ((is->is_ubaddr >> 2) & IL_EUA)|
  361                                                 LC_LDGRPS;
  362                         if (ilwait(ui, "load multi"))
  363                                 return;
  364                 } else {
  365                     is->is_if.if_flags |= IFF_ALLMULTI;
  366                     goto too_many_multis;
  367                 }
  368         }
  369 #endif /* MULTICAST */
  370         /*
  371          * Set board online.
  372          * Hang receive buffer and start any pending
  373          * writes by faking a transmit complete.
  374          * Receive bcr is not a multiple of 8 so buffer
  375          * chaining can't happen.
  376          */
  377         IL_WCSR(IL_CSR, ILC_ONLINE);
  378         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  379                 ;
  380 
  381         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  382         IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  383         IL_WCSR(IL_CSR,
  384             ((sc->sc_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE);
  385         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  386                 ;
  387         ifp->if_flags |= IFF_RUNNING | IFF_OACTIVE;
  388         sc->sc_flags |= ILF_RUNNING;
  389         sc->sc_lastcmd = 0;
  390         ilcint(sc);
  391         splx(s);
  392         return 0;
  393 }
  394 
  395 /*
  396  * Start output on interface.
  397  * Get another datagram to send off of the interface queue,
  398  * and map it to the interface before starting the output.
  399  */
  400 void
  401 ilstart(struct ifnet *ifp)
  402 {
  403         struct il_softc *sc = ifp->if_softc;
  404         int len;
  405         struct mbuf *m;
  406         short csr;
  407 
  408         IFQ_DEQUEUE(&ifp->if_snd, m);
  409         if (m == 0) {
  410                 if ((sc->sc_flags & ILF_STATPENDING) == 0)
  411                         return;
  412                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  413                 IL_WCSR(IL_BCR, sizeof (struct il_stats));
  414                 csr = ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)|ILC_STAT|IL_RIE|IL_CIE;
  415                 sc->sc_flags &= ~ILF_STATPENDING;
  416                 goto startcmd;
  417         }
  418         len = if_wubaput(&sc->sc_ifuba, m);
  419 #ifdef notdef
  420         if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
  421                 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
  422 #endif
  423         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_w.ifrw_info));
  424         IL_WCSR(IL_BCR, len);
  425         csr =
  426           ((sc->sc_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)|ILC_XMIT|IL_CIE|IL_RIE;
  427 
  428 startcmd:
  429         sc->sc_lastcmd = csr & IL_CMD;
  430         IL_WCSR(IL_CSR, csr);
  431         ifp->if_flags |= IFF_OACTIVE;
  432         return;
  433 }
  434 
  435 /*
  436  * Command done interrupt.
  437  */
  438 void
  439 ilcint(void *arg)
  440 {
  441         struct il_softc *sc = arg;
  442         short csr;
  443 
  444         if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
  445                 char bits[64];
  446 
  447                 aprint_error_dev(&sc->sc_dev, "stray xmit interrupt, csr=%s\n",
  448                     bitmask_snprintf(IL_RCSR(IL_CSR), IL_BITS, bits,
  449                     sizeof(bits)));
  450                 return;
  451         }
  452 
  453         csr = IL_RCSR(IL_CSR);
  454         /*
  455          * Hang receive buffer if it couldn't
  456          * be done earlier (in ilrint).
  457          */
  458         if (sc->sc_flags & ILF_RCVPENDING) {
  459                 int s;
  460 
  461                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  462                 IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  463                 IL_WCSR(IL_CSR,
  464                   ((sc->sc_ifuba.ifu_r.ifrw_info>>2) & IL_EUA)|ILC_RCV|IL_RIE);
  465                 s = splhigh();
  466                 while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  467                         ;
  468                 splx(s);
  469                 sc->sc_flags &= ~ILF_RCVPENDING;
  470         }
  471         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  472         csr &= IL_STATUS;
  473         switch (sc->sc_lastcmd) {
  474 
  475         case ILC_XMIT:
  476                 sc->sc_if.if_opackets++;
  477                 if (csr > ILERR_RETRIES)
  478                         sc->sc_if.if_oerrors++;
  479                 break;
  480 
  481         case ILC_STAT:
  482                 if (csr == ILERR_SUCCESS)
  483                         iltotal(sc);
  484                 break;
  485         }
  486         if_wubaend(&sc->sc_ifuba);
  487         ilstart(&sc->sc_if);
  488 }
  489 
  490 /*
  491  * Ethernet interface receiver interrupt.
  492  * If input error just drop packet.
  493  * Otherwise purge input buffered data path and examine
  494  * packet to determine type.  If can't determine length
  495  * from type, then have to drop packet.  Othewise decapsulate
  496  * packet based on type and pass to type specific higher-level
  497  * input routine.
  498  */
  499 void
  500 ilrint(void *arg)
  501 {
  502         struct il_softc *sc = arg;
  503         struct il_rheader *il;
  504         struct mbuf *m;
  505         int len, s;
  506 
  507         sc->sc_if.if_ipackets++;
  508 #ifdef notyet
  509         if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
  510                 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
  511 #endif
  512         il = (struct il_rheader *)(sc->sc_ifuba.ifu_r.ifrw_addr);
  513         len = il->ilr_length - sizeof(struct il_rheader);
  514         if ((il->ilr_status&(ILFSTAT_A|ILFSTAT_C)) || len < 46 ||
  515             len > ETHERMTU) {
  516                 sc->sc_if.if_ierrors++;
  517 #ifdef notdef
  518                 if (sc->sc_if.if_ierrors % 100 == 0)
  519                         printf("il%d: += 100 input errors\n", unit);
  520 #endif
  521                 goto setup;
  522         }
  523 
  524         if (len == 0)
  525                 goto setup;
  526 
  527         /*
  528          * Pull packet off interface.
  529          */
  530         m = if_rubaget(&sc->sc_ifuba, &sc->sc_if, len);
  531         if (m == NULL)
  532                 goto setup;
  533 
  534         /* Shave off status hdr */
  535         m_adj(m, 4);
  536         (*sc->sc_if.if_input)(&sc->sc_if, m);
  537 setup:
  538         /*
  539          * Reset for next packet if possible.
  540          * If waiting for transmit command completion, set flag
  541          * and wait until command completes.
  542          */
  543         if (sc->sc_if.if_flags & IFF_OACTIVE) {
  544                 sc->sc_flags |= ILF_RCVPENDING;
  545                 return;
  546         }
  547         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  548         IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  549         IL_WCSR(IL_CSR,
  550             ((sc->sc_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA)|ILC_RCV|IL_RIE);
  551         s = splhigh();
  552         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  553                 ;
  554         splx(s);
  555 }
  556 /*
  557  * Watchdog routine, request statistics from board.
  558  */
  559 void
  560 ilwatch(struct ifnet *ifp)
  561 {
  562         struct il_softc *sc = ifp->if_softc;
  563         int s;
  564 
  565         if (sc->sc_flags & ILF_STATPENDING) {
  566                 ifp->if_timer = sc->sc_scaninterval;
  567                 return;
  568         }
  569         s = splnet();
  570         sc->sc_flags |= ILF_STATPENDING;
  571         if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0)
  572                 ilstart(ifp);
  573         splx(s);
  574         ifp->if_timer = sc->sc_scaninterval;
  575 }
  576 
  577 /*
  578  * Total up the on-board statistics.
  579  */
  580 void
  581 iltotal(struct il_softc *sc)
  582 {
  583         struct ifnet *ifp = &sc->sc_if;
  584         u_short *interval, *sum, *end;
  585 
  586         interval = &sc->sc_stats.ils_frames;
  587         sum = &sc->sc_sum.ils_frames;
  588         end = sc->sc_sum.ils_fill2;
  589         while (sum < end)
  590                 *sum++ += *interval++;
  591         sc->sc_if.if_collisions = sc->sc_sum.ils_collis;
  592         if ((sc->sc_flags & ILF_SETADDR) &&
  593             (memcmp(sc->sc_stats.ils_addr, CLLADDR(ifp->if_sadl),
  594                     ETHER_ADDR_LEN) != 0)) {
  595                 log(LOG_ERR, "%s: physaddr reverted\n", device_xname(&sc->sc_dev));
  596                 sc->sc_flags &= ~ILF_RUNNING;
  597                 ilinit(&sc->sc_if);
  598         }
  599 }
  600 
  601 #ifdef notyet
  602 /*
  603  * set ethernet address for unit
  604  */
  605 void
  606 il_setaddr(u_char *physaddr, struct il_softc *sc)
  607 {
  608         if (! (sc->sc_flags & ILF_RUNNING))
  609                 return;
  610 
  611         bcopy((void *)physaddr, (void *)is->is_addr, sizeof is->is_addr);
  612         sc->sc_flags &= ~ILF_RUNNING;
  613         sc->sc_flags |= ILF_SETADDR;
  614         ilinit(&sc->sc_if);
  615 }
  616 #endif

Cache object: 473b33b522085a02c1255d08a4cd3be6


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