[BACK]Return to elink3.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Annotation of src/sys/dev/ic/elink3.c, Revision 1.45

1.45    ! thorpej     1: /*     $NetBSD: elink3.c,v 1.44 1998/08/17 23:20:39 thorpej Exp $      */
1.41      thorpej     2:
                      3: /*-
                      4:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
                      9:  * NASA Ames Research Center.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
1.1       thorpej    39:
                     40: /*
1.19      jonathan   41:  * Copyright (c) 1996, 1997 Jonathan Stone <jonathan@NetBSD.org>
1.6       thorpej    42:  * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org>
1.1       thorpej    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 Herb Peyerl.
                     56:  * 4. The name of Herb Peyerl may not be used to endorse or promote products
                     57:  *    derived from this software without specific prior written permission.
                     58:  *
                     59:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     60:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     61:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     62:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     63:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     64:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     65:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     66:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     67:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     68:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     69:  */
                     70:
1.39      jonathan   71: #include "opt_inet.h"
1.40      jonathan   72: #include "opt_ns.h"
1.1       thorpej    73: #include "bpfilter.h"
1.35      explorer   74: #include "rnd.h"
1.1       thorpej    75:
                     76: #include <sys/param.h>
1.3       christos   77: #include <sys/systm.h>
1.41      thorpej    78: #include <sys/kernel.h>
1.1       thorpej    79: #include <sys/mbuf.h>
                     80: #include <sys/socket.h>
                     81: #include <sys/ioctl.h>
                     82: #include <sys/errno.h>
                     83: #include <sys/syslog.h>
                     84: #include <sys/select.h>
                     85: #include <sys/device.h>
1.35      explorer   86: #if NRND > 0
                     87: #include <sys/rnd.h>
                     88: #endif
1.1       thorpej    89:
                     90: #include <net/if.h>
                     91: #include <net/if_dl.h>
1.21      is         92: #include <net/if_ether.h>
1.22      jonathan   93: #include <net/if_media.h>
1.1       thorpej    94:
                     95: #ifdef INET
                     96: #include <netinet/in.h>
                     97: #include <netinet/in_systm.h>
                     98: #include <netinet/in_var.h>
                     99: #include <netinet/ip.h>
1.21      is        100: #include <netinet/if_inarp.h>
1.1       thorpej   101: #endif
                    102:
                    103: #ifdef NS
                    104: #include <netns/ns.h>
                    105: #include <netns/ns_if.h>
                    106: #endif
                    107:
                    108: #if NBPFILTER > 0
                    109: #include <net/bpf.h>
                    110: #include <net/bpfdesc.h>
                    111: #endif
                    112:
                    113: #include <machine/cpu.h>
1.2       thorpej   114: #include <machine/bus.h>
1.7       thorpej   115: #include <machine/intr.h>
1.1       thorpej   116:
1.41      thorpej   117: #include <dev/mii/mii.h>
                    118: #include <dev/mii/miivar.h>
                    119:
1.1       thorpej   120: #include <dev/ic/elink3var.h>
                    121: #include <dev/ic/elink3reg.h>
                    122:
                    123: #define ETHER_MIN_LEN  64
                    124: #define ETHER_MAX_LEN   1518
                    125: #define ETHER_ADDR_LEN  6
                    126:
1.36      jonathan  127: #ifdef DEBUG
                    128: int epdebug = 0;
                    129: #endif
                    130:
1.23      jonathan  131: /*
1.41      thorpej   132:  * Structure to map media-present bits in boards to ifmedia codes and
                    133:  * printable media names. Used for table-driven ifmedia initialization.
1.23      jonathan  134:  */
                    135: struct ep_media {
1.41      thorpej   136:        int     epm_mpbit;              /* media present bit */
                    137:        const char *epm_name;           /* name of medium */
1.23      jonathan  138:        int     epm_ifmedia;            /* ifmedia word for medium */
1.41      thorpej   139:        int     epm_epmedia;            /* EPMEDIA_* constant */
1.23      jonathan  140: };
                    141:
                    142: /*
1.41      thorpej   143:  * Media table for the Demon/Vortex/Boomerang chipsets.
                    144:  *
                    145:  * Note that MII on the Demon and Vortex (3c59x) indicates an external
                    146:  * MII connector (for connecting an external PHY) ... I think.  Treat
                    147:  * it as `manual' on these chips.
1.23      jonathan  148:  *
1.41      thorpej   149:  * Any Boomerang (3c90x) chips with MII really do have an internal
                    150:  * MII and real PHYs attached; no `native' media.
1.23      jonathan  151:  */
1.41      thorpej   152: struct ep_media ep_vortex_media[] = {
                    153:        { EP_PCI_10BASE_T,      "10baseT",      IFM_ETHER|IFM_10_T,
                    154:          EPMEDIA_10BASE_T },
1.45    ! thorpej   155:        { EP_PCI_10BASE_T,      "10baseT-FDX",  IFM_ETHER|IFM_10_T|IFM_FDX,
        !           156:          EPMEDIA_10BASE_T },
1.41      thorpej   157:        { EP_PCI_AUI,           "10base5/AUI",  IFM_ETHER|IFM_10_5,
                    158:          EPMEDIA_AUI },
                    159:        { EP_PCI_BNC,           "10base2/BNC",  IFM_ETHER|IFM_10_2,
                    160:          EPMEDIA_10BASE_2 },
                    161:        { EP_PCI_100BASE_TX,    "100baseTX",    IFM_ETHER|IFM_100_TX,
                    162:          EPMEDIA_100BASE_TX },
1.45    ! thorpej   163:        { EP_PCI_100BASE_TX,    "100baseTX-FDX",IFM_ETHER|IFM_100_TX|IFM_FDX,
        !           164:          EPMEDIA_100BASE_TX },
1.41      thorpej   165:        { EP_PCI_100BASE_FX,    "100baseFX",    IFM_ETHER|IFM_100_FX,
                    166:          EPMEDIA_100BASE_FX },
                    167:        { EP_PCI_100BASE_MII,   "manual",       IFM_ETHER|IFM_MANUAL,
                    168:          EPMEDIA_MII },
                    169:        { EP_PCI_100BASE_T4,    "100baseT4",    IFM_ETHER|IFM_100_T4,
                    170:          EPMEDIA_100BASE_T4 },
                    171:        { 0,                    NULL,           0,
                    172:          0 },
1.23      jonathan  173: };
                    174:
                    175: /*
1.41      thorpej   176:  * Media table for the older 3Com Etherlink III chipset, used
                    177:  * in the 3c509, 3c579, and 3c589.
1.23      jonathan  178:  */
1.41      thorpej   179: struct ep_media ep_509_media[] = {
                    180:        { EP_W0_CC_UTP,         "10baseT",      IFM_ETHER|IFM_10_T,
                    181:          EPMEDIA_10BASE_T },
                    182:        { EP_W0_CC_AUI,         "10base5/AUI",  IFM_ETHER|IFM_10_5,
                    183:          EPMEDIA_AUI },
                    184:        { EP_W0_CC_BNC,         "10base2/BNC",  IFM_ETHER|IFM_10_2,
                    185:          EPMEDIA_10BASE_2 },
                    186:        { 0,                    NULL,           0,
                    187:          0 },
1.23      jonathan  188: };
                    189:
1.15      jonathan  190: void   ep_internalconfig __P((struct ep_softc *sc));
1.20      jonathan  191: void   ep_vortex_probemedia __P((struct ep_softc *sc));
1.41      thorpej   192: void   ep_509_probemedia __P((struct ep_softc *sc));
1.20      jonathan  193:
1.3       christos  194: static void eptxstat __P((struct ep_softc *));
1.1       thorpej   195: static int epstatus __P((struct ep_softc *));
                    196: void epinit __P((struct ep_softc *));
                    197: int epioctl __P((struct ifnet *, u_long, caddr_t));
                    198: void epstart __P((struct ifnet *));
1.5       thorpej   199: void epwatchdog __P((struct ifnet *));
1.1       thorpej   200: void epreset __P((struct ep_softc *));
1.16      jonathan  201: static void epshutdown __P((void *));
1.23      jonathan  202: void   epread __P((struct ep_softc *));
1.1       thorpej   203: struct mbuf *epget __P((struct ep_softc *, int));
1.23      jonathan  204: void   epmbuffill __P((void *));
                    205: void   epmbufempty __P((struct ep_softc *));
                    206: void   epsetfilter __P((struct ep_softc *));
1.41      thorpej   207: void   epsetmedia __P((struct ep_softc *));
1.34      thorpej   208:
                    209: int    epenable __P((struct ep_softc *));
                    210: void   epdisable __P((struct ep_softc *));
1.23      jonathan  211:
                    212: /* ifmedia callbacks */
                    213: int    ep_media_change __P((struct ifnet *ifp));
                    214: void   ep_media_status __P((struct ifnet *ifp, struct ifmediareq *req));
1.1       thorpej   215:
1.41      thorpej   216: /* MII callbacks */
                    217: int    ep_mii_readreg __P((struct device *, int, int));
                    218: void   ep_mii_writereg __P((struct device *, int, int, int));
                    219: void   ep_statchg __P((struct device *));
                    220:
                    221: void   ep_tick __P((void *));
                    222:
                    223: void   ep_mii_setbit __P((struct ep_softc *, u_int16_t));
                    224: void   ep_mii_clrbit __P((struct ep_softc *, u_int16_t));
                    225: u_int16_t ep_mii_readbit __P((struct ep_softc *, u_int16_t));
                    226: void   ep_mii_sync __P((struct ep_softc *));
                    227: void   ep_mii_sendbits __P((struct ep_softc *, u_int32_t, int));
                    228:
1.1       thorpej   229: static int epbusyeeprom __P((struct ep_softc *));
1.19      jonathan  230: static inline void ep_complete_cmd __P((struct ep_softc *sc,
                    231:                                        u_int cmd, u_int arg));
1.42      thorpej   232: static __inline int ep_w1_reg __P((struct ep_softc *, int));
1.19      jonathan  233:
1.42      thorpej   234: /*
                    235:  * Some chips (3c515 [Corkscrew] and 3c574 [RoadRunner]) have
                    236:  * Window 1 registers offset!
                    237:  */
                    238: static __inline int
                    239: ep_w1_reg(sc, reg)
                    240:        struct ep_softc *sc;
                    241:        int reg;
                    242: {
                    243:
                    244:        switch (sc->ep_chipset) {
                    245:        case EP_CHIPSET_CORKSCREW:
                    246:                return (reg + 0x10);
                    247:
                    248:        case EP_CHIPSET_ROADRUNNER:
                    249:                switch (reg) {
                    250:                case EP_W1_FREE_TX:
                    251:                case EP_W1_RUNNER_RDCTL:
                    252:                case EP_W1_RUNNER_WRCTL:
                    253:                        return (reg);
                    254:                }
                    255:                return (reg + 0x10);
                    256:        }
                    257:
                    258:        return (reg);
                    259: }
1.19      jonathan  260:
                    261: /*
                    262:  * Issue a (reset) command, and be sure it has completed.
                    263:  * Used for commands that reset part or all of the  board.
                    264:  * On newer hardware we could poll SC_COMMAND_IN_PROGRESS,
                    265:  * but older hardware doesn't implement it and we must delay.
                    266:  * It's easiest to just delay always.
                    267:  */
                    268: static inline void
                    269: ep_complete_cmd(sc, cmd, arg)
                    270:        struct ep_softc *sc;
                    271:        u_int cmd, arg;
                    272: {
                    273:        register bus_space_tag_t iot = sc->sc_iot;
                    274:        register bus_space_handle_t ioh = sc->sc_ioh;
                    275:
                    276:        bus_space_write_2(iot, ioh, cmd, arg);
                    277:
                    278: #ifdef notyet
                    279:        /* if this adapter family has S_COMMAND_IN_PROGRESS, use it */
                    280:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
                    281:                ;
                    282:        else
                    283: #else
                    284:        DELAY(100000);  /* need at least 1 ms, but be generous. */
                    285: #endif
                    286: }
                    287:
