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/le/am7990.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $     */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-3-Clause
    5  *
    6  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
   11  * Simulation Facility, NASA Ames Research Center.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   32  * POSSIBILITY OF SUCH DAMAGE.
   33  */
   34 
   35 /*-
   36  * Copyright (c) 1992, 1993
   37  *      The Regents of the University of California.  All rights reserved.
   38  *
   39  * This code is derived from software contributed to Berkeley by
   40  * Ralph Campbell and Rick Macklem.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. Neither the name of the University nor the names of its contributors
   51  *    may be used to endorse or promote products derived from this software
   52  *    without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   64  * SUCH DAMAGE.
   65  *
   66  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
   67  */
   68 
   69 #include <sys/cdefs.h>
   70 __FBSDID("$FreeBSD: head/sys/dev/le/am7990.c 326255 2017-11-27 14:52:40Z pfg $");
   71 
   72 #include <sys/param.h>
   73 #include <sys/bus.h>
   74 #include <sys/endian.h>
   75 #include <sys/lock.h>
   76 #include <sys/mbuf.h>
   77 #include <sys/mutex.h>
   78 #include <sys/socket.h>
   79 
   80 #include <net/bpf.h>
   81 #include <net/ethernet.h>
   82 #include <net/if.h>
   83 #include <net/if_arp.h>
   84 #include <net/if_dl.h>
   85 #include <net/if_media.h>
   86 #include <net/if_var.h>
   87 
   88 #include <machine/bus.h>
   89 
   90 #include <dev/le/lancereg.h>
   91 #include <dev/le/lancevar.h>
   92 #include <dev/le/am7990reg.h>
   93 #include <dev/le/am7990var.h>
   94 
   95 static void     am7990_meminit(struct lance_softc *);
   96 static void     am7990_rint(struct lance_softc *);
   97 static void     am7990_tint(struct lance_softc *);
   98 static void     am7990_start_locked(struct lance_softc *sc);
   99 
  100 #ifdef LEDEBUG
  101 static void     am7990_recv_print(struct lance_softc *, int);
  102 static void     am7990_xmit_print(struct lance_softc *, int);
  103 #endif
  104 
  105 int
  106 am7990_config(struct am7990_softc *sc, const char* name, int unit)
  107 {
  108         int error, mem;
  109 
  110         sc->lsc.sc_meminit = am7990_meminit;
  111         sc->lsc.sc_start_locked = am7990_start_locked;
  112 
  113         error = lance_config(&sc->lsc, name, unit);
  114         if (error != 0)
  115                 return (error);
  116 
  117         mem = 0;
  118         sc->lsc.sc_initaddr = mem;
  119         mem += sizeof(struct leinit);
  120         sc->lsc.sc_rmdaddr = mem;
  121         mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
  122         sc->lsc.sc_tmdaddr = mem;
  123         mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
  124         sc->lsc.sc_rbufaddr = mem;
  125         mem += LEBLEN * sc->lsc.sc_nrbuf;
  126         sc->lsc.sc_tbufaddr = mem;
  127         mem += LEBLEN * sc->lsc.sc_ntbuf;
  128 
  129         if (mem > sc->lsc.sc_memsize)
  130                 panic("%s: memsize", __func__);
  131 
  132         lance_attach(&sc->lsc);
  133 
  134         return (0);
  135 }
  136 
  137 void
  138 am7990_detach(struct am7990_softc *sc)
  139 {
  140 
  141         lance_detach(&sc->lsc);
  142 }
  143 
  144 /*
  145  * Set up the initialization block and the descriptor rings.
  146  */
  147 static void
  148 am7990_meminit(struct lance_softc *sc)
  149 {
  150         struct ifnet *ifp = sc->sc_ifp;
  151         struct leinit init;
  152         struct lermd rmd;
  153         struct letmd tmd;
  154         u_long a;
  155         int bix;
  156 
  157         LE_LOCK_ASSERT(sc, MA_OWNED);
  158 
  159         if (ifp->if_flags & IFF_PROMISC)
  160                 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
  161         else
  162                 init.init_mode = LE_MODE_NORMAL;
  163 
  164         init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
  165         init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
  166         init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
  167         lance_setladrf(sc, init.init_ladrf);
  168 
  169         sc->sc_last_rd = 0;
  170         sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
  171 
  172         a = sc->sc_addr + LE_RMDADDR(sc, 0);
  173         init.init_rdra = a;
  174         init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
  175 
  176         a = sc->sc_addr + LE_TMDADDR(sc, 0);
  177         init.init_tdra = a;
  178         init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
  179 
  180         (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
  181 
  182         /*
  183          * Set up receive ring descriptors.
  184          */
  185         for (bix = 0; bix < sc->sc_nrbuf; bix++) {
  186                 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
  187                 rmd.rmd0 = a;
  188                 rmd.rmd1_hadr = a >> 16;
  189                 rmd.rmd1_bits = LE_R1_OWN;
  190                 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
  191                 rmd.rmd3 = 0;
  192                 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
  193                     sizeof(rmd));
  194         }
  195 
  196         /*
  197          * Set up transmit ring descriptors.
  198          */
  199         for (bix = 0; bix < sc->sc_ntbuf; bix++) {
  200                 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
  201                 tmd.tmd0 = a;
  202                 tmd.tmd1_hadr = a >> 16;
  203                 tmd.tmd1_bits = 0;
  204                 tmd.tmd2 = LE_XMD2_ONES;
  205                 tmd.tmd3 = 0;
  206                 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  207                     sizeof(tmd));
  208         }
  209 }
  210 
  211 static void
  212 am7990_rint(struct lance_softc *sc)
  213 {
  214         struct ifnet *ifp = sc->sc_ifp;
  215         struct mbuf *m;
  216         struct lermd rmd;
  217         int bix, rp;
  218 #if defined(LANCE_REVC_BUG)
  219         struct ether_header *eh;
  220         /* Make sure this is short-aligned, for ether_cmp(). */
  221         static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
  222 #endif
  223 
  224         bix = sc->sc_last_rd;
  225 
  226         /* Process all buffers with valid data. */
  227         for (;;) {
  228                 rp = LE_RMDADDR(sc, bix);
  229                 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
  230 
  231                 if (rmd.rmd1_bits & LE_R1_OWN)
  232                         break;
  233 
  234                 m = NULL;
  235                 if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
  236                     (LE_R1_STP | LE_R1_ENP)) {
  237                         if (rmd.rmd1_bits & LE_R1_ERR) {
  238 #ifdef LEDEBUG
  239                                 if (rmd.rmd1_bits & LE_R1_ENP) {
  240                                         if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
  241                                                 if (rmd.rmd1_bits & LE_R1_FRAM)
  242                                                         if_printf(ifp,
  243                                                             "framing error\n");
  244                                                 if (rmd.rmd1_bits & LE_R1_CRC)
  245                                                         if_printf(ifp,
  246                                                             "crc mismatch\n");
  247                                         }
  248                                 } else
  249                                         if (rmd.rmd1_bits & LE_R1_OFLO)
  250                                                 if_printf(ifp, "overflow\n");
  251 #endif
  252                                 if (rmd.rmd1_bits & LE_R1_BUFF)
  253                                         if_printf(ifp,
  254                                             "receive buffer error\n");
  255                         } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
  256                             (LE_R1_STP | LE_R1_ENP))
  257                                 if_printf(ifp, "dropping chained buffer\n");
  258                 } else {
  259 #ifdef LEDEBUG
  260                         if (sc->sc_flags & LE_DEBUG)
  261                                 am7990_recv_print(sc, bix);
  262 #endif
  263                         /* Pull the packet off the interface. */
  264                         m = lance_get(sc, LE_RBUFADDR(sc, bix),
  265                             (int)rmd.rmd3 - ETHER_CRC_LEN);
  266                 }
  267 
  268                 rmd.rmd1_bits = LE_R1_OWN;
  269                 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
  270                 rmd.rmd3 = 0;
  271                 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
  272 
  273                 if (++bix == sc->sc_nrbuf)
  274                         bix = 0;
  275 
  276                 if (m != NULL) {
  277                         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
  278 
  279 #ifdef LANCE_REVC_BUG
  280                         /*
  281                          * The old LANCE (Rev. C) chips have a bug which
  282                          * causes garbage to be inserted in front of the
  283                          * received packet. The workaround is to ignore
  284                          * packets with an invalid destination address
  285                          * (garbage will usually not match).
  286                          * Of course, this precludes multicast support...
  287                          */
  288                         eh = mtod(m, struct ether_header *);
  289                         if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) &&
  290                             ether_cmp(eh->ether_dhost, bcast_enaddr)) {
  291                                 m_freem(m);
  292                                 continue;
  293                         }
  294 #endif
  295 
  296                         /* Pass the packet up. */
  297                         LE_UNLOCK(sc);
  298                         (*ifp->if_input)(ifp, m);
  299                         LE_LOCK(sc);
  300                 } else
  301                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  302         }
  303 
  304         sc->sc_last_rd = bix;
  305 }
  306 
  307 static void
  308 am7990_tint(struct lance_softc *sc)
  309 {
  310         struct ifnet *ifp = sc->sc_ifp;
  311         struct letmd tmd;
  312         int bix;
  313 
  314         bix = sc->sc_first_td;
  315 
  316         for (;;) {
  317                 if (sc->sc_no_td <= 0)
  318                         break;
  319 
  320                 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  321                     sizeof(tmd));
  322 
  323 #ifdef LEDEBUG
  324                 if (sc->sc_flags & LE_DEBUG)
  325                         if_printf(ifp, "trans tmd: "
  326                             "ladr %04x, hadr %02x, flags %02x, "
  327                             "bcnt %04x, mcnt %04x\n",
  328                             tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
  329                             tmd.tmd2, tmd.tmd3);
  330 #endif
  331 
  332                 if (tmd.tmd1_bits & LE_T1_OWN)
  333                         break;
  334 
  335                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  336 
  337                 if (tmd.tmd1_bits & LE_T1_ERR) {
  338                         if (tmd.tmd3 & LE_T3_BUFF)
  339                                 if_printf(ifp, "transmit buffer error\n");
  340                         else if (tmd.tmd3 & LE_T3_UFLO)
  341                                 if_printf(ifp, "underflow\n");
  342                         if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
  343                                 lance_init_locked(sc);
  344                                 return;
  345                         }
  346                         if (tmd.tmd3 & LE_T3_LCAR) {
  347                                 if (sc->sc_flags & LE_CARRIER)
  348                                         if_link_state_change(ifp,
  349                                             LINK_STATE_DOWN);
  350                                 sc->sc_flags &= ~LE_CARRIER;
  351                                 if (sc->sc_nocarrier)
  352                                         (*sc->sc_nocarrier)(sc);
  353                                 else
  354                                         if_printf(ifp, "lost carrier\n");
  355                         }
  356                         if (tmd.tmd3 & LE_T3_LCOL)
  357                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
  358                         if (tmd.tmd3 & LE_T3_RTRY) {
  359 #ifdef LEDEBUG
  360                                 if_printf(ifp, "excessive collisions, tdr %d\n",
  361                                     tmd.tmd3 & LE_T3_TDR_MASK);
  362 #endif
  363                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16);
  364                         }
  365                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  366                 } else {
  367                         if (tmd.tmd1_bits & LE_T1_ONE)
  368                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
  369                         else if (tmd.tmd1_bits & LE_T1_MORE)
  370                                 /* Real number is unknown. */
  371                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2);
  372                         if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
  373                 }
  374 
  375                 if (++bix == sc->sc_ntbuf)
  376                         bix = 0;
  377 
  378                 --sc->sc_no_td;
  379         }
  380 
  381         sc->sc_first_td = bix;
  382 
  383         sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
  384 }
  385 
  386 /*
  387  * Controller interrupt
  388  */
  389 void
  390 am7990_intr(void *arg)
  391 {
  392         struct lance_softc *sc = arg;
  393         struct ifnet *ifp = sc->sc_ifp;
  394         uint16_t isr;
  395 
  396         LE_LOCK(sc);
  397 
  398         if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
  399                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  400                 lance_init_locked(sc);
  401                 LE_UNLOCK(sc);
  402                 return;
  403         }
  404 
  405         isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
  406 #if defined(LEDEBUG) && LEDEBUG > 1
  407         if (sc->sc_flags & LE_DEBUG)
  408                 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
  409 #endif
  410         if ((isr & LE_C0_INTR) == 0) {
  411                 LE_UNLOCK(sc);
  412                 return;
  413         }
  414 
  415         /*
  416          * Clear interrupt source flags and turn off interrupts. If we
  417          * don't clear these flags before processing their sources we
  418          * could completely miss some interrupt events as the NIC can
  419          * change these flags while we're in this handler. We toggle
  420          * the interrupt enable bit in order to keep receiving them
  421          * (some chips work without this, some don't).
  422          */
  423         (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
  424             LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
  425 
  426         if (isr & LE_C0_ERR) {
  427                 if (isr & LE_C0_BABL) {
  428 #ifdef LEDEBUG
  429                         if_printf(ifp, "babble\n");
  430 #endif
  431                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  432                 }
  433 #if 0
  434                 if (isr & LE_C0_CERR) {
  435                         if_printf(ifp, "collision error\n");
  436                         if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
  437                 }
  438 #endif
  439                 if (isr & LE_C0_MISS) {
  440 #ifdef LEDEBUG
  441                         if_printf(ifp, "missed packet\n");
  442 #endif
  443                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  444                 }
  445                 if (isr & LE_C0_MERR) {
  446                         if_printf(ifp, "memory error\n");
  447                         lance_init_locked(sc);
  448                         LE_UNLOCK(sc);
  449                         return;
  450                 }
  451         }
  452 
  453         if ((isr & LE_C0_RXON) == 0) {
  454                 if_printf(ifp, "receiver disabled\n");
  455                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
  456                 lance_init_locked(sc);
  457                 LE_UNLOCK(sc);
  458                 return;
  459         }
  460         if ((isr & LE_C0_TXON) == 0) {
  461                 if_printf(ifp, "transmitter disabled\n");
  462                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
  463                 lance_init_locked(sc);
  464                 LE_UNLOCK(sc);
  465                 return;
  466         }
  467 
  468         /*
  469          * Pretend we have carrier; if we don't this will be cleared shortly.
  470          */
  471         if (!(sc->sc_flags & LE_CARRIER))
  472                 if_link_state_change(ifp, LINK_STATE_UP);
  473         sc->sc_flags |= LE_CARRIER;
  474 
  475         if (isr & LE_C0_RINT)
  476                 am7990_rint(sc);
  477         if (isr & LE_C0_TINT)
  478                 am7990_tint(sc);
  479 
  480         /* Enable interrupts again. */
  481         (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
  482 
  483         if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
  484                 am7990_start_locked(sc);
  485 
  486         LE_UNLOCK(sc);
  487 }
  488 
  489 /*
  490  * Set up output on interface.
  491  * Get another datagram to send off of the interface queue, and map it to the
  492  * interface before starting the output.
  493  */
  494 static void
  495 am7990_start_locked(struct lance_softc *sc)
  496 {
  497         struct ifnet *ifp = sc->sc_ifp;
  498         struct letmd tmd;
  499         struct mbuf *m;
  500         int bix, enq, len, rp;
  501 
  502         LE_LOCK_ASSERT(sc, MA_OWNED);
  503 
  504         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
  505             IFF_DRV_RUNNING)
  506                 return;
  507 
  508         bix = sc->sc_last_td;
  509         enq = 0;
  510 
  511         for (; sc->sc_no_td < sc->sc_ntbuf &&
  512             !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) {
  513                 rp = LE_TMDADDR(sc, bix);
  514                 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
  515 
  516                 if (tmd.tmd1_bits & LE_T1_OWN) {
  517                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  518                         if_printf(ifp,
  519                             "missing buffer, no_td = %d, last_td = %d\n",
  520                             sc->sc_no_td, sc->sc_last_td);
  521                 }
  522 
  523                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
  524                 if (m == NULL)
  525                         break;
  526 
  527                 /*
  528                  * If BPF is listening on this interface, let it see the packet
  529                  * before we commit it to the wire.
  530                  */
  531                 BPF_MTAP(ifp, m);
  532 
  533                 /*
  534                  * Copy the mbuf chain into the transmit buffer.
  535                  */
  536                 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
  537 
  538 #ifdef LEDEBUG
  539                 if (len > ETHERMTU + ETHER_HDR_LEN)
  540                         if_printf(ifp, "packet length %d\n", len);
  541 #endif
  542 
  543                 /*
  544                  * Init transmit registers, and set transmit start flag.
  545                  */
  546                 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
  547                 tmd.tmd2 = -len | LE_XMD2_ONES;
  548                 tmd.tmd3 = 0;
  549 
  550                 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
  551 
  552 #ifdef LEDEBUG
  553                 if (sc->sc_flags & LE_DEBUG)
  554                         am7990_xmit_print(sc, bix);
  555 #endif
  556 
  557                 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
  558                 enq++;
  559 
  560                 if (++bix == sc->sc_ntbuf)
  561                         bix = 0;
  562 
  563                 if (++sc->sc_no_td == sc->sc_ntbuf) {
  564                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  565                         break;
  566                 }
  567         }
  568 
  569         sc->sc_last_td = bix;
  570 
  571         if (enq > 0)
  572                 sc->sc_wdog_timer = 5;
  573 }
  574 
  575 #ifdef LEDEBUG
  576 static void
  577 am7990_recv_print(struct lance_softc *sc, int no)
  578 {
  579         struct ifnet *ifp = sc->sc_ifp;
  580         struct ether_header eh;
  581         struct lermd rmd;
  582         uint16_t len;
  583 
  584         (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
  585         len = rmd.rmd3;
  586         if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
  587         if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
  588         if_printf(ifp,
  589             "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
  590             rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
  591         if (len - ETHER_CRC_LEN >= sizeof(eh)) {
  592                 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
  593                 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
  594                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
  595                     ntohs(eh.ether_type));
  596         }
  597 }
  598 
  599 static void
  600 am7990_xmit_print(struct lance_softc *sc, int no)
  601 {
  602         struct ifnet *ifp = sc->sc_ifp;
  603         struct ether_header eh;
  604         struct letmd tmd;
  605         uint16_t len;
  606 
  607         (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
  608         len = -tmd.tmd2;
  609         if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
  610         if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
  611         if_printf(ifp,
  612             "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
  613             tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
  614         if (len >= sizeof(eh)) {
  615                 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
  616                 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
  617                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
  618                     ntohs(eh.ether_type));
  619         }
  620 }
  621 #endif /* LEDEBUG */

Cache object: 4dd1951372167318be99d61992ea50c7


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