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

Cache object: e22930d53bfc417824053bed9be4e6be


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