1.20      jonathan  288: /*
                    289:  * Back-end attach and configure.
                    290:  */
1.1       thorpej   291: void
1.34      thorpej   292: epconfig(sc, chipset, enaddr)
1.1       thorpej   293:        struct ep_softc *sc;
1.20      jonathan  294:        u_short chipset;
1.34      thorpej   295:        u_int8_t *enaddr;
1.1       thorpej   296: {
1.21      is        297:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.11      thorpej   298:        bus_space_tag_t iot = sc->sc_iot;
                    299:        bus_space_handle_t ioh = sc->sc_ioh;
1.7       thorpej   300:        u_int16_t i;
1.21      is        301:        u_int8_t myla[6];
1.1       thorpej   302:
1.20      jonathan  303:        sc->ep_chipset = chipset;
1.32      thorpej   304:
                    305:        /*
                    306:         * We could have been groveling around in other register
                    307:         * windows in the front-end; make sure we're in window 0
                    308:         * to read the EEPROM.
                    309:         */
                    310:        GO_WINDOW(0);
1.1       thorpej   311:
1.34      thorpej   312:        if (enaddr == NULL) {
                    313:                /*
                    314:                 * Read the station address from the eeprom
                    315:                 */
                    316:                for (i = 0; i < 3; i++) {
                    317:                        u_int16_t x;
                    318:                        if (epbusyeeprom(sc))
                    319:                                return;         /* XXX why is eeprom busy? */
                    320:                        bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
                    321:                                          READ_EEPROM | i);
                    322:                        if (epbusyeeprom(sc))
                    323:                                return;         /* XXX why is eeprom busy? */
                    324:                        x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA);
                    325:                        myla[(i << 1)] = x >> 8;
                    326:                        myla[(i << 1) + 1] = x;
                    327:                }
                    328:                enaddr = myla;
1.1       thorpej   329:        }
                    330:
1.12      jonathan  331:        /*
1.41      thorpej   332:         * Vortex-based (3c59x pci,eisa) and Boomerang (3c900) cards
1.23      jonathan  333:         * allow FDDI-sized (4500) byte packets.  Commands only take an
                    334:         * 11-bit parameter, and  11 bits isn't enough to hold a full-size
                    335:         * packet length.
1.12      jonathan  336:         * Commands to these cards implicitly upshift a packet size
                    337:         * or threshold by 2 bits.
                    338:         * To detect  cards with large-packet support, we probe by setting
                    339:         * the transmit threshold register, then change windows and
                    340:         * read back the threshold register directly, and see if the
                    341:         * threshold value was shifted or not.
                    342:         */
                    343:        bus_space_write_2(iot, ioh, EP_COMMAND,
1.13      jonathan  344:                          SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE );
1.12      jonathan  345:        GO_WINDOW(5);
                    346:        i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH);
                    347:        GO_WINDOW(1);
                    348:        switch (i)  {
1.13      jonathan  349:        case EP_LARGEWIN_PROBE:
                    350:        case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK):
1.12      jonathan  351:                sc->ep_pktlenshift = 0;
                    352:                break;
                    353:
1.13      jonathan  354:        case (EP_LARGEWIN_PROBE << 2):
1.12      jonathan  355:                sc->ep_pktlenshift = 2;
                    356:                break;
                    357:
                    358:        default:
1.34      thorpej   359:                printf("%s: wrote 0x%x to TX_AVAIL_THRESH, read back 0x%x. "
1.14      cjs       360:                    "Interface disabled\n",
1.34      thorpej   361:                    sc->sc_dev.dv_xname, EP_LARGEWIN_PROBE, (int) i);
1.12      jonathan  362:                return;
                    363:        }
1.20      jonathan  364:
1.12      jonathan  365:        /*
                    366:         * Ensure Tx-available interrupts are enabled for
                    367:         * start the interface.
1.23      jonathan  368:         * XXX should be in epinit()?
1.12      jonathan  369:         */
                    370:        bus_space_write_2(iot, ioh, EP_COMMAND,
                    371:            SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
                    372:
1.23      jonathan  373:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    374:        ifp->if_softc = sc;
                    375:        ifp->if_start = epstart;
                    376:        ifp->if_ioctl = epioctl;
                    377:        ifp->if_watchdog = epwatchdog;
                    378:        ifp->if_flags =
                    379:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    380:
                    381:        if_attach(ifp);
1.34      thorpej   382:        ether_ifattach(ifp, enaddr);
1.23      jonathan  383:
                    384:        /*
                    385:         * Finish configuration:
                    386:         * determine chipset if the front-end couldn't do so,
                    387:         * show board details, set media.
                    388:         */
                    389:
1.41      thorpej   390:        /*
                    391:         * Print RAM size.  We also print the Ethernet address in here.
                    392:         * It's extracted from the ifp, so we have to make sure it's
                    393:         * been attached first.
                    394:         */
1.23      jonathan  395:        ep_internalconfig(sc);
                    396:        GO_WINDOW(0);
                    397:
1.41      thorpej   398:        /*
1.44      thorpej   399:         * Display some additional information, if pertinent.
                    400:         */
                    401:        if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER)
                    402:                printf("%s: RoadRunner FIFO buffer enabled\n",
                    403:                    sc->sc_dev.dv_xname);
                    404:
                    405:        /*
1.41      thorpej   406:         * Initialize our media structures and MII info.  We'll
                    407:         * probe the MII if we discover that we have one.
1.20      jonathan  408:         */
1.41      thorpej   409:        sc->sc_mii.mii_ifp = ifp;
                    410:        sc->sc_mii.mii_readreg = ep_mii_readreg;
                    411:        sc->sc_mii.mii_writereg = ep_mii_writereg;
                    412:        sc->sc_mii.mii_statchg = ep_statchg;
                    413:        ifmedia_init(&sc->sc_mii.mii_media, 0, ep_media_change,
                    414:            ep_media_status);
1.20      jonathan  415:
                    416:        /*
1.41      thorpej   417:         * Now, determine which media we have.
1.20      jonathan  418:         */
                    419:        switch (sc->ep_chipset) {
1.41      thorpej   420:        case EP_CHIPSET_BOOMERANG:
1.42      thorpej   421:        case EP_CHIPSET_ROADRUNNER:
1.41      thorpej   422:                /*
                    423:                 * If the device has MII, probe it.  We won't be using
                    424:                 * any `native' media in this case, only PHYs.  If
                    425:                 * we don't, just treat the Boomerang like the Vortex.
                    426:                 */
                    427:                if (sc->ep_flags & EP_FLAGS_MII) {
                    428:                        mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff);
                    429:                        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                    430:                                ifmedia_add(&sc->sc_mii.mii_media,
                    431:                                    IFM_ETHER|IFM_NONE, 0, NULL);
                    432:                                ifmedia_set(&sc->sc_mii.mii_media,
                    433:                                    IFM_ETHER|IFM_NONE);
                    434:                        } else {
                    435:                                ifmedia_set(&sc->sc_mii.mii_media,
                    436:                                    IFM_ETHER|IFM_AUTO);
                    437:                        }
                    438:                        break;
                    439:                }
                    440:                /* FALLTHROUGH */
                    441:
1.20      jonathan  442:        case EP_CHIPSET_VORTEX:
                    443:                ep_vortex_probemedia(sc);
                    444:                break;
                    445:
                    446:        default:
1.41      thorpej   447:                ep_509_probemedia(sc);
1.20      jonathan  448:                break;
                    449:        }
1.23      jonathan  450:
1.20      jonathan  451:        GO_WINDOW(1);           /* Window 1 is operating window */
                    452:
1.1       thorpej   453: #if NBPFILTER > 0
1.21      is        454:        bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
1.1       thorpej   455:                  sizeof(struct ether_header));
                    456: #endif
                    457:
1.35      explorer  458: #if NRND > 0
                    459:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, RND_TYPE_NET);
                    460: #endif
                    461:
1.1       thorpej   462:        sc->tx_start_thresh = 20;       /* probably a good starting point. */
1.12      jonathan  463:
1.16      jonathan  464:        /*  Establish callback to reset card when we reboot. */
                    465:        shutdownhook_establish(epshutdown, sc);
                    466:
1.19      jonathan  467:        ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
                    468:        ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.1       thorpej   469: }
                    470:
1.23      jonathan  471:
1.1       thorpej   472: /*
1.15      jonathan  473:  * Show interface-model-independent info from window 3
                    474:  * internal-configuration register.
                    475:  */
                    476: void
                    477: ep_internalconfig(sc)
                    478:        struct ep_softc *sc;
                    479: {
                    480:        bus_space_tag_t iot = sc->sc_iot;
                    481:        bus_space_handle_t ioh = sc->sc_ioh;
                    482:
                    483:        u_int config0;
                    484:        u_int config1;
                    485:
                    486:        int  ram_size, ram_width, ram_speed, rom_size, ram_split;
                    487:        /*
                    488:         * NVRAM buffer Rx:Tx config names for busmastering cards
                    489:         * (Demon, Vortex, and later).
                    490:         */
                    491:        const char *onboard_ram_config[] = {
1.38      augustss  492:                "5:3", "3:1", "1:1", "3:5" };
1.15      jonathan  493:
                    494:        GO_WINDOW(3);
                    495:        config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG);
1.28      veego     496:        config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
1.15      jonathan  497:        GO_WINDOW(0);
                    498:
                    499:        ram_size  = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT;
                    500:        ram_width = (config0 & CONFIG_RAMWIDTH) >> CONFIG_RAMWIDTH_SHIFT;
                    501:        ram_speed = (config0 & CONFIG_RAMSPEED) >> CONFIG_RAMSPEED_SHIFT;
                    502:        rom_size  = (config0 & CONFIG_ROMSIZE) >> CONFIG_ROMSIZE_SHIFT;
                    503:
                    504:        ram_split  = (config1 & CONFIG_RAMSPLIT) >> CONFIG_RAMSPLIT_SHIFT;
                    505:
1.41      thorpej   506:        printf("%s: address %s, %dKB %s-wide FIFO, %s Rx:Tx split\n",
1.23      jonathan  507:               sc->sc_dev.dv_xname,
1.41      thorpej   508:               ether_sprintf(LLADDR(sc->sc_ethercom.ec_if.if_sadl)),
1.23      jonathan  509:               8 << ram_size,
                    510:               (ram_width) ? "word" : "byte",
                    511:               onboard_ram_config[ram_split]);
1.15      jonathan  512: }
                    513:
1.23      jonathan  514:
1.20      jonathan  515: /*
1.23      jonathan  516:  * Find supported media on 3c509-generation hardware that doesn't have
1.20      jonathan  517:  * a "reset_options" register in window 3.
1.23      jonathan  518:  * Use the config_cntrl register  in window 0 instead.
                    519:  * Used on original, 10Mbit ISA (3c509), 3c509B, and pre-Demon EISA cards
                    520:  * that implement  CONFIG_CTRL.  We don't have a good way to set the
                    521:  * default active mediuim; punt to ifconfig  instead.
1.20      jonathan  522:  */
                    523: void
