root/dev/ic/smc91cxx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ether_cmp
  2. smc91cxx_attach
  3. smc91cxx_mediachange
  4. smc91cxx_set_media
  5. smc91cxx_mediastatus
  6. smc91cxx_init
  7. smc91cxx_start
  8. smc91cxx_intr
  9. smc91cxx_read
  10. smc91cxx_ioctl
  11. smc91cxx_reset
  12. smc91cxx_watchdog
  13. smc91cxx_stop
  14. smc91cxx_enable
  15. smc91cxx_disable
  16. smc91cxx_activate
  17. smc91cxx_detach
  18. smc91cxx_mii_bitbang_read
  19. smc91cxx_mii_bitbang_write
  20. smc91cxx_mii_readreg
  21. smc91cxx_mii_writereg
  22. smc91cxx_statchg
  23. smc91cxx_tick

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

/* [<][>][^][v][top][bottom][index][help] */