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

Cache object: d9884638ef653aec2462995907deb4f1


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