1.41      thorpej   524: ep_509_probemedia(sc)
1.20      jonathan  525:        struct ep_softc *sc;
                    526: {
                    527:        bus_space_tag_t iot = sc->sc_iot;
                    528:        bus_space_handle_t ioh = sc->sc_ioh;
1.41      thorpej   529:        struct ifmedia *ifm = &sc->sc_mii.mii_media;
1.23      jonathan  530:        u_int16_t ep_w0_config, port;
1.41      thorpej   531:        struct ep_media *epm;
                    532:        const char *sep = "", *defmedianame = NULL;
                    533:        int defmedia = 0;
1.23      jonathan  534:
1.20      jonathan  535:        GO_WINDOW(0);
1.23      jonathan  536:        ep_w0_config = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL);
                    537:
1.41      thorpej   538:        printf("%s: ", sc->sc_dev.dv_xname);
1.23      jonathan  539:
1.41      thorpej   540:        /* Sanity check that there are any media! */
                    541:        if ((ep_w0_config & EP_W0_CC_MEDIAMASK) == 0) {
                    542:                printf("no media present!\n");
                    543:                ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL);
                    544:                ifmedia_set(ifm, IFM_ETHER|IFM_NONE);
                    545:                return;
1.23      jonathan  546:        }
                    547:
1.41      thorpej   548:        /*
                    549:         * Get the default media from the EEPROM.
                    550:         */
1.23      jonathan  551:        if (epbusyeeprom(sc))
                    552:                return;         /* XXX why is eeprom busy? */
                    553:        bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND,
1.28      veego     554:            READ_EEPROM | EEPROM_ADDR_CFG);
1.23      jonathan  555:        if (epbusyeeprom(sc))
                    556:                return;         /* XXX why is  eeprom busy? */
1.41      thorpej   557:        port = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA) >> 14;
1.23      jonathan  558:
1.41      thorpej   559: #define        PRINT(s)        printf("%s%s", sep, s); sep = ", "
1.23      jonathan  560:
1.41      thorpej   561:        for (epm = ep_509_media; epm->epm_name != NULL; epm++) {
                    562:                if (ep_w0_config & epm->epm_mpbit) {
                    563:                        if (epm->epm_epmedia == port || defmedia == 0) {
                    564:                                defmedia = epm->epm_ifmedia;
                    565:                                defmedianame = epm->epm_name;
                    566:                        }
                    567:                        ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_epmedia,
                    568:                            NULL);
                    569:                        PRINT(epm->epm_name);
                    570:                }
                    571:        }
                    572:
                    573: #undef PRINT
                    574:
                    575: #ifdef DIAGNOSTIC
                    576:        if (defmedia == 0)
                    577:                panic("ep_509_probemedia: impossible");
                    578: #endif
                    579:
                    580:        printf(" (default %s)\n", defmedianame);
                    581:        ifmedia_set(ifm, defmedia);
1.20      jonathan  582: }
                    583:
1.15      jonathan  584: /*
1.23      jonathan  585:  * Find media present on large-packet-capable elink3 devices.
                    586:  * Show onboard configuration of large-packet-capable elink3 devices
                    587:  * (Demon, Vortex, Boomerang), which do not implement CONFIG_CTRL in window 0.
                    588:  * Use media and card-version info in window 3 instead.
1.15      jonathan  589:  */
                    590: void
1.20      jonathan  591: ep_vortex_probemedia(sc)
1.15      jonathan  592:        struct ep_softc *sc;
                    593: {
                    594:        bus_space_tag_t iot = sc->sc_iot;
                    595:        bus_space_handle_t ioh = sc->sc_ioh;
1.41      thorpej   596:        struct ifmedia *ifm = &sc->sc_mii.mii_media;
                    597:        struct ep_media *epm;
                    598:        u_int config1;
1.15      jonathan  599:        int reset_options;
1.28      veego     600:        int default_media;      /* 3-bit encoding of default (EEPROM) media */
1.41      thorpej   601:        int defmedia = 0;
                    602:        const char *sep = "", *defmedianame = NULL;
1.15      jonathan  603:
                    604:        GO_WINDOW(3);
1.28      veego     605:        config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2);
1.41      thorpej   606:        reset_options = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS);
1.15      jonathan  607:        GO_WINDOW(0);
                    608:
1.23      jonathan  609:        default_media = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT;
1.15      jonathan  610:
1.41      thorpej   611:        printf("%s: ", sc->sc_dev.dv_xname);
                    612:
                    613:        /* Sanity check that there are any media! */
                    614:        if ((reset_options & EP_PCI_MEDIAMASK) == 0) {
                    615:                printf("no media present!\n");
                    616:                ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL);
                    617:                ifmedia_set(ifm, IFM_ETHER|IFM_NONE);
                    618:                return;
                    619:        }
                    620:
                    621: #define        PRINT(s)        printf("%s%s", sep, s); sep = ", "
1.23      jonathan  622:
1.41      thorpej   623:        for (epm = ep_vortex_media; epm->epm_name != NULL; epm++) {
                    624:                if (reset_options & epm->epm_mpbit) {
                    625:                        if (epm->epm_epmedia == default_media ||
                    626:                            defmedia == 0) {
                    627:                                defmedia = epm->epm_ifmedia;
                    628:                                defmedianame = epm->epm_name;
                    629:                        }
                    630:                        ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_epmedia,
                    631:                            NULL);
                    632:                        PRINT(epm->epm_name);
1.23      jonathan  633:                }
                    634:        }
1.15      jonathan  635:
1.41      thorpej   636: #undef PRINT
                    637:
                    638: #ifdef DIAGNOSTIC
                    639:        if (defmedia == 0)
                    640:                panic("ep_vortex_probemedia: impossible");
                    641: #endif
                    642:
                    643:        printf(" (default %s)\n", defmedianame);
                    644:        ifmedia_set(ifm, defmedia);
                    645: }
                    646:
                    647: /*
                    648:  * One second timer, used to tick the MII.
                    649:  */
                    650: void
                    651: ep_tick(arg)
                    652:        void *arg;
                    653: {
                    654:        struct ep_softc *sc = arg;
                    655:        int s;
1.15      jonathan  656:
1.41      thorpej   657: #ifdef DIAGNOSTIC
                    658:        if ((sc->ep_flags & EP_FLAGS_MII) == 0)
                    659:                panic("ep_tick");
                    660: #endif
1.31      jonathan  661:
1.41      thorpej   662:        s = splnet();
                    663:        mii_tick(&sc->sc_mii);
                    664:        splx(s);
1.15      jonathan  665:
1.41      thorpej   666:        timeout(ep_tick, sc, hz);
1.15      jonathan  667: }
                    668:
                    669: /*
1.20      jonathan  670:  * Bring device up.
                    671:  *
1.1       thorpej   672:  * The order in here seems important. Otherwise we may not receive
                    673:  * interrupts. ?!
                    674:  */
                    675: void
                    676: epinit(sc)
                    677:        register struct ep_softc *sc;
                    678: {
1.21      is        679:        register struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.11      thorpej   680:        bus_space_tag_t iot = sc->sc_iot;
                    681:        bus_space_handle_t ioh = sc->sc_ioh;
1.1       thorpej   682:        int i;
                    683:
1.11      thorpej   684:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1       thorpej   685:                ;
                    686:
                    687:        if (sc->bustype != EP_BUS_PCI) {
                    688:                GO_WINDOW(0);
1.11      thorpej   689:                bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0);
                    690:                bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
1.1       thorpej   691:        }
                    692:
                    693:        if (sc->bustype == EP_BUS_PCMCIA) {
1.11      thorpej   694:                bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00);
1.1       thorpej   695:        }
                    696:
                    697:        GO_WINDOW(2);
                    698:        for (i = 0; i < 6; i++) /* Reload the ether_addr. */
1.11      thorpej   699:                bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
1.21      is        700:                    LLADDR(ifp->if_sadl)[i]);
1.8       christos  701:
1.12      jonathan  702:        /*
                    703:         * Reset the station-address receive filter.
1.41      thorpej   704:         * A bug workaround for busmastering (Vortex, Demon) cards.
1.12      jonathan  705:         */
                    706:        for (i = 0; i < 6; i++)
                    707:                bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0);
1.1       thorpej   708:
1.19      jonathan  709:        ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
                    710:        ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.1       thorpej   711:
                    712:        GO_WINDOW(1);           /* Window 1 is operating window */
                    713:        for (i = 0; i < 31; i++)
1.42      thorpej   714:                bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS));
1.31      jonathan  715:
                    716:        /* Set threshhold for for Tx-space avaiable interrupt. */
                    717:        bus_space_write_2(iot, ioh, EP_COMMAND,
                    718:            SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift));
1.1       thorpej   719:
1.44      thorpej   720:        if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
                    721:                /*
                    722:                 * Enable options in the PCMCIA LAN COR register, via
                    723:                 * RoadRunner Window 1.
                    724:                 *
                    725:                 * XXX MAGIC CONSTANTS!
                    726:                 */
                    727:                u_int16_t cor;
                    728:
                    729:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, (1 << 11));
                    730:
                    731:                cor = bus_space_read_2(iot, ioh, 0) & ~0x30;
                    732:                if (sc->ep_flags & EP_FLAGS_USESHAREDMEM)
                    733:                        cor |= 0x10;
                    734:                if (sc->ep_flags & EP_FLAGS_FORCENOWAIT)
                    735:                        cor |= 0x20;
                    736:                bus_space_write_2(iot, ioh, 0, cor);
                    737:
                    738:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
                    739:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
                    740:        }
                    741:
1.18      jonathan  742:        /* Enable interrupts. */
1.28      veego     743:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE |
1.1       thorpej   744:                                S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
1.11      thorpej   745:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE |
1.1       thorpej   746:                                S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL);
                    747:
                    748:        /*
                    749:         * Attempt to get rid of any stray interrupts that occured during
                    750:         * configuration.  On the i386 this isn't possible because one may
                    751:         * already be queued.  However, a single stray interrupt is
                    752:         * unimportant.
                    753:         */
1.11      thorpej   754:        bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff);
1.1       thorpej   755:
                    756:        epsetfilter(sc);
1.41      thorpej   757:        epsetmedia(sc);
1.1       thorpej   758:
1.11      thorpej   759:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
                    760:        bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
1.1       thorpej   761:
                    762:        epmbuffill(sc);
                    763:
                    764:        /* Interface is now `running', with no output active. */
                    765:        ifp->if_flags |= IFF_RUNNING;
                    766:        ifp->if_flags &= ~IFF_OACTIVE;
                    767:
1.41      thorpej   768:        if (sc->ep_flags & EP_FLAGS_MII) {
                    769:                /* Start the one second clock. */
                    770:                timeout(ep_tick, sc, hz);
                    771:        }
                    772:
1.1       thorpej   773:        /* Attempt to start output, if any. */
                    774:        epstart(ifp);
                    775: }
                    776:
1.20      jonathan  777:
                    778: /*
                    779:  * Set multicast receive filter.
                    780:  * elink3 hardware has no selective multicast filter in hardware.
                    781:  * Enable reception of all multicasts and filter in software.
                    782:  */
1.1       thorpej   783: void
                    784: epsetfilter(sc)
                    785:        register struct ep_softc *sc;
                    786: {
1.21      is        787:        register struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1       thorpej   788:
                    789:        GO_WINDOW(1);           /* Window 1 is operating window */
1.11      thorpej   790:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER |
1.1       thorpej   791:            FIL_INDIVIDUAL | FIL_BRDCST |
                    792:            ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) |
                    793:            ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 ));
                    794: }
                    795:
