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/ic/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 /*      $NetBSD: dp83932.c,v 1.13 2005/12/11 12:21:26 christos Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Device driver for the National Semiconductor DP83932
   41  * Systems-Oriented Network Interface Controller (SONIC).
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: dp83932.c,v 1.13 2005/12/11 12:21:26 christos Exp $");
   46 
   47 #include "bpfilter.h"
   48 
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/mbuf.h>
   52 #include <sys/malloc.h>
   53 #include <sys/kernel.h>
   54 #include <sys/socket.h>
   55 #include <sys/ioctl.h>
   56 #include <sys/errno.h>
   57 #include <sys/device.h>
   58 
   59 #include <uvm/uvm_extern.h>
   60 
   61 #include <net/if.h>
   62 #include <net/if_dl.h>
   63 #include <net/if_ether.h>
   64 
   65 #if NBPFILTER > 0
   66 #include <net/bpf.h>
   67 #endif
   68 
   69 #include <machine/bus.h>
   70 #include <machine/intr.h>
   71 
   72 #include <dev/ic/dp83932reg.h>
   73 #include <dev/ic/dp83932var.h>
   74 
   75 void    sonic_start(struct ifnet *);
   76 void    sonic_watchdog(struct ifnet *);
   77 int     sonic_ioctl(struct ifnet *, u_long, caddr_t);
   78 int     sonic_init(struct ifnet *);
   79 void    sonic_stop(struct ifnet *, int);
   80 
   81 void    sonic_shutdown(void *);
   82 
   83 void    sonic_reset(struct sonic_softc *);
   84 void    sonic_rxdrain(struct sonic_softc *);
   85 int     sonic_add_rxbuf(struct sonic_softc *, int);
   86 void    sonic_set_filter(struct sonic_softc *);
   87 
   88 uint16_t sonic_txintr(struct sonic_softc *);
   89 void    sonic_rxintr(struct sonic_softc *);
   90 
   91 int     sonic_copy_small = 0;
   92 
   93 #define ETHER_PAD_LEN (ETHER_MIN_LEN - ETHER_CRC_LEN)
   94 
   95 /*
   96  * sonic_attach:
   97  *
   98  *      Attach a SONIC interface to the system.
   99  */
  100 void
  101 sonic_attach(struct sonic_softc *sc, const uint8_t *enaddr)
  102 {
  103         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  104         int i, rseg, error;
  105         bus_dma_segment_t seg;
  106         size_t cdatasize;
  107         char *nullbuf;
  108 
  109         /*
  110          * Allocate the control data structures, and create and load the
  111          * DMA map for it.
  112          */
  113         if (sc->sc_32bit)
  114                 cdatasize = sizeof(struct sonic_control_data32);
  115         else
  116                 cdatasize = sizeof(struct sonic_control_data16);
  117 
  118         if ((error = bus_dmamem_alloc(sc->sc_dmat, cdatasize + ETHER_PAD_LEN,
  119              PAGE_SIZE, (64 * 1024), &seg, 1, &rseg,
  120              BUS_DMA_NOWAIT)) != 0) {
  121                 printf("%s: unable to allocate control data, error = %d\n",
  122                     sc->sc_dev.dv_xname, error);
  123                 goto fail_0;
  124         }
  125 
  126         if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
  127             cdatasize + ETHER_PAD_LEN, (caddr_t *) &sc->sc_cdata16,
  128             BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
  129                 printf("%s: unable to map control data, error = %d\n",
  130                     sc->sc_dev.dv_xname, error);
  131                 goto fail_1;
  132         }
  133         nullbuf = (char *)sc->sc_cdata16 + cdatasize;
  134         memset(nullbuf, 0, ETHER_PAD_LEN);
  135 
  136         if ((error = bus_dmamap_create(sc->sc_dmat,
  137              cdatasize, 1, cdatasize, 0, BUS_DMA_NOWAIT,
  138              &sc->sc_cddmamap)) != 0) {
  139                 printf("%s: unable to create control data DMA map, "
  140                     "error = %d\n", sc->sc_dev.dv_xname, error);
  141                 goto fail_2;
  142         }
  143 
  144         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
  145              sc->sc_cdata16, cdatasize, NULL, BUS_DMA_NOWAIT)) != 0) {
  146                 printf("%s: unable to load control data DMA map, error = %d\n",
  147                     sc->sc_dev.dv_xname, error);
  148                 goto fail_3;
  149         }
  150 
  151         /*
  152          * Create the transmit buffer DMA maps.
  153          */
  154         for (i = 0; i < SONIC_NTXDESC; i++) {
  155                 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
  156                      SONIC_NTXFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
  157                      &sc->sc_txsoft[i].ds_dmamap)) != 0) {
  158                         printf("%s: unable to create tx DMA map %d, "
  159                             "error = %d\n", sc->sc_dev.dv_xname, i, error);
  160                         goto fail_4;
  161                 }
  162         }
  163 
  164         /*
  165          * Create the receive buffer DMA maps.
  166          */
  167         for (i = 0; i < SONIC_NRXDESC; i++) {
  168                 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
  169                      MCLBYTES, 0, BUS_DMA_NOWAIT,
  170                      &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
  171                         printf("%s: unable to create rx DMA map %d, "
  172                             "error = %d\n", sc->sc_dev.dv_xname, i, error);
  173                         goto fail_5;
  174                 }
  175                 sc->sc_rxsoft[i].ds_mbuf = NULL;
  176         }
  177 
  178         /*
  179          * create and map the pad buffer
  180          */
  181         if ((error = bus_dmamap_create(sc->sc_dmat, ETHER_PAD_LEN, 1,
  182             ETHER_PAD_LEN, 0, BUS_DMA_NOWAIT, &sc->sc_nulldmamap)) != 0) {
  183                 printf("%s: unable to create pad buffer DMA map, "
  184                     "error = %d\n", sc->sc_dev.dv_xname, error);
  185                 goto fail_5;
  186         }
  187 
  188         if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_nulldmamap,
  189             nullbuf, ETHER_PAD_LEN, NULL, BUS_DMA_NOWAIT)) != 0) {
  190                 printf("%s: unable to load pad buffer DMA map, "
  191                     "error = %d\n", sc->sc_dev.dv_xname, error);
  192                 goto fail_6;
  193         }
  194         bus_dmamap_sync(sc->sc_dmat, sc->sc_nulldmamap, 0, ETHER_PAD_LEN,
  195             BUS_DMASYNC_PREWRITE);
  196 
  197         /*
  198          * Reset the chip to a known state.
  199          */
  200         sonic_reset(sc);
  201 
  202         printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
  203             ether_sprintf(enaddr));
  204 
  205         strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
  206         ifp->if_softc = sc;
  207         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
  208         ifp->if_ioctl = sonic_ioctl;
  209         ifp->if_start = sonic_start;
  210         ifp->if_watchdog = sonic_watchdog;
  211         ifp->if_init = sonic_init;
  212         ifp->if_stop = sonic_stop;
  213         IFQ_SET_READY(&ifp->if_snd);
  214 
  215         /*
  216          * Attach the interface.
  217          */
  218         if_attach(ifp);
  219         ether_ifattach(ifp, enaddr);
  220 
  221         /*
  222          * Make sure the interface is shutdown during reboot.
  223          */
  224         sc->sc_sdhook = shutdownhook_establish(sonic_shutdown, sc);
  225         if (sc->sc_sdhook == NULL)
  226                 printf("%s: WARNING: unable to establish shutdown hook\n",
  227                     sc->sc_dev.dv_xname);
  228         return;
  229 
  230         /*
  231          * Free any resources we've allocated during the failed attach
  232          * attempt.  Do this in reverse order and fall through.
  233          */
  234  fail_6:
  235         bus_dmamap_destroy(sc->sc_dmat, sc->sc_nulldmamap);
  236  fail_5:
  237         for (i = 0; i < SONIC_NRXDESC; i++) {
  238                 if (sc->sc_rxsoft[i].ds_dmamap != NULL)
  239                         bus_dmamap_destroy(sc->sc_dmat,
  240                             sc->sc_rxsoft[i].ds_dmamap);
  241         }
  242  fail_4:
  243         for (i = 0; i < SONIC_NTXDESC; i++) {
  244                 if (sc->sc_txsoft[i].ds_dmamap != NULL)
  245                         bus_dmamap_destroy(sc->sc_dmat,
  246                             sc->sc_txsoft[i].ds_dmamap);
  247         }
  248         bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
  249  fail_3:
  250         bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
  251  fail_2:
  252         bus_dmamem_unmap(sc->sc_dmat, (caddr_t) sc->sc_cdata16, cdatasize);
  253  fail_1:
  254         bus_dmamem_free(sc->sc_dmat, &seg, rseg);
  255  fail_0:
  256         return;
  257 }
  258 
  259 /*
  260  * sonic_shutdown:
  261  *
  262  *      Make sure the interface is stopped at reboot.
  263  */
  264 void
  265 sonic_shutdown(void *arg)
  266 {
  267         struct sonic_softc *sc = arg;
  268 
  269         sonic_stop(&sc->sc_ethercom.ec_if, 1);
  270 }
  271 
  272 /*
  273  * sonic_start:         [ifnet interface function]
  274  *
  275  *      Start packet transmission on the interface.
  276  */
  277 void
  278 sonic_start(struct ifnet *ifp)
  279 {
  280         struct sonic_softc *sc = ifp->if_softc;
  281         struct mbuf *m0, *m;
  282         struct sonic_tda16 *tda16;
  283         struct sonic_tda32 *tda32;
  284         struct sonic_descsoft *ds;
  285         bus_dmamap_t dmamap;
  286         int error, olasttx, nexttx, opending, totlen, olseg;
  287         int seg = 0;    /* XXX: gcc */
  288 
  289         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  290                 return;
  291 
  292         /*
  293          * Remember the previous txpending and the current "last txdesc
  294          * used" index.
  295          */
  296         opending = sc->sc_txpending;
  297         olasttx = sc->sc_txlast;
  298 
  299         /*
  300          * Loop through the send queue, setting up transmit descriptors
  301          * until we drain the queue, or use up all available transmit
  302          * descriptors.  Leave one at the end for sanity's sake.
  303          */
  304         while (sc->sc_txpending < (SONIC_NTXDESC - 1)) {
  305                 /*
  306                  * Grab a packet off the queue.
  307                  */
  308                 IFQ_POLL(&ifp->if_snd, m0);
  309                 if (m0 == NULL)
  310                         break;
  311                 m = NULL;
  312 
  313                 /*
  314                  * Get the next available transmit descriptor.
  315                  */
  316                 nexttx = SONIC_NEXTTX(sc->sc_txlast);
  317                 ds = &sc->sc_txsoft[nexttx];
  318                 dmamap = ds->ds_dmamap;
  319 
  320                 /*
  321                  * Load the DMA map.  If this fails, the packet either
  322                  * didn't fit in the allotted number of frags, or we were
  323                  * short on resources.  In this case, we'll copy and try
  324                  * again.
  325                  */
  326                 if ((error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
  327                     BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 ||
  328                     (m0->m_pkthdr.len < ETHER_PAD_LEN &&
  329                     dmamap->dm_nsegs == SONIC_NTXFRAGS)) {
  330                         if (error == 0)
  331                                 bus_dmamap_unload(sc->sc_dmat, dmamap);
  332                         MGETHDR(m, M_DONTWAIT, MT_DATA);
  333                         if (m == NULL) {
  334                                 printf("%s: unable to allocate Tx mbuf\n",
  335                                     sc->sc_dev.dv_xname);
  336                                 break;
  337                         }
  338                         if (m0->m_pkthdr.len > MHLEN) {
  339                                 MCLGET(m, M_DONTWAIT);
  340                                 if ((m->m_flags & M_EXT) == 0) {
  341                                         printf("%s: unable to allocate Tx "
  342                                             "cluster\n", sc->sc_dev.dv_xname);
  343                                         m_freem(m);
  344                                         break;
  345                                 }
  346                         }
  347                         m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
  348                         m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
  349                         error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
  350                             m, BUS_DMA_WRITE|BUS_DMA_NOWAIT);
  351                         if (error) {
  352                                 printf("%s: unable to load Tx buffer, "
  353                                     "error = %d\n", sc->sc_dev.dv_xname, error);
  354                                 m_freem(m);
  355                                 break;
  356                         }
  357                 }
  358                 IFQ_DEQUEUE(&ifp->if_snd, m0);
  359                 if (m != NULL) {
  360                         m_freem(m0);
  361                         m0 = m;
  362                 }
  363 
  364                 /*
  365                  * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET.
  366                  */
  367 
  368                 /* Sync the DMA map. */
  369                 bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
  370                     BUS_DMASYNC_PREWRITE);
  371 
  372                 /*
  373                  * Store a pointer to the packet so we can free it later.
  374                  */
  375                 ds->ds_mbuf = m0;
  376 
  377                 /*
  378                  * Initialize the transmit descriptor.
  379                  */
  380                 totlen = 0;
  381                 if (sc->sc_32bit) {
  382                         tda32 = &sc->sc_tda32[nexttx];
  383                         for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
  384                                 tda32->tda_frags[seg].frag_ptr1 =
  385                                     htosonic32(sc,
  386                                     (dmamap->dm_segs[seg].ds_addr >> 16) &
  387                                     0xffff);
  388                                 tda32->tda_frags[seg].frag_ptr0 =
  389                                     htosonic32(sc,
  390                                     dmamap->dm_segs[seg].ds_addr & 0xffff);
  391                                 tda32->tda_frags[seg].frag_size =
  392                                     htosonic32(sc, dmamap->dm_segs[seg].ds_len);
  393                                 totlen += dmamap->dm_segs[seg].ds_len;
  394                         }
  395                         if (totlen < ETHER_PAD_LEN) {
  396                                 tda32->tda_frags[seg].frag_ptr1 =
  397                                     htosonic32(sc,
  398                                     (sc->sc_nulldma >> 16) & 0xffff);
  399                                 tda32->tda_frags[seg].frag_ptr0 =
  400                                     htosonic32(sc, sc->sc_nulldma & 0xffff);
  401                                 tda32->tda_frags[seg].frag_size =
  402                                     htosonic32(sc, ETHER_PAD_LEN - totlen);
  403                                 totlen = ETHER_PAD_LEN;
  404                                 seg++;
  405                         }
  406 
  407                         tda32->tda_status = 0;
  408                         tda32->tda_pktconfig = 0;
  409                         tda32->tda_pktsize = htosonic32(sc, totlen);
  410                         tda32->tda_fragcnt = htosonic32(sc, seg);
  411 
  412                         /* Link it up. */
  413                         tda32->tda_frags[seg].frag_ptr0 =
  414                             htosonic32(sc, SONIC_CDTXADDR32(sc,
  415                             SONIC_NEXTTX(nexttx)) & 0xffff);
  416 
  417                         /* Sync the Tx descriptor. */
  418                         SONIC_CDTXSYNC32(sc, nexttx,
  419                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  420                 } else {
  421                         tda16 = &sc->sc_tda16[nexttx];
  422                         for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
  423                                 tda16->tda_frags[seg].frag_ptr1 =
  424                                     htosonic16(sc,
  425                                     (dmamap->dm_segs[seg].ds_addr >> 16) &
  426                                     0xffff);
  427                                 tda16->tda_frags[seg].frag_ptr0 =
  428                                     htosonic16(sc,
  429                                     dmamap->dm_segs[seg].ds_addr & 0xffff);
  430                                 tda16->tda_frags[seg].frag_size =
  431                                     htosonic16(sc, dmamap->dm_segs[seg].ds_len);
  432                                 totlen += dmamap->dm_segs[seg].ds_len;
  433                         }
  434                         if (totlen < ETHER_PAD_LEN) {
  435                                 tda16->tda_frags[seg].frag_ptr1 =
  436                                     htosonic16(sc,
  437                                     (sc->sc_nulldma >> 16) & 0xffff);
  438                                 tda16->tda_frags[seg].frag_ptr0 =
  439                                     htosonic16(sc, sc->sc_nulldma & 0xffff);
  440                                 tda16->tda_frags[seg].frag_size =
  441                                     htosonic16(sc, ETHER_PAD_LEN - totlen);
  442                                 totlen = ETHER_PAD_LEN;
  443                                 seg++;
  444                         }
  445 
  446                         tda16->tda_status = 0;
  447                         tda16->tda_pktconfig = 0;
  448                         tda16->tda_pktsize = htosonic16(sc, totlen);
  449                         tda16->tda_fragcnt = htosonic16(sc, seg);
  450 
  451                         /* Link it up. */
  452                         tda16->tda_frags[seg].frag_ptr0 =
  453                             htosonic16(sc, SONIC_CDTXADDR16(sc,
  454                             SONIC_NEXTTX(nexttx)) & 0xffff);
  455 
  456                         /* Sync the Tx descriptor. */
  457                         SONIC_CDTXSYNC16(sc, nexttx,
  458                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  459                 }
  460 
  461                 /* Advance the Tx pointer. */
  462                 sc->sc_txpending++;
  463                 sc->sc_txlast = nexttx;
  464 
  465 #if NBPFILTER > 0
  466                 /*
  467                  * Pass the packet to any BPF listeners.
  468                  */
  469                 if (ifp->if_bpf)
  470                         bpf_mtap(ifp->if_bpf, m0);
  471 #endif
  472         }
  473 
  474         if (sc->sc_txpending == (SONIC_NTXDESC - 1)) {
  475                 /* No more slots left; notify upper layer. */
  476                 ifp->if_flags |= IFF_OACTIVE;
  477         }
  478 
  479         if (sc->sc_txpending != opending) {
  480                 /*
  481                  * We enqueued packets.  If the transmitter was idle,
  482                  * reset the txdirty pointer.
  483                  */
  484                 if (opending == 0)
  485                         sc->sc_txdirty = SONIC_NEXTTX(olasttx);
  486 
  487                 /*
  488                  * Stop the SONIC on the last packet we've set up,
  489                  * and clear end-of-list on the descriptor previous
  490                  * to our new chain.
  491                  *
  492                  * NOTE: our `seg' variable should still be valid!
  493                  */
  494                 if (sc->sc_32bit) {
  495                         olseg =
  496                             sonic32toh(sc, sc->sc_tda32[olasttx].tda_fragcnt);
  497                         sc->sc_tda32[sc->sc_txlast].tda_frags[seg].frag_ptr0 |=
  498                             htosonic32(sc, TDA_LINK_EOL);
  499                         SONIC_CDTXSYNC32(sc, sc->sc_txlast,
  500                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  501                         sc->sc_tda32[olasttx].tda_frags[olseg].frag_ptr0 &=
  502                             htosonic32(sc, ~TDA_LINK_EOL);
  503                         SONIC_CDTXSYNC32(sc, olasttx,
  504                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  505                 } else {
  506                         olseg =
  507                             sonic16toh(sc, sc->sc_tda16[olasttx].tda_fragcnt);
  508                         sc->sc_tda16[sc->sc_txlast].tda_frags[seg].frag_ptr0 |=
  509                             htosonic16(sc, TDA_LINK_EOL);
  510                         SONIC_CDTXSYNC16(sc, sc->sc_txlast,
  511                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  512                         sc->sc_tda16[olasttx].tda_frags[olseg].frag_ptr0 &=
  513                             htosonic16(sc, ~TDA_LINK_EOL);
  514                         SONIC_CDTXSYNC16(sc, olasttx,
  515                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  516                 }
  517 
  518                 /* Start the transmitter. */
  519                 CSR_WRITE(sc, SONIC_CR, CR_TXP);
  520 
  521                 /* Set a watchdog timer in case the chip flakes out. */
  522                 ifp->if_timer = 5;
  523         }
  524 }
  525 
  526 /*
  527  * sonic_watchdog:      [ifnet interface function]
  528  *
  529  *      Watchdog timer handler.
  530  */
  531 void
  532 sonic_watchdog(struct ifnet *ifp)
  533 {
  534         struct sonic_softc *sc = ifp->if_softc;
  535 
  536         printf("%s: device timeout\n", sc->sc_dev.dv_xname);
  537         ifp->if_oerrors++;
  538 
  539         (void) sonic_init(ifp);
  540 }
  541 
  542 /*
  543  * sonic_ioctl:         [ifnet interface function]
  544  *
  545  *      Handle control requests from the operator.
  546  */
  547 int
  548 sonic_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  549 {
  550         int s, error;
  551 
  552         s = splnet();
  553 
  554         switch (cmd) {
  555         default:
  556                 error = ether_ioctl(ifp, cmd, data);
  557                 if (error == ENETRESET) {
  558                         /*
  559                          * Multicast list has changed; set the hardware
  560                          * filter accordingly.
  561                          */
  562                         if (ifp->if_flags & IFF_RUNNING)
  563                                 (void) sonic_init(ifp);
  564                         error = 0;
  565                 }
  566                 break;
  567         }
  568 
  569         splx(s);
  570         return (error);
  571 }
  572 
  573 /*
  574  * sonic_intr:
  575  *
  576  *      Interrupt service routine.
  577  */
  578 int
  579 sonic_intr(void *arg)
  580 {
  581         struct sonic_softc *sc = arg;
  582         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  583         uint16_t isr;
  584         int handled = 0, wantinit;
  585 
  586         for (wantinit = 0; wantinit == 0;) {
  587                 isr = CSR_READ(sc, SONIC_ISR) & sc->sc_imr;
  588                 if (isr == 0)
  589                         break;
  590                 CSR_WRITE(sc, SONIC_ISR, isr);  /* ACK */
  591 
  592                 handled = 1;
  593 
  594                 if (isr & IMR_PRX)
  595                         sonic_rxintr(sc);
  596 
  597                 if (isr & (IMR_PTX|IMR_TXER)) {
  598                         if (sonic_txintr(sc) & TCR_FU) {
  599                                 printf("%s: transmit FIFO underrun\n",
  600                                     sc->sc_dev.dv_xname);
  601                                 wantinit = 1;
  602                         }
  603                 }
  604 
  605                 if (isr & (IMR_RFO|IMR_RBA|IMR_RBE|IMR_RDE)) {
  606 #define PRINTERR(bit, str)                                              \
  607                         if (isr & (bit))                                \
  608                                 printf("%s: %s\n", sc->sc_dev.dv_xname, str)
  609                         PRINTERR(IMR_RFO, "receive FIFO overrun");
  610                         PRINTERR(IMR_RBA, "receive buffer exceeded");
  611                         PRINTERR(IMR_RBE, "receive buffers exhausted");
  612                         PRINTERR(IMR_RDE, "receive descriptors exhausted");
  613                         wantinit = 1;
  614                 }
  615         }
  616 
  617         if (handled) {
  618                 if (wantinit)
  619                         (void) sonic_init(ifp);
  620                 sonic_start(ifp);
  621         }
  622 
  623         return (handled);
  624 }
  625 
  626 /*
  627  * sonic_txintr:
  628  *
  629  *      Helper; handle transmit complete interrupts.
  630  */
  631 uint16_t
  632 sonic_txintr(struct sonic_softc *sc)
  633 {
  634         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  635         struct sonic_descsoft *ds;
  636         struct sonic_tda32 *tda32;
  637         struct sonic_tda16 *tda16;
  638         uint16_t status, totstat = 0;
  639         int i;
  640 
  641         ifp->if_flags &= ~IFF_OACTIVE;
  642 
  643         for (i = sc->sc_txdirty; sc->sc_txpending != 0;
  644              i = SONIC_NEXTTX(i), sc->sc_txpending--) {
  645                 ds = &sc->sc_txsoft[i];
  646 
  647                 if (sc->sc_32bit) {
  648                         SONIC_CDTXSYNC32(sc, i,
  649                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  650                         tda32 = &sc->sc_tda32[i];
  651                         status = sonic32toh(sc, tda32->tda_status);
  652                 } else {
  653                         SONIC_CDTXSYNC16(sc, i,
  654                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  655                         tda16 = &sc->sc_tda16[i];
  656                         status = sonic16toh(sc, tda16->tda_status);
  657                 }
  658 
  659                 if ((status & ~(TCR_EXDIS|TCR_CRCI|TCR_POWC|TCR_PINT)) == 0)
  660                         break;
  661 
  662                 totstat |= status;
  663 
  664                 bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
  665                     ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
  666                 bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
  667                 m_freem(ds->ds_mbuf);
  668                 ds->ds_mbuf = NULL;
  669 
  670                 /*
  671                  * Check for errors and collisions.
  672                  */
  673                 if (status & TCR_PTX)
  674                         ifp->if_opackets++;
  675                 else
  676                         ifp->if_oerrors++;
  677                 ifp->if_collisions += TDA_STATUS_NCOL(status);
  678         }
  679 
  680         /* Update the dirty transmit buffer pointer. */
  681         sc->sc_txdirty = i;
  682 
  683         /*
  684          * Cancel the watchdog timer if there are no pending
  685          * transmissions.
  686          */
  687         if (sc->sc_txpending == 0)
  688                 ifp->if_timer = 0;
  689 
  690         return (totstat);
  691 }
  692 
  693 /*
  694  * sonic_rxintr:
  695  *
  696  *      Helper; handle receive interrupts.
  697  */
  698 void
  699 sonic_rxintr(struct sonic_softc *sc)
  700 {
  701         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
  702         struct sonic_descsoft *ds;
  703         struct sonic_rda32 *rda32;
  704         struct sonic_rda16 *rda16;
  705         struct mbuf *m;
  706         int i, len;
  707         uint16_t status, bytecount, ptr0, ptr1, seqno;
  708 
  709         for (i = sc->sc_rxptr;; i = SONIC_NEXTRX(i)) {
  710                 ds = &sc->sc_rxsoft[i];
  711 
  712                 if (sc->sc_32bit) {
  713                         SONIC_CDRXSYNC32(sc, i,
  714                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  715                         rda32 = &sc->sc_rda32[i];
  716                         if (rda32->rda_inuse != 0)
  717                                 break;
  718                         status = sonic32toh(sc, rda32->rda_status);
  719                         bytecount = sonic32toh(sc, rda32->rda_bytecount);
  720                         ptr0 = sonic32toh(sc, rda32->rda_pkt_ptr0);
  721                         ptr1 = sonic32toh(sc, rda32->rda_pkt_ptr1);
  722                         seqno = sonic32toh(sc, rda32->rda_seqno);
  723                 } else {
  724                         SONIC_CDRXSYNC16(sc, i,
  725                             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
  726                         rda16 = &sc->sc_rda16[i];
  727                         if (rda16->rda_inuse != 0)
  728                                 break;
  729                         status = sonic16toh(sc, rda16->rda_status);
  730                         bytecount = sonic16toh(sc, rda16->rda_bytecount);
  731                         ptr0 = sonic16toh(sc, rda16->rda_pkt_ptr0);
  732                         ptr1 = sonic16toh(sc, rda16->rda_pkt_ptr1);
  733                         seqno = sonic16toh(sc, rda16->rda_seqno);
  734                 }
  735 
  736                 /*
  737                  * Make absolutely sure this is the only packet
  738                  * in this receive buffer.  Our entire Rx buffer
  739                  * management scheme depends on this, and if the
  740                  * SONIC didn't follow our rule, it means we've
  741                  * misconfigured it.
  742                  */
  743                 KASSERT(status & RCR_LPKT);
  744 
  745                 /*
  746                  * Make sure the packet arrived OK.  If an error occurred,
  747                  * update stats and reset the descriptor.  The buffer will
  748                  * be reused the next time the descriptor comes up in the
  749                  * ring.
  750                  */
  751                 if ((status & RCR_PRX) == 0) {
  752                         if (status & RCR_FAER)
  753                                 printf("%s: Rx frame alignment error\n",
  754                                     sc->sc_dev.dv_xname);
  755                         else if (status & RCR_CRCR)
  756                                 printf("%s: Rx CRC error\n",
  757                                     sc->sc_dev.dv_xname);
  758                         ifp->if_ierrors++;
  759                         SONIC_INIT_RXDESC(sc, i);
  760                         continue;
  761                 }
  762 
  763                 bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
  764                     ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
  765 
  766                 /*
  767                  * The SONIC includes the CRC with every packet.
  768                  */
  769                 len = bytecount - ETHER_CRC_LEN;
  770 
  771                 /*
  772                  * Ok, if the chip is in 32-bit mode, then receive
  773                  * buffers must be aligned to 32-bit boundaries,
  774                  * which means the payload is misaligned.  In this
  775                  * case, we must allocate a new mbuf, and copy the
  776                  * packet into it, scooted forward 2 bytes to ensure
  777                  * proper alignment.
  778                  *
  779                  * Note, in 16-bit mode, we can configure the SONIC
  780                  * to do what we want, and we have.
  781                  */
  782 #ifndef __NO_STRICT_ALIGNMENT
  783                 if (sc->sc_32bit) {
  784                         MGETHDR(m, M_DONTWAIT, MT_DATA);
  785                         if (m == NULL)
  786                                 goto dropit;
  787                         if (len > (MHLEN - 2)) {
  788                                 MCLGET(m, M_DONTWAIT);
  789                                 if ((m->m_flags & M_EXT) == 0)
  790                                         goto dropit;
  791                         }
  792                         m->m_data += 2;
  793                         /*
  794                          * Note that we use a cluster for incoming frames,
  795                          * so the buffer is virtually contiguous.
  796                          */
  797                         memcpy(mtod(m, caddr_t), mtod(ds->ds_mbuf, caddr_t),
  798                             len);
  799                         SONIC_INIT_RXDESC(sc, i);
  800                         bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
  801                             ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
  802                 } else
  803 #endif /* ! __NO_STRICT_ALIGNMENT */
  804                 /*
  805                  * If the packet is small enough to fit in a single
  806                  * header mbuf, allocate one and copy the data into
  807                  * it.  This greatly reduces memory consumption when
  808                  * we receive lots of small packets.
  809                  */
  810                 if (sonic_copy_small != 0 && len <= (MHLEN - 2)) {
  811                         MGETHDR(m, M_DONTWAIT, MT_DATA);
  812                         if (m == NULL)
  813                                 goto dropit;
  814                         m->m_data += 2;
  815                         /*
  816                          * Note that we use a cluster for incoming frames,
  817                          * so the buffer is virtually contiguous.
  818                          */
  819                         memcpy(mtod(m, caddr_t), mtod(ds->ds_mbuf, caddr_t),
  820                             len);
  821                         SONIC_INIT_RXDESC(sc, i);
  822                         bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
  823                             ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
  824                 } else {
  825                         m = ds->ds_mbuf;
  826                         if (sonic_add_rxbuf(sc, i) != 0) {
  827  dropit:
  828                                 ifp->if_ierrors++;
  829                                 SONIC_INIT_RXDESC(sc, i);
  830                                 bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
  831                                     ds->ds_dmamap->dm_mapsize,
  832                                     BUS_DMASYNC_PREREAD);
  833                                 continue;
  834                         }
  835                 }
  836 
  837                 ifp->if_ipackets++;
  838                 m->m_pkthdr.rcvif = ifp;
  839                 m->m_pkthdr.len = m->m_len = len;
  840 
  841 #if NBPFILTER > 0
  842                 /*
  843                  * Pass this up to any BPF listeners.
  844                  */
  845                 if (ifp->if_bpf)
  846                         bpf_mtap(ifp->if_bpf, m);
  847 #endif /* NBPFILTER > 0 */
  848 
  849                 /* Pass it on. */
  850                 (*ifp->if_input)(ifp, m);
  851         }
  852 
  853         /* Update the receive pointer. */
  854         sc->sc_rxptr = i;
  855         CSR_WRITE(sc, SONIC_RWR, SONIC_CDRRADDR(sc, SONIC_PREVRX(i)));
  856 }
  857 
  858 /*
  859  * sonic_reset:
  860  *
  861  *      Perform a soft reset on the SONIC.
  862  */
  863 void
  864 sonic_reset(struct sonic_softc *sc)
  865 {
  866 
  867         CSR_WRITE(sc, SONIC_CR, 0);     /* ensure RST is clear */
  868         CSR_WRITE(sc, SONIC_CR, CR_RST);
  869         delay(1000);
  870         CSR_WRITE(sc, SONIC_CR, 0);
  871         delay(1000);
  872 }
  873 
  874 /*
  875  * sonic_init:          [ifnet interface function]
  876  *
  877  *      Initialize the interface.  Must be called at splnet().
  878  */
  879 int
  880 sonic_init(struct ifnet *ifp)
  881 {
  882         struct sonic_softc *sc = ifp->if_softc;
  883         struct sonic_descsoft *ds;
  884         int i, error = 0;
  885         uint16_t reg;
  886 
  887         /*
  888          * Cancel any pending I/O.
  889          */
  890         sonic_stop(ifp, 0);
  891 
  892         /*
  893          * Reset the SONIC to a known state.
  894          */
  895         sonic_reset(sc);
  896 
  897         /*
  898          * Bring the SONIC into reset state, and program the DCR.
  899          *
  900          * Note: We don't bother optimizing the transmit and receive
  901          * thresholds, here.  We just use the most conservative values:
  902          *
  903          *      - Rx: 4 bytes (RFT0,RFT0 == 0,0)
  904          *      - Tx: 28 bytes (TFT0,TFT1 == 1,1)
  905          */
  906         reg = sc->sc_dcr | DCR_TFT0 | DCR_TFT1;
  907         if (sc->sc_32bit)
  908                 reg |= DCR_DW;
  909         CSR_WRITE(sc, SONIC_CR, CR_RST);
  910         CSR_WRITE(sc, SONIC_DCR, reg);
  911         CSR_WRITE(sc, SONIC_DCR2, sc->sc_dcr2);
  912         CSR_WRITE(sc, SONIC_CR, 0);
  913 
  914         /*
  915          * Initialize the transmit descriptors.
  916          */
  917         if (sc->sc_32bit) {
  918                 for (i = 0; i < SONIC_NTXDESC; i++) {
  919                         memset(&sc->sc_tda32[i], 0, sizeof(struct sonic_tda32));
  920                         SONIC_CDTXSYNC32(sc, i,
  921                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  922                 }
  923         } else {
  924                 for (i = 0; i < SONIC_NTXDESC; i++) {
  925                         memset(&sc->sc_tda16[i], 0, sizeof(struct sonic_tda16));
  926                         SONIC_CDTXSYNC16(sc, i,
  927                             BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
  928                 }
  929         }
  930         sc->sc_txpending = 0;
  931         sc->sc_txdirty = 0;
  932         sc->sc_txlast = SONIC_NTXDESC - 1;
  933 
  934         /*
  935          * Initialize the receive descriptor ring.
  936          */
  937         for (i = 0; i < SONIC_NRXDESC; i++) {
  938                 ds = &sc->sc_rxsoft[i];
  939                 if (ds->ds_mbuf == NULL) {
  940                         if ((error = sonic_add_rxbuf(sc, i)) != 0) {
  941                                 printf("%s: unable to allocate or map Rx "
  942                                     "buffer %d, error = %d\n",
  943                                     sc->sc_dev.dv_xname, i, error);
  944                                 /*
  945                                  * XXX Should attempt to run with fewer receive
  946                                  * XXX buffers instead of just failing.
  947                                  */
  948                                 sonic_rxdrain(sc);
  949                                 goto out;
  950                         }
  951                 } else
  952                         SONIC_INIT_RXDESC(sc, i);
  953         }
  954         sc->sc_rxptr = 0;
  955 
  956         /* Give the transmit ring to the SONIC. */
  957         CSR_WRITE(sc, SONIC_UTDAR, (SONIC_CDTXADDR(sc, 0) >> 16) & 0xffff);
  958         CSR_WRITE(sc, SONIC_CTDAR, SONIC_CDTXADDR(sc, 0) & 0xffff);
  959 
  960         /* Give the receive descriptor ring to the SONIC. */
  961         CSR_WRITE(sc, SONIC_URDAR, (SONIC_CDRXADDR(sc, 0) >> 16) & 0xffff);
  962         CSR_WRITE(sc, SONIC_CRDAR, SONIC_CDRXADDR(sc, 0) & 0xffff);
  963 
  964         /* Give the receive buffer ring to the SONIC. */
  965         CSR_WRITE(sc, SONIC_URRAR, (SONIC_CDRRADDR(sc, 0) >> 16) & 0xffff);
  966         CSR_WRITE(sc, SONIC_RSAR, SONIC_CDRRADDR(sc, 0) & 0xffff);
  967         if (sc->sc_32bit)
  968                 CSR_WRITE(sc, SONIC_REAR,
  969                     (SONIC_CDRRADDR(sc, SONIC_NRXDESC - 1) +
  970                     sizeof(struct sonic_rra32)) & 0xffff);
  971         else
  972                 CSR_WRITE(sc, SONIC_REAR,
  973                     (SONIC_CDRRADDR(sc, SONIC_NRXDESC - 1) +
  974                     sizeof(struct sonic_rra16)) & 0xffff);
  975         CSR_WRITE(sc, SONIC_RRR, SONIC_CDRRADDR(sc, 0) & 0xffff);
  976         CSR_WRITE(sc, SONIC_RWR, SONIC_CDRRADDR(sc, SONIC_NRXDESC - 1));
  977 
  978         /*
  979          * Set the End-Of-Buffer counter such that only one packet
  980          * will be placed into each buffer we provide.  Note we are
  981          * following the recommendation of section 3.4.4 of the manual
  982          * here, and have "lengthened" the receive buffers accordingly.
  983          */
  984         if (sc->sc_32bit)
  985                 CSR_WRITE(sc, SONIC_EOBC, (ETHER_MAX_LEN + 2) / 2);
  986         else
  987                 CSR_WRITE(sc, SONIC_EOBC, (ETHER_MAX_LEN / 2));
  988 
  989         /* Reset the receive sequence counter. */
  990         CSR_WRITE(sc, SONIC_RSC, 0);
  991 
  992         /* Clear the tally registers. */
  993         CSR_WRITE(sc, SONIC_CRCETC, 0xffff);
  994         CSR_WRITE(sc, SONIC_FAET, 0xffff);
  995         CSR_WRITE(sc, SONIC_MPT, 0xffff);
  996 
  997         /* Set the receive filter. */
  998         sonic_set_filter(sc);
  999 
 1000         /*
 1001          * Set the interrupt mask register.
 1002          */
 1003         sc->sc_imr = IMR_RFO | IMR_RBA | IMR_RBE | IMR_RDE |
 1004             IMR_TXER | IMR_PTX | IMR_PRX;
 1005         CSR_WRITE(sc, SONIC_IMR, sc->sc_imr);
 1006 
 1007         /*
 1008          * Start the receive process in motion.  Note, we don't
 1009          * start the transmit process until we actually try to
 1010          * transmit packets.
 1011          */
 1012         CSR_WRITE(sc, SONIC_CR, CR_RXEN | CR_RRRA);
 1013 
 1014         /*
 1015          * ...all done!
 1016          */
 1017         ifp->if_flags |= IFF_RUNNING;
 1018         ifp->if_flags &= ~IFF_OACTIVE;
 1019 
 1020  out:
 1021         if (error)
 1022                 printf("%s: interface not running\n", sc->sc_dev.dv_xname);
 1023         return (error);
 1024 }
 1025 
 1026 /*
 1027  * sonic_rxdrain:
 1028  *
 1029  *      Drain the receive queue.
 1030  */
 1031 void
 1032 sonic_rxdrain(struct sonic_softc *sc)
 1033 {
 1034         struct sonic_descsoft *ds;
 1035         int i;
 1036 
 1037         for (i = 0; i < SONIC_NRXDESC; i++) {
 1038                 ds = &sc->sc_rxsoft[i];
 1039                 if (ds->ds_mbuf != NULL) {
 1040                         bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
 1041                         m_freem(ds->ds_mbuf);
 1042                         ds->ds_mbuf = NULL;
 1043                 }
 1044         }
 1045 }
 1046 
 1047 /*
 1048  * sonic_stop:          [ifnet interface function]
 1049  *
 1050  *      Stop transmission on the interface.
 1051  */
 1052 void
 1053 sonic_stop(struct ifnet *ifp, int disable)
 1054 {
 1055         struct sonic_softc *sc = ifp->if_softc;
 1056         struct sonic_descsoft *ds;
 1057         int i;
 1058 
 1059         /*
 1060          * Disable interrupts.
 1061          */
 1062         CSR_WRITE(sc, SONIC_IMR, 0);
 1063 
 1064         /*
 1065          * Stop the transmitter, receiver, and timer.
 1066          */
 1067         CSR_WRITE(sc, SONIC_CR, CR_HTX|CR_RXDIS|CR_STP);
 1068         for (i = 0; i < 1000; i++) {
 1069                 if ((CSR_READ(sc, SONIC_CR) & (CR_TXP|CR_RXEN|CR_ST)) == 0)
 1070                         break;
 1071                 delay(2);
 1072         }
 1073         if ((CSR_READ(sc, SONIC_CR) & (CR_TXP|CR_RXEN|CR_ST)) != 0)
 1074                 printf("%s: SONIC failed to stop\n", sc->sc_dev.dv_xname);
 1075 
 1076         /*
 1077          * Release any queued transmit buffers.
 1078          */
 1079         for (i = 0; i < SONIC_NTXDESC; i++) {
 1080                 ds = &sc->sc_txsoft[i];
 1081                 if (ds->ds_mbuf != NULL) {
 1082                         bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
 1083                         m_freem(ds->ds_mbuf);
 1084                         ds->ds_mbuf = NULL;
 1085                 }
 1086         }
 1087 
 1088         if (disable)
 1089                 sonic_rxdrain(sc);
 1090 
 1091         /*
 1092          * Mark the interface down and cancel the watchdog timer.
 1093          */
 1094         ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 1095         ifp->if_timer = 0;
 1096 }
 1097 
 1098 /*
 1099  * sonic_add_rxbuf:
 1100  *
 1101  *      Add a receive buffer to the indicated descriptor.
 1102  */
 1103 int
 1104 sonic_add_rxbuf(struct sonic_softc *sc, int idx)
 1105 {
 1106         struct sonic_descsoft *ds = &sc->sc_rxsoft[idx];
 1107         struct mbuf *m;
 1108         int error;
 1109 
 1110         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1111         if (m == NULL)
 1112                 return (ENOBUFS);
 1113 
 1114         MCLGET(m, M_DONTWAIT);
 1115         if ((m->m_flags & M_EXT) == 0) {
 1116                 m_freem(m);
 1117                 return (ENOBUFS);
 1118         }
 1119 
 1120         if (ds->ds_mbuf != NULL)
 1121                 bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
 1122 
 1123         ds->ds_mbuf = m;
 1124 
 1125         error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
 1126             m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
 1127             BUS_DMA_READ|BUS_DMA_NOWAIT);
 1128         if (error) {
 1129                 printf("%s: can't load rx DMA map %d, error = %d\n",
 1130                     sc->sc_dev.dv_xname, idx, error);
 1131                 panic("sonic_add_rxbuf");       /* XXX */
 1132         }
 1133 
 1134         bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
 1135             ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
 1136 
 1137         SONIC_INIT_RXDESC(sc, idx);
 1138 
 1139         return (0);
 1140 }
 1141 
 1142 static void
 1143 sonic_set_camentry(struct sonic_softc *sc, int entry, const uint8_t *enaddr)
 1144 {
 1145 
 1146         if (sc->sc_32bit) {
 1147                 struct sonic_cda32 *cda = &sc->sc_cda32[entry];
 1148 
 1149                 cda->cda_entry = htosonic32(sc, entry);
 1150                 cda->cda_addr0 = htosonic32(sc, enaddr[0] | (enaddr[1] << 8));
 1151                 cda->cda_addr1 = htosonic32(sc, enaddr[2] | (enaddr[3] << 8));
 1152                 cda->cda_addr2 = htosonic32(sc, enaddr[4] | (enaddr[5] << 8));
 1153         } else {
 1154                 struct sonic_cda16 *cda = &sc->sc_cda16[entry];
 1155 
 1156                 cda->cda_entry = htosonic16(sc, entry);
 1157                 cda->cda_addr0 = htosonic16(sc, enaddr[0] | (enaddr[1] << 8));
 1158                 cda->cda_addr1 = htosonic16(sc, enaddr[2] | (enaddr[3] << 8));
 1159                 cda->cda_addr2 = htosonic16(sc, enaddr[4] | (enaddr[5] << 8));
 1160         }
 1161 }
 1162 
 1163 /*
 1164  * sonic_set_filter:
 1165  *
 1166  *      Set the SONIC receive filter.
 1167  */
 1168 void
 1169 sonic_set_filter(struct sonic_softc *sc)
 1170 {
 1171         struct ethercom *ec = &sc->sc_ethercom;
 1172         struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 1173         struct ether_multi *enm;
 1174         struct ether_multistep step;
 1175         int i, entry = 0;
 1176         uint16_t camvalid = 0;
 1177         uint16_t rcr = 0;
 1178 
 1179         if (ifp->if_flags & IFF_BROADCAST)
 1180                 rcr |= RCR_BRD;
 1181 
 1182         if (ifp->if_flags & IFF_PROMISC) {
 1183                 rcr |= RCR_PRO;
 1184                 goto allmulti;
 1185         }
 1186 
 1187         /* Put our station address in the first CAM slot. */
 1188         sonic_set_camentry(sc, entry, LLADDR(ifp->if_sadl));
 1189         camvalid |= (1U << entry);
 1190         entry++;
 1191 
 1192         /* Add the multicast addresses to the CAM. */
 1193         ETHER_FIRST_MULTI(step, ec, enm);
 1194         while (enm != NULL) {
 1195                 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
 1196                         /*
 1197                          * We must listen to a range of multicast addresses.
 1198                          * The only way to do this on the SONIC is to enable
 1199                          * reception of all multicast packets.
 1200                          */
 1201                         goto allmulti;
 1202                 }
 1203 
 1204                 if (entry == 16) {
 1205                         /*
 1206                          * Out of CAM slots.  Have to enable reception
 1207                          * of all multicast addresses.
 1208                          */
 1209                         goto allmulti;
 1210                 }
 1211 
 1212                 sonic_set_camentry(sc, entry, enm->enm_addrlo);
 1213                 camvalid |= (1U << entry);
 1214                 entry++;
 1215 
 1216                 ETHER_NEXT_MULTI(step, enm);
 1217         }
 1218 
 1219         ifp->if_flags &= ~IFF_ALLMULTI;
 1220         goto setit;
 1221 
 1222  allmulti:
 1223         /* Use only the first CAM slot (station address). */
 1224         camvalid = 0x0001;
 1225         entry = 1;
 1226         rcr |= RCR_AMC;
 1227 
 1228  setit:
 1229         /* Load the CAM. */
 1230         SONIC_CDCAMSYNC(sc, BUS_DMASYNC_PREWRITE);
 1231         CSR_WRITE(sc, SONIC_CDP, SONIC_CDCAMADDR(sc) & 0xffff);
 1232         CSR_WRITE(sc, SONIC_CDC, entry);
 1233         CSR_WRITE(sc, SONIC_CR, CR_LCAM);
 1234         for (i = 0; i < 10000; i++) {
 1235                 if ((CSR_READ(sc, SONIC_CR) & CR_LCAM) == 0)
 1236                         break;
 1237                 delay(2);
 1238         }
 1239         if (CSR_READ(sc, SONIC_CR) & CR_LCAM)
 1240                 printf("%s: CAM load failed\n", sc->sc_dev.dv_xname);
 1241         SONIC_CDCAMSYNC(sc, BUS_DMASYNC_POSTWRITE);
 1242 
 1243         /* Set the CAM enable resgiter. */
 1244         CSR_WRITE(sc, SONIC_CER, camvalid);
 1245 
 1246         /* Set the receive control register. */
 1247         CSR_WRITE(sc, SONIC_RCR, rcr);
 1248 }

Cache object: 656f6ce25a44b6ce23f7c644c541b7ca


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