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

Cache object: 9d6f550e7087d7a734c65e8bdc5cbd73


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