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/snc/dp83932.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 /*      $FreeBSD$       */
    2 /*      $NecBSD: dp83932.c,v 1.5 1999/07/29 05:08:44 kmatsuda Exp $     */
    3 /*      $NetBSD: if_snc.c,v 1.18 1998/04/25 21:27:40 scottr Exp $       */
    4 
    5 /*-
    6  * Copyright (c) 1997, 1998, 1999
    7  *      Kouichi Matsuda.  All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by Kouichi Matsuda for
   20  *      NetBSD/pc98.
   21  * 4. The name of the author may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /*
   37  * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
   38  */
   39 
   40 /*
   41  * Modified for NetBSD/pc98 1.2G from NetBSD/mac68k 1.2G by Kouichi Matsuda.
   42  * Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
   43  * PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as
   44  * Ethernet Controller and National Semiconductor NS46C46 as
   45  * (64 * 16 bits) Microwire Serial EEPROM.
   46  */
   47 
   48 /*-
   49  * National Semiconductor  DP8393X SONIC Driver
   50  * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
   51  * You may use, copy, and modify this program so long as you retain the
   52  * copyright line.
   53  *
   54  * This driver has been substantially modified since Algorithmics donated
   55  * it.
   56  *
   57  *   Denton Gentry <denny1@home.com>
   58  * and also
   59  *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
   60  * did the work to get this running on the Macintosh.
   61  */
   62 
   63 #include "opt_inet.h"
   64 
   65 #include <sys/param.h>
   66 #include <sys/systm.h>
   67 #include <sys/sockio.h>
   68 #include <sys/mbuf.h>
   69 #include <sys/protosw.h>
   70 #include <sys/socket.h>
   71 #include <sys/syslog.h>
   72 #include <sys/errno.h>
   73 #if NRND > 0
   74 #include <sys/rnd.h>
   75 #endif
   76 
   77 #include <net/ethernet.h>
   78 #include <net/if.h>
   79 #include <net/if_arp.h>
   80 #include <net/if_dl.h>
   81 #include <net/if_media.h>
   82 
   83 #include <net/bpf.h>
   84 
   85 #include <sys/bus.h>
   86 #include <machine/bus.h>
   87 #include <dev/snc/dp83932reg.h>
   88 #include <dev/snc/dp83932var.h>
   89 
   90 hide void       sncwatchdog(struct ifnet *);
   91 hide void       sncinit(void *);
   92 hide int        sncstop(struct snc_softc *sc);
   93 hide int        sncioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
   94 hide void       sncstart(struct ifnet *ifp);
   95 hide void       sncreset(struct snc_softc *sc);
   96 
   97 hide void       caminitialise(struct snc_softc *);
   98 hide void       camentry(struct snc_softc *, int, u_char *ea);
   99 hide void       camprogram(struct snc_softc *);
  100 hide void       initialise_tda(struct snc_softc *);
  101 hide void       initialise_rda(struct snc_softc *);
  102 hide void       initialise_rra(struct snc_softc *);
  103 #ifdef SNCDEBUG
  104 hide void       camdump(struct snc_softc *sc);
  105 #endif
  106 
  107 hide void       sonictxint(struct snc_softc *);
  108 hide void       sonicrxint(struct snc_softc *);
  109 
  110 hide u_int      sonicput(struct snc_softc *sc, struct mbuf *m0, int mtd_next);
  111 hide int        sonic_read(struct snc_softc *, u_int32_t, int);
  112 hide struct mbuf *sonic_get(struct snc_softc *, u_int32_t, int);
  113 
  114 int     snc_enable(struct snc_softc *);
  115 void    snc_disable(struct snc_softc *);
  116 
  117 int     snc_mediachange(struct ifnet *);
  118 void    snc_mediastatus(struct ifnet *, struct ifmediareq *);
  119 
  120 #ifdef NetBSD
  121 #if NetBSD <= 199714
  122 struct cfdriver snc_cd = {
  123         NULL, "snc", DV_IFNET
  124 };
  125 #endif
  126 #endif
  127 
  128 #undef assert
  129 #undef _assert
  130 
  131 #ifdef NDEBUG
  132 #define assert(e)       ((void)0)
  133 #define _assert(e)      ((void)0)
  134 #else
  135 #define _assert(e)      assert(e)
  136 #ifdef __STDC__
  137 #define assert(e)       ((e) ? (void)0 : __assert("snc ", __FILE__, __LINE__, #e))
  138 #else   /* PCC */
  139 #define assert(e)       ((e) ? (void)0 : __assert("snc "__FILE__, __LINE__, "e"))
  140 #endif
  141 #endif
  142 
  143 #ifdef  SNCDEBUG
  144 #define SNC_SHOWTXHDR   0x01    /* show tx ether_header */
  145 #define SNC_SHOWRXHDR   0x02    /* show rx ether_header */
  146 #define SNC_SHOWCAMENT  0x04    /* show CAM entry */
  147 #endif  /* SNCDEBUG */
  148 int sncdebug = 0;
  149 
  150 
  151 void
  152 sncconfig(sc, media, nmedia, defmedia, myea)
  153         struct snc_softc *sc;
  154         int *media, nmedia, defmedia;
  155         u_int8_t *myea;
  156 {
  157         struct ifnet *ifp = &sc->sc_if;
  158         int i;
  159 
  160 #ifdef SNCDEBUG
  161         if ((sncdebug & SNC_SHOWCAMENT) != 0) {
  162                 camdump(sc);
  163         }
  164 #endif
  165 
  166 #ifdef SNCDEBUG
  167         device_printf(sc->sc_dev,
  168                       "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
  169                       sc->v_rra[0], sc->v_cda,
  170                       sc->v_rda, sc->mtda[0].mtd_vtxp);
  171 #endif
  172 
  173         ifp->if_softc = sc;
  174         if_initname(ifp, device_get_name(sc->sc_dev),
  175             device_get_unit(sc->sc_dev));
  176         ifp->if_ioctl = sncioctl;
  177         ifp->if_start = sncstart;
  178         ifp->if_flags =
  179             IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_NEEDSGIANT;
  180         ifp->if_watchdog = sncwatchdog;
  181         ifp->if_init = sncinit;
  182         ifp->if_mtu = ETHERMTU;
  183         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  184         bcopy(myea, sc->sc_ethercom.ac_enaddr, ETHER_ADDR_LEN);
  185 
  186         /* Initialize media goo. */
  187         ifmedia_init(&sc->sc_media, 0, snc_mediachange,
  188             snc_mediastatus);
  189         if (media != NULL) {
  190                 for (i = 0; i < nmedia; i++)
  191                         ifmedia_add(&sc->sc_media, media[i], 0, NULL);
  192                 ifmedia_set(&sc->sc_media, defmedia);
  193         } else {
  194                 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
  195                 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
  196         }
  197 
  198         ether_ifattach(ifp, myea);
  199 
  200 #if NRND > 0
  201         rnd_attach_source(&sc->rnd_source, device_get_nameunit(sc->sc_dev),
  202             RND_TYPE_NET, 0);
  203 #endif
  204 }
  205 
  206 void
  207 sncshutdown(arg)
  208         void *arg;
  209 {
  210 
  211         sncstop((struct snc_softc *)arg);
  212 }
  213 
  214 /*
  215  * Media change callback.
  216  */
  217 int
  218 snc_mediachange(ifp)
  219         struct ifnet *ifp;
  220 {
  221         struct snc_softc *sc = ifp->if_softc;
  222 
  223         if (sc->sc_mediachange)
  224                 return ((*sc->sc_mediachange)(sc));
  225         return (EINVAL);
  226 }
  227 
  228 /*
  229  * Media status callback.
  230  */
  231 void
  232 snc_mediastatus(ifp, ifmr)
  233         struct ifnet *ifp;
  234         struct ifmediareq *ifmr;
  235 {
  236         struct snc_softc *sc = ifp->if_softc;
  237 
  238         if (sc->sc_enabled == 0) {
  239                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
  240                 ifmr->ifm_status = 0;
  241                 return;
  242         }
  243 
  244         if (sc->sc_mediastatus)
  245                 (*sc->sc_mediastatus)(sc, ifmr);
  246 }
  247 
  248 
  249 hide int
  250 sncioctl(ifp, cmd, data)
  251         struct ifnet *ifp;
  252         u_long cmd;
  253         caddr_t data;
  254 {
  255         struct ifreq *ifr;
  256         struct snc_softc *sc = ifp->if_softc;
  257         int     s = splhardnet(), err = 0;
  258         int     temp;
  259 
  260         switch (cmd) {
  261 
  262         case SIOCSIFFLAGS:
  263                 if ((ifp->if_flags & IFF_UP) == 0 &&
  264                     (ifp->if_flags & IFF_RUNNING) != 0) {
  265                         /*
  266                          * If interface is marked down and it is running,
  267                          * then stop it.
  268                          */
  269                         sncstop(sc);
  270                         ifp->if_flags &= ~IFF_RUNNING;
  271                         snc_disable(sc);
  272                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  273                     (ifp->if_flags & IFF_RUNNING) == 0) {
  274                         /*
  275                          * If interface is marked up and it is stopped,
  276                          * then start it.
  277                          */
  278                         if ((err = snc_enable(sc)) != 0)
  279                                 break;
  280                         sncinit(sc);
  281                 } else if (sc->sc_enabled) {
  282                         /*
  283                          * reset the interface to pick up any other changes
  284                          * in flags
  285                          */
  286                         temp = ifp->if_flags & IFF_UP;
  287                         sncreset(sc);
  288                         ifp->if_flags |= temp;
  289                         sncstart(ifp);
  290                 }
  291                 break;
  292 
  293         case SIOCADDMULTI:
  294         case SIOCDELMULTI:
  295                 if (sc->sc_enabled == 0) {
  296                         err = EIO;
  297                         break;
  298                 }
  299                 temp = ifp->if_flags & IFF_UP;
  300                 sncreset(sc);
  301                 ifp->if_flags |= temp;
  302                 err = 0;
  303                 break;
  304         case SIOCGIFMEDIA:
  305         case SIOCSIFMEDIA:
  306                 ifr = (struct ifreq *) data;
  307                 err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
  308                 break;
  309         default:
  310                 err = ether_ioctl(ifp, cmd, data);
  311                 break;
  312         }
  313         splx(s);
  314         return (err);
  315 }
  316 
  317 /*
  318  * Encapsulate a packet of type family for the local net.
  319  */
  320 hide void
  321 sncstart(ifp)
  322         struct ifnet *ifp;
  323 {
  324         struct snc_softc        *sc = ifp->if_softc;
  325         struct mbuf     *m;
  326         int             mtd_next;
  327 
  328         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  329                 return;
  330 
  331 outloop:
  332         /* Check for room in the xmit buffer. */
  333         if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
  334                 mtd_next = 0;
  335 
  336         if (mtd_next == sc->mtd_hw) {
  337                 ifp->if_flags |= IFF_OACTIVE;
  338                 return;
  339         }
  340 
  341         IF_DEQUEUE(&ifp->if_snd, m);
  342         if (m == 0)
  343                 return;
  344 
  345         /* We need the header for m_pkthdr.len. */
  346         M_ASSERTPKTHDR(m);
  347 
  348         /*
  349          * If there is nothing in the o/p queue, and there is room in
  350          * the Tx ring, then send the packet directly.  Otherwise append
  351          * it to the o/p queue.
  352          */
  353         if ((sonicput(sc, m, mtd_next)) == 0) {
  354                 IF_PREPEND(&ifp->if_snd, m);
  355                 return;
  356         }
  357 
  358         /*
  359          * If bpf is listening on this interface, let it see the packet
  360          * before we commit it to the wire, but only if we are really
  361          * committed to send it.
  362          *
  363          * XXX: Locking must protect m against premature m_freem() in
  364          * sonictxint().
  365          */
  366         BPF_MTAP(ifp, m);
  367 
  368         sc->mtd_prev = sc->mtd_free;
  369         sc->mtd_free = mtd_next;
  370 
  371         ifp->if_opackets++;             /* # of pkts */
  372 
  373         /* Jump back for possibly more punishment. */
  374         goto outloop;
  375 }
  376 
  377 /*
  378  * reset and restart the SONIC.  Called in case of fatal
  379  * hardware/software errors.
  380  */
  381 hide void
  382 sncreset(sc)
  383         struct snc_softc *sc;
  384 {
  385         sncstop(sc);
  386         sncinit(sc);
  387 }
  388 
  389 hide void
  390 sncinit(xsc)
  391         void *xsc;
  392 {
  393         struct snc_softc *sc = xsc;
  394         u_long  s_rcr;
  395         int     s;
  396 
  397         if (sc->sc_if.if_flags & IFF_RUNNING)
  398                 /* already running */
  399                 return;
  400 
  401         s = splhardnet();
  402 
  403         NIC_PUT(sc, SNCR_CR, CR_RST);   /* DCR only accessable in reset mode! */
  404 
  405         /* config it */
  406         NIC_PUT(sc, SNCR_DCR, (sc->sncr_dcr |
  407                 (sc->bitmode ? DCR_DW32 : DCR_DW16)));
  408         NIC_PUT(sc, SNCR_DCR2, sc->sncr_dcr2);
  409 
  410         s_rcr = RCR_BRD | RCR_LBNONE;
  411         if (sc->sc_if.if_flags & IFF_PROMISC)
  412                 s_rcr |= RCR_PRO;
  413         if (sc->sc_if.if_flags & IFF_ALLMULTI)
  414                 s_rcr |= RCR_AMC;
  415         NIC_PUT(sc, SNCR_RCR, s_rcr);
  416 
  417         NIC_PUT(sc, SNCR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN));
  418 
  419         /* clear pending interrupts */
  420         NIC_PUT(sc, SNCR_ISR, ISR_ALL);
  421 
  422         /* clear tally counters */
  423         NIC_PUT(sc, SNCR_CRCT, -1);
  424         NIC_PUT(sc, SNCR_FAET, -1);
  425         NIC_PUT(sc, SNCR_MPT, -1);
  426 
  427         initialise_tda(sc);
  428         initialise_rda(sc);
  429         initialise_rra(sc);
  430 
  431         /* enable the chip */
  432         NIC_PUT(sc, SNCR_CR, 0);
  433         wbflush();
  434 
  435         /* program the CAM */
  436         camprogram(sc);
  437 
  438         /* get it to read resource descriptors */
  439         NIC_PUT(sc, SNCR_CR, CR_RRRA);
  440         wbflush();
  441         while ((NIC_GET(sc, SNCR_CR)) & CR_RRRA)
  442                 continue;
  443 
  444         /* enable rx */
  445         NIC_PUT(sc, SNCR_CR, CR_RXEN);
  446         wbflush();
  447 
  448         /* flag interface as "running" */
  449         sc->sc_if.if_flags |= IFF_RUNNING;
  450         sc->sc_if.if_flags &= ~IFF_OACTIVE;
  451 
  452         splx(s);
  453         return;
  454 }
  455 
  456 /*
  457  * close down an interface and free its buffers
  458  * Called on final close of device, or if sncinit() fails
  459  * part way through.
  460  */
  461 hide int
  462 sncstop(sc)
  463         struct snc_softc *sc;
  464 {
  465         struct mtd *mtd;
  466         int     s = splhardnet();
  467 
  468         /* stick chip in reset */
  469         NIC_PUT(sc, SNCR_CR, CR_RST);
  470         wbflush();
  471 
  472         /* free all receive buffers (currently static so nothing to do) */
  473 
  474         /* free all pending transmit mbufs */
  475         while (sc->mtd_hw != sc->mtd_free) {
  476                 mtd = &sc->mtda[sc->mtd_hw];
  477                 if (mtd->mtd_mbuf)
  478                         m_freem(mtd->mtd_mbuf);
  479                 if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
  480         }
  481 
  482         sc->sc_if.if_timer = 0;
  483         sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP);
  484 
  485         splx(s);
  486         return (0);
  487 }
  488 
  489 /*
  490  * Called if any Tx packets remain unsent after 5 seconds,
  491  * In all cases we just reset the chip, and any retransmission
  492  * will be handled by higher level protocol timeouts.
  493  */
  494 hide void
  495 sncwatchdog(ifp)
  496         struct ifnet *ifp;
  497 {
  498         struct snc_softc *sc = ifp->if_softc;
  499         struct mtd *mtd;
  500         int     temp;
  501 
  502         if (sc->mtd_hw != sc->mtd_free) {
  503                 /* something still pending for transmit */
  504                 mtd = &sc->mtda[sc->mtd_hw];
  505                 if (SRO(sc, mtd->mtd_vtxp, TXP_STATUS) == 0)
  506                         log(LOG_ERR, "%s: Tx - timeout\n",
  507                             device_get_nameunit(sc->sc_dev));
  508                 else
  509                         log(LOG_ERR, "%s: Tx - lost interrupt\n",
  510                             device_get_nameunit(sc->sc_dev));
  511                 temp = ifp->if_flags & IFF_UP;
  512                 sncreset(sc);
  513                 ifp->if_flags |= temp;
  514         }
  515 }
  516 
  517 /*
  518  * stuff packet into sonic (at splnet)
  519  */
  520 hide u_int
  521 sonicput(sc, m0, mtd_next)
  522         struct snc_softc *sc;
  523         struct mbuf *m0;
  524         int mtd_next;
  525 {
  526         struct mtd *mtdp;
  527         struct mbuf *m;
  528         u_int32_t buff;
  529         u_int32_t txp;
  530         u_int   len = 0;
  531         u_int   totlen = 0;
  532 
  533 #ifdef whyonearthwouldyoudothis
  534         if (NIC_GET(sc, SNCR_CR) & CR_TXP)
  535                 return (0);
  536 #endif
  537 
  538         /* grab the replacement mtd */
  539         mtdp = &sc->mtda[sc->mtd_free];
  540 
  541         buff = mtdp->mtd_vbuf;
  542         
  543         /* this packet goes to mtdnext fill in the TDA */
  544         mtdp->mtd_mbuf = m0;
  545         txp = mtdp->mtd_vtxp;
  546 
  547         /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */
  548         if (sc->mtd_pint == 0) {
  549                 sc->mtd_pint = NTDA/2;
  550                 SWO(sc, txp, TXP_CONFIG, TCR_PINT);
  551         } else {
  552                 sc->mtd_pint--;
  553                 SWO(sc, txp, TXP_CONFIG, 0);
  554         }
  555 
  556         for (m = m0; m; m = m->m_next) {
  557                 len = m->m_len;
  558                 totlen += len;
  559                 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), buff, len);
  560                 buff += len;
  561         }
  562         if (totlen >= TXBSIZE) {
  563                 panic("%s: sonicput: packet overflow",
  564                       device_get_nameunit(sc->sc_dev));
  565         }
  566 
  567         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO,
  568             LOWER(mtdp->mtd_vbuf));
  569         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI,
  570             UPPER(mtdp->mtd_vbuf));
  571 
  572         if (totlen < ETHERMIN + sizeof(struct ether_header)) {
  573                 int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
  574                 (*sc->sc_zerobuf)(sc, mtdp->mtd_vbuf + totlen, pad);
  575                 totlen = ETHERMIN + sizeof(struct ether_header);
  576         }
  577 
  578         SWO(sc, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE,
  579             totlen);
  580         SWO(sc, txp, TXP_FRAGCNT, 1);
  581         SWO(sc, txp, TXP_PKTSIZE, totlen);
  582 
  583         /* link onto the next mtd that will be used */
  584         SWO(sc, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO,
  585             LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
  586 
  587         /*
  588          * The previous txp.tlink currently contains a pointer to
  589          * our txp | EOL. Want to clear the EOL, so write our
  590          * pointer to the previous txp.
  591          */
  592         SWO(sc, sc->mtda[sc->mtd_prev].mtd_vtxp, sc->mtd_tlinko,
  593             LOWER(mtdp->mtd_vtxp));
  594 
  595         /* make sure chip is running */
  596         wbflush();
  597         NIC_PUT(sc, SNCR_CR, CR_TXP);
  598         wbflush();
  599         sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
  600 
  601         return (totlen);
  602 }
  603 
  604 /*
  605  * These are called from sonicioctl() when /etc/ifconfig is run to set
  606  * the address or switch the i/f on.
  607  */
  608 /*
  609  * CAM support
  610  */
  611 hide void
  612 caminitialise(sc)
  613         struct snc_softc *sc;
  614 {
  615         u_int32_t v_cda = sc->v_cda;
  616         int     i;
  617         int     camoffset;
  618 
  619         for (i = 0; i < MAXCAM; i++) {
  620                 camoffset = i * CDA_CAMDESC;
  621                 SWO(sc, v_cda, (camoffset + CDA_CAMEP), i);
  622                 SWO(sc, v_cda, (camoffset + CDA_CAMAP2), 0);
  623                 SWO(sc, v_cda, (camoffset + CDA_CAMAP1), 0);
  624                 SWO(sc, v_cda, (camoffset + CDA_CAMAP0), 0);
  625         }
  626         SWO(sc, v_cda, CDA_ENABLE, 0);
  627 
  628 #ifdef SNCDEBUG
  629         if ((sncdebug & SNC_SHOWCAMENT) != 0) {
  630                 camdump(sc);
  631         }
  632 #endif
  633 }
  634 
  635 hide void
  636 camentry(sc, entry, ea)
  637         int entry;
  638         u_char *ea;
  639         struct snc_softc *sc;
  640 {
  641         u_int32_t v_cda = sc->v_cda;
  642         int     camoffset = entry * CDA_CAMDESC;
  643 
  644         SWO(sc, v_cda, camoffset + CDA_CAMEP, entry);
  645         SWO(sc, v_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
  646         SWO(sc, v_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
  647         SWO(sc, v_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
  648         SWO(sc, v_cda, CDA_ENABLE, 
  649             (SRO(sc, v_cda, CDA_ENABLE) | (1 << entry)));
  650 }
  651 
  652 hide void
  653 camprogram(sc)
  654         struct snc_softc *sc;
  655 {
  656         struct ifmultiaddr      *ifma;
  657         struct ifnet *ifp;
  658         int     timeout;
  659         int     mcount = 0;
  660 
  661         caminitialise(sc);
  662 
  663         ifp = &sc->sc_if;
  664 
  665         /* Always load our own address first. */
  666         camentry (sc, mcount, sc->sc_ethercom.ac_enaddr);
  667         mcount++;
  668 
  669         /* Assume we won't need allmulti bit. */
  670         ifp->if_flags &= ~IFF_ALLMULTI;
  671 
  672         /* Loop through multicast addresses */
  673         IF_ADDR_LOCK(ifp);
  674         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
  675                 if (ifma->ifma_addr->sa_family != AF_LINK)
  676                         continue;
  677                 if (mcount == MAXCAM) {
  678                          ifp->if_flags |= IFF_ALLMULTI;
  679                          break;
  680                 }
  681 
  682                 /* program the CAM with the specified entry */
  683                 camentry(sc, mcount,
  684                          LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
  685                 mcount++;
  686         }
  687         IF_ADDR_UNLOCK(ifp);
  688 
  689         NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda));
  690         NIC_PUT(sc, SNCR_CDC, MAXCAM);
  691         NIC_PUT(sc, SNCR_CR, CR_LCAM);
  692         wbflush();
  693 
  694         timeout = 10000;
  695         while ((NIC_GET(sc, SNCR_CR) & CR_LCAM) && timeout--)
  696                 continue;
  697         if (timeout == 0) {
  698                 /* XXX */
  699                 panic("%s: CAM initialisation failed\n",
  700                       device_get_nameunit(sc->sc_dev));
  701         }
  702         timeout = 10000;
  703         while (((NIC_GET(sc, SNCR_ISR) & ISR_LCD) == 0) && timeout--)
  704                 continue;
  705 
  706         if (NIC_GET(sc, SNCR_ISR) & ISR_LCD)
  707                 NIC_PUT(sc, SNCR_ISR, ISR_LCD);
  708         else
  709                 device_printf(sc->sc_dev,
  710                               "CAM initialisation without interrupt\n");
  711 }
  712 
  713 #ifdef SNCDEBUG
  714 hide void
  715 camdump(sc)
  716         struct snc_softc *sc;
  717 {
  718         int     i;
  719 
  720         printf("CAM entries:\n");
  721         NIC_PUT(sc, SNCR_CR, CR_RST);
  722         wbflush();
  723 
  724         for (i = 0; i < 16; i++) {
  725                 u_short  ap2, ap1, ap0;
  726                 NIC_PUT(sc, SNCR_CEP, i);
  727                 wbflush();
  728                 ap2 = NIC_GET(sc, SNCR_CAP2);
  729                 ap1 = NIC_GET(sc, SNCR_CAP1);
  730                 ap0 = NIC_GET(sc, SNCR_CAP0);
  731                 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
  732         }
  733         printf("CAM enable 0x%x\n", NIC_GET(sc, SNCR_CEP));
  734 
  735         NIC_PUT(sc, SNCR_CR, 0);
  736         wbflush();
  737 }
  738 #endif
  739 
  740 hide void
  741 initialise_tda(sc)
  742         struct snc_softc *sc;
  743 {
  744         struct mtd *mtd;
  745         int     i;
  746 
  747         for (i = 0; i < NTDA; i++) {
  748                 mtd = &sc->mtda[i];
  749                 mtd->mtd_mbuf = 0;
  750         }
  751 
  752         sc->mtd_hw = 0;
  753         sc->mtd_prev = NTDA - 1;
  754         sc->mtd_free = 0;
  755         sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
  756         sc->mtd_pint = NTDA/2;
  757 
  758         NIC_PUT(sc, SNCR_UTDA, UPPER(sc->mtda[0].mtd_vtxp));
  759         NIC_PUT(sc, SNCR_CTDA, LOWER(sc->mtda[0].mtd_vtxp));
  760 }
  761 
  762 hide void
  763 initialise_rda(sc)
  764         struct snc_softc *sc;
  765 {
  766         int             i;
  767         u_int32_t       vv_rda = 0;
  768         u_int32_t       v_rda = 0;
  769 
  770         /* link the RDA's together into a circular list */
  771         for (i = 0; i < (sc->sc_nrda - 1); i++) {
  772                 v_rda = sc->v_rda + (i * RXPKT_SIZE(sc));
  773                 vv_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc));
  774                 SWO(sc, v_rda, RXPKT_RLINK, LOWER(vv_rda));
  775                 SWO(sc, v_rda, RXPKT_INUSE, 1);
  776         }
  777         v_rda = sc->v_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc));
  778         SWO(sc, v_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL);
  779         SWO(sc, v_rda, RXPKT_INUSE, 1);
  780 
  781         /* mark end of receive descriptor list */
  782         sc->sc_rdamark = sc->sc_nrda - 1;
  783 
  784         sc->sc_rxmark = 0;
  785 
  786         NIC_PUT(sc, SNCR_URDA, UPPER(sc->v_rda));
  787         NIC_PUT(sc, SNCR_CRDA, LOWER(sc->v_rda));
  788         wbflush();
  789 }
  790 
  791 hide void
  792 initialise_rra(sc)
  793         struct snc_softc *sc;
  794 {
  795         int     i;
  796         u_int   v;
  797         int     bitmode = sc->bitmode;
  798 
  799         if (bitmode)
  800                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 2);
  801         else
  802                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 1);
  803 
  804         NIC_PUT(sc, SNCR_URRA, UPPER(sc->v_rra[0]));
  805         NIC_PUT(sc, SNCR_RSA, LOWER(sc->v_rra[0]));
  806         /* rea must point just past the end of the rra space */
  807         NIC_PUT(sc, SNCR_REA, LOWER(sc->v_rea));
  808         NIC_PUT(sc, SNCR_RRP, LOWER(sc->v_rra[0]));
  809         NIC_PUT(sc, SNCR_RSC, 0);
  810 
  811         /* fill up SOME of the rra with buffers */
  812         for (i = 0; i < NRBA; i++) {
  813                 v = SONIC_GETDMA(sc->rbuf[i]);
  814                 SWO(sc, sc->v_rra[i], RXRSRC_PTRHI, UPPER(v));
  815                 SWO(sc, sc->v_rra[i], RXRSRC_PTRLO, LOWER(v));
  816                 SWO(sc, sc->v_rra[i], RXRSRC_WCHI, UPPER(NBPG/2));
  817                 SWO(sc, sc->v_rra[i], RXRSRC_WCLO, LOWER(NBPG/2));
  818         }
  819         sc->sc_rramark = NRBA;
  820         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[sc->sc_rramark]));
  821         wbflush();
  822 }
  823 
  824 void
  825 sncintr(arg)
  826         void    *arg;
  827 {
  828         struct snc_softc *sc = (struct snc_softc *)arg;
  829         int     isr;
  830 
  831         if (sc->sc_enabled == 0)
  832                 return;
  833 
  834         while ((isr = (NIC_GET(sc, SNCR_ISR) & ISR_ALL)) != 0) {
  835                 /* scrub the interrupts that we are going to service */
  836                 NIC_PUT(sc, SNCR_ISR, isr);
  837                 wbflush();
  838 
  839                 if (isr & (ISR_BR | ISR_LCD | ISR_TC))
  840                         device_printf(sc->sc_dev,
  841                                       "unexpected interrupt status 0x%x\n",
  842                                       isr);
  843 
  844                 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
  845                         sonictxint(sc);
  846 
  847                 if (isr & ISR_PKTRX)
  848                         sonicrxint(sc);
  849 
  850                 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
  851                         if (isr & ISR_HBL)
  852                                 /*
  853                                  * The repeater is not providing a heartbeat.
  854                                  * In itself this isn't harmful, lots of the
  855                                  * cheap repeater hubs don't supply a heartbeat.
  856                                  * So ignore the lack of heartbeat. Its only
  857                                  * if we can't detect a carrier that we have a
  858                                  * problem.
  859                                  */
  860                                 ;
  861                         if (isr & ISR_RDE)
  862                                 device_printf(sc->sc_dev, 
  863                                         "receive descriptors exhausted\n");
  864                         if (isr & ISR_RBE)
  865                                 device_printf(sc->sc_dev, 
  866                                         "receive buffers exhausted\n");
  867                         if (isr & ISR_RBAE)
  868                                 device_printf(sc->sc_dev, 
  869                                         "receive buffer area exhausted\n");
  870                         if (isr & ISR_RFO)
  871                                 device_printf(sc->sc_dev, 
  872                                         "receive FIFO overrun\n");
  873                 }
  874                 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
  875 #ifdef notdef
  876                         if (isr & ISR_CRC)
  877                                 sc->sc_crctally++;
  878                         if (isr & ISR_FAE)
  879                                 sc->sc_faetally++;
  880                         if (isr & ISR_MP)
  881                                 sc->sc_mptally++;
  882 #endif
  883                 }
  884                 sncstart(&sc->sc_if);
  885 
  886 #if NRND > 0
  887                 if (isr)
  888                         rnd_add_uint32(&sc->rnd_source, isr);
  889 #endif
  890         }
  891         return;
  892 }
  893 
  894 /*
  895  * Transmit interrupt routine
  896  */
  897 hide void
  898 sonictxint(sc)
  899         struct snc_softc *sc;
  900 {
  901         struct mtd      *mtd;
  902         u_int32_t       txp;
  903         unsigned short  txp_status;
  904         int             mtd_hw;
  905         struct ifnet    *ifp = &sc->sc_if;
  906 
  907         mtd_hw = sc->mtd_hw;
  908 
  909         if (mtd_hw == sc->mtd_free)
  910                 return;
  911 
  912         while (mtd_hw != sc->mtd_free) {
  913                 mtd = &sc->mtda[mtd_hw];
  914 
  915                 txp = mtd->mtd_vtxp;
  916 
  917                 if (SRO(sc, txp, TXP_STATUS) == 0) {
  918                         break; /* it hasn't really gone yet */
  919                 }
  920 
  921 #ifdef SNCDEBUG
  922                 if ((sncdebug & SNC_SHOWTXHDR) != 0)
  923                 {
  924                         struct ether_header eh;
  925 
  926                         (*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh));
  927                         device_printf(sc->sc_dev,
  928                             "xmit status=0x%x len=%d type=0x%x from %6D",
  929                             SRO(sc, txp, TXP_STATUS),
  930                             SRO(sc, txp, TXP_PKTSIZE),
  931                             htons(eh.ether_type),
  932                             eh.ether_shost, ":");
  933                         printf(" (to %6D)\n", eh.ether_dhost, ":");
  934                 }
  935 #endif /* SNCDEBUG */
  936 
  937                 ifp->if_flags &= ~IFF_OACTIVE;
  938 
  939                 if (mtd->mtd_mbuf != 0) {
  940                         m_freem(mtd->mtd_mbuf);
  941                         mtd->mtd_mbuf = 0;
  942                 }
  943                 if (++mtd_hw == NTDA) mtd_hw = 0;
  944 
  945                 txp_status = SRO(sc, txp, TXP_STATUS);
  946 
  947                 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
  948                         ((txp_status & TCR_NC) >> 12);
  949 
  950                 if ((txp_status & TCR_PTX) == 0) {
  951                         ifp->if_oerrors++;
  952                         device_printf(sc->sc_dev, "Tx packet status=0x%x\n",
  953                                       txp_status);
  954                         
  955                         /* XXX - DG This looks bogus */
  956                         if (mtd_hw != sc->mtd_free) {
  957                                 printf("resubmitting remaining packets\n");
  958                                 mtd = &sc->mtda[mtd_hw];
  959                                 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp));
  960                                 NIC_PUT(sc, SNCR_CR, CR_TXP);
  961                                 wbflush();
  962                                 break;
  963                         }
  964                 }
  965         }
  966 
  967         sc->mtd_hw = mtd_hw;
  968         return;
  969 }
  970 
  971 /*
  972  * Receive interrupt routine
  973  */
  974 hide void
  975 sonicrxint(sc)
  976         struct snc_softc *sc;
  977 {
  978         u_int32_t rda;
  979         int     orra;
  980         int     len;
  981         int     rramark;
  982         int     rdamark;
  983         u_int16_t rxpkt_ptr;
  984 
  985         rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
  986 
  987         while (SRO(sc, rda, RXPKT_INUSE) == 0) {
  988                 u_int status = SRO(sc, rda, RXPKT_STATUS);
  989 
  990                 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK;
  991                 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO);
  992                 /*
  993                  * Do not trunc ether_header length.
  994                  * Our sonic_read() and sonic_get() require it.
  995                  */
  996                 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE;
  997                 if (status & RCR_PRX) {
  998                         /* XXX: Does PGOFSET require? */
  999                         u_int32_t pkt =
 1000                             sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PGOFSET);
 1001                         if (sonic_read(sc, pkt, len))
 1002                                 sc->sc_if.if_ipackets++;
 1003                         else
 1004                                 sc->sc_if.if_ierrors++;
 1005                 } else
 1006                         sc->sc_if.if_ierrors++;
 1007 
 1008                 /*
 1009                  * give receive buffer area back to chip.
 1010                  *
 1011                  * If this was the last packet in the RRA, give the RRA to
 1012                  * the chip again.
 1013                  * If sonic read didnt copy it out then we would have to
 1014                  * wait !!
 1015                  * (dont bother add it back in again straight away)
 1016                  *
 1017                  * Really, we're doing v_rra[rramark] = v_rra[orra] but
 1018                  * we have to use the macros because SONIC might be in
 1019                  * 16 or 32 bit mode.
 1020                  */
 1021                 if (status & RCR_LPKT) {
 1022                         u_int32_t tmp1, tmp2;
 1023 
 1024                         rramark = sc->sc_rramark;
 1025                         tmp1 = sc->v_rra[rramark];
 1026                         tmp2 = sc->v_rra[orra];
 1027                         SWO(sc, tmp1, RXRSRC_PTRLO,
 1028                                 SRO(sc, tmp2, RXRSRC_PTRLO));
 1029                         SWO(sc, tmp1, RXRSRC_PTRHI,
 1030                                 SRO(sc, tmp2, RXRSRC_PTRHI));
 1031                         SWO(sc, tmp1, RXRSRC_WCLO,
 1032                                 SRO(sc, tmp2, RXRSRC_WCLO));
 1033                         SWO(sc, tmp1, RXRSRC_WCHI,
 1034                                 SRO(sc, tmp2, RXRSRC_WCHI));
 1035 
 1036                         /* zap old rra for fun */
 1037                         SWO(sc, tmp2, RXRSRC_WCHI, 0);
 1038                         SWO(sc, tmp2, RXRSRC_WCLO, 0);
 1039 
 1040                         sc->sc_rramark = (++rramark) & RRAMASK;
 1041                         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark]));
 1042                         wbflush();
 1043                 }
 1044 
 1045                 /*
 1046                  * give receive descriptor back to chip simple
 1047                  * list is circular
 1048                  */
 1049                 rdamark = sc->sc_rdamark;
 1050                 SWO(sc, rda, RXPKT_INUSE, 1);
 1051                 SWO(sc, rda, RXPKT_RLINK,
 1052                         SRO(sc, rda, RXPKT_RLINK) | EOL);
 1053                 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
 1054                         SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))),
 1055                         RXPKT_RLINK) & ~EOL);
 1056                 sc->sc_rdamark = sc->sc_rxmark;
 1057 
 1058                 if (++sc->sc_rxmark >= sc->sc_nrda)
 1059                         sc->sc_rxmark = 0;
 1060                 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
 1061         }
 1062 }
 1063 
 1064 /*
 1065  * sonic_read -- pull packet off interface and forward to
 1066  * appropriate protocol handler
 1067  */
 1068 hide int
 1069 sonic_read(sc, pkt, len)
 1070         struct snc_softc *sc;
 1071         u_int32_t pkt;
 1072         int len;
 1073 {
 1074         struct ifnet *ifp = &sc->sc_if;
 1075         struct ether_header *et;
 1076         struct mbuf *m;
 1077 
 1078         if (len <= sizeof(struct ether_header) ||
 1079             len > ETHERMTU + sizeof(struct ether_header)) {
 1080                 device_printf(sc->sc_dev,
 1081                               "invalid packet length %d bytes\n", len);
 1082                 return (0);
 1083         }
 1084 
 1085         /* Pull packet off interface. */
 1086         m = sonic_get(sc, pkt, len);
 1087         if (m == 0) {
 1088                 return (0);
 1089         }
 1090 
 1091         /* We assume that the header fit entirely in one mbuf. */
 1092         et = mtod(m, struct ether_header *);
 1093 
 1094 #ifdef SNCDEBUG
 1095         if ((sncdebug & SNC_SHOWRXHDR) != 0)
 1096         {
 1097                 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D",
 1098                     pkt, len, htons(et->ether_type),
 1099                     et->ether_shost, ":");
 1100                 printf(" (to %6D)\n", et->ether_dhost, ":");
 1101         }
 1102 #endif /* SNCDEBUG */
 1103 
 1104         /* Pass the packet up. */
 1105         (*ifp->if_input)(ifp, m);
 1106         return (1);
 1107 }
 1108 
 1109 
 1110 /*
 1111  * munge the received packet into an mbuf chain
 1112  */
 1113 hide struct mbuf *
 1114 sonic_get(sc, pkt, datalen)
 1115         struct snc_softc *sc;
 1116         u_int32_t pkt;
 1117         int datalen;
 1118 {
 1119         struct  mbuf *m, *top, **mp;
 1120         int     len;
 1121         /*
 1122          * Do not trunc ether_header length.
 1123          * Our sonic_read() and sonic_get() require it.
 1124          */
 1125 
 1126         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1127         if (m == 0)
 1128                 return (0);
 1129         m->m_pkthdr.rcvif = &sc->sc_if;
 1130         m->m_pkthdr.len = datalen;
 1131         len = MHLEN;
 1132         top = 0;
 1133         mp = &top;
 1134 
 1135         while (datalen > 0) {
 1136                 if (top) {
 1137                         MGET(m, M_DONTWAIT, MT_DATA);
 1138                         if (m == 0) {
 1139                                 m_freem(top);
 1140                                 return (0);
 1141                         }
 1142                         len = MLEN;
 1143                 }
 1144                 if (datalen >= MINCLSIZE) {
 1145                         MCLGET(m, M_DONTWAIT);
 1146                         if ((m->m_flags & M_EXT) == 0) {
 1147                                 if (top) m_freem(top);
 1148                                 return (0);
 1149                         }
 1150                         len = MCLBYTES;
 1151                 }
 1152 #if 0
 1153                 /* XXX: Require? */
 1154                 if (!top) {
 1155                         register int pad =
 1156                             ALIGN(sizeof(struct ether_header)) -
 1157                                 sizeof(struct ether_header);
 1158                         m->m_data += pad;
 1159                         len -= pad;
 1160                 }
 1161 #endif
 1162                 m->m_len = len = min(datalen, len);
 1163 
 1164                 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len);
 1165                 pkt += len;
 1166                 datalen -= len;
 1167                 *mp = m;
 1168                 mp = &m->m_next;
 1169         }
 1170 
 1171         return (top);
 1172 }
 1173 /*
 1174  * Enable power on the interface.
 1175  */
 1176 int
 1177 snc_enable(sc)
 1178         struct snc_softc *sc;
 1179 {
 1180 
 1181 #ifdef  SNCDEBUG
 1182         device_printf(sc->sc_dev, "snc_enable()\n");
 1183 #endif  /* SNCDEBUG */
 1184 
 1185         if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
 1186                 if ((*sc->sc_enable)(sc) != 0) {
 1187                         device_printf(sc->sc_dev, "device enable failed\n");
 1188                         return (EIO);
 1189                 }
 1190         }
 1191 
 1192         sc->sc_enabled = 1;
 1193         return (0);
 1194 }
 1195 
 1196 /*
 1197  * Disable power on the interface.
 1198  */
 1199 void
 1200 snc_disable(sc)
 1201         struct snc_softc *sc;
 1202 {
 1203 
 1204 #ifdef  SNCDEBUG
 1205         device_printf(sc->sc_dev, "snc_disable()\n");
 1206 #endif  /* SNCDEBUG */
 1207 
 1208         if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
 1209                 (*sc->sc_disable)(sc);
 1210                 sc->sc_enabled = 0;
 1211         }
 1212 }
 1213 
 1214 

Cache object: 2d499d9a9898f262a0b0652dffdd884b


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