1.23      jonathan  796: int
                    797: ep_media_change(ifp)
                    798:        struct ifnet *ifp;
                    799: {
                    800:        register struct ep_softc *sc = ifp->if_softc;
                    801:
1.41      thorpej   802:        if (sc->enabled && (ifp->if_flags & IFF_UP) != 0)
                    803:                epreset(sc);
1.34      thorpej   804:
                    805:        return (0);
1.23      jonathan  806: }
                    807:
1.15      jonathan  808: /*
1.41      thorpej   809:  * Set the card to use the specified media.
1.15      jonathan  810:  */
1.34      thorpej   811: void
1.41      thorpej   812: epsetmedia(sc)
                    813:        struct ep_softc *sc;
1.1       thorpej   814: {
1.11      thorpej   815:        bus_space_tag_t iot = sc->sc_iot;
                    816:        bus_space_handle_t ioh = sc->sc_ioh;
1.23      jonathan  817:
1.41      thorpej   818:        /* Turn everything off.  First turn off linkbeat and UTP. */
1.1       thorpej   819:        GO_WINDOW(4);
1.41      thorpej   820:        bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, 0x0);
1.23      jonathan  821:
                    822:        /* Turn off coax */
                    823:        bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
                    824:        delay(1000);
                    825:
1.29      jonathan  826:        /*
1.41      thorpej   827:         * If the device has MII, select it, and then tell the
                    828:         * PHY which media to use.
                    829:         */
                    830:        if (sc->ep_flags & EP_FLAGS_MII) {
                    831:                int config0, config1;
                    832:
                    833:                GO_WINDOW(3);
1.44      thorpej   834:
                    835:                if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
                    836:                        int resopt;
                    837:
                    838:                        resopt = bus_space_read_2(iot, ioh,
                    839:                            EP_W3_RESET_OPTIONS);
                    840:                        bus_space_write_2(iot, ioh,
                    841:                            EP_W3_RESET_OPTIONS, resopt|EP_RUNNER_ENABLE_MII);
                    842:                }
                    843:
1.41      thorpej   844:                config0 = (u_int)bus_space_read_2(iot, ioh,
                    845:                    EP_W3_INTERNAL_CONFIG);
                    846:                config1 = (u_int)bus_space_read_2(iot, ioh,
                    847:                    EP_W3_INTERNAL_CONFIG + 2);
                    848:
                    849:                config1 = config1 & ~CONFIG_MEDIAMASK;
                    850:                config1 |= (EPMEDIA_MII << CONFIG_MEDIAMASK_SHIFT);
                    851:
                    852:                bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
                    853:                bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
                    854:                GO_WINDOW(1);   /* back to operating window */
                    855:
                    856:                mii_mediachg(&sc->sc_mii);
                    857:                return;
                    858:        }
                    859:
                    860:        /*
1.29      jonathan  861:         * Now turn on the selected media/transceiver.
                    862:         */
                    863:        GO_WINDOW(4);
1.41      thorpej   864:        switch (IFM_SUBTYPE(sc->sc_mii.mii_media.ifm_cur->ifm_media)) {
                    865:        case IFM_10_T:
1.23      jonathan  866:                bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41      thorpej   867:                    JABBER_GUARD_ENABLE|LINKBEAT_ENABLE);
1.23      jonathan  868:                break;
                    869:
1.41      thorpej   870:        case IFM_10_2:
1.11      thorpej   871:                bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER);
1.23      jonathan  872:                DELAY(1000);    /* 50ms not enmough? */
                    873:                break;
                    874:
1.41      thorpej   875:        case IFM_100_TX:
                    876:        case IFM_100_FX:
                    877:        case IFM_100_T4:                /* XXX check documentation */
1.28      veego     878:                bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41      thorpej   879:                    LINKBEAT_ENABLE);
1.23      jonathan  880:                DELAY(1000);    /* not strictly necessary? */
                    881:                break;
                    882:
1.41      thorpej   883:        case IFM_10_5:
1.23      jonathan  884:                bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE,
1.41      thorpej   885:                    SQE_ENABLE);
                    886:                DELAY(1000);    /* not strictly necessary? */
                    887:                break;
                    888:
                    889:        case IFM_MANUAL:
                    890:                /*
                    891:                 * Nothing to do here; we are actually enabling the
                    892:                 * external PHY on the MII port.
                    893:                 */
1.23      jonathan  894:                break;
1.41      thorpej   895:
                    896:        case IFM_NONE:
                    897:                printf("%s: interface disabled\n", sc->sc_dev.dv_xname);
                    898:                return;
                    899:
1.23      jonathan  900:        default:
1.41      thorpej   901:                panic("epsetmedia: impossible");
1.1       thorpej   902:        }
1.23      jonathan  903:
                    904:        /*
1.41      thorpej   905:         * Tell the chip which port to use.
1.23      jonathan  906:         */
1.41      thorpej   907:        switch (sc->ep_chipset) {
                    908:        case EP_CHIPSET_VORTEX:
                    909:        case EP_CHIPSET_BOOMERANG:
                    910:            {
1.45    ! thorpej   911:                int mctl, config0, config1;
1.23      jonathan  912:
                    913:                GO_WINDOW(3);
                    914:                config0 = (u_int)bus_space_read_2(iot, ioh,
1.28      veego     915:                    EP_W3_INTERNAL_CONFIG);
1.23      jonathan  916:                config1 = (u_int)bus_space_read_2(iot, ioh,
1.28      veego     917:                    EP_W3_INTERNAL_CONFIG + 2);
1.23      jonathan  918:
                    919:                config1 = config1 & ~CONFIG_MEDIAMASK;
1.41      thorpej   920:                config1 |= (sc->sc_mii.mii_media.ifm_cur->ifm_data <<
                    921:                    CONFIG_MEDIAMASK_SHIFT);
                    922:
1.28      veego     923:                bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0);
                    924:                bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1);
1.45    ! thorpej   925:
        !           926:                mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL);
        !           927:                if (sc->sc_mii.mii_media.ifm_cur->ifm_media & IFM_FDX)
        !           928:                        mctl |= MAC_CONTROL_FDX;
        !           929:                else
        !           930:                        mctl &= ~MAC_CONTROL_FDX;
        !           931:                bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl);
1.41      thorpej   932:                break;
                    933:            }
                    934:        default:
                    935:            {
                    936:                int w0_addr_cfg;
1.28      veego     937:
                    938:                GO_WINDOW(0);
1.29      jonathan  939:                w0_addr_cfg = bus_space_read_2(iot, ioh, EP_W0_ADDRESS_CFG);
                    940:                w0_addr_cfg &= 0x3fff;
1.41      thorpej   941:                bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, w0_addr_cfg |
                    942:                    (sc->sc_mii.mii_media.ifm_cur->ifm_data << 14));
1.28      veego     943:                DELAY(1000);
1.41      thorpej   944:                break;
                    945:            }
1.23      jonathan  946:        }
                    947:
                    948:        GO_WINDOW(1);           /* Window 1 is operating window */
                    949: }
                    950:
                    951: /*
                    952:  * Get currently-selected media from card.
                    953:  * (if_media callback, may be called before interface is brought up).
                    954:  */
                    955: void
                    956: ep_media_status(ifp, req)
                    957:        struct ifnet *ifp;
                    958:        struct ifmediareq *req;
                    959: {
                    960:        register struct ep_softc *sc = ifp->if_softc;
                    961:        bus_space_tag_t iot = sc->sc_iot;
                    962:        bus_space_handle_t ioh = sc->sc_ioh;
                    963:
1.34      thorpej   964:        if (sc->enabled == 0) {
                    965:                req->ifm_active = IFM_ETHER|IFM_NONE;
                    966:                req->ifm_status = 0;
                    967:                return;
                    968:        }
                    969:
1.41      thorpej   970:        /*
                    971:         * If we have MII, go ask the PHY what's going on.
                    972:         */
                    973:        if (sc->ep_flags & EP_FLAGS_MII) {
                    974:                mii_pollstat(&sc->sc_mii);
                    975:                req->ifm_active = sc->sc_mii.mii_media_active;
                    976:                req->ifm_status = sc->sc_mii.mii_media_status;
                    977:                return;
                    978:        }
                    979:
                    980:        /*
                    981:         * Ok, at this point we claim that our active media is
                    982:         * the currently selected media.  We'll update our status
                    983:         * if our chipset allows us to detect link.
                    984:         */
                    985:        req->ifm_active = sc->sc_mii.mii_media.ifm_cur->ifm_media;
                    986:        req->ifm_status = 0;
                    987:
1.23      jonathan  988:        switch (sc->ep_chipset) {
                    989:        case EP_CHIPSET_VORTEX:
                    990:        case EP_CHIPSET_BOOMERANG:
                    991:                GO_WINDOW(4);
1.41      thorpej   992:                req->ifm_status = IFM_AVALID;
                    993:                if (bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE) &
                    994:                    LINKBEAT_DETECT)
                    995:                        req->ifm_status |= IFM_ACTIVE;
                    996:                GO_WINDOW(1);   /* back to operating window */
1.23      jonathan  997:                break;
1.1       thorpej   998:        }
                    999: }
                   1000:
1.23      jonathan 1001:
                   1002:
1.1       thorpej  1003: /*
                   1004:  * Start outputting on the interface.
                   1005:  * Always called as splnet().
                   1006:  */
                   1007: void
                   1008: epstart(ifp)
                   1009:        struct ifnet *ifp;
                   1010: {
1.5       thorpej  1011:        register struct ep_softc *sc = ifp->if_softc;
1.11      thorpej  1012:        bus_space_tag_t iot = sc->sc_iot;
                   1013:        bus_space_handle_t ioh = sc->sc_ioh;
1.1       thorpej  1014:        struct mbuf *m, *m0;
                   1015:        int sh, len, pad;
1.42      thorpej  1016:        bus_addr_t txreg;
1.1       thorpej  1017:
                   1018:        /* Don't transmit if interface is busy or not running */
1.28      veego    1019:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1.1       thorpej  1020:                return;
                   1021:
                   1022: startagain:
                   1023:        /* Sneak a peek at the next packet */
                   1024:        m0 = ifp->if_snd.ifq_head;
                   1025:        if (m0 == 0)
                   1026:                return;
                   1027:
                   1028:        /* We need to use m->m_pkthdr.len, so require the header */
                   1029:        if ((m0->m_flags & M_PKTHDR) == 0)
                   1030:                panic("epstart: no header mbuf");
                   1031:        len = m0->m_pkthdr.len;
                   1032:
                   1033:        pad = (4 - len) & 3;
                   1034:
                   1035:        /*
                   1036:         * The 3c509 automatically pads short packets to minimum ethernet
                   1037:         * length, but we drop packets that are too large. Perhaps we should
                   1038:         * truncate them instead?
                   1039:         */
                   1040:        if (len + pad > ETHER_MAX_LEN) {
                   1041:                /* packet is obviously too large: toss it */
                   1042:                ++ifp->if_oerrors;
                   1043:                IF_DEQUEUE(&ifp->if_snd, m0);
                   1044:                m_freem(m0);
                   1045:                goto readcheck;
                   1046:        }
                   1047:
1.42      thorpej  1048:        if (bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_FREE_TX)) <
                   1049:            len + pad + 4) {
1.11      thorpej  1050:                bus_space_write_2(iot, ioh, EP_COMMAND,
1.12      jonathan 1051:                    SET_TX_AVAIL_THRESH |
                   1052:                    ((len + pad + 4) >> sc->ep_pktlenshift));
1.1       thorpej  1053:                /* not enough room in FIFO */
                   1054:                ifp->if_flags |= IFF_OACTIVE;
                   1055:                return;
                   1056:        } else {
1.11      thorpej  1057:                bus_space_write_2(iot, ioh, EP_COMMAND,
1.12      jonathan 1058:                    SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE );
1.1       thorpej  1059:        }
                   1060:
                   1061:        IF_DEQUEUE(&ifp->if_snd, m0);
                   1062:        if (m0 == 0)            /* not really needed */
                   1063:                return;
                   1064:
