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/smc91cxx.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: smc91cxx.c,v 1.51 2005/02/27 00:27:02 perry 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 of the Numerical Aerospace Simulation Facility,
    9  * 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  * 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) 1996 Gardner Buchanan <gbuchanan@shl.com>
   42  * All rights reserved.
   43  *
   44  * Redistribution and use in source and binary forms, with or without
   45  * modification, are permitted provided that the following conditions
   46  * are met:
   47  * 1. Redistributions of source code must retain the above copyright
   48  *    notice, this list of conditions and the following disclaimer.
   49  * 2. Redistributions in binary form must reproduce the above copyright
   50  *    notice, this list of conditions and the following disclaimer in the
   51  *    documentation and/or other materials provided with the distribution.
   52  * 3. All advertising materials mentioning features or use of this software
   53  *    must display the following acknowledgement:
   54  *      This product includes software developed by Gardner Buchanan.
   55  * 4. The name of Gardner Buchanan may not be used to endorse or promote
   56  *    products derived from this software without specific prior written
   57  *    permission.
   58  *
   59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   69  *
   70  *   from FreeBSD Id: if_sn.c,v 1.4 1996/03/18 15:47:16 gardner Exp
   71  */
   72 
   73 /*
   74  * Core driver for the SMC 91Cxx family of Ethernet chips.
   75  *
   76  * Memory allocation interrupt logic is drived from an SMC 91C90 driver
   77  * written for NetBSD/amiga by Michael Hitch.
   78  */
   79 
   80 #include <sys/cdefs.h>
   81 __KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.51 2005/02/27 00:27:02 perry Exp $");
   82 
   83 #include "opt_inet.h"
   84 #include "opt_ccitt.h"
   85 #include "opt_llc.h"
   86 #include "opt_ns.h"
   87 #include "bpfilter.h"
   88 #include "rnd.h"
   89 
   90 #include <sys/param.h>
   91 #include <sys/systm.h>
   92 #include <sys/mbuf.h>
   93 #include <sys/syslog.h>
   94 #include <sys/socket.h>
   95 #include <sys/device.h>
   96 #include <sys/kernel.h>
   97 #include <sys/malloc.h>
   98 #include <sys/ioctl.h>
   99 #include <sys/errno.h>
  100 #if NRND > 0
  101 #include <sys/rnd.h>
  102 #endif
  103 
  104 #include <machine/bus.h>
  105 #include <machine/intr.h>
  106 
  107 #include <net/if.h>
  108 #include <net/if_dl.h>
  109 #include <net/if_ether.h>
  110 #include <net/if_media.h>
  111 
  112 #ifdef INET
  113 #include <netinet/in.h>
  114 #include <netinet/if_inarp.h>
  115 #include <netinet/in_systm.h>
  116 #include <netinet/in_var.h>
  117 #include <netinet/ip.h>
  118 #endif
  119 
  120 #ifdef NS
  121 #include <netns/ns.h>
  122 #include <netns/ns_if.h>
  123 #endif
  124 
  125 #if defined(CCITT) && defined(LLC)
  126 #include <sys/socketvar.h>
  127 #include <netccitt/x25.h>
  128 #include <netccitt/pk.h>
  129 #include <netccitt/pk_var.h>
  130 #include <netccitt/pk_extern.h>
  131 #endif
  132 
  133 #if NBPFILTER > 0
  134 #include <net/bpf.h>
  135 #include <net/bpfdesc.h>
  136 #endif
  137 
  138 #include <dev/mii/mii.h>
  139 #include <dev/mii/miivar.h>
  140 #include <dev/mii/mii_bitbang.h>
  141 
  142 #include <dev/ic/smc91cxxreg.h>
  143 #include <dev/ic/smc91cxxvar.h>
  144 
  145 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
  146 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
  147 #define bus_space_write_multi_stream_4 bus_space_write_multi_4
  148 #define bus_space_read_multi_stream_2  bus_space_read_multi_2
  149 #define bus_space_read_multi_stream_4  bus_space_read_multi_4
  150 
  151 #define bus_space_write_stream_4 bus_space_write_4
  152 #define bus_space_read_stream_4  bus_space_read_4
  153 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
  154 
  155 /* XXX Hardware padding doesn't work yet(?) */
  156 #define SMC91CXX_SW_PAD
  157 
  158 const char *smc91cxx_idstrs[] = {
  159         NULL,                           /* 0 */
  160         NULL,                           /* 1 */
  161         NULL,                           /* 2 */
  162         "SMC91C90/91C92",               /* 3 */
  163         "SMC91C94/91C96",               /* 4 */
  164         "SMC91C95",                     /* 5 */
  165         NULL,                           /* 6 */
  166         "SMC91C100",                    /* 7 */
  167         "SMC91C100FD",                  /* 8 */
  168         "SMC91C111",                    /* 9 */
  169         NULL,                           /* 10 */
  170         NULL,                           /* 11 */
  171         NULL,                           /* 12 */
  172         NULL,                           /* 13 */
  173         NULL,                           /* 14 */
  174         NULL,                           /* 15 */
  175 };
  176 
  177 /* Supported media types. */
  178 const int smc91cxx_media[] = {
  179         IFM_ETHER|IFM_10_T,
  180         IFM_ETHER|IFM_10_5,
  181 };
  182 #define NSMC91CxxMEDIA  (sizeof(smc91cxx_media) / sizeof(smc91cxx_media[0]))
  183 
  184 /*
  185  * MII bit-bang glue.
  186  */
  187 u_int32_t smc91cxx_mii_bitbang_read(struct device *);
  188 void smc91cxx_mii_bitbang_write(struct device *, u_int32_t);
  189 
  190 const struct mii_bitbang_ops smc91cxx_mii_bitbang_ops = {
  191         smc91cxx_mii_bitbang_read,
  192         smc91cxx_mii_bitbang_write,
  193         {
  194                 MR_MDO,         /* MII_BIT_MDO */
  195                 MR_MDI,         /* MII_BIT_MDI */
  196                 MR_MCLK,        /* MII_BIT_MDC */
  197                 MR_MDOE,        /* MII_BIT_DIR_HOST_PHY */
  198                 0,              /* MII_BIT_DIR_PHY_HOST */
  199         }
  200 };
  201 
  202 /* MII callbacks */
  203 int     smc91cxx_mii_readreg(struct device *, int, int);
  204 void    smc91cxx_mii_writereg(struct device *, int, int, int);
  205 void    smc91cxx_statchg(struct device *);
  206 void    smc91cxx_tick(void *);
  207 
  208 int     smc91cxx_mediachange(struct ifnet *);
  209 void    smc91cxx_mediastatus(struct ifnet *, struct ifmediareq *);
  210 
  211 int     smc91cxx_set_media(struct smc91cxx_softc *, int);
  212 
  213 void    smc91cxx_init(struct smc91cxx_softc *);
  214 void    smc91cxx_read(struct smc91cxx_softc *);
  215 void    smc91cxx_reset(struct smc91cxx_softc *);
  216 void    smc91cxx_start(struct ifnet *);
  217 void    smc91cxx_copy_tx_frame(struct smc91cxx_softc *, struct mbuf *);
  218 void    smc91cxx_resume(struct smc91cxx_softc *);
  219 void    smc91cxx_stop(struct smc91cxx_softc *);
  220 void    smc91cxx_watchdog(struct ifnet *);
  221 int     smc91cxx_ioctl(struct ifnet *, u_long, caddr_t);
  222 
  223 static __inline int ether_cmp(void *, void *);
  224 static __inline int
  225 ether_cmp(va, vb)
  226         void *va, *vb;
  227 {
  228         u_int8_t *a = va;
  229         u_int8_t *b = vb;
  230 
  231         return ((a[5] != b[5]) || (a[4] != b[4]) || (a[3] != b[3]) ||
  232                 (a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
  233 }
  234 
  235 void
  236 smc91cxx_attach(sc, myea)
  237         struct smc91cxx_softc *sc;
  238         u_int8_t *myea;
  239 {
  240         struct ifnet *ifp = &sc->sc_ec.ec_if;
  241         bus_space_tag_t bst = sc->sc_bst;
  242         bus_space_handle_t bsh = sc->sc_bsh;
  243         struct ifmedia *ifm = &sc->sc_mii.mii_media;
  244         const char *idstr;
  245         u_int32_t miicapabilities;
  246         u_int16_t tmp;
  247         u_int8_t enaddr[ETHER_ADDR_LEN];
  248         int i, aui, mult, scale, memsize;
  249         char pbuf[9];
  250 
  251         tmp = bus_space_read_2(bst, bsh, BANK_SELECT_REG_W);
  252         /* check magic number */
  253         if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
  254                 aprint_error("%s: failed to detect chip, bsr=%04x\n",
  255                     sc->sc_dev.dv_xname, tmp);
  256                 return;
  257         }
  258 
  259         /* Make sure the chip is stopped. */
  260         smc91cxx_stop(sc);
  261 
  262         SMC_SELECT_BANK(sc, 3);
  263         tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
  264         sc->sc_chipid = RR_ID(tmp);
  265         idstr = smc91cxx_idstrs[sc->sc_chipid];
  266 
  267         aprint_normal("%s: ", sc->sc_dev.dv_xname);
  268         if (idstr != NULL)
  269                 aprint_normal("%s, ", idstr);
  270         else
  271                 aprint_normal("unknown chip id %d, ", sc->sc_chipid);
  272         aprint_normal("revision %d, ", RR_REV(tmp));
  273 
  274         SMC_SELECT_BANK(sc, 0);
  275         switch (sc->sc_chipid) {
  276         default:
  277                 mult = MCR_MEM_MULT(bus_space_read_2(bst, bsh, MEM_CFG_REG_W));
  278                 scale = MIR_SCALE_91C9x;
  279                 break;
  280 
  281         case CHIP_91C111:
  282                 mult = MIR_MULT_91C111;
  283                 scale = MIR_SCALE_91C111;
  284         }
  285         memsize = bus_space_read_2(bst, bsh, MEM_INFO_REG_W) & MIR_TOTAL_MASK;
  286         if (memsize == 255) memsize++;
  287         memsize *= scale * mult;
  288 
  289         format_bytes(pbuf, sizeof(pbuf), memsize);
  290         aprint_normal("buffer size: %s\n", pbuf);
  291 
  292         /* Read the station address from the chip. */
  293         SMC_SELECT_BANK(sc, 1);
  294         if (myea == NULL) {
  295                 myea = enaddr;
  296                 for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
  297                         tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
  298                         myea[i + 1] = (tmp >> 8) & 0xff;
  299                         myea[i] = tmp & 0xff;
  300                 }
  301         }
  302         aprint_normal("%s: MAC address %s, ", sc->sc_dev.dv_xname,
  303             ether_sprintf(myea));
  304 
  305         /* Initialize the ifnet structure. */
  306         strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
  307         ifp->if_softc = sc;
  308         ifp->if_start = smc91cxx_start;
  309         ifp->if_ioctl = smc91cxx_ioctl;
  310         ifp->if_watchdog = smc91cxx_watchdog;
  311         ifp->if_flags =
  312             IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
  313         IFQ_SET_READY(&ifp->if_snd);
  314 
  315         /* Attach the interface. */
  316         if_attach(ifp);
  317         ether_ifattach(ifp, myea);
  318 
  319         /*
  320          * Initialize our media structures and MII info.  We will
  321          * probe the MII if we are on the SMC91Cxx
  322          */
  323         sc->sc_mii.mii_ifp = ifp;
  324         sc->sc_mii.mii_readreg = smc91cxx_mii_readreg;
  325         sc->sc_mii.mii_writereg = smc91cxx_mii_writereg;
  326         sc->sc_mii.mii_statchg = smc91cxx_statchg;
  327         ifmedia_init(ifm, IFM_IMASK, smc91cxx_mediachange, smc91cxx_mediastatus);
  328 
  329         SMC_SELECT_BANK(sc, 1);
  330         tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
  331 
  332         miicapabilities = BMSR_MEDIAMASK|BMSR_ANEG;
  333         switch (sc->sc_chipid) {
  334         case CHIP_91100:
  335                 /*
  336                  * The 91100 does not have full-duplex capabilities,
  337                  * even if the PHY does.
  338                  */
  339                 miicapabilities &= ~(BMSR_100TXFDX | BMSR_10TFDX);
  340         case CHIP_91100FD:
  341         case CHIP_91C111:
  342                 if (tmp & CR_MII_SELECT) {
  343                         aprint_normal("default media MII");
  344                         if (sc->sc_chipid == CHIP_91C111) {
  345                                 aprint_normal(" (%s PHY)\n", (tmp & CR_AUI_SELECT) ?
  346                                     "external" : "internal");
  347                                 sc->sc_internal_phy = !(tmp & CR_AUI_SELECT);
  348                         } else
  349                                 aprint_normal("\n");
  350                         mii_attach(&sc->sc_dev, &sc->sc_mii, miicapabilities,
  351                             MII_PHY_ANY, MII_OFFSET_ANY, 0);
  352                         if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
  353                                 ifmedia_add(&sc->sc_mii.mii_media,
  354                                     IFM_ETHER|IFM_NONE, 0, NULL);
  355                                 ifmedia_set(&sc->sc_mii.mii_media,
  356                                     IFM_ETHER|IFM_NONE);
  357                         } else {
  358                                 ifmedia_set(&sc->sc_mii.mii_media,
  359                                     IFM_ETHER|IFM_AUTO);
  360                         }
  361                         sc->sc_flags |= SMC_FLAGS_HAS_MII;
  362                         break;
  363                 } else
  364                 if (sc->sc_chipid == CHIP_91C111) {
  365                         /*
  366                          * XXX: Should bring it out of low-power mode
  367                          */
  368                         aprint_normal("EPH interface in low power mode\n");
  369                         sc->sc_internal_phy = 0;
  370                         return;
  371                 }
  372                 /*FALLTHROUGH*/
  373         default:
  374                 aprint_normal("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
  375                     "AUI" : "UTP");
  376                 for (i = 0; i < NSMC91CxxMEDIA; i++)
  377                         ifmedia_add(ifm, smc91cxx_media[i], 0, NULL);
  378                 ifmedia_set(ifm, IFM_ETHER | (aui ? IFM_10_5 : IFM_10_T));
  379                 break;
  380         }
  381 
  382 #if NRND > 0
  383         rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
  384                           RND_TYPE_NET, 0);
  385 #endif
  386 
  387         /* The attach is successful. */
  388         sc->sc_flags |= SMC_FLAGS_ATTACHED;
  389 }
  390 
  391 /*
  392  * Change media according to request.
  393  */
  394 int
  395 smc91cxx_mediachange(ifp)
  396         struct ifnet *ifp;
  397 {
  398         struct smc91cxx_softc *sc = ifp->if_softc;
  399 
  400         return (smc91cxx_set_media(sc, sc->sc_mii.mii_media.ifm_media));
  401 }
  402 
  403 int
  404 smc91cxx_set_media(sc, media)
  405         struct smc91cxx_softc *sc;
  406         int media;
  407 {
  408         bus_space_tag_t bst = sc->sc_bst;
  409         bus_space_handle_t bsh = sc->sc_bsh;
  410         u_int16_t tmp;
  411 
  412         /*
  413          * If the interface is not currently powered on, just return.
  414          * When it is enabled later, smc91cxx_init() will properly set
  415          * up the media for us.
  416          */
  417         if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0)
  418                 return (0);
  419 
  420         if (IFM_TYPE(media) != IFM_ETHER)
  421                 return (EINVAL);
  422 
  423         if (sc->sc_flags & SMC_FLAGS_HAS_MII)
  424                 return (mii_mediachg(&sc->sc_mii));
  425 
  426         switch (IFM_SUBTYPE(media)) {
  427         case IFM_10_T:
  428         case IFM_10_5:
  429                 SMC_SELECT_BANK(sc, 1);
  430                 tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
  431                 if (IFM_SUBTYPE(media) == IFM_10_5)
  432                         tmp |= CR_AUI_SELECT;
  433                 else
  434                         tmp &= ~CR_AUI_SELECT;
  435                 bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
  436                 delay(20000);   /* XXX is this needed? */
  437                 break;
  438 
  439         default:
  440                 return (EINVAL);
  441         }
  442 
  443         return (0);
  444 }
  445 
  446 /*
  447  * Notify the world which media we're using.
  448  */
  449 void
  450 smc91cxx_mediastatus(ifp, ifmr)
  451         struct ifnet *ifp;
  452         struct ifmediareq *ifmr;
  453 {
  454         struct smc91cxx_softc *sc = ifp->if_softc;
  455         bus_space_tag_t bst = sc->sc_bst;
  456         bus_space_handle_t bsh = sc->sc_bsh;
  457         u_int16_t tmp;
  458 
  459         if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
  460                 ifmr->ifm_active = IFM_ETHER | IFM_NONE;
  461                 ifmr->ifm_status = 0;
  462                 return;
  463         }
  464 
  465         /*
  466          * If we have MII, go ask the PHY what's going on.
  467          */
  468         if (sc->sc_flags & SMC_FLAGS_HAS_MII) {
  469                 mii_pollstat(&sc->sc_mii);
  470                 ifmr->ifm_active = sc->sc_mii.mii_media_active;
  471                 ifmr->ifm_status = sc->sc_mii.mii_media_status;
  472                 return;
  473         }
  474 
  475         SMC_SELECT_BANK(sc, 1);
  476         tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
  477         ifmr->ifm_active =
  478             IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
  479 }
  480 
  481 /*
  482  * Reset and initialize the chip.
  483  */
  484 void
  485 smc91cxx_init(sc)
  486         struct smc91cxx_softc *sc;
  487 {
  488         struct ifnet *ifp = &sc->sc_ec.ec_if;
  489         bus_space_tag_t bst = sc->sc_bst;
  490         bus_space_handle_t bsh = sc->sc_bsh;
  491         u_int16_t tmp;
  492         u_int8_t *enaddr;
  493         int s, i;
  494 
  495         s = splnet();
  496 
  497         /*
  498          * This resets the registers mostly to defaults, but doesn't
  499          * affect the EEPROM.  After the reset cycle, we pause briefly
  500          * for the chip to recover.
  501          *
  502          * XXX how long are we really supposed to delay?  --thorpej
  503          */
  504         SMC_SELECT_BANK(sc, 0);
  505         bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
  506         delay(100);
  507         bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
  508         delay(200);
  509 
  510         bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
  511 
  512         /* Set the Ethernet address. */
  513         SMC_SELECT_BANK(sc, 1);
  514         enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
  515         for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
  516                 tmp = enaddr[i + 1] << 8 | enaddr[i];
  517                 bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
  518         }
  519 
  520         /*
  521          * Set the control register to automatically release successfully
  522          * transmitted packets (making the best use of our limited memory)
  523          * and enable the EPH interrupt on certain TX errors.
  524          */
  525         bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
  526             CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
  527 
  528         /*
  529          * Reset the MMU and wait for it to be un-busy.
  530          */
  531         SMC_SELECT_BANK(sc, 2);
  532         bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
  533         for (;;) {
  534                 tmp = bus_space_read_2(bst, bsh, MMU_CMD_REG_W);
  535                 if (tmp == 0xffff)      /* card went away! */
  536                         return;
  537                 if ((tmp & MMUCR_BUSY) == 0)
  538                         break;
  539         }
  540 
  541         /*
  542          * Disable all interrupts.
  543          */
  544         bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
  545 
  546         /*
  547          * On the 91c111, enable auto-negotiation, and set the LED
  548          * status pins to something sane.
  549          * XXX: Should be some way for MD code to decide the latter.
  550          */
  551         SMC_SELECT_BANK(sc, 0);
  552         if (sc->sc_chipid == CHIP_91C111) {
  553                 bus_space_write_2(bst, bsh, RX_PHY_CONTROL_REG_W,
  554                     RPC_ANEG |
  555                     (RPC_LS_LINK_DETECT << RPC_LSA_SHIFT) |
  556                     (RPC_LS_TXRX << RPC_LSB_SHIFT));
  557         }
  558 
  559         /*
  560          * Set current media.
  561          */
  562         smc91cxx_set_media(sc, sc->sc_mii.mii_media.ifm_cur->ifm_media);
  563 
  564         /*
  565          * Set the receive filter.  We want receive enable and auto
  566          * strip of CRC from received packet.  If we are in promisc. mode,
  567          * then set that bit as well.
  568          *
  569          * XXX Initialize multicast filter.  For now, we just accept
  570          * XXX all multicast.
  571          */
  572         SMC_SELECT_BANK(sc, 0);
  573 
  574         tmp = RCR_ENABLE | RCR_STRIP_CRC | RCR_ALMUL;
  575         if (ifp->if_flags & IFF_PROMISC)
  576                 tmp |= RCR_PROMISC;
  577 
  578         bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
  579 
  580         /*
  581          * Set transmitter control to "enabled".
  582          */
  583         tmp = TCR_ENABLE;
  584 
  585 #ifndef SMC91CXX_SW_PAD
  586         /*
  587          * Enable hardware padding of transmitted packets.
  588          * XXX doesn't work?
  589          */
  590         tmp |= TCR_PAD_ENABLE;
  591 #endif
  592 
  593         bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
  594 
  595         /*
  596          * Now, enable interrupts.
  597          */
  598         SMC_SELECT_BANK(sc, 2);
  599 
  600         if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy) {
  601                 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
  602                     IM_EPH_INT | IM_RX_OVRN_INT |
  603                     IM_RCV_INT | IM_TX_INT | IM_MD_INT);
  604         } else {
  605                 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
  606                     IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
  607         }
  608 
  609         /* Interface is now running, with no output active. */
  610         ifp->if_flags |= IFF_RUNNING;
  611         ifp->if_flags &= ~IFF_OACTIVE;
  612 
  613         if (sc->sc_flags & SMC_FLAGS_HAS_MII) {
  614                 /* Start the one second clock. */
  615                 callout_reset(&sc->sc_mii_callout, hz, smc91cxx_tick, sc);
  616         }
  617 
  618         /*
  619          * Attempt to start any pending transmission.
  620          */
  621         smc91cxx_start(ifp);
  622 
  623         splx(s);
  624 }
  625 
  626 /*
  627  * Start output on an interface.
  628  * Must be called at splnet or interrupt level.
  629  */
  630 void
  631 smc91cxx_start(ifp)
  632         struct ifnet *ifp;
  633 {
  634         struct smc91cxx_softc *sc = ifp->if_softc;
  635         bus_space_tag_t bst = sc->sc_bst;
  636         bus_space_handle_t bsh = sc->sc_bsh;
  637         u_int len;
  638         struct mbuf *m;
  639         u_int16_t length, npages;
  640         u_int8_t packetno;
  641         int timo, pad;
  642 
  643         if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
  644                 return;
  645 
  646  again:
  647         /*
  648          * Peek at the next packet.
  649          */
  650         IFQ_POLL(&ifp->if_snd, m);
  651         if (m == NULL)
  652                 return;
  653 
  654         /*
  655          * Compute the frame length and set pad to give an overall even
  656          * number of bytes.  Below, we assume that the packet length
  657          * is even.
  658          */
  659         for (len = 0; m != NULL; m = m->m_next)
  660                 len += m->m_len;
  661         pad = (len & 1);
  662 
  663         /*
  664          * We drop packets that are too large.  Perhaps we should
  665          * truncate them instead?
  666          */
  667         if ((len + pad) > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
  668                 printf("%s: large packet discarded\n", sc->sc_dev.dv_xname);
  669                 ifp->if_oerrors++;
  670                 IFQ_DEQUEUE(&ifp->if_snd, m);
  671                 m_freem(m);
  672                 goto readcheck;
  673         }
  674 
  675 #ifdef SMC91CXX_SW_PAD
  676         /*
  677          * Not using hardware padding; pad to ETHER_MIN_LEN.
  678          */
  679         if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN))
  680                 pad = ETHER_MIN_LEN - ETHER_CRC_LEN - len;
  681 #endif
  682 
  683         length = pad + len;
  684 
  685         /*
  686          * The MMU has a 256 byte page size.  The MMU expects us to
  687          * ask for "npages - 1".  We include space for the status word,
  688          * byte count, and control bytes in the allocation request.
  689          */
  690         npages = (length + 6) >> 8;
  691 
  692         /*
  693          * Now allocate the memory.
  694          */
  695         SMC_SELECT_BANK(sc, 2);
  696         bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
  697 
  698         timo = MEMORY_WAIT_TIME;
  699         do {
  700                 if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
  701                         break;
  702                 delay(1);
  703         } while (--timo);
  704 
  705         packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
  706 
  707         if (packetno & ARR_FAILED || timo == 0) {
  708                 /*
  709                  * No transmit memory is available.  Record the number
  710                  * of requestd pages and enable the allocation completion
  711                  * interrupt.  Set up the watchdog timer in case we miss
  712                  * the interrupt.  Mark the interface as active so that
  713                  * no one else attempts to transmit while we're allocating
  714                  * memory.
  715                  */
  716                 bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
  717                     bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
  718 
  719                 ifp->if_timer = 5;
  720                 ifp->if_flags |= IFF_OACTIVE;
  721 
  722                 return;
  723         }
  724 
  725         /*
  726          * We have a packet number - set the data window.
  727          */
  728         bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
  729 
  730         /*
  731          * Point to the beginning of the packet.
  732          */
  733         bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
  734 
  735         /*
  736          * Send the packet length (+6 for stats, length, and control bytes)
  737          * and the status word (set to zeros).
  738          */
  739         bus_space_write_2(bst, bsh, DATA_REG_W, 0);
  740         bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
  741         bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
  742 
  743         /*
  744          * Get the packet from the kernel.  This will include the Ethernet
  745          * frame header, MAC address, etc.
  746          */
  747         IFQ_DEQUEUE(&ifp->if_snd, m);
  748 
  749         /*
  750          * Push the packet out to the card.
  751          */
  752         smc91cxx_copy_tx_frame(sc, m);
  753 
  754 #ifdef SMC91CXX_SW_PAD
  755         /*
  756          * Push out padding.
  757          */
  758         while (pad > 1) {
  759                 bus_space_write_2(bst, bsh, DATA_REG_W, 0);
  760                 pad -= 2;
  761         }
  762         if (pad)
  763                 bus_space_write_1(bst, bsh, DATA_REG_B, 0);
  764 #endif
  765 
  766         /*
  767          * Push out control byte and unused packet byte.  The control byte
  768          * is 0, meaning the packet is even lengthed and no special
  769          * CRC handling is necessary.
  770          */
  771         bus_space_write_2(bst, bsh, DATA_REG_W, 0);
  772 
  773         /*
  774          * Enable transmit interrupts and let the chip go.  Set a watchdog
  775          * in case we miss the interrupt.
  776          */
  777         bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
  778             bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
  779             IM_TX_INT | IM_TX_EMPTY_INT);
  780 
  781         bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
  782 
  783         ifp->if_timer = 5;
  784 
  785 #if NBPFILTER > 0
  786         /* Hand off a copy to the bpf. */
  787         if (ifp->if_bpf)
  788                 bpf_mtap(ifp->if_bpf, m);
  789 #endif
  790 
  791         ifp->if_opackets++;
  792         m_freem(m);
  793 
  794  readcheck:
  795         /*
  796          * Check for incoming pcakets.  We don't want to overflow the small
  797          * RX FIFO.  If nothing has arrived, attempt to queue another
  798          * transmit packet.
  799          */
  800         if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
  801                 goto again;
  802 }
  803 
  804 /*
  805  * Squirt a (possibly misaligned) mbuf to the device
  806  */
  807 void
  808 smc91cxx_copy_tx_frame(sc, m0)
  809         struct smc91cxx_softc *sc;
  810         struct mbuf *m0;
  811 {
  812         bus_space_tag_t bst = sc->sc_bst;
  813         bus_space_handle_t bsh = sc->sc_bsh;
  814         struct mbuf *m;
  815         int len, leftover;
  816         u_int16_t dbuf;
  817         u_int8_t *p;
  818 #ifdef DIAGNOSTIC
  819         u_int8_t *lim;
  820 #endif
  821 
  822         /* start out with no leftover data */
  823         leftover = 0;
  824         dbuf = 0;
  825 
  826         /* Process the chain of mbufs */
  827         for (m = m0; m != NULL; m = m->m_next) {
  828                 /*
  829                  * Process all of the data in a single mbuf.
  830                  */
  831                 p = mtod(m, u_int8_t *);
  832                 len = m->m_len;
  833 #ifdef DIAGNOSTIC
  834                 lim = p + len;
  835 #endif
  836 
  837                 while (len > 0) {
  838                         if (leftover) {
  839                                 /*
  840                                  * Data left over (from mbuf or realignment).
  841                                  * Buffer the next byte, and write it and
  842                                  * the leftover data out.
  843                                  */
  844                                 dbuf |= *p++ << 8;
  845                                 len--;
  846                                 bus_space_write_2(bst, bsh, DATA_REG_W, dbuf);
  847                                 leftover = 0;
  848                         } else if ((long) p & 1) {
  849                                 /*
  850                                  * Misaligned data.  Buffer the next byte.
  851                                  */
  852                                 dbuf = *p++;
  853                                 len--;
  854                                 leftover = 1;
  855                         } else {
  856                                 /*
  857                                  * Aligned data.  This is the case we like.
  858                                  *
  859                                  * Write-region out as much as we can, then
  860                                  * buffer the remaining byte (if any).
  861                                  */
  862                                 leftover = len & 1;
  863                                 len &= ~1;
  864                                 bus_space_write_multi_stream_2(bst, bsh,
  865                                     DATA_REG_W, (u_int16_t *)p, len >> 1);
  866                                 p += len;
  867 
  868                                 if (leftover)
  869                                         dbuf = *p++;
  870                                 len = 0;
  871                         }
  872                 }
  873                 if (len < 0)
  874                         panic("smc91cxx_copy_tx_frame: negative len");
  875 #ifdef DIAGNOSTIC
  876                 if (p != lim)
  877                         panic("smc91cxx_copy_tx_frame: p != lim");
  878 #endif
  879         }
  880         if (leftover)
  881                 bus_space_write_1(bst, bsh, DATA_REG_B, dbuf);
  882 }
  883 
  884 /*
  885  * Interrupt service routine.
  886  */
  887 int
  888 smc91cxx_intr(arg)
  889         void *arg;
  890 {
  891         struct smc91cxx_softc *sc = arg;
  892         struct ifnet *ifp = &sc->sc_ec.ec_if;
  893         bus_space_tag_t bst = sc->sc_bst;
  894         bus_space_handle_t bsh = sc->sc_bsh;
  895         u_int8_t mask, interrupts, status;
  896         u_int16_t packetno, tx_status, card_stats;
  897 
  898         if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 ||
  899             (sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
  900                 return (0);
  901 
  902         SMC_SELECT_BANK(sc, 2);
  903 
  904         /*
  905          * Obtain the current interrupt mask.
  906          */
  907         mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
  908 
  909         /*
  910          * Get the set of interrupt which occurred and eliminate any
  911          * which are not enabled.
  912          */
  913         interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
  914         status = interrupts & mask;
  915 
  916         /* Ours? */
  917         if (status == 0)
  918                 return (0);
  919 
  920         /*
  921          * It's ours; disable all interrupts while we process them.
  922          */
  923         bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
  924 
  925         /*
  926          * Receive overrun interrupts.
  927          */
  928         if (status & IM_RX_OVRN_INT) {
  929                 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
  930                 ifp->if_ierrors++;
  931         }
  932 
  933         /*
  934          * Receive interrupts.
  935          */
  936         if (status & IM_RCV_INT) {
  937 #if 1 /* DIAGNOSTIC */
  938                 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
  939                 if (packetno & FIFO_REMPTY) {
  940                         printf("%s: receive interrupt on empty fifo\n",
  941                             sc->sc_dev.dv_xname);
  942                         goto out;
  943                 } else
  944 #endif
  945                 smc91cxx_read(sc);
  946         }
  947 
  948         /*
  949          * Memory allocation interrupts.
  950          */
  951         if (status & IM_ALLOC_INT) {
  952                 /* Disable this interrupt. */
  953                 mask &= ~IM_ALLOC_INT;
  954 
  955                 /*
  956                  * Release the just-allocated memory.  We will reallocate
  957                  * it through the normal start logic.
  958                  */
  959                 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
  960                         /* XXX bound this loop! */ ;
  961                 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
  962 
  963                 ifp->if_flags &= ~IFF_OACTIVE;
  964                 ifp->if_timer = 0;
  965         }
  966 
  967         /*
  968          * Transmit complete interrupt.  Handle transmission error messages.
  969          * This will only be called on error condition because of AUTO RELEASE
  970          * mode.
  971          */
  972         if (status & IM_TX_INT) {
  973                 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
  974 
  975                 packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
  976                     FIFO_TX_MASK;
  977 
  978                 /*
  979                  * Select this as the packet to read from.
  980                  */
  981                 bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
  982 
  983                 /*
  984                  * Position the pointer to the beginning of the packet.
  985                  */
  986                 bus_space_write_2(bst, bsh, POINTER_REG_W,
  987                     PTR_AUTOINC | PTR_READ /* | 0x0000 */);
  988 
  989                 /*
  990                  * Fetch the TX status word.  This will be a copy of
  991                  * the EPH_STATUS_REG_W at the time of the transmission
  992                  * failure.
  993                  */
  994                 tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
  995 
  996                 if (tx_status & EPHSR_TX_SUC)
  997                         printf("%s: successful packet caused TX interrupt?!\n",
  998                             sc->sc_dev.dv_xname);
  999                 else
 1000                         ifp->if_oerrors++;
 1001 
 1002                 if (tx_status & EPHSR_LATCOL)
 1003                         ifp->if_collisions++;
 1004 
 1005                 /*
 1006                  * Some of these errors disable the transmitter; reenable it.
 1007                  */
 1008                 SMC_SELECT_BANK(sc, 0);
 1009 #ifdef SMC91CXX_SW_PAD
 1010                 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
 1011 #else
 1012                 bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
 1013                     TCR_ENABLE | TCR_PAD_ENABLE);
 1014 #endif
 1015 
 1016                 /*
 1017                  * Kill the failed packet and wait for the MMU to unbusy.
 1018                  */
 1019                 SMC_SELECT_BANK(sc, 2);
 1020                 while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
 1021                         /* XXX bound this loop! */ ;
 1022                 bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
 1023 
 1024                 ifp->if_timer = 0;
 1025         }
 1026 
 1027         /*
 1028          * Transmit underrun interrupts.  We use this opportunity to
 1029          * update transmit statistics from the card.
 1030          */
 1031         if (status & IM_TX_EMPTY_INT) {
 1032                 bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
 1033 
 1034                 /* Disable this interrupt. */
 1035                 mask &= ~IM_TX_EMPTY_INT;
 1036 
 1037                 SMC_SELECT_BANK(sc, 0);
 1038                 card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
 1039 
 1040                 /* Single collisions. */
 1041                 ifp->if_collisions += card_stats & ECR_COLN_MASK;
 1042 
 1043                 /* Multiple collisions. */
 1044                 ifp->if_collisions += (card_stats & ECR_MCOLN_MASK) >> 4;
 1045 
 1046                 SMC_SELECT_BANK(sc, 2);
 1047 
 1048                 ifp->if_timer = 0;
 1049         }
 1050 
 1051         if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy &&
 1052             (status & IM_MD_INT)) {
 1053                 /*
 1054                  * Internal PHY status change
 1055                  */
 1056                 mii_tick(&sc->sc_mii);
 1057         }
 1058 
 1059         /*
 1060          * Other errors.  Reset the interface.
 1061          */
 1062         if (status & IM_EPH_INT) {
 1063                 smc91cxx_stop(sc);
 1064                 smc91cxx_init(sc);
 1065         }
 1066 
 1067         /*
 1068          * Attempt to queue more packets for transmission.
 1069          */
 1070         smc91cxx_start(ifp);
 1071 
 1072 out:
 1073         /*
 1074          * Reenable the interrupts we wish to receive now that processing
 1075          * is complete.
 1076          */
 1077         mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
 1078         bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
 1079 
 1080 #if NRND > 0
 1081         if (status)
 1082                 rnd_add_uint32(&sc->rnd_source, status);
 1083 #endif
 1084 
 1085         return (1);
 1086 }
 1087 
 1088 /*
 1089  * Read a packet from the card and pass it up to the kernel.
 1090  * NOTE!  WE EXPECT TO BE IN REGISTER WINDOW 2!
 1091  */
 1092 void
 1093 smc91cxx_read(sc)
 1094         struct smc91cxx_softc *sc;
 1095 {
 1096         struct ifnet *ifp = &sc->sc_ec.ec_if;
 1097         bus_space_tag_t bst = sc->sc_bst;
 1098         bus_space_handle_t bsh = sc->sc_bsh;
 1099         struct ether_header *eh;
 1100         struct mbuf *m;
 1101         u_int16_t status, packetno, packetlen;
 1102         u_int8_t *data;
 1103         u_int32_t dr;
 1104 
 1105  again:
 1106         /*
 1107          * Set data pointer to the beginning of the packet.  Since
 1108          * PTR_RCV is set, the packet number will be found automatically
 1109          * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
 1110          */
 1111         bus_space_write_2(bst, bsh, POINTER_REG_W,
 1112             PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
 1113 
 1114         /*
 1115          * First two words are status and packet length.
 1116          */
 1117         if ((sc->sc_flags & SMC_FLAGS_32BIT_READ) == 0) {
 1118                 status = bus_space_read_2(bst, bsh, DATA_REG_W);
 1119                 packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
 1120         } else {
 1121                 dr = bus_space_read_4(bst, bsh, DATA_REG_W);
 1122 #if BYTE_ORDER == LITTLE_ENDIAN
 1123                 status = (u_int16_t)dr;
 1124                 packetlen = (u_int16_t)(dr >> 16);
 1125 #else
 1126                 packetlen = (u_int16_t)dr;
 1127                 status = (u_int16_t)(dr >> 16);
 1128 #endif
 1129         }
 1130 
 1131         packetlen &= RLEN_MASK;
 1132 
 1133         /*
 1134          * The packet length includes 3 extra words: status, length,
 1135          * and an extra word that includes the control byte.
 1136          */
 1137         packetlen -= 6;
 1138 
 1139         /*
 1140          * Account for receive errors and discard.
 1141          */
 1142         if (status & RS_ERRORS) {
 1143                 ifp->if_ierrors++;
 1144                 goto out;
 1145         }
 1146 
 1147         /*
 1148          * Adjust for odd-length packet.
 1149          */
 1150         if (status & RS_ODDFRAME)
 1151                 packetlen++;
 1152 
 1153         /*
 1154          * Allocate a header mbuf.
 1155          */
 1156         MGETHDR(m, M_DONTWAIT, MT_DATA);
 1157         if (m == NULL)
 1158                 goto out;
 1159         m->m_pkthdr.rcvif = ifp;
 1160         m->m_pkthdr.len = packetlen;
 1161 
 1162         /*
 1163          * Always put the packet in a cluster.
 1164          * XXX should chain small mbufs if less than threshold.
 1165          */
 1166         MCLGET(m, M_DONTWAIT);
 1167         if ((m->m_flags & M_EXT) == 0) {
 1168                 m_freem(m);
 1169                 ifp->if_ierrors++;
 1170                 printf("%s: can't allocate cluster for incoming packet\n",
 1171                     sc->sc_dev.dv_xname);
 1172                 goto out;
 1173         }
 1174 
 1175         /*
 1176          * Pull the packet off the interface.  Make sure the payload
 1177          * is aligned.
 1178          */
 1179         if ((sc->sc_flags & SMC_FLAGS_32BIT_READ) == 0) {
 1180                 m->m_data = (caddr_t) ALIGN(mtod(m, caddr_t) +
 1181                     sizeof(struct ether_header)) - sizeof(struct ether_header);
 1182 
 1183                 eh = mtod(m, struct ether_header *);
 1184                 data = mtod(m, u_int8_t *);
 1185                 if (packetlen > 1)
 1186                         bus_space_read_multi_stream_2(bst, bsh, DATA_REG_W,
 1187                             (u_int16_t *)data, packetlen >> 1);
 1188                 if (packetlen & 1) {
 1189                         data += packetlen & ~1;
 1190                         *data = bus_space_read_1(bst, bsh, DATA_REG_B);
 1191                 }
 1192         } else {
 1193                 u_int8_t *dp;
 1194 
 1195                 m->m_data = (caddr_t) ALIGN(mtod(m, caddr_t));
 1196                 eh = mtod(m, struct ether_header *);
 1197                 dp = data = mtod(m, u_int8_t *);
 1198                 if (packetlen > 3)
 1199                         bus_space_read_multi_stream_4(bst, bsh, DATA_REG_W,
 1200                             (u_int32_t *)data, packetlen >> 2);
 1201                 if (packetlen & 3) {
 1202                         data += packetlen & ~3;
 1203                         *((u_int32_t *)data) =
 1204                             bus_space_read_stream_4(bst, bsh, DATA_REG_W);
 1205                 }
 1206         }
 1207 
 1208         ifp->if_ipackets++;
 1209 
 1210         /*
 1211          * Make sure to behave as IFF_SIMPLEX in all cases.
 1212          * This is to cope with SMC91C92 (Megahertz XJ10BT), which
 1213          * loops back packets to itself on promiscuous mode.
 1214          * (should be ensured by chipset configuration)
 1215          */
 1216         if ((ifp->if_flags & IFF_PROMISC) != 0) {
 1217                 /*
 1218                  * Drop packet looped back from myself.
 1219                  */
 1220                 if (ether_cmp(eh->ether_shost, LLADDR(ifp->if_sadl)) == 0) {
 1221                         m_freem(m);
 1222                         goto out;
 1223                 }
 1224         }
 1225 
 1226         m->m_pkthdr.len = m->m_len = packetlen;
 1227 
 1228 #if NBPFILTER > 0
 1229         /*
 1230          * Hand the packet off to bpf listeners.
 1231          */
 1232         if (ifp->if_bpf)
 1233                 bpf_mtap(ifp->if_bpf, m);
 1234 #endif
 1235 
 1236         (*ifp->if_input)(ifp, m);
 1237 
 1238  out:
 1239         /*
 1240          * Tell the card to free the memory occupied by this packet.
 1241          */
 1242         while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
 1243                 /* XXX bound this loop! */ ;
 1244         bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
 1245 
 1246         /*
 1247          * Check for another packet.
 1248          */
 1249         packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
 1250         if (packetno & FIFO_REMPTY)
 1251                 return;
 1252         goto again;
 1253 }
 1254 
 1255 /*
 1256  * Process an ioctl request.
 1257  */
 1258 int
 1259 smc91cxx_ioctl(ifp, cmd, data)
 1260         struct ifnet *ifp;
 1261         u_long cmd;
 1262         caddr_t data;
 1263 {
 1264         struct smc91cxx_softc *sc = ifp->if_softc;
 1265         struct ifaddr *ifa = (struct ifaddr *)data;
 1266         struct ifreq *ifr = (struct ifreq *)data;
 1267         int s, error = 0;
 1268 
 1269         s = splnet();
 1270 
 1271         switch (cmd) {
 1272         case SIOCSIFADDR:
 1273                 if ((error = smc91cxx_enable(sc)) != 0)
 1274                         break;
 1275                 ifp->if_flags |= IFF_UP;
 1276                 switch (ifa->ifa_addr->sa_family) {
 1277 #ifdef INET
 1278                 case AF_INET:
 1279                 smc91cxx_init(sc);
 1280                 arp_ifinit(ifp, ifa);
 1281                 break;
 1282 #endif
 1283 #ifdef NS
 1284                 case AF_NS:
 1285                     {
 1286                         struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
 1287 
 1288                         if (ns_nullhost(*ina))
 1289                                 ina->x_host =
 1290                                     *(union ns_host *)LLADDR(ifp->if_sadl);
 1291                         else {
 1292                                 memcpy(LLADDR(ifp->if_sadl), ina->x_host.c_host,
 1293                                     ETHER_ADDR_LEN);
 1294                         }
 1295 
 1296                         /*
 1297                          * Set new address.  Reset, because the receiver
 1298                          * has to be stopped before we can set the new
 1299                          * MAC address.
 1300                          */
 1301                         smc91cxx_reset(sc);
 1302                         break;
 1303                     }
 1304 #endif
 1305                 default:
 1306                         smc91cxx_init(sc);
 1307                         break;
 1308                 }
 1309                 break;
 1310 
 1311 #if defined(CCITT) && defined(LLC)
 1312         case SIOCSIFCONF_X25:
 1313                 if ((error = smc91cxx_enable(sc)) != 0)
 1314                         break;
 1315                 ifp->if_flags |= IFF_UP;
 1316                 ifa->ifa_rtrequest = cons_rtrequest;    /* XXX */
 1317                 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
 1318                 if (error == 0)
 1319                         smc91cxx_init(sc);
 1320                 break;
 1321 #endif
 1322 
 1323         case SIOCSIFFLAGS:
 1324                 if ((ifp->if_flags & IFF_UP) == 0 &&
 1325                     (ifp->if_flags & IFF_RUNNING) != 0) {
 1326                         /*
 1327                          * If interface is marked down and it is running,
 1328                          * stop it.
 1329                          */
 1330                         smc91cxx_stop(sc);
 1331                         ifp->if_flags &= ~IFF_RUNNING;
 1332                         smc91cxx_disable(sc);
 1333                 } else if ((ifp->if_flags & IFF_UP) != 0 &&
 1334                            (ifp->if_flags & IFF_RUNNING) == 0) {
 1335                         /*
 1336                          * If interface is marked up and it is stopped,
 1337                          * start it.
 1338                          */
 1339                         if ((error = smc91cxx_enable(sc)) != 0)
 1340                                 break;
 1341                         smc91cxx_init(sc);
 1342                 } else if ((ifp->if_flags & IFF_UP) != 0) {
 1343                         /*
 1344                          * Reset the interface to pick up changes in any
 1345                          * other flags that affect hardware registers.
 1346                          */
 1347                         smc91cxx_reset(sc);
 1348                 }
 1349                 break;
 1350 
 1351         case SIOCADDMULTI:
 1352         case SIOCDELMULTI:
 1353                 if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0) {
 1354                         error = EIO;
 1355                         break;
 1356                 }
 1357 
 1358                 error = (cmd == SIOCADDMULTI) ?
 1359                     ether_addmulti(ifr, &sc->sc_ec) :
 1360                     ether_delmulti(ifr, &sc->sc_ec);
 1361                 if (error == ENETRESET) {
 1362                         /*
 1363                          * Multicast list has changed; set the hardware
 1364                          * filter accordingly.
 1365                          */
 1366                         if (ifp->if_flags & IFF_RUNNING)
 1367                                 smc91cxx_reset(sc);
 1368                         error = 0;
 1369                 }
 1370                 break;
 1371 
 1372         case SIOCGIFMEDIA:
 1373         case SIOCSIFMEDIA:
 1374                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
 1375                 break;
 1376 
 1377         default:
 1378                 error = EINVAL;
 1379                 break;
 1380         }
 1381 
 1382         splx(s);
 1383         return (error);
 1384 }
 1385 
 1386 /*
 1387  * Reset the interface.
 1388  */
 1389 void
 1390 smc91cxx_reset(sc)
 1391         struct smc91cxx_softc *sc;
 1392 {
 1393         int s;
 1394 
 1395         s = splnet();
 1396         smc91cxx_stop(sc);
 1397         smc91cxx_init(sc);
 1398         splx(s);
 1399 }
 1400 
 1401 /*
 1402  * Watchdog timer.
 1403  */
 1404 void
 1405 smc91cxx_watchdog(ifp)
 1406         struct ifnet *ifp;
 1407 {
 1408         struct smc91cxx_softc *sc = ifp->if_softc;
 1409 
 1410         log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
 1411         ifp->if_oerrors++;
 1412         smc91cxx_reset(sc);
 1413 }
 1414 
 1415 /*
 1416  * Stop output on the interface.
 1417  */
 1418 void
 1419 smc91cxx_stop(sc)
 1420         struct smc91cxx_softc *sc;
 1421 {
 1422         bus_space_tag_t bst = sc->sc_bst;
 1423         bus_space_handle_t bsh = sc->sc_bsh;
 1424 
 1425         /*
 1426          * Clear interrupt mask; disable all interrupts.
 1427          */
 1428         SMC_SELECT_BANK(sc, 2);
 1429         bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
 1430 
 1431         /*
 1432          * Disable transmitter and receiver.
 1433          */
 1434         SMC_SELECT_BANK(sc, 0);
 1435         bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
 1436         bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
 1437 
 1438         /*
 1439          * Cancel watchdog timer.
 1440          */
 1441         sc->sc_ec.ec_if.if_timer = 0;
 1442 }
 1443 
 1444 /*
 1445  * Enable power on the interface.
 1446  */
 1447 int
 1448 smc91cxx_enable(sc)
 1449         struct smc91cxx_softc *sc;
 1450 {
 1451 
 1452         if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 && sc->sc_enable != NULL) {
 1453                 if ((*sc->sc_enable)(sc) != 0) {
 1454                         printf("%s: device enable failed\n",
 1455                             sc->sc_dev.dv_xname);
 1456                         return (EIO);
 1457                 }
 1458         }
 1459 
 1460         sc->sc_flags |= SMC_FLAGS_ENABLED;
 1461         return (0);
 1462 }
 1463 
 1464 /*
 1465  * Disable power on the interface.
 1466  */
 1467 void
 1468 smc91cxx_disable(sc)
 1469         struct smc91cxx_softc *sc;
 1470 {
 1471 
 1472         if ((sc->sc_flags & SMC_FLAGS_ENABLED) != 0 && sc->sc_disable != NULL) {
 1473                 (*sc->sc_disable)(sc);
 1474                 sc->sc_flags &= ~SMC_FLAGS_ENABLED;
 1475         }
 1476 }
 1477 
 1478 int
 1479 smc91cxx_activate(self, act)
 1480         struct device *self;
 1481         enum devact act;
 1482 {
 1483         struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
 1484         int rv = 0, s;
 1485 
 1486         s = splnet();
 1487         switch (act) {
 1488         case DVACT_ACTIVATE:
 1489                 rv = EOPNOTSUPP;
 1490                 break;
 1491 
 1492         case DVACT_DEACTIVATE:
 1493                 if_deactivate(&sc->sc_ec.ec_if);
 1494                 break;
 1495         }
 1496         splx(s);
 1497         return (rv);
 1498 }
 1499 
 1500 int
 1501 smc91cxx_detach(self, flags)
 1502         struct device *self;
 1503         int flags;
 1504 {
 1505         struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
 1506         struct ifnet *ifp = &sc->sc_ec.ec_if;
 1507 
 1508         /* Succeed now if there's no work to do. */
 1509         if ((sc->sc_flags & SMC_FLAGS_ATTACHED) == 0)
 1510                 return (0);
 1511 
 1512 
 1513         /* smc91cxx_disable() checks SMC_FLAGS_ENABLED */
 1514         smc91cxx_disable(sc);
 1515 
 1516         /* smc91cxx_attach() never fails */
 1517 
 1518         /* Delete all media. */
 1519         ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
 1520 
 1521 #if NRND > 0
 1522         rnd_detach_source(&sc->rnd_source);
 1523 #endif
 1524         ether_ifdetach(ifp);
 1525         if_detach(ifp);
 1526 
 1527         return (0);
 1528 }
 1529 
 1530 u_int32_t
 1531 smc91cxx_mii_bitbang_read(self)
 1532         struct device *self;
 1533 {
 1534         struct smc91cxx_softc *sc = (void *) self;
 1535 
 1536         /* We're already in bank 3. */
 1537         return (bus_space_read_2(sc->sc_bst, sc->sc_bsh, MGMT_REG_W));
 1538 }
 1539 
 1540 void
 1541 smc91cxx_mii_bitbang_write(self, val)
 1542         struct device *self;
 1543         u_int32_t val;
 1544 {
 1545         struct smc91cxx_softc *sc = (void *) self;
 1546 
 1547         /* We're already in bank 3. */
 1548         bus_space_write_2(sc->sc_bst, sc->sc_bsh, MGMT_REG_W, val);
 1549 }
 1550 
 1551 int
 1552 smc91cxx_mii_readreg(self, phy, reg)
 1553         struct device *self;
 1554         int phy, reg;
 1555 {
 1556         struct smc91cxx_softc *sc = (void *) self;
 1557         int val;
 1558 
 1559         SMC_SELECT_BANK(sc, 3);
 1560 
 1561         val = mii_bitbang_readreg(self, &smc91cxx_mii_bitbang_ops, phy, reg);
 1562 
 1563         SMC_SELECT_BANK(sc, 2);
 1564 
 1565         return (val);
 1566 }
 1567 
 1568 void
 1569 smc91cxx_mii_writereg(self, phy, reg, val)
 1570         struct device *self;
 1571         int phy, reg, val;
 1572 {
 1573         struct smc91cxx_softc *sc = (void *) self;
 1574 
 1575         SMC_SELECT_BANK(sc, 3);
 1576 
 1577         mii_bitbang_writereg(self, &smc91cxx_mii_bitbang_ops, phy, reg, val);
 1578 
 1579         SMC_SELECT_BANK(sc, 2);
 1580 }
 1581 
 1582 void
 1583 smc91cxx_statchg(self)
 1584         struct device *self;
 1585 {
 1586         struct smc91cxx_softc *sc = (struct smc91cxx_softc *)self;
 1587         bus_space_tag_t bst = sc->sc_bst;
 1588         bus_space_handle_t bsh = sc->sc_bsh;
 1589         int mctl;
 1590 
 1591         SMC_SELECT_BANK(sc, 0);
 1592         mctl = bus_space_read_2(bst, bsh, TXMIT_CONTROL_REG_W);
 1593         if (sc->sc_mii.mii_media_active & IFM_FDX)
 1594                 mctl |= TCR_SWFDUP;
 1595         else
 1596                 mctl &= ~TCR_SWFDUP;
 1597         bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, mctl);
 1598         SMC_SELECT_BANK(sc, 2); /* back to operating window */
 1599 }
 1600 
 1601 /*
 1602  * One second timer, used to tick the MII.
 1603  */
 1604 void
 1605 smc91cxx_tick(arg)
 1606         void *arg;
 1607 {
 1608         struct smc91cxx_softc *sc = arg;
 1609         int s;
 1610 
 1611 #ifdef DIAGNOSTIC
 1612         if ((sc->sc_flags & SMC_FLAGS_HAS_MII) == 0)
 1613                 panic("smc91cxx_tick");
 1614 #endif
 1615 
 1616         if ((sc->sc_dev.dv_flags & DVF_ACTIVE) == 0)
 1617                 return;
 1618 
 1619         s = splnet();
 1620         mii_tick(&sc->sc_mii);
 1621         splx(s);
 1622 
 1623         callout_reset(&sc->sc_mii_callout, hz, smc91cxx_tick, sc);
 1624 }
 1625 

Cache object: 567ce41ae74fd8d3d614b6dfa641b55c


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