[BACK]Return to if_ef_isapnp.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/if_ef_isapnp.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_ef_isapnp.c,v 1.21 2006/03/25 22:41:44 djm Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
                     28:
                     29: #include "bpfilter.h"
                     30:
                     31: #include <sys/param.h>
                     32: #include <sys/systm.h>
                     33: #include <sys/mbuf.h>
                     34: #include <sys/socket.h>
                     35: #include <sys/ioctl.h>
                     36: #include <sys/errno.h>
                     37: #include <sys/syslog.h>
                     38: #include <sys/selinfo.h>
                     39: #include <sys/device.h>
                     40: #include <sys/queue.h>
                     41: #include <sys/kernel.h>
                     42: #include <sys/timeout.h>
                     43:
                     44: #include <net/if.h>
                     45: #include <net/if_dl.h>
                     46: #include <net/if_types.h>
                     47: #include <net/netisr.h>
                     48: #include <net/if_media.h>
                     49:
                     50: #ifdef INET
                     51: #include <netinet/in.h>
                     52: #include <netinet/in_systm.h>
                     53: #include <netinet/in_var.h>
                     54: #include <netinet/ip.h>
                     55: #include <netinet/if_ether.h>
                     56: #endif
                     57:
                     58: #if NBPFILTER > 0
                     59: #include <net/bpf.h>
                     60: #endif
                     61:
                     62: #include <machine/cpu.h>
                     63: #include <machine/bus.h>
                     64: #include <machine/intr.h>
                     65:
                     66: #include <dev/mii/mii.h>
                     67: #include <dev/mii/miivar.h>
                     68: #include <dev/isa/isavar.h>
                     69: #include <dev/isa/isadmavar.h>
                     70: #include <dev/ic/elink3reg.h>
                     71:
                     72: #undef EF_DEBUG
                     73:
                     74: struct ef_softc {
                     75:        struct device           sc_dv;
                     76:        bus_space_tag_t         sc_iot;
                     77:        bus_space_handle_t      sc_ioh;
                     78:        struct arpcom           sc_arpcom;
                     79:        struct mii_data         sc_mii;
                     80:        struct timeout          sc_tick_tmo;
                     81:        void *                  sc_ih;
                     82:        int                     sc_tx_start_thresh;
                     83:        int                     sc_tx_succ_ok;
                     84:        int                     sc_busmaster;
                     85: };
                     86:
                     87: #define        EF_W0_EEPROM_COMMAND    0x200a
                     88: #define    EF_EEPROM_BUSY      (1 << 9)
                     89: #define    EF_EEPROM_READ      (1 << 7)
                     90: #define        EF_W0_EEPROM_DATA       0x200c
                     91:
                     92: #define        EF_W1_TX_PIO_WR_1       0x10
                     93: #define        EF_W1_RX_PIO_RR_1       0x10
                     94: #define        EF_W1_RX_ERRORS         0x14
                     95: #define        EF_W1_RX_STATUS         0x18
                     96: #define        EF_W1_TX_STATUS         0x1b
                     97: #define        EF_W1_FREE_TX           0x1c
                     98:
                     99: #define        EF_W4_MEDIA             0x0a
                    100: #define    EF_MEDIA_SQE                0x0008          /* sqe error for aui */
                    101: #define           EF_MEDIA_TP          0x00c0          /* link/jabber, 10baseT */
                    102: #define           EF_MEDIA_LNK         0x0080          /* linkbeat, 100baseTX/FX */
                    103: #define           EF_MEDIA_LNKBEAT     0x0800
                    104:
                    105: /* Window 4: EP_W4_CTRLR_STATUS: mii manipulation */
                    106: #define        EF_MII_CLK              0x01            /* clock bit */
                    107: #define        EF_MII_DATA             0x02            /* data bit */
                    108: #define        EF_MII_DIR              0x04            /* direction */
                    109:
                    110: int ef_isapnp_match(struct device *, void *, void *);
                    111: void ef_isapnp_attach(struct device *, struct device *, void *);
                    112:
                    113: void efstart(struct ifnet *);
                    114: int efioctl(struct ifnet *, u_long, caddr_t);
                    115: void efwatchdog(struct ifnet *);
                    116: void efreset(struct ef_softc *);
                    117: void efstop(struct ef_softc *);
                    118: void efsetmulti(struct ef_softc *);
                    119: int efbusyeeprom(struct ef_softc *);
                    120: int efintr(void *);
                    121: void efinit(struct ef_softc *);
                    122: void efcompletecmd(struct ef_softc *, u_int, u_int);
                    123: void eftxstat(struct ef_softc *);
                    124: void efread(struct ef_softc *);
                    125: struct mbuf *efget(struct ef_softc *, int totlen);
                    126:
                    127: void ef_miibus_writereg(struct device *, int, int, int);
                    128: void ef_miibus_statchg(struct device *);
                    129: int ef_miibus_readreg(struct device *, int, int);
                    130: void ef_mii_writeb(struct ef_softc *, int);
                    131: void ef_mii_sync(struct ef_softc *);
                    132: int ef_ifmedia_upd(struct ifnet *);
                    133: void ef_ifmedia_sts(struct ifnet *, struct ifmediareq *);
                    134: void ef_tick(void *);
                    135:
                    136: struct cfdriver ef_cd = {
                    137:        NULL, "ef", DV_IFNET
                    138: };
                    139:
                    140: struct cfattach ef_isapnp_ca = {
                    141:        sizeof(struct ef_softc), ef_isapnp_match, ef_isapnp_attach
                    142: };
                    143:
                    144: int
                    145: ef_isapnp_match(parent, match, aux)
                    146:        struct device *parent;
                    147:        void *match, *aux;
                    148: {
                    149:        return (1);
                    150: }
                    151:
                    152: void
                    153: ef_isapnp_attach(parent, self, aux)
                    154:        struct device *parent, *self;
                    155:        void *aux;
                    156: {
                    157:        struct ef_softc *sc = (void *)self;
                    158:        struct isa_attach_args *ia = aux;
                    159:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    160:        bus_space_tag_t iot;
                    161:        bus_space_handle_t ioh;
                    162:        int i;
                    163:        u_int16_t x;
                    164:        u_int32_t cfg;
                    165:
                    166:        sc->sc_iot = iot = ia->ia_iot;
                    167:        sc->sc_ioh = ioh = ia->ipa_io[0].h;
                    168:
                    169:        efcompletecmd(sc, EP_COMMAND, GLOBAL_RESET);
                    170:        DELAY(1500);
                    171:
                    172:        for (i = 0; i < 3; i++) {
                    173:                if (efbusyeeprom(sc))
                    174:                        return;
                    175:
                    176:                bus_space_write_2(iot, ioh, EF_W0_EEPROM_COMMAND,
                    177:                    EF_EEPROM_READ | i);
                    178:
                    179:                if (efbusyeeprom(sc))
                    180:                        return;
                    181:
                    182:                x = bus_space_read_2(iot, ioh, EF_W0_EEPROM_DATA);
                    183:
                    184:                sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8;
                    185:                sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x;
                    186:        }
                    187:
                    188:        printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
                    189:
                    190:        GO_WINDOW(3);
                    191:        cfg = bus_space_read_4(iot, ioh, EP_W3_INTERNAL_CONFIG);
                    192:        cfg &= ~(0x00f00000);
                    193:        cfg |= (0x06 << 20);
                    194:        bus_space_write_4(iot, ioh, EP_W3_INTERNAL_CONFIG, cfg);
                    195:
                    196:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
                    197:            IPL_NET, efintr, sc, sc->sc_dv.dv_xname);
                    198:
                    199:        if (ia->ia_drq != DRQUNK)
                    200:                isadma_cascade(ia->ia_drq);
                    201:
                    202:        timeout_set(&sc->sc_tick_tmo, ef_tick, sc);
                    203:
                    204:        bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
                    205:        ifp->if_softc = sc;
                    206:        ifp->if_start = efstart;
                    207:        ifp->if_ioctl = efioctl;
                    208:        ifp->if_watchdog = efwatchdog;
                    209:        ifp->if_flags =
                    210:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    211:        IFQ_SET_READY(&ifp->if_snd);
                    212:
                    213:        sc->sc_mii.mii_ifp = ifp;
                    214:        sc->sc_mii.mii_readreg = ef_miibus_readreg;
                    215:        sc->sc_mii.mii_writereg = ef_miibus_writereg;
                    216:        sc->sc_mii.mii_statchg = ef_miibus_statchg;
                    217:        ifmedia_init(&sc->sc_mii.mii_media, 0, ef_ifmedia_upd, ef_ifmedia_sts);
                    218:        mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
                    219:            0);
                    220:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                    221:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
                    222:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
                    223:        } else
                    224:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
                    225:
                    226:        if_attach(ifp);
                    227:        ether_ifattach(ifp);
                    228:
                    229:        sc->sc_tx_start_thresh = 20;
                    230:
                    231:        efcompletecmd(sc, EP_COMMAND, RX_RESET);
                    232:        efcompletecmd(sc, EP_COMMAND, TX_RESET);
                    233: }
                    234:
                    235: void
                    236: efstart(ifp)
                    237:        struct ifnet *ifp;
                    238: {
                    239:        struct ef_softc *sc = ifp->if_softc;
                    240:        bus_space_tag_t iot = sc->sc_iot;
                    241:        bus_space_handle_t ioh = sc->sc_ioh;
                    242:        struct mbuf *m, *m0;
                    243:        int s, len, pad, i;
                    244:        int fillcnt = 0;
                    245:        u_int32_t filler = 0;
                    246:
                    247:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    248:                return;
                    249:
                    250: startagain:
                    251:        IFQ_POLL(&ifp->if_snd, m0);
                    252:        if (m0 == NULL)
                    253:                return;
                    254:
                    255:        if ((m0->m_flags & M_PKTHDR) == 0)
                    256:                panic("efstart: no header mbuf");
                    257:        len = m0->m_pkthdr.len;
                    258:        pad = (4 - len) & 3;
                    259:
                    260:        if (len + pad > ETHER_MAX_LEN) {
                    261:                ifp->if_oerrors++;
                    262:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                    263:                m_freem(m0);
                    264:                goto startagain;
                    265:        }
                    266:
                    267:        if (bus_space_read_2(iot, ioh, EF_W1_FREE_TX) < len + pad + 4) {
                    268:                bus_space_write_2(iot, ioh, EP_COMMAND,
                    269:                    SET_TX_AVAIL_THRESH | ((len + pad) >> 2));
                    270:                ifp->if_flags |= IFF_OACTIVE;
                    271:                return;
                    272:        } else {
                    273:                bus_space_write_2(iot, ioh, EP_COMMAND,
                    274:                    SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE);
                    275:        }
                    276:
                    277:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH |
                    278:            ((len / 4 + sc->sc_tx_start_thresh)));
                    279:
                    280: #if NBPFILTER
                    281:        if (ifp->if_bpf)
                    282:                bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
                    283: #endif
                    284:
                    285:        IFQ_DEQUEUE(&ifp->if_snd, m0);
                    286:        if (m0 == NULL) /* XXX not needed */
                    287:                return;
                    288:
                    289:        s = splhigh();
                    290:
                    291:        bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1, len);
                    292:        for (m = m0; m; ) {
                    293:                if (fillcnt) {
                    294:                        while (m->m_len && fillcnt < 4) {
                    295:                                fillcnt++;
                    296:                                filler >>= 8;
                    297:                                filler |= m->m_data[0] << 24;
                    298:                                m->m_data++;
                    299:                                m->m_len--;
                    300:                        }
                    301:                        if (fillcnt == 4) {
                    302:                                bus_space_write_4(iot, ioh,
                    303:                                    EF_W1_TX_PIO_WR_1, filler);
                    304:                                filler = 0;
                    305:                                fillcnt = 0;
                    306:                        }
                    307:                }
                    308:
                    309:                if (m->m_len & ~3)
                    310:                        bus_space_write_multi_4(iot, ioh,
                    311:                            EF_W1_TX_PIO_WR_1, (u_int32_t *)m->m_data,
                    312:                            m->m_len >> 2);
                    313:                for (i = 0; i < (m->m_len & 3); i++) {
                    314:                        fillcnt++;
                    315:                        filler >>= 8;
                    316:                        filler |= m->m_data[(m->m_len & ~3) + i] << 24;
                    317:                }
                    318:                MFREE(m, m0);
                    319:                m = m0;
                    320:        }
                    321:
                    322:        if (fillcnt) {
                    323:                bus_space_write_4(iot, ioh, EF_W1_TX_PIO_WR_1,
                    324:                    filler >> (32 - (8 * fillcnt)));
                    325:                fillcnt = 0;
                    326:                filler = 0;
                    327:        }
                    328:
                    329:        splx(s);
                    330:
                    331:        ifp->if_opackets++;
                    332:
                    333:        goto startagain;
                    334: }
                    335:
                    336: int
                    337: efioctl(ifp, cmd, data)
                    338:        struct ifnet *ifp;
                    339:        u_long cmd;
                    340:        caddr_t data;
                    341: {
                    342:        struct ef_softc *sc = ifp->if_softc;
                    343:        struct ifaddr *ifa = (struct ifaddr *)data;
                    344:        struct ifreq *ifr = (struct ifreq *)data;
                    345:        int s, error = 0;
                    346:
                    347:        s = splnet();
                    348:
                    349:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
                    350:                splx(s);
                    351:                return (error);
                    352:        }
                    353:
                    354:        switch (cmd) {
                    355:        case SIOCSIFADDR:
                    356:                ifp->if_flags |= IFF_UP;
                    357:                switch (ifa->ifa_addr->sa_family) {
                    358: #ifdef INET
                    359:                case AF_INET:
                    360:                        efinit(sc);
                    361:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    362:                        break;
                    363: #endif
                    364:                default:
                    365:                        efinit(sc);
                    366:                        break;
                    367:                }
                    368:                break;
                    369:        case SIOCSIFMEDIA:
                    370:        case SIOCGIFMEDIA:
                    371:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
                    372:                break;
                    373:        case SIOCSIFFLAGS:
                    374:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    375:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    376:                        efstop(sc);
                    377:                        ifp->if_flags &= ~IFF_RUNNING;
                    378:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    379:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                    380:                        efinit(sc);
                    381:                }
                    382:                efsetmulti(sc);
                    383:                break;
                    384:
                    385:        case SIOCADDMULTI:
                    386:        case SIOCDELMULTI:
                    387:                error = (cmd == SIOCADDMULTI) ?
                    388:                    ether_addmulti(ifr, &sc->sc_arpcom) :
                    389:                    ether_delmulti(ifr, &sc->sc_arpcom);
                    390:
                    391:                if (error == ENETRESET) {
                    392:                        if (ifp->if_flags & IFF_RUNNING)
                    393:                                efreset(sc);
                    394:                        error = 0;
                    395:                }
                    396:                efsetmulti(sc);
                    397:                break;
                    398:        default:
                    399:                error = EINVAL;
                    400:                break;
                    401:        }
                    402:
                    403:        splx(s);
                    404:        return (error);
                    405: }
                    406:
                    407: void
                    408: efinit(sc)
                    409:        struct ef_softc *sc;
                    410: {
                    411:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    412:        bus_space_tag_t iot = sc->sc_iot;
                    413:        bus_space_handle_t ioh = sc->sc_ioh;
                    414:        int i, s;
                    415:
                    416:        s = splnet();
                    417:
                    418:        efstop(sc);
                    419:
                    420:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
                    421:                ;
                    422:
                    423:        GO_WINDOW(2);
                    424:        for (i = 0; i < 6; i++)
                    425:                bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i,
                    426:                    sc->sc_arpcom.ac_enaddr[i]);
                    427:        for (i = 0; i < 3; i += 2)
                    428:                bus_space_write_2(iot, ioh, EP_W2_RECVMASK_0 + (i * 2), 0);
                    429:
                    430:        efcompletecmd(sc, EP_COMMAND, RX_RESET);
                    431:        efcompletecmd(sc, EP_COMMAND, TX_RESET);
                    432:
                    433:        bus_space_write_2(iot, ioh, EP_COMMAND,
                    434:            SET_TX_AVAIL_THRESH | (ETHER_MAX_DIX_LEN >> 2));
                    435:
                    436:        efsetmulti(sc);
                    437:
                    438:        bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE | 0);
                    439:
                    440:        GO_WINDOW(6);
                    441:        for (i = 0; i < 10; i++)
                    442:                (void)bus_space_read_1(iot, ioh, i);
                    443:        (void)bus_space_read_2(iot, ioh, 10);
                    444:        (void)bus_space_read_2(iot, ioh, 12);
                    445:        GO_WINDOW(4);
                    446:        (void)bus_space_read_1(iot, ioh, 12);
                    447:        bus_space_write_2(iot, ioh, EP_W4_NET_DIAG, 0x0040);
                    448:
                    449:        GO_WINDOW(7);
                    450:
                    451:        efsetmulti(sc);
                    452:
                    453:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE);
                    454:        bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
                    455:
                    456:        bus_space_write_2(iot, ioh, EP_COMMAND, STATUS_ENABLE |
                    457:            S_CARD_FAILURE | S_INT_RQD | S_UPD_STATS | S_TX_COMPLETE |
                    458:            S_TX_AVAIL | S_RX_COMPLETE |
                    459:            (sc->sc_busmaster ? S_DMA_DONE : 0));
                    460:        bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR |
                    461:            S_INTR_LATCH | S_TX_AVAIL | S_RX_EARLY | S_INT_RQD);
                    462:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK |
                    463:            S_INTR_LATCH | S_TX_AVAIL | S_RX_COMPLETE | S_UPD_STATS |
                    464:            (sc->sc_busmaster ? S_DMA_DONE : 0) | S_UP_COMPLETE |
                    465:            S_DOWN_COMPLETE | S_CARD_FAILURE | S_TX_COMPLETE);
                    466:
                    467:        mii_mediachg(&sc->sc_mii);
                    468:
                    469:        ifp->if_flags |= IFF_RUNNING;
                    470:        ifp->if_flags &= ~IFF_OACTIVE;
                    471:
                    472:        splx(s);
                    473:
                    474:        timeout_add(&sc->sc_tick_tmo, hz);
                    475:
                    476:        efstart(ifp);
                    477: }
                    478:
                    479: void
                    480: efreset(sc)
                    481:        struct ef_softc *sc;
                    482: {
                    483:        int s;
                    484:
                    485:        s = splnet();
                    486:        efstop(sc);
                    487:        efinit(sc);
                    488:        splx(s);
                    489: }
                    490:
                    491: void
                    492: efstop(sc)
                    493:        struct ef_softc *sc;
                    494: {
                    495:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    496:        bus_space_tag_t iot = sc->sc_iot;
                    497:        bus_space_handle_t ioh = sc->sc_ioh;
                    498:
                    499:        ifp->if_timer = 0;
                    500:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                    501:
                    502:        timeout_del(&sc->sc_tick_tmo);
                    503:
                    504:        bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE);
                    505:        efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
                    506:
                    507:        bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE);
                    508:        bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER);
                    509:
                    510:        efcompletecmd(sc, EP_COMMAND, RX_RESET);
                    511:        efcompletecmd(sc, EP_COMMAND, TX_RESET);
                    512:
                    513:        bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH);
                    514:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK);
                    515:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK);
                    516:        bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER);
                    517: }
                    518:
                    519: void
                    520: efcompletecmd(sc, cmd, arg)
                    521:        struct ef_softc *sc;
                    522:        u_int cmd, arg;
                    523: {
                    524:        bus_space_tag_t iot = sc->sc_iot;
                    525:        bus_space_handle_t ioh = sc->sc_ioh;
                    526:
                    527:        bus_space_write_2(iot, ioh, cmd, arg);
                    528:        while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS)
                    529:                ;
                    530: }
                    531:
                    532: int
                    533: efintr(vsc)
                    534:        void *vsc;
                    535: {
                    536:        struct ef_softc *sc = vsc;
                    537:        bus_space_tag_t iot = sc->sc_iot;
                    538:        bus_space_handle_t ioh = sc->sc_ioh;
                    539:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    540:        u_int16_t status;
                    541:        int r = 0;
                    542:
                    543:        status = bus_space_read_2(iot, ioh, EP_STATUS);
                    544:
                    545:        do {
                    546:                if (status & S_RX_COMPLETE) {
                    547:                        r = 1;
                    548:                        bus_space_write_2(iot, ioh, EP_STATUS, C_RX_COMPLETE);
                    549:                        efread(sc);
                    550:                }
                    551:                if (status & S_TX_AVAIL) {
                    552:                        bus_space_write_2(iot, ioh, EP_STATUS, C_TX_AVAIL);
                    553:                        r = 1;
                    554:                        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
                    555:                        efstart(&sc->sc_arpcom.ac_if);
                    556:                }
                    557:                if (status & S_CARD_FAILURE) {
                    558:                        r = 1;
                    559:                        efreset(sc);
                    560:                        printf("%s: adapter failure (%x)\n",
                    561:                           sc->sc_dv.dv_xname, status);
                    562:                        bus_space_write_2(iot, ioh, EP_COMMAND,
                    563:                                          C_CARD_FAILURE);
                    564:                        return (1);
                    565:                }
                    566:                if (status & S_TX_COMPLETE) {
                    567:                        r = 1;
                    568:                        eftxstat(sc);
                    569:                        efstart(ifp);
                    570:                }
                    571:                bus_space_write_2(iot, ioh, EP_COMMAND,
                    572:                    C_INTR_LATCH | C_INT_RQD);
                    573:        } while ((status = bus_space_read_2(iot, ioh, EP_STATUS)) &
                    574:            (S_INT_RQD | S_RX_COMPLETE));
                    575:
                    576:        return (r);
                    577: }
                    578:
                    579: void
                    580: eftxstat(sc)
                    581:        struct ef_softc *sc;
                    582: {
                    583:        bus_space_tag_t iot = sc->sc_iot;
                    584:        bus_space_handle_t ioh = sc->sc_ioh;
                    585:        int i;
                    586:
                    587:        while ((i = bus_space_read_1(iot, ioh, EF_W1_TX_STATUS)) &
                    588:           TXS_COMPLETE) {
                    589:                bus_space_write_1(iot, ioh, EF_W1_TX_STATUS, 0);
                    590:
                    591:                if (i & TXS_JABBER) {
                    592:                        sc->sc_arpcom.ac_if.if_oerrors++;
                    593: #ifdef EF_DEBUG
                    594:                        if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
                    595:                                printf("%s: jabber (%x)\n",
                    596:                                    sc->sc_dv.dv_xname, i);
                    597: #endif
                    598:                        efreset(sc);
                    599:                }
                    600:                else if (i & TXS_UNDERRUN) {
                    601:                        sc->sc_arpcom.ac_if.if_oerrors++;
                    602: #ifdef EF_DEBUG
                    603:                        if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
                    604:                                printf("%s: fifo underrun (%x) @%d\n",
                    605:                                    sc->sc_dv.dv_xname, i,
                    606:                                    sc->sc_tx_start_thresh);
                    607: #endif
                    608:                        if (sc->sc_tx_succ_ok < 100)
                    609:                                sc->sc_tx_start_thresh = min(ETHER_MAX_LEN,
                    610:                                    sc->sc_tx_start_thresh + 20);
                    611:                        sc->sc_tx_succ_ok = 0;
                    612:                        efreset(sc);
                    613:                }
                    614:                else if (i & TXS_MAX_COLLISION) {
                    615:                        sc->sc_arpcom.ac_if.if_collisions++;
                    616:                        bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE);
                    617:                        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
                    618:                }
                    619:                else
                    620:                        sc->sc_tx_succ_ok = (sc->sc_tx_succ_ok + 1) & 127;
                    621:        }
                    622: }
                    623:
                    624: int
                    625: efbusyeeprom(sc)
                    626:        struct ef_softc *sc;
                    627: {
                    628:        int i = 100, j;
                    629:
                    630:        while (i--) {
                    631:                j = bus_space_read_2(sc->sc_iot, sc->sc_ioh,
                    632:                                     EF_W0_EEPROM_COMMAND);
                    633:                if (j & EF_EEPROM_BUSY)
                    634:                        delay(100);
                    635:                else
                    636:                        break;
                    637:        }
                    638:        if (i == 0) {
                    639:                printf("%s: eeprom failed to come ready\n",
                    640:                   sc->sc_dv.dv_xname);
                    641:                return (1);
                    642:        }
                    643:
                    644:        return (0);
                    645: }
                    646:
                    647: void
                    648: efwatchdog(ifp)
                    649:        struct ifnet *ifp;
                    650: {
                    651:        struct ef_softc *sc = ifp->if_softc;
                    652:
                    653:        printf("%s: device timeout\n", sc->sc_dv.dv_xname);
                    654:        sc->sc_arpcom.ac_if.if_oerrors++;
                    655:        efreset(sc);
                    656: }
                    657:
                    658: void
                    659: efsetmulti(sc)
                    660:        struct ef_softc *sc;
                    661: {
                    662:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    663:        struct arpcom *ac = &sc->sc_arpcom;
                    664:        bus_space_tag_t iot = sc->sc_iot;
                    665:        bus_space_handle_t ioh = sc->sc_ioh;
                    666:        struct ether_multi *enm;
                    667:        struct ether_multistep step;
                    668:        u_int16_t cmd = SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST;
                    669:        int mcnt = 0;
                    670:
                    671:        ETHER_FIRST_MULTI(step, ac, enm);
                    672:        while (enm != NULL) {
                    673:                mcnt++;
                    674:                ETHER_NEXT_MULTI(step, enm);
                    675:        }
                    676:        if (mcnt || ifp->if_flags & IFF_ALLMULTI)
                    677:                cmd |= FIL_MULTICAST;
                    678:
                    679:        if (ifp->if_flags & IFF_PROMISC)
                    680:                cmd |= FIL_PROMISC;
                    681:
                    682:        bus_space_write_2(iot, ioh, EP_COMMAND, cmd);
                    683: }
                    684:
                    685: void
                    686: efread(sc)
                    687:        struct ef_softc *sc;
                    688: {
                    689:        bus_space_tag_t iot = sc->sc_iot;
                    690:        bus_space_handle_t ioh = sc->sc_ioh;
                    691:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    692:        struct mbuf *m;
                    693:        int len;
                    694:
                    695:        len = bus_space_read_2(iot, ioh, EF_W1_RX_STATUS);
                    696:
                    697: #ifdef EF_DEBUG
                    698:        if (ifp->if_flags & IFF_DEBUG) {
                    699:                int err = len & ERR_MASK;
                    700:                char *s = NULL;
                    701:
                    702:                if (len & ERR_INCOMPLETE)
                    703:                        s = "incomplete packet";
                    704:                else if (err == ERR_OVERRUN)
                    705:                        s = "packet overrun";
                    706:                else if (err == ERR_RUNT)
                    707:                        s = "runt packet";
                    708:                else if (err == ERR_ALIGNMENT)
                    709:                        s = "bad alignment";
                    710:                else if (err == ERR_CRC)
                    711:                        s = "bad crc";
                    712:                else if (err == ERR_OVERSIZE)
                    713:                        s = "oversized packet";
                    714:                else if (err == ERR_DRIBBLE)
                    715:                        s = "dribble bits";
                    716:
                    717:                if (s)
                    718:                        printf("%s: %s\n", sc->sc_dv.dv_xname, s);
                    719:        }
                    720: #endif
                    721:
                    722:        if (len & ERR_INCOMPLETE)
                    723:                return;
                    724:
                    725:        if (len & ERR_RX) {
                    726:                ifp->if_ierrors++;
                    727:                efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
                    728:                return;
                    729:        }
                    730:
                    731:        len &= RX_BYTES_MASK;
                    732:        m = efget(sc, len);
                    733:        if (m == NULL) {
                    734:                ifp->if_ierrors++;
                    735:                efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
                    736:                return;
                    737:        }
                    738:
                    739:        ifp->if_ipackets++;
                    740:
                    741: #if NBPFILTER > 0
                    742:        if (ifp->if_bpf)
                    743:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    744: #endif
                    745:
                    746:        ether_input_mbuf(ifp, m);
                    747: }
                    748:
                    749: struct mbuf *
                    750: efget(sc, totlen)
                    751:        struct ef_softc *sc;
                    752:        int totlen;
                    753: {
                    754:        bus_space_tag_t iot = sc->sc_iot;
                    755:        bus_space_handle_t ioh = sc->sc_ioh;
                    756:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    757:        struct mbuf *top, **mp, *m;
                    758:        int len, pad, s;
                    759:
                    760:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    761:        if (m == NULL)
                    762:                return (NULL);
                    763:        m->m_pkthdr.rcvif = ifp;
                    764:        m->m_pkthdr.len = totlen;
                    765:        pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
                    766:        m->m_data += pad;
                    767:        len = MHLEN -pad;
                    768:        top = 0;
                    769:        mp = &top;
                    770:
                    771:        s = splhigh();
                    772:
                    773:        while (totlen > 0) {
                    774:                if (top) {
                    775:                        MGET(m, M_DONTWAIT, MT_DATA);
                    776:                        if (m == NULL) {
                    777:                                m_freem(top);
                    778:                                splx(s);
                    779:                                return (NULL);
                    780:                        }
                    781:                        len = MLEN;
                    782:                }
                    783:                if (top && totlen >= MINCLSIZE) {
                    784:                        MCLGET(m, M_DONTWAIT);
                    785:                        if (m->m_flags & M_EXT)
                    786:                                len = MCLBYTES;
                    787:                }
                    788:                len = min(totlen, len);
                    789:                if (len > 1) {
                    790:                        len &= ~1;
                    791:                        bus_space_read_raw_multi_2(iot, ioh,
                    792:                            EF_W1_RX_PIO_RR_1, mtod(m, u_int8_t *),
                    793:                            len);
                    794:                } else
                    795:                        *(mtod(m, u_int8_t *)) =
                    796:                            bus_space_read_1(iot, ioh, EF_W1_RX_PIO_RR_1);
                    797:
                    798:                m->m_len = len;
                    799:                totlen -= len;
                    800:                *mp = m;
                    801:                mp = &m->m_next;
                    802:        }
                    803:
                    804:        efcompletecmd(sc, EP_COMMAND, RX_DISCARD_TOP_PACK);
                    805:
                    806:        splx(s);
                    807:
                    808:        return (top);
                    809: }
                    810:
                    811: #define MII_SET(sc, x) \
                    812:        bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
                    813:            bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
                    814:            | (x))
                    815:
                    816: #define MII_CLR(sc, x) \
                    817:        bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS, \
                    818:            bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, EP_W4_CTRLR_STATUS) \
                    819:            & (~(x)))
                    820:
                    821: void
                    822: ef_mii_writeb(sc, b)
                    823:        struct ef_softc *sc;
                    824:        int b;
                    825: {
                    826:        MII_CLR(sc, EF_MII_CLK);
                    827:
                    828:        if (b)
                    829:                MII_SET(sc, EF_MII_DATA);
                    830:        else
                    831:                MII_CLR(sc, EF_MII_DATA);
                    832:
                    833:        MII_CLR(sc, EF_MII_CLK);
                    834:        DELAY(1);
                    835:        MII_SET(sc, EF_MII_CLK);
                    836:        DELAY(1);
                    837: }
                    838:
                    839: void
                    840: ef_mii_sync(sc)
                    841:        struct ef_softc *sc;
                    842: {
                    843:        int i;
                    844:
                    845:        for (i = 0; i < 32; i++)
                    846:                ef_mii_writeb(sc, 1);
                    847: }
                    848:
                    849: int
                    850: ef_miibus_readreg(dev, phy, reg)
                    851:        struct device *dev;
                    852:        int phy, reg;
                    853: {
                    854:        struct ef_softc *sc = (struct ef_softc *)dev;
                    855:        int i, ack, s, val = 0;
                    856:
                    857:        s = splnet();
                    858:
                    859:        GO_WINDOW(4);
                    860:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
                    861:
                    862:        /* Turn on xmit */
                    863:        MII_SET(sc, EF_MII_DIR);
                    864:        MII_CLR(sc, EF_MII_CLK);
                    865:
                    866:        ef_mii_sync(sc);
                    867:
                    868:        /* Transmit start sequence */
                    869:        ef_mii_writeb(sc, 0);
                    870:        ef_mii_writeb(sc, 1);
                    871:
                    872:        /* Transmit read sequence */
                    873:        ef_mii_writeb(sc, 1);
                    874:        ef_mii_writeb(sc, 0);
                    875:
                    876:        /* Transmit phy addr */
                    877:        for (i = 0x10; i; i >>= 1)
                    878:                ef_mii_writeb(sc, (phy & i) ? 1 : 0);
                    879:
                    880:        /* Transmit reg addr */
                    881:        for (i = 0x10; i; i >>= 1)
                    882:                ef_mii_writeb(sc, (reg & i) ? 1 : 0);
                    883:
                    884:        /* First cycle of turnaround */
                    885:        MII_CLR(sc, EF_MII_CLK | EF_MII_DATA);
                    886:        DELAY(1);
                    887:        MII_SET(sc, EF_MII_CLK);
                    888:        DELAY(1);
                    889:
                    890:        /* Turn off xmit */
                    891:        MII_CLR(sc, EF_MII_DIR);
                    892:
                    893:        /* Second cycle of turnaround */
                    894:        MII_CLR(sc, EF_MII_CLK);
                    895:        DELAY(1);
                    896:        MII_SET(sc, EF_MII_CLK);
                    897:        DELAY(1);
                    898:        ack = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS) &
                    899:            EF_MII_DATA;
                    900:
                    901:        /* Read 16bit data */
                    902:        for (i = 0x8000; i; i >>= 1) {
                    903:                MII_CLR(sc, EF_MII_CLK);
                    904:                DELAY(1);
                    905:                if (bus_space_read_2(sc->sc_iot, sc->sc_ioh,
                    906:                                     EP_W4_CTRLR_STATUS) & EF_MII_DATA)
                    907:                        val |= i;
                    908:                MII_SET(sc, EF_MII_CLK);
                    909:                DELAY(1);
                    910:        }
                    911:
                    912:        MII_CLR(sc, EF_MII_CLK);
                    913:        DELAY(1);
                    914:        MII_SET(sc, EF_MII_CLK);
                    915:        DELAY(1);
                    916:
                    917:        splx(s);
                    918:
                    919:        return (val);
                    920: }
                    921:
                    922: void
                    923: ef_miibus_writereg(dev, phy, reg, val)
                    924:        struct device *dev;
                    925:        int phy, reg, val;
                    926: {
                    927:        struct ef_softc *sc = (struct ef_softc *)dev;
                    928:        int s, i;
                    929:
                    930:        s = splnet();
                    931:
                    932:        GO_WINDOW(4);
                    933:        bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_CTRLR_STATUS, 0);
                    934:
                    935:        /* Turn on xmit */
                    936:        MII_SET(sc, EF_MII_DIR);
                    937:
                    938:        ef_mii_sync(sc);
                    939:
                    940:        ef_mii_writeb(sc, 0);
                    941:        ef_mii_writeb(sc, 1);
                    942:        ef_mii_writeb(sc, 0);
                    943:        ef_mii_writeb(sc, 1);
                    944:
                    945:        for (i = 0x10; i; i >>= 1)
                    946:                ef_mii_writeb(sc, (phy & i) ? 1 : 0);
                    947:
                    948:        for (i = 0x10; i; i >>= 1)
                    949:                ef_mii_writeb(sc, (reg & i) ? 1 : 0);
                    950:
                    951:        ef_mii_writeb(sc, 1);
                    952:        ef_mii_writeb(sc, 0);
                    953:
                    954:        for (i = 0x8000; i; i >>= 1)
                    955:                ef_mii_writeb(sc, (val & i) ? 1 : 0);
                    956:
                    957:        splx(s);
                    958: }
                    959:
                    960: int
                    961: ef_ifmedia_upd(ifp)
                    962:        struct ifnet *ifp;
                    963: {
                    964:        struct ef_softc *sc = ifp->if_softc;
                    965:
                    966:        mii_mediachg(&sc->sc_mii);
                    967:        return (0);
                    968: }
                    969:
                    970: void
                    971: ef_ifmedia_sts(ifp, ifmr)
                    972:        struct ifnet *ifp;
                    973:        struct ifmediareq *ifmr;
                    974: {
                    975:        struct ef_softc *sc = ifp->if_softc;
                    976:
                    977:        mii_pollstat(&sc->sc_mii);
                    978:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
                    979:        ifmr->ifm_active = sc->sc_mii.mii_media_active;
                    980: }
                    981:
                    982: void
                    983: ef_miibus_statchg(self)
                    984:        struct device *self;
                    985: {
                    986:        struct ef_softc *sc = (struct ef_softc *)self;
                    987:        int s;
                    988:
                    989:        s = splnet();
                    990:        GO_WINDOW(3);
                    991:        /* Set duplex bit appropriately */
                    992:        if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
                    993:                bus_space_write_1(sc->sc_iot, sc->sc_ioh,
                    994:                    EP_W3_MAC_CONTROL, 0x20);
                    995:        else
                    996:                bus_space_write_1(sc->sc_iot, sc->sc_ioh,
                    997:                    EP_W3_MAC_CONTROL, 0x00);
                    998:        GO_WINDOW(7);
                    999:        splx(s);
                   1000: }
                   1001:
                   1002: void
                   1003: ef_tick(v)
                   1004:        void *v;
                   1005: {
                   1006:        struct ef_softc *sc = v;
                   1007:        int s;
                   1008:
                   1009:        s = splnet();
                   1010:        mii_tick(&sc->sc_mii);
                   1011:        splx(s);
                   1012:        timeout_add(&sc->sc_tick_tmo, hz);
                   1013: }

CVSweb