1.11      thorpej  1065:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
1.12      jonathan 1066:            ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) );
1.1       thorpej  1067:
                   1068: #if NBPFILTER > 0
                   1069:        if (ifp->if_bpf)
                   1070:                bpf_mtap(ifp->if_bpf, m0);
                   1071: #endif
                   1072:
                   1073:        /*
                   1074:         * Do the output at splhigh() so that an interrupt from another device
                   1075:         * won't cause a FIFO underrun.
                   1076:         */
                   1077:        sh = splhigh();
                   1078:
1.42      thorpej  1079:        txreg = ep_w1_reg(sc, EP_W1_TX_PIO_WR_1);
                   1080:
1.44      thorpej  1081:        if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) {
                   1082:                /*
                   1083:                 * Prime the FIFO buffer counter (number of 16-bit
                   1084:                 * words about to be written to the FIFO).
                   1085:                 *
                   1086:                 * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS
                   1087:                 * COUNTER IS NON-ZERO!
                   1088:                 */
                   1089:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL,
                   1090:                    (len + pad) >> 1);
                   1091:        }
                   1092:
1.42      thorpej  1093:        bus_space_write_2(iot, ioh, txreg, len);
                   1094:        bus_space_write_2(iot, ioh, txreg, 0xffff); /* Second is meaningless */
1.1       thorpej  1095:        if (EP_IS_BUS_32(sc->bustype)) {
                   1096:                for (m = m0; m; ) {
1.14      cjs      1097:                        if (m->m_len > 3)  {
                   1098:                                /* align our reads from core */
                   1099:                                if (mtod(m, u_long) & 3)  {
                   1100:                                        u_long count =
                   1101:                                            4 - (mtod(m, u_long) & 3);
                   1102:                                        bus_space_write_multi_1(iot, ioh,
1.42      thorpej  1103:                                            txreg, mtod(m, u_int8_t *), count);
1.14      cjs      1104:                                        m->m_data =
                   1105:                                            (void *)(mtod(m, u_long) + count);
                   1106:                                        m->m_len -= count;
                   1107:                                }
1.11      thorpej  1108:                                bus_space_write_multi_4(iot, ioh,
1.42      thorpej  1109:                                    txreg, mtod(m, u_int32_t *), m->m_len >> 2);
1.14      cjs      1110:                                m->m_data = (void *)(mtod(m, u_long) +
                   1111:                                        (u_long)(m->m_len & ~3));
                   1112:                                m->m_len -= m->m_len & ~3;
                   1113:                        }
                   1114:                        if (m->m_len)  {
1.11      thorpej  1115:                                bus_space_write_multi_1(iot, ioh,
1.42      thorpej  1116:                                    txreg, mtod(m, u_int8_t *), m->m_len);
1.14      cjs      1117:                        }
1.1       thorpej  1118:                        MFREE(m, m0);
                   1119:                        m = m0;
                   1120:                }
                   1121:        } else {
                   1122:                for (m = m0; m; ) {
1.14      cjs      1123:                        if (m->m_len > 1)  {
                   1124:                                if (mtod(m, u_long) & 1)  {
                   1125:                                        bus_space_write_1(iot, ioh,
1.42      thorpej  1126:                                            txreg, *(mtod(m, u_int8_t *)));
1.14      cjs      1127:                                        m->m_data =
                   1128:                                            (void *)(mtod(m, u_long) + 1);
                   1129:                                        m->m_len -= 1;
                   1130:                                }
1.11      thorpej  1131:                                bus_space_write_multi_2(iot, ioh,
1.42      thorpej  1132:                                    txreg, mtod(m, u_int16_t *),
1.14      cjs      1133:                                    m->m_len >> 1);
                   1134:                        }
                   1135:                        if (m->m_len & 1)  {
1.42      thorpej  1136:                                bus_space_write_1(iot, ioh, txreg,
1.2       thorpej  1137:                                     *(mtod(m, u_int8_t *) + m->m_len - 1));
1.14      cjs      1138:                        }
1.1       thorpej  1139:                        MFREE(m, m0);
                   1140:                        m = m0;
                   1141:                }
                   1142:        }
                   1143:        while (pad--)
1.42      thorpej  1144:                bus_space_write_1(iot, ioh, txreg, 0);
1.1       thorpej  1145:
                   1146:        splx(sh);
                   1147:
                   1148:        ++ifp->if_opackets;
                   1149:
                   1150: readcheck:
1.42      thorpej  1151:        if ((bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS)) &
                   1152:            ERR_INCOMPLETE) == 0) {
1.1       thorpej  1153:                /* We received a complete packet. */
1.11      thorpej  1154:                u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS);
1.1       thorpej  1155:
                   1156:                if ((status & S_INTR_LATCH) == 0) {
                   1157:                        /*
                   1158:                         * No interrupt, read the packet and continue
                   1159:                         * Is  this supposed to happen? Is my motherboard
                   1160:                         * completely busted?
                   1161:                         */
                   1162:                        epread(sc);
1.28      veego    1163:                } else {
1.1       thorpej  1164:                        /* Got an interrupt, return so that it gets serviced. */
                   1165:                        return;
1.28      veego    1166:                }
                   1167:        } else {
1.1       thorpej  1168:                /* Check if we are stuck and reset [see XXX comment] */
                   1169:                if (epstatus(sc)) {
                   1170:                        if (ifp->if_flags & IFF_DEBUG)
1.10      christos 1171:                                printf("%s: adapter reset\n",
1.9       christos 1172:                                    sc->sc_dev.dv_xname);
1.1       thorpej  1173:                        epreset(sc);
                   1174:                }
                   1175:        }
                   1176:
                   1177:        goto startagain;
                   1178: }
                   1179:
                   1180:
                   1181: /*
                   1182:  * XXX: The 3c509 card can get in a mode where both the fifo status bit
                   1183:  *     FIFOS_RX_OVERRUN and the status bit ERR_INCOMPLETE are set
                   1184:  *     We detect this situation and we reset the adapter.
                   1185:  *     It happens at times when there is a lot of broadcast traffic
                   1186:  *     on the cable (once in a blue moon).
                   1187:  */
                   1188: static int
                   1189: epstatus(sc)
                   1190:        register struct ep_softc *sc;
                   1191: {
1.11      thorpej  1192:        bus_space_tag_t iot = sc->sc_iot;
                   1193:        bus_space_handle_t ioh = sc->sc_ioh;
1.7       thorpej  1194:        u_int16_t fifost;
1.1       thorpej  1195:
                   1196:        /*
                   1197:         * Check the FIFO status and act accordingly
                   1198:         */
                   1199:        GO_WINDOW(4);
1.11      thorpej  1200:        fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG);
1.1       thorpej  1201:        GO_WINDOW(1);
                   1202:
                   1203:        if (fifost & FIFOS_RX_UNDERRUN) {
1.21      is       1204:                if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1205:                        printf("%s: RX underrun\n", sc->sc_dev.dv_xname);
1.1       thorpej  1206:                epreset(sc);
                   1207:                return 0;
                   1208:        }
                   1209:
                   1210:        if (fifost & FIFOS_RX_STATUS_OVERRUN) {
1.21      is       1211:                if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1212:                        printf("%s: RX Status overrun\n", sc->sc_dev.dv_xname);
1.1       thorpej  1213:                return 1;
                   1214:        }
                   1215:
                   1216:        if (fifost & FIFOS_RX_OVERRUN) {
1.21      is       1217:                if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1218:                        printf("%s: RX overrun\n", sc->sc_dev.dv_xname);
1.1       thorpej  1219:                return 1;
                   1220:        }
                   1221:
                   1222:        if (fifost & FIFOS_TX_OVERRUN) {
1.21      is       1223:                if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1224:                        printf("%s: TX overrun\n", sc->sc_dev.dv_xname);
1.1       thorpej  1225:                epreset(sc);
                   1226:                return 0;
                   1227:        }
                   1228:
                   1229:        return 0;
                   1230: }
                   1231:
                   1232:
                   1233: static void
                   1234: eptxstat(sc)
                   1235:        register struct ep_softc *sc;
                   1236: {
1.11      thorpej  1237:        bus_space_tag_t iot = sc->sc_iot;
                   1238:        bus_space_handle_t ioh = sc->sc_ioh;
1.1       thorpej  1239:        int i;
                   1240:
                   1241:        /*
                   1242:         * We need to read+write TX_STATUS until we get a 0 status
                   1243:         * in order to turn off the interrupt flag.
                   1244:         */
1.42      thorpej  1245:        while ((i = bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS)))
                   1246:            & TXS_COMPLETE) {
                   1247:                bus_space_write_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS),
                   1248:                    0x0);
