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.37 2021/08/01 15:29:30 andvar 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.37 2021/08/01 15:29:30 andvar 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         device_t 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(device_t, cfdata_t, void *);
  115 static  void ilattach(device_t, device_t, void *);
  116 static  void ilcint(void *);
  117 static  void ilrint(void *);
  118 static  void ilreset(device_t);
  119 static  int ilwait(struct il_softc *, const 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_NEW(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(device_t parent, cfdata_t cf, void *aux)
  138 {
  139         struct uba_attach_args *ua = aux;
  140 
  141         bus_space_write_2(ua->ua_iot, ua->ua_ioh, IL_CSR,
  142             ILC_OFFLINE | IL_CIE);
  143         DELAY(100000);
  144         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(device_t parent, device_t 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_dev = self;
  164         sc->sc_iot = ua->ua_iot;
  165         sc->sc_ioh = ua->ua_ioh;
  166         sc->sc_dmat = ua->ua_dmat;
  167 
  168         /*
  169          * Map interrupt vectors and reset function.
  170          */
  171         uba_intr_establish(ua->ua_icookie, ua->ua_cvec, ilcint,
  172             sc, &sc->sc_cintrcnt);
  173         evcnt_attach_dynamic(&sc->sc_cintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  174             device_xname(sc->sc_dev), "intr");
  175         uba_intr_establish(ua->ua_icookie, ua->ua_cvec-4, ilrint,
  176             sc, &sc->sc_rintrcnt);
  177         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  178             device_xname(sc->sc_dev), "intr");
  179         uba_reset_establish(ilreset, sc->sc_dev);
  180 
  181         /*
  182          * Reset the board and map the statistics
  183          * buffer onto the Unibus.
  184          */
  185         IL_WCSR(IL_CSR, ILC_RESET);
  186         (void)ilwait(sc, "reset");
  187         sc->sc_ui.ui_size = sizeof(struct il_stats);
  188         sc->sc_ui.ui_vaddr = (void *)&sc->sc_stats;
  189         if ((error = uballoc(device_private(parent), &sc->sc_ui, 0)))
  190                 return printf(": failed uballoc, error = %d\n", error);
  191 
  192         IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  193         IL_WCSR(IL_BCR, sizeof(struct il_stats));
  194         IL_WCSR(IL_CSR, ((sc->sc_ui.ui_baddr >> 2) & IL_EUA) | ILC_STAT);
  195         (void)ilwait(sc, "status");
  196         ubfree(device_private(parent), &sc->sc_ui);
  197         printf("%s: module=%s firmware=%s\n", device_xname(sc->sc_dev),
  198                 sc->sc_stats.ils_module, sc->sc_stats.ils_firmware);
  199         printf("%s: hardware address %s\n", device_xname(sc->sc_dev),
  200                 ether_sprintf(sc->sc_stats.ils_addr));
  201 
  202         strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
  203         ifp->if_softc = sc;
  204         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  205         ifp->if_init = ilinit;
  206         ifp->if_stop = ilstop;
  207         ifp->if_ioctl = ether_ioctl;
  208         ifp->if_start = ilstart;
  209         ifp->if_watchdog = ilwatch;
  210         IFQ_SET_READY(&ifp->if_snd);
  211 
  212         if_attach(ifp);
  213         ether_ifattach(ifp, sc->sc_stats.ils_addr);
  214 }
  215 
  216 void
  217 ilstop(struct ifnet *ifp, int a)
  218 {
  219         struct il_softc *sc = ifp->if_softc;
  220 
  221         IL_WCSR(IL_CSR, ILC_RESET);
  222 }
  223 
  224 
  225 int
  226 ilwait(struct il_softc *sc, const char *op)
  227 {
  228 
  229         while ((IL_RCSR(IL_CSR)&IL_CDONE) == 0)
  230                 ;
  231         if (IL_RCSR(IL_CSR)&IL_STATUS) {
  232                 char bits[64];
  233 
  234                 snprintb(bits, sizeof(bits), IL_BITS, IL_RCSR(IL_CSR));
  235                 aprint_error_dev(sc->sc_dev, "%s failed, csr=%s\n", op, 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(device_t 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                     device_private(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(device_private(device_parent(sc->sc_dev)),
  280                     &sc->sc_ui, 0);
  281         }
  282         sc->sc_scaninterval = ILWATCHINTERVAL;
  283         ifp->if_timer = sc->sc_scaninterval;
  284 
  285         /*
  286          * Turn off source address insertion (it's faster this way),
  287          * and set board online.  Former doesn't work if board is
  288          * already online (happens on ubareset), so we put it offline
  289          * first.
  290          */
  291         s = splnet();
  292         IL_WCSR(IL_CSR, ILC_RESET);
  293         if (ilwait(sc, "hardware diag")) {
  294                 sc->sc_if.if_flags &= ~IFF_UP;
  295                 goto out;
  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                 memcpy(&sc->sc_isu, CLLADDR(ifp->if_sadl), 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,
  312                     ((sc->sc_ui.ui_baddr >> 2) & IL_EUA) | ILC_LDPA);
  313                 if (ilwait(sc, "setaddr"))
  314                         goto out;
  315                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  316                 IL_WCSR(IL_BCR, sizeof (struct il_stats));
  317                 IL_WCSR(IL_CSR,
  318                     ((sc->sc_ui.ui_baddr >> 2) & IL_EUA) | ILC_STAT);
  319                 if (ilwait(sc, "verifying setaddr"))
  320                         goto out;
  321                 if (memcmp(sc->sc_stats.ils_addr,
  322                     CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN) != 0) {
  323                         aprint_error_dev(sc->sc_dev, "setaddr didn't work\n");
  324                         goto out;
  325                 }
  326         }
  327         if (sc->sc_if.if_flags & IFF_PROMISC) {
  328                 IL_WCSR(IL_CSR, ILC_PRMSC);
  329                 if (ilwait(sc, "all multi"))
  330                         goto out;
  331         } else if (sc->sc_if.if_flags & IFF_ALLMULTI) {
  332 too_many_multis:
  333                 IL_WCSR(IL_CSR, ILC_ALLMC);
  334                 if (ilwait(sc, "all multi"))
  335                         goto out;
  336         } else {
  337                 int i;
  338                 struct ethercom *ec = &sc->sc_ec;
  339                 register struct ether_addr *ep = sc->sc_maddrs;
  340                 struct ether_multi *enm;
  341                 struct ether_multistep step;
  342                 /*
  343                  * Step through our list of multicast addresses.  If we have
  344                  * too many multicast addresses, or if we have to listen to
  345                  * a range of multicast addresses, turn on reception of all
  346                  * multicasts.
  347                  */
  348                 i = 0;
  349                 ETHER_LOCK(ec);
  350                 ETHER_FIRST_MULTI(step, ec, enm);
  351                 while (enm != NULL) {
  352                         if (++i > 63 /* && k != 0 */) {
  353                                 break;
  354                         }
  355                         *ep++ = *(struct ether_addr *)enm->enm_addrlo;
  356                         ETHER_NEXT_MULTI(step, enm);
  357                 }
  358                 ETHER_UNLOCK(ec);
  359                 if (i == 0) {
  360                         /* no multicasts! */
  361                 } else if (i <= 63) {
  362                         IL_WCSR(IL_BAR, sc->sc_ubaddr & 0xffff);
  363                         IL_WCSR(IL_BCR, i * sizeof(struct ether_addr));
  364                         IL_WCSR(IL_CSR,
  365                             ((sc->sc_ubaddr >> 2) & IL_EUA) | ILC_LDGRPS);
  366                         if (ilwait(sc, "load multi"))
  367                                 goto out;
  368                 } else {
  369                         sc->sc_if.if_flags |= IFF_ALLMULTI;
  370                         goto too_many_multis;
  371                 }
  372         }
  373         /*
  374          * Set board online.
  375          * Hang receive buffer and start any pending
  376          * writes by faking a transmit complete.
  377          * Receive bcr is not a multiple of 8 so buffer
  378          * chaining can't happen.
  379          */
  380         IL_WCSR(IL_CSR, ILC_ONLINE);
  381         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  382                 ;
  383 
  384         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  385         IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  386         IL_WCSR(IL_CSR,
  387             ((sc->sc_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA) | ILC_RCV | IL_RIE);
  388         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  389                 ;
  390         ifp->if_flags |= IFF_RUNNING | IFF_OACTIVE;
  391         sc->sc_flags |= ILF_RUNNING;
  392         sc->sc_lastcmd = 0;
  393         ilcint(sc);
  394 out:
  395         splx(s);
  396         return 0;
  397 }
  398 
  399 /*
  400  * Start output on interface.
  401  * Get another datagram to send off of the interface queue,
  402  * and map it to the interface before starting the output.
  403  */
  404 void
  405 ilstart(struct ifnet *ifp)
  406 {
  407         struct il_softc *sc = ifp->if_softc;
  408         int len;
  409         struct mbuf *m;
  410         short csr;
  411 
  412         IFQ_DEQUEUE(&ifp->if_snd, m);
  413         if (m == 0) {
  414                 if ((sc->sc_flags & ILF_STATPENDING) == 0)
  415                         return;
  416                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ui.ui_baddr));
  417                 IL_WCSR(IL_BCR, sizeof (struct il_stats));
  418                 csr = ((sc->sc_ui.ui_baddr >> 2) & IL_EUA)
  419                     | ILC_STAT | IL_RIE | IL_CIE;
  420                 sc->sc_flags &= ~ILF_STATPENDING;
  421                 goto startcmd;
  422         }
  423         len = if_wubaput(&sc->sc_ifuba, m);
  424 #ifdef notdef
  425         if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
  426                 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_w.ifrw_bdp);
  427 #endif
  428         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_w.ifrw_info));
  429         IL_WCSR(IL_BCR, len);
  430         csr = ((sc->sc_ifuba.ifu_w.ifrw_info >> 2) & IL_EUA)
  431             | ILC_XMIT | IL_CIE | IL_RIE;
  432 
  433 startcmd:
  434         sc->sc_lastcmd = csr & IL_CMD;
  435         IL_WCSR(IL_CSR, csr);
  436         ifp->if_flags |= IFF_OACTIVE;
  437         return;
  438 }
  439 
  440 /*
  441  * Command done interrupt.
  442  */
  443 void
  444 ilcint(void *arg)
  445 {
  446         struct il_softc *sc = arg;
  447         short csr;
  448 
  449         if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
  450                 char bits[64];
  451 
  452                 snprintb(bits, sizeof(bits), IL_BITS, IL_RCSR(IL_CSR));
  453                 aprint_error_dev(sc->sc_dev,
  454                                  "stray xmit interrupt, csr=%s\n", bits);
  455                 return;
  456         }
  457 
  458         csr = IL_RCSR(IL_CSR);
  459         /*
  460          * Hang receive buffer if it couldn't
  461          * be done earlier (in ilrint).
  462          */
  463         if (sc->sc_flags & ILF_RCVPENDING) {
  464                 int s;
  465 
  466                 IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  467                 IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  468                 IL_WCSR(IL_CSR, ((sc->sc_ifuba.ifu_r.ifrw_info>>2) & IL_EUA)
  469                     | ILC_RCV | IL_RIE);
  470                 s = splhigh();
  471                 while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  472                         ;
  473                 splx(s);
  474                 sc->sc_flags &= ~ILF_RCVPENDING;
  475         }
  476         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  477         csr &= IL_STATUS;
  478         switch (sc->sc_lastcmd) {
  479 
  480         case ILC_XMIT:
  481                 sc->sc_if.if_opackets++;
  482                 if (csr > ILERR_RETRIES)
  483                         sc->sc_if.if_oerrors++;
  484                 break;
  485 
  486         case ILC_STAT:
  487                 if (csr == ILERR_SUCCESS)
  488                         iltotal(sc);
  489                 break;
  490         }
  491         if_wubaend(&sc->sc_ifuba);
  492         ilstart(&sc->sc_if);
  493 }
  494 
  495 /*
  496  * Ethernet interface receiver interrupt.
  497  * If input error just drop packet.
  498  * Otherwise purge input buffered data path and examine
  499  * packet to determine type.  If can't determine length
  500  * from type, then have to drop packet.  Otherwise decapsulate
  501  * packet based on type and pass to type specific higher-level
  502  * input routine.
  503  */
  504 void
  505 ilrint(void *arg)
  506 {
  507         struct il_softc *sc = arg;
  508         struct il_rheader *il;
  509         struct mbuf *m;
  510         int len, s;
  511 
  512 #ifdef notyet
  513         if (sc->sc_ifuba.ifu_flags & UBA_NEEDBDP)
  514                 UBAPURGE(is->is_ifuba.ifu_uba, is->is_ifuba.ifu_r.ifrw_bdp);
  515 #endif
  516         il = (struct il_rheader *)(sc->sc_ifuba.ifu_r.ifrw_addr);
  517         len = il->ilr_length - sizeof(struct il_rheader);
  518         if ((il->ilr_status&(ILFSTAT_A | ILFSTAT_C)) || len < 46 ||
  519             len > ETHERMTU) {
  520                 sc->sc_if.if_ierrors++;
  521 #ifdef notdef
  522                 if (sc->sc_if.if_ierrors % 100 == 0)
  523                         printf("il%d: += 100 input errors\n", unit);
  524 #endif
  525                 goto setup;
  526         }
  527 
  528         if (len == 0)
  529                 goto setup;
  530 
  531         /*
  532          * Pull packet off interface.
  533          */
  534         m = if_rubaget(&sc->sc_ifuba, &sc->sc_if, len);
  535         if (m == NULL)
  536                 goto setup;
  537 
  538         /* Shave off status hdr */
  539         m_adj(m, 4);
  540         if_percpuq_enqueue((&sc->sc_if)->if_percpuq, m);
  541 setup:
  542         /*
  543          * Reset for next packet if possible.
  544          * If waiting for transmit command completion, set flag
  545          * and wait until command completes.
  546          */
  547         if (sc->sc_if.if_flags & IFF_OACTIVE) {
  548                 sc->sc_flags |= ILF_RCVPENDING;
  549                 return;
  550         }
  551         IL_WCSR(IL_BAR, LOWORD(sc->sc_ifuba.ifu_r.ifrw_info));
  552         IL_WCSR(IL_BCR, sizeof(struct il_rheader) + ETHERMTU + 6);
  553         IL_WCSR(IL_CSR,
  554             ((sc->sc_ifuba.ifu_r.ifrw_info >> 2) & IL_EUA) | ILC_RCV | IL_RIE);
  555         s = splhigh();
  556         while ((IL_RCSR(IL_CSR) & IL_CDONE) == 0)
  557                 ;
  558         splx(s);
  559 }
  560 /*
  561  * Watchdog routine, request statistics from board.
  562  */
  563 void
  564 ilwatch(struct ifnet *ifp)
  565 {
  566         struct il_softc *sc = ifp->if_softc;
  567         int s;
  568 
  569         if (sc->sc_flags & ILF_STATPENDING) {
  570                 ifp->if_timer = sc->sc_scaninterval;
  571                 return;
  572         }
  573         s = splnet();
  574         sc->sc_flags |= ILF_STATPENDING;
  575         if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0)
  576                 ilstart(ifp);
  577         splx(s);
  578         ifp->if_timer = sc->sc_scaninterval;
  579 }
  580 
  581 /*
  582  * Total up the on-board statistics.
  583  */
  584 void
  585 iltotal(struct il_softc *sc)
  586 {
  587         struct ifnet *ifp = &sc->sc_if;
  588         u_short *interval, *sum, *end;
  589 
  590         interval = &sc->sc_stats.ils_frames;
  591         sum = &sc->sc_sum.ils_frames;
  592         end = sc->sc_sum.ils_fill2;
  593         while (sum < end)
  594                 *sum++ += *interval++;
  595         sc->sc_if.if_collisions = sc->sc_sum.ils_collis;
  596         if ((sc->sc_flags & ILF_SETADDR) &&
  597             (memcmp(sc->sc_stats.ils_addr, CLLADDR(ifp->if_sadl),
  598                     ETHER_ADDR_LEN) != 0)) {
  599                 log(LOG_ERR, "%s: physaddr reverted\n",
  600                     device_xname(sc->sc_dev));
  601                 sc->sc_flags &= ~ILF_RUNNING;
  602                 ilinit(&sc->sc_if);
  603         }
  604 }
  605 
  606 #ifdef notyet
  607 /*
  608  * set ethernet address for unit
  609  */
  610 void
  611 il_setaddr(u_char *physaddr, struct il_softc *sc)
  612 {
  613         if (! (sc->sc_flags & ILF_RUNNING))
  614                 return;
  615 
  616         memcpy((void *)is->is_addr, (void *)physaddr, sizeof is->is_addr);
  617         sc->sc_flags &= ~ILF_RUNNING;
  618         sc->sc_flags |= ILF_SETADDR;
  619         ilinit(&sc->sc_if);
  620 }
  621 #endif

Cache object: c8c64a53fa3fe8a1d5f941eb53d6cf66


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