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

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  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.71 2008/04/28 20:23:49 martin 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 __KERNEL_RCSID(0, "$NetBSD: am7990.c,v 1.71 2008/04/28 20:23:49 martin Exp $");
   69 
   70 #include "bpfilter.h"
   71 #include "rnd.h"
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/syslog.h>
   77 #include <sys/socket.h>
   78 #include <sys/device.h>
   79 #include <sys/malloc.h>
   80 #include <sys/ioctl.h>
   81 #include <sys/errno.h>
   82 #if NRND > 0
   83 #include <sys/rnd.h>
   84 #endif
   85 
   86 #include <net/if.h>
   87 #include <net/if_dl.h>
   88 #include <net/if_ether.h>
   89 #include <net/if_media.h>
   90 
   91 #if NBPFILTER > 0
   92 #include <net/bpf.h>
   93 #include <net/bpfdesc.h>
   94 #endif
   95 
   96 #include <dev/ic/lancereg.h>
   97 #include <dev/ic/lancevar.h>
   98 #include <dev/ic/am7990reg.h>
   99 #include <dev/ic/am7990var.h>
  100 
  101 static void     am7990_meminit(struct lance_softc *);
  102 static void     am7990_start(struct ifnet *);
  103 
  104 #if defined(_KERNEL_OPT)
  105 #include "opt_ddb.h"
  106 #endif
  107 
  108 #ifdef LEDEBUG
  109 static void     am7990_recv_print(struct lance_softc *, int);
  110 static void     am7990_xmit_print(struct lance_softc *, int);
  111 #endif
  112 
  113 #define ifp     (&sc->sc_ethercom.ec_if)
  114 
  115 void
  116 am7990_config(struct am7990_softc *sc)
  117 {
  118         int mem, i;
  119 
  120         sc->lsc.sc_meminit = am7990_meminit;
  121         sc->lsc.sc_start = am7990_start;
  122 
  123         lance_config(&sc->lsc);
  124 
  125         mem = 0;
  126         sc->lsc.sc_initaddr = mem;
  127         mem += sizeof(struct leinit);
  128         sc->lsc.sc_rmdaddr = mem;
  129         mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
  130         sc->lsc.sc_tmdaddr = mem;
  131         mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
  132         for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
  133                 sc->lsc.sc_rbufaddr[i] = mem;
  134         for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
  135                 sc->lsc.sc_tbufaddr[i] = mem;
  136 #ifdef notyet
  137         if (mem > ...)
  138                 panic(...);
  139 #endif
  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         u_long a;
  149         int bix;
  150         struct leinit init;
  151         struct lermd rmd;
  152         struct letmd tmd;
  153         uint8_t *myaddr;
  154 
  155 #if NBPFILTER > 0
  156         if (ifp->if_flags & IFF_PROMISC)
  157                 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
  158         else
  159 #endif
  160                 init.init_mode = LE_MODE_NORMAL;
  161         if (sc->sc_initmodemedia == 1)
  162                 init.init_mode |= LE_MODE_PSEL0;
  163 
  164         /*
  165          * Update our private copy of the Ethernet address.
  166          * We NEED the copy so we can ensure its alignment!
  167          */
  168         memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
  169         myaddr = sc->sc_enaddr;
  170 
  171         init.init_padr[0] = (myaddr[1] << 8) | myaddr[0];
  172         init.init_padr[1] = (myaddr[3] << 8) | myaddr[2];
  173         init.init_padr[2] = (myaddr[5] << 8) | myaddr[4];
  174         lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
  175 
  176         sc->sc_last_rd = 0;
  177         sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
  178 
  179         a = sc->sc_addr + LE_RMDADDR(sc, 0);
  180         init.init_rdra = a;
  181         init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
  182 
  183         a = sc->sc_addr + LE_TMDADDR(sc, 0);
  184         init.init_tdra = a;
  185         init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
  186 
  187         (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
  188 
  189         /*
  190          * Set up receive ring descriptors.
  191          */
  192         for (bix = 0; bix < sc->sc_nrbuf; bix++) {
  193                 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
  194                 rmd.rmd0 = a;
  195                 rmd.rmd1_hadr = a >> 16;
  196                 rmd.rmd1_bits = LE_R1_OWN;
  197                 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
  198                 rmd.rmd3 = 0;
  199                 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
  200                     sizeof(rmd));
  201         }
  202 
  203         /*
  204          * Set up transmit ring descriptors.
  205          */
  206         for (bix = 0; bix < sc->sc_ntbuf; bix++) {
  207                 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
  208                 tmd.tmd0 = a;
  209                 tmd.tmd1_hadr = a >> 16;
  210                 tmd.tmd1_bits = 0;
  211                 tmd.tmd2 = 0 | LE_XMD2_ONES;
  212                 tmd.tmd3 = 0;
  213                 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  214                     sizeof(tmd));
  215         }
  216 }
  217 
  218 static void
  219 am7990_rint(struct lance_softc *sc)
  220 {
  221         int bix;
  222         int rp;
  223         struct lermd rmd;
  224 
  225         bix = sc->sc_last_rd;
  226 
  227         /* Process all buffers with valid data. */
  228         for (;;) {
  229                 rp = LE_RMDADDR(sc, bix);
  230                 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
  231 
  232                 if (rmd.rmd1_bits & LE_R1_OWN)
  233                         break;
  234 
  235                 if (rmd.rmd1_bits & LE_R1_ERR) {
  236                         if (rmd.rmd1_bits & LE_R1_ENP) {
  237 #ifdef LEDEBUG
  238                                 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
  239                                         if (rmd.rmd1_bits & LE_R1_FRAM)
  240                                                 printf("%s: framing error\n",
  241                                                     device_xname(sc->sc_dev));
  242                                         if (rmd.rmd1_bits & LE_R1_CRC)
  243                                                 printf("%s: crc mismatch\n",
  244                                                     device_xname(sc->sc_dev));
  245                                 }
  246 #endif
  247                         } else {
  248                                 if (rmd.rmd1_bits & LE_R1_OFLO)
  249                                         printf("%s: overflow\n",
  250                                             device_xname(sc->sc_dev));
  251                         }
  252                         if (rmd.rmd1_bits & LE_R1_BUFF)
  253                                 printf("%s: receive buffer error\n",
  254                                     device_xname(sc->sc_dev));
  255                         ifp->if_ierrors++;
  256                 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
  257                     (LE_R1_STP | LE_R1_ENP)) {
  258                         printf("%s: dropping chained buffer\n",
  259                             device_xname(sc->sc_dev));
  260                         ifp->if_ierrors++;
  261                 } else {
  262 #ifdef LEDEBUG
  263                         if (sc->sc_debug > 1)
  264                                 am7990_recv_print(sc, sc->sc_last_rd);
  265 #endif
  266                         lance_read(sc, LE_RBUFADDR(sc, bix),
  267                                    (int)rmd.rmd3 - 4);
  268                 }
  269 
  270                 rmd.rmd1_bits = LE_R1_OWN;
  271                 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
  272                 rmd.rmd3 = 0;
  273                 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
  274 
  275 #ifdef LEDEBUG
  276                 if (sc->sc_debug)
  277                         printf("sc->sc_last_rd = %x, rmd: "
  278                                "ladr %04x, hadr %02x, flags %02x, "
  279                                "bcnt %04x, mcnt %04x\n",
  280                                 sc->sc_last_rd,
  281                                 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
  282                                 rmd.rmd2, rmd.rmd3);
  283 #endif
  284 
  285                 if (++bix == sc->sc_nrbuf)
  286                         bix = 0;
  287         }
  288 
  289         sc->sc_last_rd = bix;
  290 }
  291 
  292 static void
  293 am7990_tint(struct lance_softc *sc)
  294 {
  295         int bix;
  296         struct letmd tmd;
  297 
  298         bix = sc->sc_first_td;
  299 
  300         for (;;) {
  301                 if (sc->sc_no_td <= 0)
  302                         break;
  303 
  304                 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
  305                     sizeof(tmd));
  306 
  307 #ifdef LEDEBUG
  308                 if (sc->sc_debug)
  309                         printf("trans tmd: "
  310                             "ladr %04x, hadr %02x, flags %02x, "
  311                             "bcnt %04x, mcnt %04x\n",
  312                             tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
  313                             tmd.tmd2, tmd.tmd3);
  314 #endif
  315 
  316                 if (tmd.tmd1_bits & LE_T1_OWN)
  317                         break;
  318 
  319                 ifp->if_flags &= ~IFF_OACTIVE;
  320 
  321                 if (tmd.tmd1_bits & LE_T1_ERR) {
  322                         if (tmd.tmd3 & LE_T3_BUFF)
  323                                 printf("%s: transmit buffer error\n",
  324                                     device_xname(sc->sc_dev));
  325                         else if (tmd.tmd3 & LE_T3_UFLO)
  326                                 printf("%s: underflow\n",
  327                                     device_xname(sc->sc_dev));
  328                         if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
  329                                 lance_reset(sc);
  330                                 return;
  331                         }
  332                         if (tmd.tmd3 & LE_T3_LCAR) {
  333                                 sc->sc_havecarrier = 0;
  334                                 if (sc->sc_nocarrier)
  335                                         (*sc->sc_nocarrier)(sc);
  336                                 else
  337                                         printf("%s: lost carrier\n",
  338                                             device_xname(sc->sc_dev));
  339                         }
  340                         if (tmd.tmd3 & LE_T3_LCOL)
  341                                 ifp->if_collisions++;
  342                         if (tmd.tmd3 & LE_T3_RTRY) {
  343 #ifdef LEDEBUG
  344                                 printf("%s: excessive collisions, tdr %d\n",
  345                                     device_xname(sc->sc_dev),
  346                                     tmd.tmd3 & LE_T3_TDR_MASK);
  347 #endif
  348                                 ifp->if_collisions += 16;
  349                         }
  350                         ifp->if_oerrors++;
  351                 } else {
  352                         if (tmd.tmd1_bits & LE_T1_ONE)
  353                                 ifp->if_collisions++;
  354                         else if (tmd.tmd1_bits & LE_T1_MORE)
  355                                 /* Real number is unknown. */
  356                                 ifp->if_collisions += 2;
  357                         ifp->if_opackets++;
  358                 }
  359 
  360                 if (++bix == sc->sc_ntbuf)
  361                         bix = 0;
  362 
  363                 --sc->sc_no_td;
  364         }
  365 
  366         sc->sc_first_td = bix;
  367 
  368         am7990_start(ifp);
  369 
  370         if (sc->sc_no_td == 0)
  371                 ifp->if_timer = 0;
  372 }
  373 
  374 /*
  375  * Controller interrupt.
  376  */
  377 int
  378 am7990_intr(void *arg)
  379 {
  380         struct lance_softc *sc = arg;
  381         uint16_t isr;
  382 
  383         isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
  384         sc->sc_saved_csr0 = 0;
  385 #if defined(LEDEBUG) && LEDEBUG > 1
  386         if (sc->sc_debug)
  387                 printf("%s: am7990_intr entering with isr=%04x\n",
  388                     device_xname(sc->sc_dev), isr);
  389 #endif
  390         if ((isr & LE_C0_INTR) == 0)
  391                 return (0);
  392 
  393 #ifdef __vax__
  394         /*
  395          * DEC needs this write order to the registers, don't know
  396          * the results on other arch's.  Ragge 991029
  397          */
  398         isr &= ~LE_C0_INEA;
  399         (*sc->sc_wrcsr)(sc, LE_CSR0, isr);
  400         (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
  401 #else
  402         (*sc->sc_wrcsr)(sc, LE_CSR0,
  403             isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
  404                    LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
  405 #endif
  406         if (isr & LE_C0_ERR) {
  407                 if (isr & LE_C0_BABL) {
  408 #ifdef LEDEBUG
  409                         printf("%s: babble\n", device_xname(sc->sc_dev));
  410 #endif
  411                         ifp->if_oerrors++;
  412                 }
  413 #if 0
  414                 if (isr & LE_C0_CERR) {
  415                         printf("%s: collision error\n",
  416                             device_xname(sc->sc_dev));
  417                         ifp->if_collisions++;
  418                 }
  419 #endif
  420                 if (isr & LE_C0_MISS) {
  421 #ifdef LEDEBUG
  422                         printf("%s: missed packet\n", device_xname(sc->sc_dev));
  423 #endif
  424                         ifp->if_ierrors++;
  425                 }
  426                 if (isr & LE_C0_MERR) {
  427                         printf("%s: memory error\n", device_xname(sc->sc_dev));
  428                         lance_reset(sc);
  429                         return (1);
  430                 }
  431         }
  432 
  433         if ((isr & LE_C0_RXON) == 0) {
  434                 printf("%s: receiver disabled\n", device_xname(sc->sc_dev));
  435                 ifp->if_ierrors++;
  436                 lance_reset(sc);
  437                 return (1);
  438         }
  439         if ((isr & LE_C0_TXON) == 0) {
  440                 printf("%s: transmitter disabled\n", device_xname(sc->sc_dev));
  441                 ifp->if_oerrors++;
  442                 lance_reset(sc);
  443                 return (1);
  444         }
  445 
  446         /*
  447          * Pretend we have carrier; if we don't this will be cleared
  448          * shortly.
  449          */
  450         sc->sc_havecarrier = 1;
  451 
  452         if (isr & LE_C0_RINT)
  453                 am7990_rint(sc);
  454         if (isr & LE_C0_TINT)
  455                 am7990_tint(sc);
  456 
  457 #if NRND > 0
  458         rnd_add_uint32(&sc->rnd_source, isr);
  459 #endif
  460 
  461         return (1);
  462 }
  463 
  464 #undef ifp
  465 
  466 /*
  467  * Setup output on interface.
  468  * Get another datagram to send off of the interface queue, and map it to the
  469  * interface before starting the output.
  470  * Called only at splnet or interrupt level.
  471  */
  472 static void
  473 am7990_start(struct ifnet *ifp)
  474 {
  475         struct lance_softc *sc = ifp->if_softc;
  476         int bix;
  477         struct mbuf *m;
  478         struct letmd tmd;
  479         int rp;
  480         int len;
  481 
  482         if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
  483                 return;
  484 
  485         bix = sc->sc_last_td;
  486 
  487         for (;;) {
  488                 rp = LE_TMDADDR(sc, bix);
  489                 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
  490 
  491                 if (tmd.tmd1_bits & LE_T1_OWN) {
  492                         ifp->if_flags |= IFF_OACTIVE;
  493                         printf("missing buffer, no_td = %d, last_td = %d\n",
  494                             sc->sc_no_td, sc->sc_last_td);
  495                 }
  496 
  497                 IFQ_DEQUEUE(&ifp->if_snd, m);
  498                 if (m == 0)
  499                         break;
  500 
  501 #if NBPFILTER > 0
  502                 /*
  503                  * If BPF is listening on this interface, let it see the packet
  504                  * before we commit it to the wire.
  505                  */
  506                 if (ifp->if_bpf)
  507                         bpf_mtap(ifp->if_bpf, m);
  508 #endif
  509 
  510                 /*
  511                  * Copy the mbuf chain into the transmit buffer.
  512                  */
  513                 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
  514 
  515 #ifdef LEDEBUG
  516                 if (len > ETHERMTU + sizeof(struct ether_header))
  517                         printf("packet length %d\n", len);
  518 #endif
  519 
  520                 ifp->if_timer = 5;
  521 
  522                 /*
  523                  * Init transmit registers, and set transmit start flag.
  524                  */
  525                 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
  526                 tmd.tmd2 = -len | LE_XMD2_ONES;
  527                 tmd.tmd3 = 0;
  528 
  529                 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
  530 
  531 #ifdef LEDEBUG
  532                 if (sc->sc_debug > 1)
  533                         am7990_xmit_print(sc, sc->sc_last_td);
  534 #endif
  535 
  536                 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
  537 
  538                 if (++bix == sc->sc_ntbuf)
  539                         bix = 0;
  540 
  541                 if (++sc->sc_no_td == sc->sc_ntbuf) {
  542                         ifp->if_flags |= IFF_OACTIVE;
  543                         break;
  544                 }
  545 
  546         }
  547 
  548         sc->sc_last_td = bix;
  549 }
  550 
  551 #ifdef LEDEBUG
  552 static void
  553 am7990_recv_print(struct lance_softc *sc, int no)
  554 {
  555         struct lermd rmd;
  556         uint16_t len;
  557         struct ether_header eh;
  558 
  559         (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
  560         len = rmd.rmd3;
  561         printf("%s: receive buffer %d, len = %d\n",
  562             device_xname(sc->sc_dev), no, len);
  563         printf("%s: status %04x\n", device_xname(sc->sc_dev),
  564             (*sc->sc_rdcsr)(sc, LE_CSR0));
  565         printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
  566             device_xname(sc->sc_dev),
  567             rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
  568         if (len >= sizeof(eh)) {
  569                 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
  570                 printf("%s: dst %s", device_xname(sc->sc_dev),
  571                         ether_sprintf(eh.ether_dhost));
  572                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
  573                         ntohs(eh.ether_type));
  574         }
  575 }
  576 
  577 static void
  578 am7990_xmit_print(struct lance_softc *sc, int no)
  579 {
  580         struct letmd tmd;
  581         uint16_t len;
  582         struct ether_header eh;
  583 
  584         (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
  585         len = -tmd.tmd2;
  586         printf("%s: transmit buffer %d, len = %d\n",
  587             device_xname(sc->sc_dev), no, len);
  588         printf("%s: status %04x\n", device_xname(sc->sc_dev),
  589             (*sc->sc_rdcsr)(sc, LE_CSR0));
  590         printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
  591             device_xname(sc->sc_dev),
  592             tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
  593         if (len >= sizeof(eh)) {
  594                 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
  595                 printf("%s: dst %s", device_xname(sc->sc_dev),
  596                         ether_sprintf(eh.ether_dhost));
  597                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
  598                     ntohs(eh.ether_type));
  599         }
  600 }
  601 #endif /* LEDEBUG */

Cache object: 42f71b26b1afd1ec79ee1e3139462a89


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