1.1       thorpej  1249:
                   1250:                if (i & TXS_JABBER) {
1.21      is       1251:                        ++sc->sc_ethercom.ec_if.if_oerrors;
                   1252:                        if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1253:                                printf("%s: jabber (%x)\n",
1.1       thorpej  1254:                                       sc->sc_dev.dv_xname, i);
                   1255:                        epreset(sc);
                   1256:                } else if (i & TXS_UNDERRUN) {
1.21      is       1257:                        ++sc->sc_ethercom.ec_if.if_oerrors;
                   1258:                        if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
1.10      christos 1259:                                printf("%s: fifo underrun (%x) @%d\n",
1.1       thorpej  1260:                                       sc->sc_dev.dv_xname, i,
                   1261:                                       sc->tx_start_thresh);
                   1262:                        if (sc->tx_succ_ok < 100)
                   1263:                                    sc->tx_start_thresh = min(ETHER_MAX_LEN,
                   1264:                                            sc->tx_start_thresh + 20);
                   1265:                        sc->tx_succ_ok = 0;
                   1266:                        epreset(sc);
                   1267:                } else if (i & TXS_MAX_COLLISION) {
1.21      is       1268:                        ++sc->sc_ethercom.ec_if.if_collisions;
1.11      thorpej  1269:                        bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
1.21      is       1270:                        sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
1.1       thorpej  1271:                } else
                   1272:                        sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127;
                   1273:        }
                   1274: }
                   1275:
                   1276: int
                   1277: epintr(arg)
                   1278:        void *arg;
                   1279: {
                   1280:        register struct ep_softc *sc = arg;
1.11      thorpej  1281:        bus_space_tag_t iot = sc->sc_iot;
                   1282:        bus_space_handle_t ioh = sc->sc_ioh;
1.21      is       1283:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.7       thorpej  1284:        u_int16_t status;
1.1       thorpej  1285:        int ret = 0;
1.35      explorer 1286:        int addrandom = 0;
1.1       thorpej  1287:
1.34      thorpej  1288:        if (sc->enabled == 0)
                   1289:                return (0);
                   1290:
1.1       thorpej  1291:        for (;;) {
1.11      thorpej  1292:                bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
1.1       thorpej  1293:
1.11      thorpej  1294:                status = bus_space_read_2(iot, ioh, EP_STATUS);
1.1       thorpej  1295:
                   1296:                if ((status & (S_TX_COMPLETE | S_TX_AVAIL |
1.34      thorpej  1297:                               S_RX_COMPLETE | S_CARD_FAILURE)) == 0) {
                   1298:                        if ((status & S_INTR_LATCH) == 0) {
                   1299: #if 0
                   1300:                                printf("%s: intr latch cleared\n",
                   1301:                                       sc->sc_dev.dv_xname);
                   1302: #endif
                   1303:                                break;
                   1304:                        }
                   1305:                }
1.1       thorpej  1306:
                   1307:                ret = 1;
                   1308:
                   1309:                /*
                   1310:                 * Acknowledge any interrupts.  It's important that we do this
                   1311:                 * first, since there would otherwise be a race condition.
                   1312:                 * Due to the i386 interrupt queueing, we may get spurious
                   1313:                 * interrupts occasionally.
                   1314:                 */
1.34      thorpej  1315:                bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
                   1316:                                  (status & (C_INTR_LATCH |
                   1317:                                             C_CARD_FAILURE |
                   1318:                                             C_TX_COMPLETE |
                   1319:                                             C_TX_AVAIL |
                   1320:                                             C_RX_COMPLETE |
                   1321:                                             C_RX_EARLY |
                   1322:                                             C_INT_RQD |
                   1323:                                             C_UPD_STATS)));
                   1324:
                   1325: #if 0
                   1326:                status = bus_space_read_2(iot, ioh, EP_STATUS);
                   1327:
                   1328:                printf("%s: intr%s%s%s%s\n", sc->sc_dev.dv_xname,
                   1329:                       (status & S_RX_COMPLETE)?" RX_COMPLETE":"",
                   1330:                       (status & S_TX_COMPLETE)?" TX_COMPLETE":"",
                   1331:                       (status & S_TX_AVAIL)?" TX_AVAIL":"",
                   1332:                       (status & S_CARD_FAILURE)?" CARD_FAILURE":"");
                   1333: #endif
1.1       thorpej  1334:
1.35      explorer 1335:                if (status & S_RX_COMPLETE) {
1.1       thorpej  1336:                        epread(sc);
1.35      explorer 1337:                        addrandom = 1;
                   1338:                }
1.1       thorpej  1339:                if (status & S_TX_AVAIL) {
1.21      is       1340:                        sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE;
                   1341:                        epstart(&sc->sc_ethercom.ec_if);
1.35      explorer 1342:                        addrandom = 1;
1.1       thorpej  1343:                }
                   1344:                if (status & S_CARD_FAILURE) {
1.10      christos 1345:                        printf("%s: adapter failure (%x)\n",
1.9       christos 1346:                            sc->sc_dev.dv_xname, status);
1.1       thorpej  1347:                        epreset(sc);
                   1348:                        return (1);
                   1349:                }
                   1350:                if (status & S_TX_COMPLETE) {
                   1351:                        eptxstat(sc);
                   1352:                        epstart(ifp);
1.35      explorer 1353:                        addrandom = 1;
1.1       thorpej  1354:                }
1.35      explorer 1355:
                   1356: #if NRND > 0
                   1357:                if (status)
                   1358:                        rnd_add_uint32(&sc->rnd_source, status);
                   1359: #endif
1.1       thorpej  1360:        }
                   1361:
                   1362:        /* no more interrupts */
                   1363:        return (ret);
                   1364: }
                   1365:
                   1366: void
                   1367: epread(sc)
                   1368:        register struct ep_softc *sc;
                   1369: {
1.11      thorpej  1370:        bus_space_tag_t iot = sc->sc_iot;
                   1371:        bus_space_handle_t ioh = sc->sc_ioh;
1.21      is       1372:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.1       thorpej  1373:        struct mbuf *m;
                   1374:        struct ether_header *eh;
                   1375:        int len;
                   1376:
1.42      thorpej  1377:        len = bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS));
1.1       thorpej  1378:
                   1379: again:
                   1380:        if (ifp->if_flags & IFF_DEBUG) {
                   1381:                int err = len & ERR_MASK;
                   1382:                char *s = NULL;
                   1383:
                   1384:                if (len & ERR_INCOMPLETE)
                   1385:                        s = "incomplete packet";
                   1386:                else if (err == ERR_OVERRUN)
                   1387:                        s = "packet overrun";
                   1388:                else if (err == ERR_RUNT)
                   1389:                        s = "runt packet";
                   1390:                else if (err == ERR_ALIGNMENT)
                   1391:                        s = "bad alignment";
                   1392:                else if (err == ERR_CRC)
                   1393:                        s = "bad crc";
                   1394:                else if (err == ERR_OVERSIZE)
                   1395:                        s = "oversized packet";
                   1396:                else if (err == ERR_DRIBBLE)
                   1397:                        s = "dribble bits";
                   1398:
                   1399:                if (s)
1.10      christos 1400:                        printf("%s: %s\n", sc->sc_dev.dv_xname, s);
1.1       thorpej  1401:        }
                   1402:
                   1403:        if (len & ERR_INCOMPLETE)
                   1404:                return;
                   1405:
                   1406:        if (len & ERR_RX) {
                   1407:                ++ifp->if_ierrors;
                   1408:                goto abort;
                   1409:        }
                   1410:
                   1411:        len &= RX_BYTES_MASK;   /* Lower 11 bits = RX bytes. */
                   1412:
                   1413:        /* Pull packet off interface. */
                   1414:        m = epget(sc, len);
                   1415:        if (m == 0) {
                   1416:                ifp->if_ierrors++;
                   1417:                goto abort;
                   1418:        }
                   1419:
                   1420:        ++ifp->if_ipackets;
                   1421:
                   1422:        /* We assume the header fit entirely in one mbuf. */
                   1423:        eh = mtod(m, struct ether_header *);
                   1424:
                   1425: #if NBPFILTER > 0
                   1426:        /*
                   1427:         * Check if there's a BPF listener on this interface.
                   1428:         * If so, hand off the raw packet to BPF.
                   1429:         */
                   1430:        if (ifp->if_bpf) {
                   1431:                bpf_mtap(ifp->if_bpf, m);
                   1432:
                   1433:                /*
                   1434:                 * Note that the interface cannot be in promiscuous mode if
                   1435:                 * there are no BPF listeners.  And if we are in promiscuous
                   1436:                 * mode, we have to check if this packet is really ours.
                   1437:                 */
                   1438:                if ((ifp->if_flags & IFF_PROMISC) &&
                   1439:                    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
1.21      is       1440:                    bcmp(eh->ether_dhost, LLADDR(sc->sc_ethercom.ec_if.if_sadl),
1.1       thorpej  1441:                            sizeof(eh->ether_dhost)) != 0) {
                   1442:                        m_freem(m);
                   1443:                        return;
                   1444:                }
                   1445:        }
                   1446: #endif
                   1447:
                   1448:        /* We assume the header fit entirely in one mbuf. */
                   1449:        m_adj(m, sizeof(struct ether_header));
1.43      thorpej  1450:        ether_input(ifp, eh, m);
1.1       thorpej  1451:
                   1452:        /*
                   1453:         * In periods of high traffic we can actually receive enough
                   1454:         * packets so that the fifo overrun bit will be set at this point,
                   1455:         * even though we just read a packet. In this case we
                   1456:         * are not going to receive any more interrupts. We check for
                   1457:         * this condition and read again until the fifo is not full.
                   1458:         * We could simplify this test by not using epstatus(), but
                   1459:         * rechecking the RX_STATUS register directly. This test could
                   1460:         * result in unnecessary looping in cases where there is a new
                   1461:         * packet but the fifo is not full, but it will not fix the
                   1462:         * stuck behavior.
                   1463:         *
                   1464:         * Even with this improvement, we still get packet overrun errors
                   1465:         * which are hurting performance. Maybe when I get some more time
                   1466:         * I'll modify epread() so that it can handle RX_EARLY interrupts.
                   1467:         */
                   1468:        if (epstatus(sc)) {
1.42      thorpej  1469:                len = bus_space_read_2(iot, ioh,
                   1470:                    ep_w1_reg(sc, EP_W1_RX_STATUS));
1.1       thorpej  1471:                /* Check if we are stuck and reset [see XXX comment] */
                   1472:                if (len & ERR_INCOMPLETE) {
                   1473:                        if (ifp->if_flags & IFF_DEBUG)
1.10      christos 1474:                                printf("%s: adapter reset\n",
1.9       christos 1475:                                    sc->sc_dev.dv_xname);
1.1       thorpej  1476:                        epreset(sc);
                   1477:                        return;
                   1478:                }
                   1479:                goto again;
                   1480:        }
                   1481:
                   1482:        return;
                   1483:
                   1484: abort:
1.11      thorpej  1485:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
                   1486:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1       thorpej  1487:                ;
                   1488: }
                   1489:
                   1490: struct mbuf *
                   1491: epget(sc, totlen)
                   1492:        struct ep_softc *sc;
                   1493:        int totlen;
                   1494: {
1.11      thorpej  1495:        bus_space_tag_t iot = sc->sc_iot;
                   1496:        bus_space_handle_t ioh = sc->sc_ioh;
1.21      is       1497:        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1.44      thorpej  1498:        struct mbuf *top, **mp, *m, *rv = NULL;
1.42      thorpej  1499:        bus_addr_t rxreg;
1.14      cjs      1500:        int len, remaining;
1.1       thorpej  1501:        int sh;
                   1502:
                   1503:        m = sc->mb[sc->next_mb];
                   1504:        sc->mb[sc->next_mb] = 0;
                   1505:        if (m == 0) {
                   1506:                MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1507:                if (m == 0)
                   1508:                        return 0;
                   1509:        } else {
                   1510:                /* If the queue is no longer full, refill. */
                   1511:                if (sc->last_mb == sc->next_mb)
                   1512:                        timeout(epmbuffill, sc, 1);
                   1513:                /* Convert one of our saved mbuf's. */
                   1514:                sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
                   1515:                m->m_data = m->m_pktdat;
                   1516:                m->m_flags = M_PKTHDR;
                   1517:        }
                   1518:        m->m_pkthdr.rcvif = ifp;
                   1519:        m->m_pkthdr.len = totlen;
                   1520:        len = MHLEN;
                   1521:        top = 0;
                   1522:        mp = &top;
                   1523:
                   1524:        /*
                   1525:         * We read the packet at splhigh() so that an interrupt from another
                   1526:         * device doesn't cause the card's buffer to overflow while we're
                   1527:         * reading it.  We may still lose packets at other times.
                   1528:         */
                   1529:        sh = splhigh();
                   1530:
1.42      thorpej  1531:        rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1);
                   1532:
1.44      thorpej  1533:        if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) {
                   1534:                /*
                   1535:                 * Prime the FIFO buffer counter (number of 16-bit
                   1536:                 * words about to be read from the FIFO).
                   1537:                 *
                   1538:                 * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS
                   1539:                 * COUNTER IS NON-ZERO!
                   1540:                 */
                   1541:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, totlen >> 1);
                   1542:        }
                   1543:
