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

Cache object: 45bfa8f00bc63bdc7a08820d29f5b7d1


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