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

Cache object: 851804e40cfde02310e34fc5491e176c


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