1.1       thorpej  1544:        while (totlen > 0) {
                   1545:                if (top) {
                   1546:                        m = sc->mb[sc->next_mb];
                   1547:                        sc->mb[sc->next_mb] = 0;
                   1548:                        if (m == 0) {
                   1549:                                MGET(m, M_DONTWAIT, MT_DATA);
                   1550:                                if (m == 0) {
                   1551:                                        m_freem(top);
1.44      thorpej  1552:                                        goto out;
1.1       thorpej  1553:                                }
                   1554:                        } else {
                   1555:                                sc->next_mb = (sc->next_mb + 1) % MAX_MBS;
                   1556:                        }
                   1557:                        len = MLEN;
                   1558:                }
                   1559:                if (totlen >= MINCLSIZE) {
                   1560:                        MCLGET(m, M_DONTWAIT);
1.27      mycroft  1561:                        if ((m->m_flags & M_EXT) == 0) {
1.30      mycroft  1562:                                m_free(m);
1.26      mycroft  1563:                                m_freem(top);
1.44      thorpej  1564:                                goto out;
1.26      mycroft  1565:                        }
                   1566:                        len = MCLBYTES;
1.1       thorpej  1567:                }
1.24      cjs      1568:                if (top == 0)  {
1.25      cjs      1569:                        /* align the struct ip header */
                   1570:                        caddr_t newdata = (caddr_t)
                   1571:                            ALIGN(m->m_data + sizeof(struct ether_header))
                   1572:                            - sizeof(struct ether_header);
                   1573:                        len -= newdata - m->m_data;
                   1574:                        m->m_data = newdata;
1.14      cjs      1575:                }
                   1576:                remaining = len = min(totlen, len);
1.1       thorpej  1577:                if (EP_IS_BUS_32(sc->bustype)) {
1.14      cjs      1578:                        u_long offset = mtod(m, u_long);
                   1579:                        /*
                   1580:                         * Read bytes up to the point where we are aligned.
                   1581:                         * (We can align to 4 bytes, rather than ALIGNBYTES,
                   1582:                         * here because we're later reading 4-byte chunks.)
                   1583:                         */
                   1584:                        if ((remaining > 3) && (offset & 3))  {
                   1585:                                int count = (4 - (offset & 3));
                   1586:                                bus_space_read_multi_1(iot, ioh,
1.42      thorpej  1587:                                    rxreg, (u_int8_t *) offset, count);
1.14      cjs      1588:                                offset += count;
                   1589:                                remaining -= count;
                   1590:                        }
                   1591:                        if (remaining > 3) {
1.11      thorpej  1592:                                bus_space_read_multi_4(iot, ioh,
1.42      thorpej  1593:                                    rxreg, (u_int32_t *) offset,
                   1594:                                    remaining >> 2);
1.14      cjs      1595:                                offset += remaining & ~3;
                   1596:                                remaining &= 3;
                   1597:                        }
                   1598:                        if (remaining)  {
1.11      thorpej  1599:                                bus_space_read_multi_1(iot, ioh,
1.42      thorpej  1600:                                    rxreg, (u_int8_t *) offset, remaining);
1.14      cjs      1601:                        }
1.1       thorpej  1602:                } else {
1.14      cjs      1603:                        u_long offset = mtod(m, u_long);
                   1604:                        if ((remaining > 1) && (offset & 1))  {
                   1605:                                bus_space_read_multi_1(iot, ioh,
1.42      thorpej  1606:                                    rxreg, (u_int8_t *) offset, 1);
1.14      cjs      1607:                                remaining -= 1;
                   1608:                                offset += 1;
                   1609:                        }
                   1610:                        if (remaining > 1) {
1.11      thorpej  1611:                                bus_space_read_multi_2(iot, ioh,
1.42      thorpej  1612:                                    rxreg, (u_int16_t *) offset,
                   1613:                                    remaining >> 1);
1.14      cjs      1614:                                offset += remaining & ~1;
                   1615:                        }
                   1616:                        if (remaining & 1)  {
                   1617:                                bus_space_read_multi_1(iot, ioh,
1.42      thorpej  1618:                                    rxreg, (u_int8_t *) offset, remaining & 1);
1.14      cjs      1619:                        }
1.1       thorpej  1620:                }
                   1621:                m->m_len = len;
                   1622:                totlen -= len;
                   1623:                *mp = m;
                   1624:                mp = &m->m_next;
                   1625:        }
                   1626:
1.44      thorpej  1627:        rv = top;
                   1628:
1.11      thorpej  1629:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
                   1630:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1       thorpej  1631:                ;
                   1632:
1.44      thorpej  1633:  out:
                   1634:        if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER)
                   1635:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
1.1       thorpej  1636:        splx(sh);
                   1637:
1.44      thorpej  1638:        return rv;
1.1       thorpej  1639: }
                   1640:
                   1641: int
                   1642: epioctl(ifp, cmd, data)
                   1643:        register struct ifnet *ifp;
                   1644:        u_long cmd;
                   1645:        caddr_t data;
                   1646: {
1.5       thorpej  1647:        struct ep_softc *sc = ifp->if_softc;
1.1       thorpej  1648:        struct ifaddr *ifa = (struct ifaddr *)data;
                   1649:        struct ifreq *ifr = (struct ifreq *)data;
                   1650:        int s, error = 0;
                   1651:
                   1652:        s = splnet();
                   1653:
                   1654:        switch (cmd) {
                   1655:
                   1656:        case SIOCSIFADDR:
1.34      thorpej  1657:                if ((error = epenable(sc)) != 0)
                   1658:                        break;
                   1659:                /* epinit is called just below */
1.1       thorpej  1660:                ifp->if_flags |= IFF_UP;
                   1661:                switch (ifa->ifa_addr->sa_family) {
                   1662: #ifdef INET
                   1663:                case AF_INET:
                   1664:                        epinit(sc);
1.21      is       1665:                        arp_ifinit(&sc->sc_ethercom.ec_if, ifa);
1.1       thorpej  1666:                        break;
                   1667: #endif
                   1668: #ifdef NS
                   1669:                case AF_NS:
                   1670:                    {
                   1671:                        register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                   1672:
                   1673:                        if (ns_nullhost(*ina))
1.21      is       1674:                                ina->x_host = *(union ns_host *)
                   1675:                                    LLADDR(ifp->if_sadl);
1.1       thorpej  1676:                        else
                   1677:                                bcopy(ina->x_host.c_host,
1.21      is       1678:                                    LLADDR(ifp->if_sadl),
                   1679:                                    ifp->if_addrlen);
1.1       thorpej  1680:                        /* Set new address. */
                   1681:                        epinit(sc);
                   1682:                        break;
                   1683:                    }
                   1684: #endif
                   1685:                default:
                   1686:                        epinit(sc);
                   1687:                        break;
                   1688:                }
                   1689:                break;
                   1690:
1.23      jonathan 1691:        case SIOCSIFMEDIA:
                   1692:        case SIOCGIFMEDIA:
1.41      thorpej  1693:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
1.23      jonathan 1694:                break;
                   1695:
1.1       thorpej  1696:        case SIOCSIFFLAGS:
                   1697:                if ((ifp->if_flags & IFF_UP) == 0 &&
                   1698:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                   1699:                        /*
                   1700:                         * If interface is marked down and it is running, then
                   1701:                         * stop it.
                   1702:                         */
                   1703:                        epstop(sc);
                   1704:                        ifp->if_flags &= ~IFF_RUNNING;
1.34      thorpej  1705:                        epdisable(sc);
1.1       thorpej  1706:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                   1707:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                   1708:                        /*
                   1709:                         * If interface is marked up and it is stopped, then
                   1710:                         * start it.
                   1711:                         */
1.34      thorpej  1712:                        if ((error = epenable(sc)) != 0)
                   1713:                                break;
1.1       thorpej  1714:                        epinit(sc);
1.34      thorpej  1715:                } else if (sc->enabled) {
1.1       thorpej  1716:                        /*
                   1717:                         * deal with flags changes:
1.23      jonathan 1718:                         * IFF_MULTICAST, IFF_PROMISC.
1.1       thorpej  1719:                         */
                   1720:                        epsetfilter(sc);
                   1721:                }
                   1722:                break;
                   1723:
                   1724:        case SIOCADDMULTI:
                   1725:        case SIOCDELMULTI:
1.34      thorpej  1726:                if (sc->enabled == 0) {
                   1727:                        error = EIO;
                   1728:                        break;
                   1729:                }
                   1730:
1.1       thorpej  1731:                error = (cmd == SIOCADDMULTI) ?
1.21      is       1732:                    ether_addmulti(ifr, &sc->sc_ethercom) :
                   1733:                    ether_delmulti(ifr, &sc->sc_ethercom);
1.1       thorpej  1734:
                   1735:                if (error == ENETRESET) {
                   1736:                        /*
                   1737:                         * Multicast list has changed; set the hardware filter
                   1738:                         * accordingly.
                   1739:                         */
                   1740:                        epreset(sc);
                   1741:                        error = 0;
                   1742:                }
                   1743:                break;
                   1744:
                   1745:        default:
                   1746:                error = EINVAL;
                   1747:                break;
                   1748:        }
                   1749:
                   1750:        splx(s);
                   1751:        return (error);
                   1752: }
                   1753:
                   1754: void
                   1755: epreset(sc)
                   1756:        struct ep_softc *sc;
                   1757: {
                   1758:        int s;
                   1759:
                   1760:        s = splnet();
                   1761:        epstop(sc);
                   1762:        epinit(sc);
                   1763:        splx(s);
                   1764: }
                   1765:
                   1766: void
1.5       thorpej  1767: epwatchdog(ifp)
                   1768:        struct ifnet *ifp;
1.1       thorpej  1769: {
1.5       thorpej  1770:        struct ep_softc *sc = ifp->if_softc;
1.1       thorpej  1771:
                   1772:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1.21      is       1773:        ++sc->sc_ethercom.ec_if.if_oerrors;
1.1       thorpej  1774:
                   1775:        epreset(sc);
                   1776: }
                   1777:
                   1778: void
                   1779: epstop(sc)
                   1780:        register struct ep_softc *sc;
                   1781: {
1.11      thorpej  1782:        bus_space_tag_t iot = sc->sc_iot;
                   1783:        bus_space_handle_t ioh = sc->sc_ioh;
1.1       thorpej  1784:
1.41      thorpej  1785:        if (sc->ep_flags & EP_FLAGS_MII) {
                   1786:                /* Stop the one second clock. */
                   1787:                untimeout(ep_tick, sc);
1.44      thorpej  1788:        }
                   1789:
                   1790:        if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) {
                   1791:                /*
                   1792:                 * Clear the FIFO buffer count, thus halting
                   1793:                 * any currently-running transactions.
                   1794:                 */
                   1795:                GO_WINDOW(1);           /* sanity */
                   1796:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0);
                   1797:                bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0);
1.41      thorpej  1798:        }
                   1799:
1.11      thorpej  1800:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
                   1801:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK);
                   1802:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
1.1       thorpej  1803:                ;
1.11      thorpej  1804:        bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
                   1805:        bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
1.18      jonathan 1806:
1.19      jonathan 1807:        ep_complete_cmd(sc, EP_COMMAND, RX_RESET);
                   1808:        ep_complete_cmd(sc, EP_COMMAND, TX_RESET);
1.18      jonathan 1809:
1.11      thorpej  1810:        bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
                   1811:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
                   1812:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
                   1813:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
1.1       thorpej  1814:
                   1815:        epmbufempty(sc);
                   1816: }
1.16      jonathan 1817:
                   1818:
                   1819: /*
                   1820:  * Before reboots, reset card completely.
                   1821:  */
                   1822: static void
                   1823: epshutdown(arg)
                   1824:        void *arg;
                   1825: {
                   1826:        register struct ep_softc *sc = arg;
                   1827:
1.34      thorpej  1828:        if (sc->enabled) {
                   1829:                epstop(sc);
                   1830:                ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET);
                   1831:        }
