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: releng/5.0/sys/dev/snc/dp83932.c 106937 2002-11-14 23:54:55Z sam $    */
    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         device_printf(sc->sc_dev, "address %6D\n", myea, ":");
  166 
  167 #ifdef SNCDEBUG
  168         device_printf(sc->sc_dev,
  169                       "buffers: rra=0x%x cda=0x%x rda=0x%x tda=0x%x\n",
  170                       sc->v_rra[0], sc->v_cda,
  171                       sc->v_rda, sc->mtda[0].mtd_vtxp);
  172 #endif
  173 
  174         ifp->if_softc = sc;
  175         ifp->if_unit = device_get_unit(sc->sc_dev);
  176         ifp->if_name = "snc";
  177         ifp->if_ioctl = sncioctl;
  178         ifp->if_output = ether_output;
  179         ifp->if_start = sncstart;
  180         ifp->if_flags =
  181             IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  182         ifp->if_watchdog = sncwatchdog;
  183         ifp->if_init = sncinit;
  184         ifp->if_mtu = ETHERMTU;
  185         ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  186         bcopy(myea, sc->sc_ethercom.ac_enaddr, ETHER_ADDR_LEN);
  187 
  188         /* Initialize media goo. */
  189         ifmedia_init(&sc->sc_media, 0, snc_mediachange,
  190             snc_mediastatus);
  191         if (media != NULL) {
  192                 for (i = 0; i < nmedia; i++)
  193                         ifmedia_add(&sc->sc_media, media[i], 0, NULL);
  194                 ifmedia_set(&sc->sc_media, defmedia);
  195         } else {
  196                 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
  197                 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
  198         }
  199 
  200         ether_ifattach(ifp, myea);
  201 
  202 #if NRND > 0
  203         rnd_attach_source(&sc->rnd_source, device_get_nameunit(sc->sc_dev),
  204             RND_TYPE_NET, 0);
  205 #endif
  206 }
  207 
  208 void
  209 sncshutdown(arg)
  210         void *arg;
  211 {
  212 
  213         sncstop((struct snc_softc *)arg);
  214 }
  215 
  216 /*
  217  * Media change callback.
  218  */
  219 int
  220 snc_mediachange(ifp)
  221         struct ifnet *ifp;
  222 {
  223         struct snc_softc *sc = ifp->if_softc;
  224 
  225         if (sc->sc_mediachange)
  226                 return ((*sc->sc_mediachange)(sc));
  227         return (EINVAL);
  228 }
  229 
  230 /*
  231  * Media status callback.
  232  */
  233 void
  234 snc_mediastatus(ifp, ifmr)
  235         struct ifnet *ifp;
  236         struct ifmediareq *ifmr;
  237 {
  238         struct snc_softc *sc = ifp->if_softc;
  239 
  240         if (sc->sc_enabled == 0) {
  241                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
  242                 ifmr->ifm_status = 0;
  243                 return;
  244         }
  245 
  246         if (sc->sc_mediastatus)
  247                 (*sc->sc_mediastatus)(sc, ifmr);
  248 }
  249 
  250 
  251 hide int
  252 sncioctl(ifp, cmd, data)
  253         struct ifnet *ifp;
  254         u_long cmd;
  255         caddr_t data;
  256 {
  257         struct ifreq *ifr;
  258         struct snc_softc *sc = ifp->if_softc;
  259         int     s = splnet(), err = 0;
  260         int     temp;
  261 
  262         switch (cmd) {
  263 
  264         case SIOCSIFFLAGS:
  265                 if ((ifp->if_flags & IFF_UP) == 0 &&
  266                     (ifp->if_flags & IFF_RUNNING) != 0) {
  267                         /*
  268                          * If interface is marked down and it is running,
  269                          * then stop it.
  270                          */
  271                         sncstop(sc);
  272                         ifp->if_flags &= ~IFF_RUNNING;
  273                         snc_disable(sc);
  274                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
  275                     (ifp->if_flags & IFF_RUNNING) == 0) {
  276                         /*
  277                          * If interface is marked up and it is stopped,
  278                          * then start it.
  279                          */
  280                         if ((err = snc_enable(sc)) != 0)
  281                                 break;
  282                         sncinit(sc);
  283                 } else if (sc->sc_enabled) {
  284                         /*
  285                          * reset the interface to pick up any other changes
  286                          * in flags
  287                          */
  288                         temp = ifp->if_flags & IFF_UP;
  289                         sncreset(sc);
  290                         ifp->if_flags |= temp;
  291                         sncstart(ifp);
  292                 }
  293                 break;
  294 
  295         case SIOCADDMULTI:
  296         case SIOCDELMULTI:
  297                 if (sc->sc_enabled == 0) {
  298                         err = EIO;
  299                         break;
  300                 }
  301                 temp = ifp->if_flags & IFF_UP;
  302                 sncreset(sc);
  303                 ifp->if_flags |= temp;
  304                 err = 0;
  305                 break;
  306         case SIOCGIFMEDIA:
  307         case SIOCSIFMEDIA:
  308                 ifr = (struct ifreq *) data;
  309                 err = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
  310                 break;
  311         default:
  312                 err = ether_ioctl(ifp, cmd, data);
  313                 break;
  314         }
  315         splx(s);
  316         return (err);
  317 }
  318 
  319 /*
  320  * Encapsulate a packet of type family for the local net.
  321  */
  322 hide void
  323 sncstart(ifp)
  324         struct ifnet *ifp;
  325 {
  326         struct snc_softc        *sc = ifp->if_softc;
  327         struct mbuf     *m;
  328         int             mtd_next;
  329 
  330         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  331                 return;
  332 
  333 outloop:
  334         /* Check for room in the xmit buffer. */
  335         if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
  336                 mtd_next = 0;
  337 
  338         if (mtd_next == sc->mtd_hw) {
  339                 ifp->if_flags |= IFF_OACTIVE;
  340                 return;
  341         }
  342 
  343         IF_DEQUEUE(&ifp->if_snd, m);
  344         if (m == 0)
  345                 return;
  346 
  347         /* We need the header for m_pkthdr.len. */
  348         if ((m->m_flags & M_PKTHDR) == 0)
  349                 panic("%s: sncstart: no header mbuf",
  350                       device_get_nameunit(sc->sc_dev));
  351 
  352         /*
  353          * If bpf is listening on this interface, let it
  354          * see the packet before we commit it to the wire.
  355          */
  356         BPF_MTAP(ifp, m);
  357 
  358         /*
  359          * If there is nothing in the o/p queue, and there is room in
  360          * the Tx ring, then send the packet directly.  Otherwise append
  361          * it to the o/p queue.
  362          */
  363         if ((sonicput(sc, m, mtd_next)) == 0) {
  364                 IF_PREPEND(&ifp->if_snd, m);
  365                 return;
  366         }
  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 = splnet();
  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 = splnet();
  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         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
  674                 if (ifma->ifma_addr->sa_family != AF_LINK)
  675                         continue;
  676                 if (mcount == MAXCAM) {
  677                          ifp->if_flags |= IFF_ALLMULTI;
  678                          break;
  679                 }
  680 
  681                 /* program the CAM with the specified entry */
  682                 camentry(sc, mcount,
  683                          LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
  684                 mcount++;
  685         }
  686 
  687         NIC_PUT(sc, SNCR_CDP, LOWER(sc->v_cda));
  688         NIC_PUT(sc, SNCR_CDC, MAXCAM);
  689         NIC_PUT(sc, SNCR_CR, CR_LCAM);
  690         wbflush();
  691 
  692         timeout = 10000;
  693         while ((NIC_GET(sc, SNCR_CR) & CR_LCAM) && timeout--)
  694                 continue;
  695         if (timeout == 0) {
  696                 /* XXX */
  697                 panic("%s: CAM initialisation failed\n",
  698                       device_get_nameunit(sc->sc_dev));
  699         }
  700         timeout = 10000;
  701         while (((NIC_GET(sc, SNCR_ISR) & ISR_LCD) == 0) && timeout--)
  702                 continue;
  703 
  704         if (NIC_GET(sc, SNCR_ISR) & ISR_LCD)
  705                 NIC_PUT(sc, SNCR_ISR, ISR_LCD);
  706         else
  707                 device_printf(sc->sc_dev,
  708                               "CAM initialisation without interrupt\n");
  709 }
  710 
  711 #ifdef SNCDEBUG
  712 hide void
  713 camdump(sc)
  714         struct snc_softc *sc;
  715 {
  716         int     i;
  717 
  718         printf("CAM entries:\n");
  719         NIC_PUT(sc, SNCR_CR, CR_RST);
  720         wbflush();
  721 
  722         for (i = 0; i < 16; i++) {
  723                 ushort  ap2, ap1, ap0;
  724                 NIC_PUT(sc, SNCR_CEP, i);
  725                 wbflush();
  726                 ap2 = NIC_GET(sc, SNCR_CAP2);
  727                 ap1 = NIC_GET(sc, SNCR_CAP1);
  728                 ap0 = NIC_GET(sc, SNCR_CAP0);
  729                 printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
  730         }
  731         printf("CAM enable 0x%x\n", NIC_GET(sc, SNCR_CEP));
  732 
  733         NIC_PUT(sc, SNCR_CR, 0);
  734         wbflush();
  735 }
  736 #endif
  737 
  738 hide void
  739 initialise_tda(sc)
  740         struct snc_softc *sc;
  741 {
  742         struct mtd *mtd;
  743         int     i;
  744 
  745         for (i = 0; i < NTDA; i++) {
  746                 mtd = &sc->mtda[i];
  747                 mtd->mtd_mbuf = 0;
  748         }
  749 
  750         sc->mtd_hw = 0;
  751         sc->mtd_prev = NTDA - 1;
  752         sc->mtd_free = 0;
  753         sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
  754         sc->mtd_pint = NTDA/2;
  755 
  756         NIC_PUT(sc, SNCR_UTDA, UPPER(sc->mtda[0].mtd_vtxp));
  757         NIC_PUT(sc, SNCR_CTDA, LOWER(sc->mtda[0].mtd_vtxp));
  758 }
  759 
  760 hide void
  761 initialise_rda(sc)
  762         struct snc_softc *sc;
  763 {
  764         int             i;
  765         u_int32_t       vv_rda = 0;
  766         u_int32_t       v_rda = 0;
  767 
  768         /* link the RDA's together into a circular list */
  769         for (i = 0; i < (sc->sc_nrda - 1); i++) {
  770                 v_rda = sc->v_rda + (i * RXPKT_SIZE(sc));
  771                 vv_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc));
  772                 SWO(sc, v_rda, RXPKT_RLINK, LOWER(vv_rda));
  773                 SWO(sc, v_rda, RXPKT_INUSE, 1);
  774         }
  775         v_rda = sc->v_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc));
  776         SWO(sc, v_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL);
  777         SWO(sc, v_rda, RXPKT_INUSE, 1);
  778 
  779         /* mark end of receive descriptor list */
  780         sc->sc_rdamark = sc->sc_nrda - 1;
  781 
  782         sc->sc_rxmark = 0;
  783 
  784         NIC_PUT(sc, SNCR_URDA, UPPER(sc->v_rda));
  785         NIC_PUT(sc, SNCR_CRDA, LOWER(sc->v_rda));
  786         wbflush();
  787 }
  788 
  789 hide void
  790 initialise_rra(sc)
  791         struct snc_softc *sc;
  792 {
  793         int     i;
  794         u_int   v;
  795         int     bitmode = sc->bitmode;
  796 
  797         if (bitmode)
  798                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 2);
  799         else
  800                 NIC_PUT(sc, SNCR_EOBC, RBASIZE(sc) / 2 - 1);
  801 
  802         NIC_PUT(sc, SNCR_URRA, UPPER(sc->v_rra[0]));
  803         NIC_PUT(sc, SNCR_RSA, LOWER(sc->v_rra[0]));
  804         /* rea must point just past the end of the rra space */
  805         NIC_PUT(sc, SNCR_REA, LOWER(sc->v_rea));
  806         NIC_PUT(sc, SNCR_RRP, LOWER(sc->v_rra[0]));
  807         NIC_PUT(sc, SNCR_RSC, 0);
  808 
  809         /* fill up SOME of the rra with buffers */
  810         for (i = 0; i < NRBA; i++) {
  811                 v = SONIC_GETDMA(sc->rbuf[i]);
  812                 SWO(sc, sc->v_rra[i], RXRSRC_PTRHI, UPPER(v));
  813                 SWO(sc, sc->v_rra[i], RXRSRC_PTRLO, LOWER(v));
  814                 SWO(sc, sc->v_rra[i], RXRSRC_WCHI, UPPER(NBPG/2));
  815                 SWO(sc, sc->v_rra[i], RXRSRC_WCLO, LOWER(NBPG/2));
  816         }
  817         sc->sc_rramark = NRBA;
  818         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[sc->sc_rramark]));
  819         wbflush();
  820 }
  821 
  822 void
  823 sncintr(arg)
  824         void    *arg;
  825 {
  826         struct snc_softc *sc = (struct snc_softc *)arg;
  827         int     isr;
  828 
  829         if (sc->sc_enabled == 0)
  830                 return;
  831 
  832         while ((isr = (NIC_GET(sc, SNCR_ISR) & ISR_ALL)) != 0) {
  833                 /* scrub the interrupts that we are going to service */
  834                 NIC_PUT(sc, SNCR_ISR, isr);
  835                 wbflush();
  836 
  837                 if (isr & (ISR_BR | ISR_LCD | ISR_TC))
  838                         device_printf(sc->sc_dev,
  839                                       "unexpected interrupt status 0x%x\n",
  840                                       isr);
  841 
  842                 if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
  843                         sonictxint(sc);
  844 
  845                 if (isr & ISR_PKTRX)
  846                         sonicrxint(sc);
  847 
  848                 if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
  849                         if (isr & ISR_HBL)
  850                                 /*
  851                                  * The repeater is not providing a heartbeat.
  852                                  * In itself this isn't harmful, lots of the
  853                                  * cheap repeater hubs don't supply a heartbeat.
  854                                  * So ignore the lack of heartbeat. Its only
  855                                  * if we can't detect a carrier that we have a
  856                                  * problem.
  857                                  */
  858                                 ;
  859                         if (isr & ISR_RDE)
  860                                 device_printf(sc->sc_dev, 
  861                                         "receive descriptors exhausted\n");
  862                         if (isr & ISR_RBE)
  863                                 device_printf(sc->sc_dev, 
  864                                         "receive buffers exhausted\n");
  865                         if (isr & ISR_RBAE)
  866                                 device_printf(sc->sc_dev, 
  867                                         "receive buffer area exhausted\n");
  868                         if (isr & ISR_RFO)
  869                                 device_printf(sc->sc_dev, 
  870                                         "receive FIFO overrun\n");
  871                 }
  872                 if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
  873 #ifdef notdef
  874                         if (isr & ISR_CRC)
  875                                 sc->sc_crctally++;
  876                         if (isr & ISR_FAE)
  877                                 sc->sc_faetally++;
  878                         if (isr & ISR_MP)
  879                                 sc->sc_mptally++;
  880 #endif
  881                 }
  882                 sncstart(&sc->sc_if);
  883 
  884 #if NRND > 0
  885                 if (isr)
  886                         rnd_add_uint32(&sc->rnd_source, isr);
  887 #endif
  888         }
  889         return;
  890 }
  891 
  892 /*
  893  * Transmit interrupt routine
  894  */
  895 hide void
  896 sonictxint(sc)
  897         struct snc_softc *sc;
  898 {
  899         struct mtd      *mtd;
  900         u_int32_t       txp;
  901         unsigned short  txp_status;
  902         int             mtd_hw;
  903         struct ifnet    *ifp = &sc->sc_if;
  904 
  905         mtd_hw = sc->mtd_hw;
  906 
  907         if (mtd_hw == sc->mtd_free)
  908                 return;
  909 
  910         while (mtd_hw != sc->mtd_free) {
  911                 mtd = &sc->mtda[mtd_hw];
  912 
  913                 txp = mtd->mtd_vtxp;
  914 
  915                 if (SRO(sc, txp, TXP_STATUS) == 0) {
  916                         break; /* it hasn't really gone yet */
  917                 }
  918 
  919 #ifdef SNCDEBUG
  920                 if ((sncdebug & SNC_SHOWTXHDR) != 0)
  921                 {
  922                         struct ether_header eh;
  923 
  924                         (*sc->sc_copyfrombuf)(sc, &eh, mtd->mtd_vbuf, sizeof(eh));
  925                         device_printf(sc->sc_dev,
  926                             "xmit status=0x%x len=%d type=0x%x from %6D",
  927                             SRO(sc, txp, TXP_STATUS),
  928                             SRO(sc, txp, TXP_PKTSIZE),
  929                             htons(eh.ether_type),
  930                             eh.ether_shost, ":");
  931                         printf(" (to %6D)\n", eh.ether_dhost, ":");
  932                 }
  933 #endif /* SNCDEBUG */
  934 
  935                 ifp->if_flags &= ~IFF_OACTIVE;
  936 
  937                 if (mtd->mtd_mbuf != 0) {
  938                         m_freem(mtd->mtd_mbuf);
  939                         mtd->mtd_mbuf = 0;
  940                 }
  941                 if (++mtd_hw == NTDA) mtd_hw = 0;
  942 
  943                 txp_status = SRO(sc, txp, TXP_STATUS);
  944 
  945                 ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
  946                         ((txp_status & TCR_NC) >> 12);
  947 
  948                 if ((txp_status & TCR_PTX) == 0) {
  949                         ifp->if_oerrors++;
  950                         device_printf(sc->sc_dev, "Tx packet status=0x%x\n",
  951                                       txp_status);
  952                         
  953                         /* XXX - DG This looks bogus */
  954                         if (mtd_hw != sc->mtd_free) {
  955                                 printf("resubmitting remaining packets\n");
  956                                 mtd = &sc->mtda[mtd_hw];
  957                                 NIC_PUT(sc, SNCR_CTDA, LOWER(mtd->mtd_vtxp));
  958                                 NIC_PUT(sc, SNCR_CR, CR_TXP);
  959                                 wbflush();
  960                                 break;
  961                         }
  962                 }
  963         }
  964 
  965         sc->mtd_hw = mtd_hw;
  966         return;
  967 }
  968 
  969 /*
  970  * Receive interrupt routine
  971  */
  972 hide void
  973 sonicrxint(sc)
  974         struct snc_softc *sc;
  975 {
  976         u_int32_t rda;
  977         int     orra;
  978         int     len;
  979         int     rramark;
  980         int     rdamark;
  981         u_int16_t rxpkt_ptr;
  982 
  983         rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
  984 
  985         while (SRO(sc, rda, RXPKT_INUSE) == 0) {
  986                 u_int status = SRO(sc, rda, RXPKT_STATUS);
  987 
  988                 orra = RBASEQ(SRO(sc, rda, RXPKT_SEQNO)) & RRAMASK;
  989                 rxpkt_ptr = SRO(sc, rda, RXPKT_PTRLO);
  990                 /*
  991                  * Do not trunc ether_header length.
  992                  * Our sonic_read() and sonic_get() require it.
  993                  */
  994                 len = SRO(sc, rda, RXPKT_BYTEC) - FCSSIZE;
  995                 if (status & RCR_PRX) {
  996                         /* XXX: Does PGOFSET require? */
  997                         u_int32_t pkt =
  998                             sc->rbuf[orra & RBAMASK] + (rxpkt_ptr & PGOFSET);
  999                         if (sonic_read(sc, pkt, len))
 1000                                 sc->sc_if.if_ipackets++;
 1001                         else
 1002                                 sc->sc_if.if_ierrors++;
 1003                 } else
 1004                         sc->sc_if.if_ierrors++;
 1005 
 1006                 /*
 1007                  * give receive buffer area back to chip.
 1008                  *
 1009                  * If this was the last packet in the RRA, give the RRA to
 1010                  * the chip again.
 1011                  * If sonic read didnt copy it out then we would have to
 1012                  * wait !!
 1013                  * (dont bother add it back in again straight away)
 1014                  *
 1015                  * Really, we're doing v_rra[rramark] = v_rra[orra] but
 1016                  * we have to use the macros because SONIC might be in
 1017                  * 16 or 32 bit mode.
 1018                  */
 1019                 if (status & RCR_LPKT) {
 1020                         u_int32_t tmp1, tmp2;
 1021 
 1022                         rramark = sc->sc_rramark;
 1023                         tmp1 = sc->v_rra[rramark];
 1024                         tmp2 = sc->v_rra[orra];
 1025                         SWO(sc, tmp1, RXRSRC_PTRLO,
 1026                                 SRO(sc, tmp2, RXRSRC_PTRLO));
 1027                         SWO(sc, tmp1, RXRSRC_PTRHI,
 1028                                 SRO(sc, tmp2, RXRSRC_PTRHI));
 1029                         SWO(sc, tmp1, RXRSRC_WCLO,
 1030                                 SRO(sc, tmp2, RXRSRC_WCLO));
 1031                         SWO(sc, tmp1, RXRSRC_WCHI,
 1032                                 SRO(sc, tmp2, RXRSRC_WCHI));
 1033 
 1034                         /* zap old rra for fun */
 1035                         SWO(sc, tmp2, RXRSRC_WCHI, 0);
 1036                         SWO(sc, tmp2, RXRSRC_WCLO, 0);
 1037 
 1038                         sc->sc_rramark = (++rramark) & RRAMASK;
 1039                         NIC_PUT(sc, SNCR_RWP, LOWER(sc->v_rra[rramark]));
 1040                         wbflush();
 1041                 }
 1042 
 1043                 /*
 1044                  * give receive descriptor back to chip simple
 1045                  * list is circular
 1046                  */
 1047                 rdamark = sc->sc_rdamark;
 1048                 SWO(sc, rda, RXPKT_INUSE, 1);
 1049                 SWO(sc, rda, RXPKT_RLINK,
 1050                         SRO(sc, rda, RXPKT_RLINK) | EOL);
 1051                 SWO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
 1052                         SRO(sc, (sc->v_rda + (rdamark * RXPKT_SIZE(sc))),
 1053                         RXPKT_RLINK) & ~EOL);
 1054                 sc->sc_rdamark = sc->sc_rxmark;
 1055 
 1056                 if (++sc->sc_rxmark >= sc->sc_nrda)
 1057                         sc->sc_rxmark = 0;
 1058                 rda = sc->v_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
 1059         }
 1060 }
 1061 
 1062 /*
 1063  * sonic_read -- pull packet off interface and forward to
 1064  * appropriate protocol handler
 1065  */
 1066 hide int
 1067 sonic_read(sc, pkt, len)
 1068         struct snc_softc *sc;
 1069         u_int32_t pkt;
 1070         int len;
 1071 {
 1072         struct ifnet *ifp = &sc->sc_if;
 1073         struct ether_header *et;
 1074         struct mbuf *m;
 1075 
 1076         if (len <= sizeof(struct ether_header) ||
 1077             len > ETHERMTU + sizeof(struct ether_header)) {
 1078                 device_printf(sc->sc_dev,
 1079                               "invalid packet length %d bytes\n", len);
 1080                 return (0);
 1081         }
 1082 
 1083         /* Pull packet off interface. */
 1084         m = sonic_get(sc, pkt, len);
 1085         if (m == 0) {
 1086                 return (0);
 1087         }
 1088 
 1089         /* We assume that the header fit entirely in one mbuf. */
 1090         et = mtod(m, struct ether_header *);
 1091 
 1092 #ifdef SNCDEBUG
 1093         if ((sncdebug & SNC_SHOWRXHDR) != 0)
 1094         {
 1095                 device_printf(sc->sc_dev, "rcvd 0x%x len=%d type=0x%x from %6D",
 1096                     pkt, len, htons(et->ether_type),
 1097                     et->ether_shost, ":");
 1098                 printf(" (to %6D)\n", et->ether_dhost, ":");
 1099         }
 1100 #endif /* SNCDEBUG */
 1101 
 1102         /* Pass the packet up. */
 1103         (*ifp->if_input)(ifp, m);
 1104         return (1);
 1105 }
 1106 
 1107 
 1108 /*
 1109  * munge the received packet into an mbuf chain
 1110  */
 1111 hide struct mbuf *
 1112 sonic_get(sc, pkt, datalen)
 1113         struct snc_softc *sc;
 1114         u_int32_t pkt;
 1115         int datalen;
 1116 {
 1117         struct  mbuf *m, *top, **mp;
 1118         int     len;
 1119         /*
 1120          * Do not trunc ether_header length.
 1121          * Our sonic_read() and sonic_get() require it.
 1122          */
 1123 
 1124         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1125         if (m == 0)
 1126                 return (0);
 1127         m->m_pkthdr.rcvif = &sc->sc_if;
 1128         m->m_pkthdr.len = datalen;
 1129         len = MHLEN;
 1130         top = 0;
 1131         mp = &top;
 1132 
 1133         while (datalen > 0) {
 1134                 if (top) {
 1135                         MGET(m, M_DONTWAIT, MT_DATA);
 1136                         if (m == 0) {
 1137                                 m_freem(top);
 1138                                 return (0);
 1139                         }
 1140                         len = MLEN;
 1141                 }
 1142                 if (datalen >= MINCLSIZE) {
 1143                         MCLGET(m, M_DONTWAIT);
 1144                         if ((m->m_flags & M_EXT) == 0) {
 1145                                 if (top) m_freem(top);
 1146                                 return (0);
 1147                         }
 1148                         len = MCLBYTES;
 1149                 }
 1150 #if 0
 1151                 /* XXX: Require? */
 1152                 if (!top) {
 1153                         register int pad =
 1154                             ALIGN(sizeof(struct ether_header)) -
 1155                                 sizeof(struct ether_header);
 1156                         m->m_data += pad;
 1157                         len -= pad;
 1158                 }
 1159 #endif
 1160                 m->m_len = len = min(datalen, len);
 1161 
 1162                 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), pkt, len);
 1163                 pkt += len;
 1164                 datalen -= len;
 1165                 *mp = m;
 1166                 mp = &m->m_next;
 1167         }
 1168 
 1169         return (top);
 1170 }
 1171 /*
 1172  * Enable power on the interface.
 1173  */
 1174 int
 1175 snc_enable(sc)
 1176         struct snc_softc *sc;
 1177 {
 1178 
 1179 #ifdef  SNCDEBUG
 1180         device_printf(sc->sc_dev, "snc_enable()\n");
 1181 #endif  /* SNCDEBUG */
 1182 
 1183         if (sc->sc_enabled == 0 && sc->sc_enable != NULL) {
 1184                 if ((*sc->sc_enable)(sc) != 0) {
 1185                         device_printf(sc->sc_dev, "device enable failed\n");
 1186                         return (EIO);
 1187                 }
 1188         }
 1189 
 1190         sc->sc_enabled = 1;
 1191         return (0);
 1192 }
 1193 
 1194 /*
 1195  * Disable power on the interface.
 1196  */
 1197 void
 1198 snc_disable(sc)
 1199         struct snc_softc *sc;
 1200 {
 1201 
 1202 #ifdef  SNCDEBUG
 1203         device_printf(sc->sc_dev, "snc_disable()\n");
 1204 #endif  /* SNCDEBUG */
 1205 
 1206         if (sc->sc_enabled != 0 && sc->sc_disable != NULL) {
 1207                 (*sc->sc_disable)(sc);
 1208                 sc->sc_enabled = 0;
 1209         }
 1210 }
 1211 
 1212 

Cache object: ed9caea9d2b85997799ec8f706693e07


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