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

Cache object: ed416c0ef4081fc624b052c45ef0e7e8


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