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

Cache object: 2e970dad6e0215a40ff02875e850c9fb


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