1.16      jonathan 1832: }
1.1       thorpej  1833:
                   1834: /*
                   1835:  * We get eeprom data from the id_port given an offset into the
                   1836:  * eeprom.  Basically; after the ID_sequence is sent to all of
                   1837:  * the cards; they enter the ID_CMD state where they will accept
                   1838:  * command requests. 0x80-0xbf loads the eeprom data.  We then
                   1839:  * read the port 16 times and with every read; the cards check
                   1840:  * for contention (ie: if one card writes a 0 bit and another
                   1841:  * writes a 1 bit then the host sees a 0. At the end of the cycle;
                   1842:  * each card compares the data on the bus; if there is a difference
                   1843:  * then that card goes into ID_WAIT state again). In the meantime;
                   1844:  * one bit of data is returned in the AX register which is conveniently
1.11      thorpej  1845:  * returned to us by bus_space_read_1().  Hence; we read 16 times getting one
1.1       thorpej  1846:  * bit of data with each read.
1.2       thorpej  1847:  *
                   1848:  * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
1.1       thorpej  1849:  */
1.2       thorpej  1850: u_int16_t
1.11      thorpej  1851: epreadeeprom(iot, ioh, offset)
                   1852:        bus_space_tag_t iot;
                   1853:        bus_space_handle_t ioh;
1.2       thorpej  1854:        int offset;
1.1       thorpej  1855: {
1.2       thorpej  1856:        u_int16_t data = 0;
                   1857:        int i;
1.1       thorpej  1858:
1.11      thorpej  1859:        bus_space_write_1(iot, ioh, 0, 0x80 + offset);
1.1       thorpej  1860:        delay(1000);
                   1861:        for (i = 0; i < 16; i++)
1.11      thorpej  1862:                data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
1.1       thorpej  1863:        return (data);
                   1864: }
                   1865:
                   1866: static int
                   1867: epbusyeeprom(sc)
                   1868:        struct ep_softc *sc;
                   1869: {
1.11      thorpej  1870:        bus_space_tag_t iot = sc->sc_iot;
                   1871:        bus_space_handle_t ioh = sc->sc_ioh;
1.1       thorpej  1872:        int i = 100, j;
                   1873:
                   1874:        if (sc->bustype == EP_BUS_PCMCIA) {
                   1875:                delay(1000);
                   1876:                return 0;
                   1877:        }
                   1878:
1.33      jonathan 1879:        j = 0;          /* bad GCC flow analysis */
1.1       thorpej  1880:        while (i--) {
1.11      thorpej  1881:                j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND);
1.1       thorpej  1882:                if (j & EEPROM_BUSY)
                   1883:                        delay(100);
                   1884:                else
                   1885:                        break;
                   1886:        }
                   1887:        if (!i) {
1.10      christos 1888:                printf("\n%s: eeprom failed to come ready\n",
1.1       thorpej  1889:                    sc->sc_dev.dv_xname);
                   1890:                return (1);
                   1891:        }
                   1892:        if (j & EEPROM_TST_MODE) {
1.29      jonathan 1893:                /* XXX PnP mode? */
1.28      veego    1894:                printf("\n%s: erase pencil mark!\n", sc->sc_dev.dv_xname);
1.1       thorpej  1895:                return (1);
                   1896:        }
                   1897:        return (0);
                   1898: }
                   1899:
                   1900: void
1.3       christos 1901: epmbuffill(v)
                   1902:        void *v;
1.1       thorpej  1903: {
1.3       christos 1904:        struct ep_softc *sc = v;
1.1       thorpej  1905:        int s, i;
                   1906:
                   1907:        s = splnet();
                   1908:        i = sc->last_mb;
                   1909:        do {
                   1910:                if (sc->mb[i] == NULL)
                   1911:                        MGET(sc->mb[i], M_DONTWAIT, MT_DATA);
                   1912:                if (sc->mb[i] == NULL)
                   1913:                        break;
                   1914:                i = (i + 1) % MAX_MBS;
                   1915:        } while (i != sc->next_mb);
                   1916:        sc->last_mb = i;
                   1917:        /* If the queue was not filled, try again. */
                   1918:        if (sc->last_mb != sc->next_mb)
                   1919:                timeout(epmbuffill, sc, 1);
                   1920:        splx(s);
                   1921: }
                   1922:
                   1923: void
                   1924: epmbufempty(sc)
                   1925:        struct ep_softc *sc;
                   1926: {
                   1927:        int s, i;
                   1928:
                   1929:        s = splnet();
                   1930:        for (i = 0; i<MAX_MBS; i++) {
                   1931:                if (sc->mb[i]) {
                   1932:                        m_freem(sc->mb[i]);
                   1933:                        sc->mb[i] = NULL;
                   1934:                }
                   1935:        }
                   1936:        sc->last_mb = sc->next_mb = 0;
                   1937:        untimeout(epmbuffill, sc);
                   1938:        splx(s);
1.34      thorpej  1939: }
                   1940:
                   1941: int
                   1942: epenable(sc)
                   1943:        struct ep_softc *sc;
                   1944: {
                   1945:
                   1946:        if (sc->enabled == 0 && sc->enable != NULL) {
                   1947:                if ((*sc->enable)(sc) != 0) {
                   1948:                        printf("%s: device enable failed\n",
                   1949:                            sc->sc_dev.dv_xname);
                   1950:                        return (EIO);
                   1951:                }
                   1952:        }
                   1953:
                   1954:        sc->enabled = 1;
                   1955:        return (0);
                   1956: }
                   1957:
                   1958: void
                   1959: epdisable(sc)
                   1960:        struct ep_softc *sc;
                   1961: {
                   1962:
                   1963:        if (sc->enabled != 0 && sc->disable != NULL) {
                   1964:                (*sc->disable)(sc);
                   1965:                sc->enabled = 0;
                   1966:        }
1.41      thorpej  1967: }
                   1968:
                   1969: void
                   1970: ep_mii_setbit(sc, bit)
                   1971:        struct ep_softc *sc;
                   1972:        u_int16_t bit;
                   1973: {
                   1974:        u_int16_t val;
                   1975:
                   1976:        /* We assume we're already in Window 4 */
                   1977:        val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
                   1978:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
                   1979:            val | bit);
                   1980: }
                   1981:
                   1982: void
                   1983: ep_mii_clrbit(sc, bit)
                   1984:        struct ep_softc *sc;
                   1985:        u_int16_t bit;
                   1986: {
                   1987:        u_int16_t val;
                   1988:
                   1989:        /* We assume we're already in Window 4 */
                   1990:        val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT);
                   1991:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT,
                   1992:            val & ~bit);
                   1993: }
                   1994:
                   1995: u_int16_t
                   1996: ep_mii_readbit(sc, bit)
                   1997:        struct ep_softc *sc;
                   1998:        u_int16_t bit;
                   1999: {
                   2000:
                   2001:        /* We assume we're already in Window 4 */
                   2002:        return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT) &
                   2003:            bit);
                   2004: }
                   2005:
                   2006: void
                   2007: ep_mii_sync(sc)
                   2008:        struct ep_softc *sc;
                   2009: {
                   2010:        int i;
                   2011:
                   2012:        /* We assume we're already in Window 4 */
                   2013:        ep_mii_clrbit(sc, PHYSMGMT_DIR);
                   2014:        for (i = 0; i < 32; i++) {
                   2015:                ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2016:                ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2017:        }
                   2018: }
                   2019:
                   2020: void
                   2021: ep_mii_sendbits(sc, data, nbits)
                   2022:        struct ep_softc *sc;
                   2023:        u_int32_t data;
                   2024:        int nbits;
                   2025: {
                   2026:        int i;
                   2027:
                   2028:        /* We assume we're already in Window 4 */
                   2029:        ep_mii_setbit(sc, PHYSMGMT_DIR);
                   2030:        for (i = 1 << (nbits - 1); i; i = i >> 1) {
                   2031:                ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2032:                ep_mii_readbit(sc, PHYSMGMT_CLK);
                   2033:                if (data & i)
                   2034:                        ep_mii_setbit(sc, PHYSMGMT_DATA);
                   2035:                else
                   2036:                        ep_mii_clrbit(sc, PHYSMGMT_DATA);
                   2037:                ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2038:                ep_mii_readbit(sc, PHYSMGMT_CLK);
                   2039:        }
                   2040: }
                   2041:
                   2042: int
                   2043: ep_mii_readreg(self, phy, reg)
                   2044:        struct device *self;
                   2045:        int phy, reg;
                   2046: {
                   2047:        struct ep_softc *sc = (struct ep_softc *)self;
                   2048:        int val = 0, i, err;
                   2049:
                   2050:        /*
                   2051:         * Read the PHY register by manually driving the MII control lines.
                   2052:         */
                   2053:
                   2054:        GO_WINDOW(4);
                   2055:
                   2056:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, 0);
                   2057:
                   2058:        ep_mii_sync(sc);
                   2059:        ep_mii_sendbits(sc, MII_COMMAND_START, 2);
                   2060:        ep_mii_sendbits(sc, MII_COMMAND_READ, 2);
                   2061:        ep_mii_sendbits(sc, phy, 5);
                   2062:        ep_mii_sendbits(sc, reg, 5);
                   2063:
                   2064:        ep_mii_clrbit(sc, PHYSMGMT_DIR);
                   2065:        ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2066:        ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2067:        ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2068:
                   2069:        err = ep_mii_readbit(sc, PHYSMGMT_DATA);
                   2070:        ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2071:
                   2072:        /* Even if an error occurs, must still clock out the cycle. */
                   2073:        for (i = 0; i < 16; i++) {
                   2074:                val <<= 1;
                   2075:                ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2076:                if (err == 0 && ep_mii_readbit(sc, PHYSMGMT_DATA))
                   2077:                        val |= 1;
                   2078:                ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2079:        }
                   2080:        ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2081:        ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2082:
                   2083:        GO_WINDOW(1);   /* back to operating window */
                   2084:
                   2085:        return (err ? 0 : val);
                   2086: }
                   2087:
                   2088: void
                   2089: ep_mii_writereg(self, phy, reg, val)
                   2090:        struct device *self;
                   2091:        int phy, reg, val;
                   2092: {
                   2093:        struct ep_softc *sc = (struct ep_softc *)self;
                   2094:
                   2095:        /*
                   2096:         * Write the PHY register by manually driving the MII control lines.
                   2097:         */
                   2098:
                   2099:        GO_WINDOW(4);
                   2100:
                   2101:        ep_mii_sync(sc);
                   2102:        ep_mii_sendbits(sc, MII_COMMAND_START, 2);
                   2103:        ep_mii_sendbits(sc, MII_COMMAND_WRITE, 2);
                   2104:        ep_mii_sendbits(sc, phy, 5);
                   2105:        ep_mii_sendbits(sc, reg, 5);
                   2106:        ep_mii_sendbits(sc, MII_COMMAND_ACK, 2);
                   2107:        ep_mii_sendbits(sc, val, 16);
                   2108:
                   2109:        ep_mii_clrbit(sc, PHYSMGMT_CLK);
                   2110:        ep_mii_setbit(sc, PHYSMGMT_CLK);
                   2111:
                   2112:        GO_WINDOW(1);   /* back to operating window */
                   2113: }
                   2114:
                   2115: void
                   2116: ep_statchg(self)
                   2117:        struct device *self;
                   2118: {
1.45    ! thorpej  2119:        struct ep_softc *sc = (struct ep_softc *)self;
        !          2120:        bus_space_tag_t iot = sc->sc_iot;
        !          2121:        bus_space_handle_t ioh = sc->sc_ioh;
        !          2122:        int mctl;
1.41      thorpej  2123:
                   2124:        /* XXX Update ifp->if_baudrate */
1.45    ! thorpej  2125:
        !          2126:        GO_WINDOW(3);
        !          2127:        mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL);
        !          2128:        if (sc->sc_mii.mii_media_active & IFM_FDX)
        !          2129:                mctl |= MAC_CONTROL_FDX;
        !          2130:        else
        !          2131:                mctl &= ~MAC_CONTROL_FDX;
        !          2132:        bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl);
        !          2133:        GO_WINDOW(1);   /* back to operating window */
1.1       thorpej  2134: }

CVSweb <webmaster@jp.NetBSD.org>