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/am79900.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: am79900.c,v 1.20 2008/04/28 20:23:49 martin Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1997 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  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*-
   33  * Copyright (c) 1992, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * This code is derived from software contributed to Berkeley by
   37  * Ralph Campbell and Rick Macklem.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  * 3. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  *
   63  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
   64  */
   65 
   66 /*-
   67  * Copyright (c) 1998
   68  *      Matthias Drochner.  All rights reserved.
   69  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
   70  *
   71  * This code is derived from software contributed to Berkeley by
   72  * Ralph Campbell and Rick Macklem.
   73  *
   74  * Redistribution and use in source and binary forms, with or without
   75  * modification, are permitted provided that the following conditions
   76  * are met:
   77  * 1. Redistributions of source code must retain the above copyright
   78  *    notice, this list of conditions and the following disclaimer.
   79  * 2. Redistributions in binary form must reproduce the above copyright
   80  *    notice, this list of conditions and the following disclaimer in the
   81  *    documentation and/or other materials provided with the distribution.
   82  * 3. All advertising materials mentioning features or use of this software
   83  *    must display the following acknowledgement:
   84  *      This product includes software developed by the University of
   85  *      California, Berkeley and its contributors.
   86  * 4. Neither the name of the University nor the names of its contributors
   87  *    may be used to endorse or promote products derived from this software
   88  *    without specific prior written permission.
   89  *
   90  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   91  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   92  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   93  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   94  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   95  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   96  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   97  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   98  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   99  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  100  * SUCH DAMAGE.
  101  *
  102  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
  103  */
  104 
  105 #include <sys/cdefs.h>
  106 __KERNEL_RCSID(0, "$NetBSD: am79900.c,v 1.20 2008/04/28 20:23:49 martin Exp $");
  107 
  108 #include "bpfilter.h"
  109 #include "rnd.h"
  110 
  111 #include <sys/param.h>
  112 #include <sys/systm.h>
  113 #include <sys/mbuf.h>
  114 #include <sys/syslog.h>
  115 #include <sys/socket.h>
  116 #include <sys/device.h>
  117 #include <sys/malloc.h>
  118 #include <sys/ioctl.h>
  119 #include <sys/errno.h>
  120 #if NRND > 0
  121 #include <sys/rnd.h>
  122 #endif
  123 
  124 #include <net/if.h>
  125 #include <net/if_dl.h>
  126 #include <net/if_ether.h>
  127 #include <net/if_media.h>
  128 
  129 #if NBPFILTER > 0
  130 #include <net/bpf.h>
  131 #include <net/bpfdesc.h>
  132 #endif
  133 
  134 #include <dev/ic/lancereg.h>
  135 #include <dev/ic/lancevar.h>
  136 #include <dev/ic/am79900reg.h>
  137 #include <dev/ic/am79900var.h>
  138 
  139 static void     am79900_meminit(struct lance_softc *);
  140 static void     am79900_start(struct ifnet *);
  141 
  142 #if defined(_KERNEL_OPT)
  143 #include "opt_ddb.h"
  144 #endif
  145 
  146 #ifdef LEDEBUG
  147 static void     am79900_recv_print(struct lance_softc *, int);
  148 static void     am79900_xmit_print(struct lance_softc *, int);
  149 #endif
  150 
  151 #define ifp     (&sc->sc_ethercom.ec_if)
  152 
  153 void
  154 am79900_config(struct am79900_softc *sc)
  155 {
  156         int mem, i;
  157 
  158         sc->lsc.sc_meminit = am79900_meminit;
  159         sc->lsc.sc_start = am79900_start;
  160 
  161         lance_config(&sc->lsc);
  162 
  163         mem = 0;
  164         sc->lsc.sc_initaddr = mem;
  165         mem += sizeof(struct leinit);
  166         sc->lsc.sc_rmdaddr = mem;
  167         mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
  168         sc->lsc.sc_tmdaddr = mem;
  169         mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
  170         for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
  171                 sc->lsc.sc_rbufaddr[i] = mem;
  172         for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
  173                 sc->lsc.sc_tbufaddr[i] = mem;
  174 
  175         if (mem > sc->lsc.sc_memsize)
  176                 panic("%s: memsize", device_xname(sc->lsc.sc_dev));
  177 }
  178 
  179 /*
  180  * Set up the initialization block and the descriptor rings.
  181  */
  182 static void
  183 am79900_meminit(struct lance_softc *sc)
  184 {
  185         u_long a;
  186         int bix;
  187         struct leinit init;
  188         struct lermd rmd;
  189         struct letmd tmd;
  190         uint8_t *myaddr;
  191 
  192 #if NBPFILTER > 0
  193         if (ifp->if_flags & IFF_PROMISC)
  194                 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
  195         else
  196 #endif
  197                 init.init_mode = LE_MODE_NORMAL;
  198         if (sc->sc_initmodemedia == 1)
  199                 init.init_mode |= LE_MODE_PSEL0;
  200 
  201         init.init_mode |= ((ffs(sc->sc_ntbuf) - 1) << 28)
  202           | ((ffs(sc->sc_nrbuf) - 1) << 20);
  203 
  204         /*
  205          * Update our private copy of the Ethernet address.
  206          * We NEED the copy so we can ensure its alignment!
  207          */
  208         memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
  209         myaddr = sc->sc_enaddr;
  210 
  211         init.init_padr[0] = myaddr[0] | (myaddr[1] << 8)
  212           | (myaddr[2] << 16) | (myaddr[3] << 24);
  213         init.init_padr[1] = myaddr[4] | (myaddr[5] << 8);
  214         lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
  215 
  216         sc->sc_last_rd = 0;
  217         sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
  218 
  219         a = sc->sc_addr + LE_RMDADDR(sc, 0);
  220         init.init_rdra = a;
  221 
  222         a = sc->sc_addr + LE_TMDADDR(sc, 0);
  223         init.init_tdra = a;
  224 
  225         (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
  226 
  227         /*
  228          * Set up receive ring descriptors.
  229          */
  230         for (bix = 0; bix < sc->sc_nrbuf; bix++) {
  231                 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
  232                 rmd.rmd0 = a;
  233                 rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
  234                 rmd.rmd2 = 0;
  235                 rmd.rmd3 = 0;
  236                 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
  237                     sizeof(rmd));
  238         }
  239 
  240         /*
  241          * Set up transmit ring descriptors.
  242          */
  243         for (bix = 0; bix < sc->sc_ntbuf; bix++) {
  244                 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
  245                 tmd.tmd0 = a;
  246                 tmd.tmd1 = LE_T1_ONES;
  247                 tmd.tmd2 = 0;
  248                 tmd.tmd3 = 0;
  249                 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  250                     sizeof(tmd));
  251         }
  252 }
  253 
  254 static inline void
  255 am79900_rint(struct lance_softc *sc)
  256 {
  257         int bix;
  258         int rp;
  259         struct lermd rmd;
  260 
  261         bix = sc->sc_last_rd;
  262 
  263         /* Process all buffers with valid data. */
  264         for (;;) {
  265                 rp = LE_RMDADDR(sc, bix);
  266                 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
  267 
  268                 if (rmd.rmd1 & LE_R1_OWN)
  269                         break;
  270 
  271                 if (rmd.rmd1 & LE_R1_ERR) {
  272                         if (rmd.rmd1 & LE_R1_ENP) {
  273 #ifdef LEDEBUG
  274                                 if ((rmd.rmd1 & LE_R1_OFLO) == 0) {
  275                                         if (rmd.rmd1 & LE_R1_FRAM)
  276                                                 printf("%s: framing error\n",
  277                                                     device_xname(sc->sc_dev));
  278                                         if (rmd.rmd1 & LE_R1_CRC)
  279                                                 printf("%s: crc mismatch\n",
  280                                                     device_xname(sc->sc_dev));
  281                                 }
  282 #endif
  283                         } else {
  284                                 if (rmd.rmd1 & LE_R1_OFLO)
  285                                         printf("%s: overflow\n",
  286                                             device_xname(sc->sc_dev));
  287                         }
  288                         if (rmd.rmd1 & LE_R1_BUFF)
  289                                 printf("%s: receive buffer error\n",
  290                                     device_xname(sc->sc_dev));
  291                         ifp->if_ierrors++;
  292                 } else if ((rmd.rmd1 & (LE_R1_STP | LE_R1_ENP)) !=
  293                     (LE_R1_STP | LE_R1_ENP)) {
  294                         printf("%s: dropping chained buffer\n",
  295                             device_xname(sc->sc_dev));
  296                         ifp->if_ierrors++;
  297                 } else {
  298 #ifdef LEDEBUG
  299                         if (sc->sc_debug)
  300                                 am79900_recv_print(sc, sc->sc_last_rd);
  301 #endif
  302                         lance_read(sc, LE_RBUFADDR(sc, bix),
  303                                    (rmd.rmd2  & 0xfff) - 4);
  304                 }
  305 
  306                 rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
  307                 rmd.rmd2 = 0;
  308                 rmd.rmd3 = 0;
  309                 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
  310 
  311 #ifdef LEDEBUG
  312                 if (sc->sc_debug)
  313                         printf("sc->sc_last_rd = %x, rmd: "
  314                                "adr %08x, flags/blen %08x\n",
  315                                 sc->sc_last_rd,
  316                                 rmd.rmd0, rmd.rmd1);
  317 #endif
  318 
  319                 if (++bix == sc->sc_nrbuf)
  320                         bix = 0;
  321         }
  322 
  323         sc->sc_last_rd = bix;
  324 }
  325 
  326 static inline void
  327 am79900_tint(struct lance_softc *sc)
  328 {
  329         int bix;
  330         struct letmd tmd;
  331 
  332         bix = sc->sc_first_td;
  333 
  334         for (;;) {
  335                 if (sc->sc_no_td <= 0)
  336                         break;
  337 
  338                 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  339                     sizeof(tmd));
  340 
  341 #ifdef LEDEBUG
  342                 if (sc->sc_debug)
  343                         printf("trans tmd: "
  344                             "adr %08x, flags/blen %08x\n",
  345                             tmd.tmd0, tmd.tmd1);
  346 #endif
  347 
  348                 if (tmd.tmd1 & LE_T1_OWN)
  349                         break;
  350 
  351                 ifp->if_flags &= ~IFF_OACTIVE;
  352 
  353                 if (tmd.tmd1 & LE_T1_ERR) {
  354                         if (tmd.tmd2 & LE_T2_BUFF)
  355                                 printf("%s: transmit buffer error\n",
  356                                     device_xname(sc->sc_dev));
  357                         else if (tmd.tmd2 & LE_T2_UFLO)
  358                                 printf("%s: underflow\n",
  359                                     device_xname(sc->sc_dev));
  360                         if (tmd.tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) {
  361                                 lance_reset(sc);
  362                                 return;
  363                         }
  364                         if (tmd.tmd2 & LE_T2_LCAR) {
  365                                 sc->sc_havecarrier = 0;
  366                                 if (sc->sc_nocarrier)
  367                                         (*sc->sc_nocarrier)(sc);
  368                                 else
  369                                         printf("%s: lost carrier\n",
  370                                             device_xname(sc->sc_dev));
  371                         }
  372                         if (tmd.tmd2 & LE_T2_LCOL)
  373                                 ifp->if_collisions++;
  374                         if (tmd.tmd2 & LE_T2_RTRY) {
  375 #ifdef LEDEBUG
  376                                 printf("%s: excessive collisions\n",
  377                                     device_xname(sc->sc_dev));
  378 #endif
  379                                 ifp->if_collisions += 16;
  380                         }
  381                         ifp->if_oerrors++;
  382                 } else {
  383                         if (tmd.tmd1 & LE_T1_ONE)
  384                                 ifp->if_collisions++;
  385                         else if (tmd.tmd1 & LE_T1_MORE)
  386                                 /* Real number is unknown. */
  387                                 ifp->if_collisions += 2;
  388                         ifp->if_opackets++;
  389                 }
  390 
  391                 if (++bix == sc->sc_ntbuf)
  392                         bix = 0;
  393 
  394                 --sc->sc_no_td;
  395         }
  396 
  397         sc->sc_first_td = bix;
  398 
  399         am79900_start(ifp);
  400 
  401         if (sc->sc_no_td == 0)
  402                 ifp->if_timer = 0;
  403 }
  404 
  405 /*
  406  * Controller interrupt.
  407  */
  408 int
  409 am79900_intr(void *arg)
  410 {
  411         struct lance_softc *sc = arg;
  412         uint16_t isr;
  413 
  414         isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
  415         sc->sc_saved_csr0 = 0;
  416 #if defined(LEDEBUG) && LEDEBUG > 1
  417         if (sc->sc_debug)
  418                 printf("%s: am79900_intr entering with isr=%04x\n",
  419                     device_xname(sc->sc_dev), isr);
  420 #endif
  421         if ((isr & LE_C0_INTR) == 0)
  422                 return (0);
  423 
  424         (*sc->sc_wrcsr)(sc, LE_CSR0,
  425             isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
  426                    LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
  427         if (isr & LE_C0_ERR) {
  428                 if (isr & LE_C0_BABL) {
  429 #ifdef LEDEBUG
  430                         printf("%s: babble\n", device_xname(sc->sc_dev));
  431 #endif
  432                         ifp->if_oerrors++;
  433                 }
  434 #if 0
  435                 if (isr & LE_C0_CERR) {
  436                         printf("%s: collision error\n",
  437                             device_xname(sc->sc_dev));
  438                         ifp->if_collisions++;
  439                 }
  440 #endif
  441                 if (isr & LE_C0_MISS) {
  442 #ifdef LEDEBUG
  443                         printf("%s: missed packet\n", device_xname(sc->sc_dev));
  444 #endif
  445                         ifp->if_ierrors++;
  446                 }
  447                 if (isr & LE_C0_MERR) {
  448                         printf("%s: memory error\n", device_xname(sc->sc_dev));
  449                         lance_reset(sc);
  450                         return (1);
  451                 }
  452         }
  453 
  454         if ((isr & LE_C0_RXON) == 0) {
  455                 printf("%s: receiver disabled\n", device_xname(sc->sc_dev));
  456                 ifp->if_ierrors++;
  457                 lance_reset(sc);
  458                 return (1);
  459         }
  460         if ((isr & LE_C0_TXON) == 0) {
  461                 printf("%s: transmitter disabled\n", device_xname(sc->sc_dev));
  462                 ifp->if_oerrors++;
  463                 lance_reset(sc);
  464                 return (1);
  465         }
  466 
  467         /*
  468          * Pretend we have carrier; if we don't this will be cleared
  469          * shortly.
  470          */
  471         sc->sc_havecarrier = 1;
  472 
  473         if (isr & LE_C0_RINT)
  474                 am79900_rint(sc);
  475         if (isr & LE_C0_TINT)
  476                 am79900_tint(sc);
  477 
  478 #if NRND > 0
  479         rnd_add_uint32(&sc->rnd_source, isr);
  480 #endif
  481 
  482         return (1);
  483 }
  484 
  485 #undef  ifp
  486 
  487 /*
  488  * Setup 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  * Called only at splnet or interrupt level.
  492  */
  493 static void
  494 am79900_start(struct ifnet *ifp)
  495 {
  496         struct lance_softc *sc = ifp->if_softc;
  497         int bix;
  498         struct mbuf *m;
  499         struct letmd tmd;
  500         int rp;
  501         int len;
  502 
  503         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  504                 return;
  505 
  506         bix = sc->sc_last_td;
  507 
  508         for (;;) {
  509                 rp = LE_TMDADDR(sc, bix);
  510                 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
  511 
  512                 if (tmd.tmd1 & LE_T1_OWN) {
  513                         ifp->if_flags |= IFF_OACTIVE;
  514                         printf("missing buffer, no_td = %d, last_td = %d\n",
  515                             sc->sc_no_td, sc->sc_last_td);
  516                 }
  517 
  518                 IFQ_DEQUEUE(&ifp->if_snd, m);
  519                 if (m == 0)
  520                         break;
  521 
  522 #if NBPFILTER > 0
  523                 /*
  524                  * If BPF is listening on this interface, let it see the packet
  525                  * before we commit it to the wire.
  526                  */
  527                 if (ifp->if_bpf)
  528                         bpf_mtap(ifp->if_bpf, m);
  529 #endif
  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 + sizeof(struct ether_header))
  538                         printf("packet length %d\n", len);
  539 #endif
  540 
  541                 ifp->if_timer = 5;
  542 
  543                 /*
  544                  * Init transmit registers, and set transmit start flag.
  545                  */
  546                 tmd.tmd1 = LE_T1_OWN | LE_T1_STP | LE_T1_ENP | LE_T1_ONES | (-len & 0xfff);
  547                 tmd.tmd2 = 0;
  548                 tmd.tmd3 = 0;
  549 
  550                 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
  551 
  552 #ifdef LEDEBUG
  553                 if (sc->sc_debug)
  554                         am79900_xmit_print(sc, sc->sc_last_td);
  555 #endif
  556 
  557                 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
  558 
  559                 if (++bix == sc->sc_ntbuf)
  560                         bix = 0;
  561 
  562                 if (++sc->sc_no_td == sc->sc_ntbuf) {
  563                         ifp->if_flags |= IFF_OACTIVE;
  564                         break;
  565                 }
  566 
  567         }
  568 
  569         sc->sc_last_td = bix;
  570 }
  571 
  572 #ifdef LEDEBUG
  573 static void
  574 am79900_recv_print(struct lance_softc *sc, int no)
  575 {
  576         struct lermd rmd;
  577         uint16_t len;
  578         struct ether_header eh;
  579 
  580         (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
  581         len = (rmd.rmd2  & 0xfff) - 4;
  582         printf("%s: receive buffer %d, len = %d\n",
  583             device_xname(sc->sc_dev), no, len);
  584         printf("%s: status %04x\n", device_xname(sc->sc_dev),
  585             (*sc->sc_rdcsr)(sc, LE_CSR0));
  586         printf("%s: adr %08x, flags/blen %08x\n",
  587             device_xname(sc->sc_dev), rmd.rmd0, rmd.rmd1);
  588         if (len >= sizeof(eh)) {
  589                 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
  590                 printf("%s: dst %s", device_xname(sc->sc_dev),
  591                         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 am79900_xmit_print(struct lance_softc *sc, int no)
  599 {
  600         struct letmd tmd;
  601         uint16_t len;
  602         struct ether_header eh;
  603 
  604         (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
  605         len = -(tmd.tmd1 & 0xfff);
  606         printf("%s: transmit buffer %d, len = %d\n",
  607             device_xname(sc->sc_dev), no, len);
  608         printf("%s: status %04x\n", device_xname(sc->sc_dev),
  609             (*sc->sc_rdcsr)(sc, LE_CSR0));
  610         printf("%s: adr %08x, flags/blen %08x\n",
  611             device_xname(sc->sc_dev), tmd.tmd0, tmd.tmd1);
  612         if (len >= sizeof(eh)) {
  613                 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
  614                 printf("%s: dst %s", device_xname(sc->sc_dev),
  615                         ether_sprintf(eh.ether_dhost));
  616                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
  617                     ntohs(eh.ether_type));
  618         }
  619 }
  620 #endif /* LEDEBUG */

Cache object: eebd0b4f515e3999be8a791fe3f86975


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