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

Cache object: 0fa5ed6abdc065167c60d7af2beb9829


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