[BACK]Return to sgec.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / if

Annotation of sys/arch/vax/if/sgec.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sgec.c,v 1.15 2006/08/31 22:10:57 miod Exp $  */
        !             2: /*      $NetBSD: sgec.c,v 1.5 2000/06/04 02:14:14 matt Exp $ */
        !             3: /*
        !             4:  * Copyright (c) 1999 Ludd, University of Lule}, Sweden. All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. All advertising materials mentioning features or use of this software
        !            15:  *    must display the following acknowledgement:
        !            16:  *      This product includes software developed at Ludd, University of
        !            17:  *      Lule}, Sweden and its contributors.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: /*
        !            34:  * Driver for the SGEC (Second Generation Ethernet Controller), sitting
        !            35:  * on for example the VAX 4000/300 (KA670).
        !            36:  *
        !            37:  * The SGEC looks like a mixture of the DEQNA and the TULIP. Fun toy.
        !            38:  *
        !            39:  * Even though the chip is capable to use virtual addresses (read the
        !            40:  * System Page Table directly) this driver doesn't do so, and there
        !            41:  * is no benefit in doing it either in NetBSD of today.
        !            42:  *
        !            43:  * Things that is still to do:
        !            44:  *     Collect statistics.
        !            45:  *     Use imperfect filtering when many multicast addresses.
        !            46:  */
        !            47:
        !            48: #include "bpfilter.h"
        !            49:
        !            50: #include <sys/param.h>
        !            51: #include <sys/mbuf.h>
        !            52: #include <sys/socket.h>
        !            53: #include <sys/device.h>
        !            54: #include <sys/systm.h>
        !            55: #include <sys/sockio.h>
        !            56:
        !            57: #include <net/if.h>
        !            58: #include <net/if_dl.h>
        !            59:
        !            60: #include <netinet/in.h>
        !            61: #include <netinet/if_ether.h>
        !            62:
        !            63: #if NBPFILTER > 0
        !            64: #include <net/bpf.h>
        !            65: #include <net/bpfdesc.h>
        !            66: #endif
        !            67:
        !            68: #include <machine/bus.h>
        !            69:
        !            70: #include <vax/if/sgecreg.h>
        !            71: #include <vax/if/sgecvar.h>
        !            72:
        !            73: void   sgec_rxintr(struct ze_softc *);
        !            74: void   sgec_txintr(struct ze_softc *);
        !            75: void   zeinit(struct ze_softc *);
        !            76: int    zeioctl(struct ifnet *, u_long, caddr_t);
        !            77: void   zekick(struct ze_softc *);
        !            78: int    zereset(struct ze_softc *);
        !            79: void   zestart(struct ifnet *);
        !            80: void   zetimeout(struct ifnet *);
        !            81: int    ze_add_rxbuf(struct ze_softc *, int);
        !            82: void   ze_setup(struct ze_softc *);
        !            83:
        !            84: struct cfdriver ze_cd = {
        !            85:        NULL, "ze", DV_IFNET
        !            86: };
        !            87:
        !            88: #define        ZE_WCSR(csr, val) \
        !            89:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, csr, val)
        !            90: #define        ZE_RCSR(csr) \
        !            91:        bus_space_read_4(sc->sc_iot, sc->sc_ioh, csr)
        !            92:
        !            93: /*
        !            94:  * Interface exists: make available by filling in network interface
        !            95:  * record.  System will initialize the interface when it is ready
        !            96:  * to accept packets.
        !            97:  */
        !            98: void
        !            99: sgec_attach(sc)
        !           100:        struct ze_softc *sc;
        !           101: {
        !           102:        struct  ifnet *ifp = (struct ifnet *)&sc->sc_if;
        !           103:        struct  ze_tdes *tp;
        !           104:        struct  ze_rdes *rp;
        !           105:        bus_dma_segment_t seg;
        !           106:        int i, s, rseg, error;
        !           107:
        !           108:         /*
        !           109:          * Allocate DMA safe memory for descriptors and setup memory.
        !           110:          */
        !           111:        if ((error = bus_dmamem_alloc(sc->sc_dmat,
        !           112:            sizeof(struct ze_cdata), NBPG, 0, &seg, 1, &rseg,
        !           113:            BUS_DMA_NOWAIT)) != 0) {
        !           114:                printf(": unable to allocate control data, error = %d\n",
        !           115:                    error);
        !           116:                goto fail_0;
        !           117:        }
        !           118:
        !           119:        if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
        !           120:            sizeof(struct ze_cdata), (caddr_t *)&sc->sc_zedata,
        !           121:            BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
        !           122:                printf(": unable to map control data, error = %d\n", error);
        !           123:                goto fail_1;
        !           124:        }
        !           125:
        !           126:        if ((error = bus_dmamap_create(sc->sc_dmat,
        !           127:            sizeof(struct ze_cdata), 1,
        !           128:            sizeof(struct ze_cdata), 0, BUS_DMA_NOWAIT,
        !           129:            &sc->sc_cmap)) != 0) {
        !           130:                printf(": unable to create control data DMA map, error = %d\n",
        !           131:                    error);
        !           132:                goto fail_2;
        !           133:        }
        !           134:
        !           135:        if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cmap,
        !           136:            sc->sc_zedata, sizeof(struct ze_cdata), NULL,
        !           137:            BUS_DMA_NOWAIT)) != 0) {
        !           138:                printf(": unable to load control data DMA map, error = %d\n",
        !           139:                    error);
        !           140:                goto fail_3;
        !           141:        }
        !           142:
        !           143:        /*
        !           144:         * Zero the newly allocated memory.
        !           145:         */
        !           146:        bzero(sc->sc_zedata, sizeof(struct ze_cdata));
        !           147:        /*
        !           148:         * Create the transmit descriptor DMA maps.
        !           149:         */
        !           150:        for (i = 0; i < TXDESCS; i++) {
        !           151:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
        !           152:                    1, MCLBYTES, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
        !           153:                    &sc->sc_xmtmap[i]))) {
        !           154:                        printf(": unable to create tx DMA map %d, error = %d\n",
        !           155:                            i, error);
        !           156:                        goto fail_4;
        !           157:                }
        !           158:        }
        !           159:
        !           160:        /*
        !           161:         * Create receive buffer DMA maps.
        !           162:         */
        !           163:        for (i = 0; i < RXDESCS; i++) {
        !           164:                if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
        !           165:                    MCLBYTES, 0, BUS_DMA_NOWAIT,
        !           166:                    &sc->sc_rcvmap[i]))) {
        !           167:                        printf(": unable to create rx DMA map %d, error = %d\n",
        !           168:                            i, error);
        !           169:                        goto fail_5;
        !           170:                }
        !           171:        }
        !           172:        /*
        !           173:         * Pre-allocate the receive buffers.
        !           174:         */
        !           175:        s = splnet();
        !           176:        for (i = 0; i < RXDESCS; i++) {
        !           177:                if ((error = ze_add_rxbuf(sc, i)) != 0) {
        !           178:                        printf(": unable to allocate or map rx buffer %d\n,"
        !           179:                            " error = %d\n", i, error);
        !           180:                        goto fail_6;
        !           181:                }
        !           182:        }
        !           183:        splx(s);
        !           184:
        !           185:        /*
        !           186:         * Create ring loops of the buffer chains.
        !           187:         * This is only done once.
        !           188:         */
        !           189:        sc->sc_pzedata = (struct ze_cdata *)sc->sc_cmap->dm_segs[0].ds_addr;
        !           190:
        !           191:        rp = sc->sc_zedata->zc_recv;
        !           192:        rp[RXDESCS].ze_framelen = ZE_FRAMELEN_OW;
        !           193:        rp[RXDESCS].ze_rdes1 = ZE_RDES1_CA;
        !           194:        rp[RXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_recv;
        !           195:
        !           196:        tp = sc->sc_zedata->zc_xmit;
        !           197:        tp[TXDESCS].ze_tdr = ZE_TDR_OW;
        !           198:        tp[TXDESCS].ze_tdes1 = ZE_TDES1_CA;
        !           199:        tp[TXDESCS].ze_bufaddr = (char *)sc->sc_pzedata->zc_xmit;
        !           200:
        !           201:        if (zereset(sc))
        !           202:                return;
        !           203:
        !           204:        strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
        !           205:        ifp->if_softc = sc;
        !           206:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           207:        ifp->if_start = zestart;
        !           208:        ifp->if_ioctl = zeioctl;
        !           209:        ifp->if_watchdog = zetimeout;
        !           210:
        !           211:        /*
        !           212:         * Attach the interface.
        !           213:         */
        !           214:        if_attach(ifp);
        !           215:        ether_ifattach(ifp);
        !           216:
        !           217:        printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
        !           218:        return;
        !           219:
        !           220:        /*
        !           221:         * Free any resources we've allocated during the failed attach
        !           222:         * attempt.  Do this in reverse order and fall through.
        !           223:         */
        !           224:  fail_6:
        !           225:        for (i = 0; i < RXDESCS; i++) {
        !           226:                if (sc->sc_rxmbuf[i] != NULL) {
        !           227:                        bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
        !           228:                        m_freem(sc->sc_rxmbuf[i]);
        !           229:                }
        !           230:        }
        !           231:  fail_5:
        !           232:        for (i = 0; i < RXDESCS; i++) {
        !           233:                if (sc->sc_xmtmap[i] != NULL)
        !           234:                        bus_dmamap_destroy(sc->sc_dmat, sc->sc_xmtmap[i]);
        !           235:        }
        !           236:  fail_4:
        !           237:        for (i = 0; i < TXDESCS; i++) {
        !           238:                if (sc->sc_rcvmap[i] != NULL)
        !           239:                        bus_dmamap_destroy(sc->sc_dmat, sc->sc_rcvmap[i]);
        !           240:        }
        !           241:        bus_dmamap_unload(sc->sc_dmat, sc->sc_cmap);
        !           242:  fail_3:
        !           243:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_cmap);
        !           244:  fail_2:
        !           245:        bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_zedata,
        !           246:            sizeof(struct ze_cdata));
        !           247:  fail_1:
        !           248:        bus_dmamem_free(sc->sc_dmat, &seg, rseg);
        !           249:  fail_0:
        !           250:        return;
        !           251: }
        !           252:
        !           253: /*
        !           254:  * Initialization of interface.
        !           255:  */
        !           256: void
        !           257: zeinit(sc)
        !           258:        struct ze_softc *sc;
        !           259: {
        !           260:        struct ifnet *ifp = (struct ifnet *)&sc->sc_if;
        !           261:        struct ze_cdata *zc = sc->sc_zedata;
        !           262:        int i;
        !           263:
        !           264:        /*
        !           265:         * Reset the interface.
        !           266:         */
        !           267:        if (zereset(sc))
        !           268:                return;
        !           269:
        !           270:        sc->sc_nexttx = sc->sc_inq = sc->sc_lastack = 0;
        !           271:        /*
        !           272:         * Release and init transmit descriptors.
        !           273:         */
        !           274:        for (i = 0; i < TXDESCS; i++) {
        !           275:                if (sc->sc_txmbuf[i]) {
        !           276:                        bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[i]);
        !           277:                        m_freem(sc->sc_txmbuf[i]);
        !           278:                        sc->sc_txmbuf[i] = 0;
        !           279:                }
        !           280:                zc->zc_xmit[i].ze_tdr = 0; /* Clear valid bit */
        !           281:        }
        !           282:
        !           283:
        !           284:        /*
        !           285:         * Init receive descriptors.
        !           286:         */
        !           287:        for (i = 0; i < RXDESCS; i++)
        !           288:                zc->zc_recv[i].ze_framelen = ZE_FRAMELEN_OW;
        !           289:        sc->sc_nextrx = 0;
        !           290:
        !           291:        ZE_WCSR(ZE_CSR6, ZE_NICSR6_IE | ZE_NICSR6_BL_8 | ZE_NICSR6_ST |
        !           292:            ZE_NICSR6_SR | ZE_NICSR6_DC);
        !           293:
        !           294:        ifp->if_flags |= IFF_RUNNING;
        !           295:        ifp->if_flags &= ~IFF_OACTIVE;
        !           296:
        !           297:        /*
        !           298:         * Send a setup frame.
        !           299:         * This will start the transmit machinery as well.
        !           300:         */
        !           301:        ze_setup(sc);
        !           302:
        !           303: }
        !           304:
        !           305: /*
        !           306:  * Kick off the transmit logic, if it is stopped.
        !           307:  * On the VXT2000 we need to always reprogram CSR4,
        !           308:  * so stop it unconditionnaly.
        !           309:  */
        !           310: void
        !           311: zekick(struct ze_softc *sc)
        !           312: {
        !           313:        u_int csr5;
        !           314:
        !           315:        csr5 = ZE_RCSR(ZE_CSR5);
        !           316:        if (ISSET(sc->sc_flags, SGECF_VXTQUIRKS)) {
        !           317:                if ((csr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN) {
        !           318:                        ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) & ~ZE_NICSR6_ST);
        !           319:                        while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) !=
        !           320:                            ZE_NICSR5_TS_STOP)
        !           321:                                DELAY(10);
        !           322:                }
        !           323:                ZE_WCSR(ZE_CSR4,
        !           324:                    (vaddr_t)&sc->sc_pzedata->zc_xmit[sc->sc_nexttx]);
        !           325:                ZE_WCSR(ZE_CSR1, ZE_NICSR1_TXPD);
        !           326:                if ((csr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN) {
        !           327:                        ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) | ZE_NICSR6_ST);
        !           328:                        while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_TS) ==
        !           329:                            ZE_NICSR5_TS_STOP)
        !           330:                                DELAY(10);
        !           331:                }
        !           332:        } else {
        !           333:                if ((csr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_RUN)
        !           334:                        ZE_WCSR(ZE_CSR1, ZE_NICSR1_TXPD);
        !           335:        }
        !           336: }
        !           337:
        !           338: /*
        !           339:  * Start output on interface.
        !           340:  */
        !           341: void
        !           342: zestart(ifp)
        !           343:        struct ifnet *ifp;
        !           344: {
        !           345:        struct ze_softc *sc = ifp->if_softc;
        !           346:        struct ze_cdata *zc = sc->sc_zedata;
        !           347:        paddr_t buffer;
        !           348:        struct mbuf *m, *m0;
        !           349:        int idx, len, s, i, totlen, error;
        !           350:        int old_inq = sc->sc_inq;
        !           351:        short orword;
        !           352:
        !           353:        s = splnet();
        !           354:        while (sc->sc_inq < (TXDESCS - 1)) {
        !           355:                if (ISSET(sc->sc_flags, SGECF_SETUP)) {
        !           356:                        ze_setup(sc);
        !           357:                        continue;
        !           358:                }
        !           359:                idx = sc->sc_nexttx;
        !           360:                IF_DEQUEUE(&sc->sc_if.if_snd, m);
        !           361:                if (m == 0)
        !           362:                        goto out;
        !           363:                /*
        !           364:                 * Count number of mbufs in chain.
        !           365:                 * Always do DMA directly from mbufs, therefore the transmit
        !           366:                 * ring is really big.
        !           367:                 */
        !           368:                for (m0 = m, i = 0; m0; m0 = m0->m_next)
        !           369:                        if (m0->m_len)
        !           370:                                i++;
        !           371:                if (i >= TXDESCS)
        !           372:                        panic("zestart"); /* XXX */
        !           373:
        !           374:                if ((i + sc->sc_inq) >= (TXDESCS - 1)) {
        !           375:                        IF_PREPEND(&sc->sc_if.if_snd, m);
        !           376:                        ifp->if_flags |= IFF_OACTIVE;
        !           377:                        goto out;
        !           378:                }
        !           379:
        !           380: #if NBPFILTER > 0
        !           381:                if (ifp->if_bpf)
        !           382:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
        !           383: #endif
        !           384:                /*
        !           385:                 * m now points to a mbuf chain that can be loaded.
        !           386:                 * Loop around and set it.
        !           387:                 */
        !           388:                totlen = 0;
        !           389:                for (m0 = m; m0; m0 = m0->m_next) {
        !           390:                        error = bus_dmamap_load(sc->sc_dmat, sc->sc_xmtmap[idx],
        !           391:                            mtod(m0, void *), m0->m_len, 0, 0);
        !           392:                        buffer = sc->sc_xmtmap[idx]->dm_segs[0].ds_addr;
        !           393:                        len = m0->m_len;
        !           394:                        if (len == 0)
        !           395:                                continue;
        !           396:
        !           397:                        totlen += len;
        !           398:                        /* Word alignment calc */
        !           399:                        orword = 0;
        !           400:                        if (totlen == len)
        !           401:                                orword = ZE_TDES1_FS;
        !           402:                        if (totlen == m->m_pkthdr.len) {
        !           403:                                if (totlen < ETHER_ADDR_LEN)
        !           404:                                        len += (ETHER_ADDR_LEN - totlen);
        !           405:                                orword |= ZE_TDES1_LS;
        !           406:                                sc->sc_txmbuf[idx] = m;
        !           407:                        }
        !           408:                        zc->zc_xmit[idx].ze_bufsize = len;
        !           409:                        zc->zc_xmit[idx].ze_bufaddr = (char *)buffer;
        !           410:                        zc->zc_xmit[idx].ze_tdes1 = orword | ZE_TDES1_IC;
        !           411:                        zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
        !           412:
        !           413:                        if (++idx == TXDESCS)
        !           414:                                idx = 0;
        !           415:                        sc->sc_inq++;
        !           416:                }
        !           417: #ifdef DIAGNOSTIC
        !           418:                if (totlen != m->m_pkthdr.len)
        !           419:                        panic("zestart: len fault");
        !           420: #endif
        !           421:
        !           422:                /*
        !           423:                 * Kick off the transmit logic, if it is stopped.
        !           424:                 */
        !           425:                zekick(sc);
        !           426:                sc->sc_nexttx = idx;
        !           427:        }
        !           428:        if (sc->sc_inq == (TXDESCS - 1))
        !           429:                ifp->if_flags |= IFF_OACTIVE;
        !           430:
        !           431: out:   if (old_inq < sc->sc_inq)
        !           432:                ifp->if_timer = 5; /* If transmit logic dies */
        !           433:        splx(s);
        !           434: }
        !           435:
        !           436: void
        !           437: sgec_rxintr(struct ze_softc *sc)
        !           438: {
        !           439:        struct ze_cdata *zc = sc->sc_zedata;
        !           440:        struct ifnet *ifp = &sc->sc_if;
        !           441:        struct ether_header *eh;
        !           442:        struct mbuf *m;
        !           443:        u_short rdes0;
        !           444:        int len;
        !           445:
        !           446:        while ((zc->zc_recv[sc->sc_nextrx].ze_framelen &
        !           447:            ZE_FRAMELEN_OW) == 0) {
        !           448:                rdes0 = zc->zc_recv[sc->sc_nextrx].ze_rdes0;
        !           449:                if (rdes0 & ZE_RDES0_ES) {
        !           450:                        rdes0 &= ~ZE_RDES0_TL;  /* not really an error */
        !           451:                        if ((rdes0 & (ZE_RDES0_OF | ZE_RDES0_CE | ZE_RDES0_CS |
        !           452:                            ZE_RDES0_LE | ZE_RDES0_RF)) == 0)
        !           453:                                rdes0 &= ~ZE_RDES0_ES;
        !           454:                }
        !           455:                if (rdes0 & ZE_RDES0_ES) {
        !           456:                        ifp->if_ierrors++;
        !           457:                        if (rdes0 & ZE_RDES0_CS)
        !           458:                                ifp->if_collisions++;
        !           459:                        m = NULL;
        !           460:                } else {
        !           461:                        ifp->if_ipackets++;
        !           462:                        m = sc->sc_rxmbuf[sc->sc_nextrx];
        !           463:                        len = zc->zc_recv[sc->sc_nextrx].ze_framelen;
        !           464:                }
        !           465:                ze_add_rxbuf(sc, sc->sc_nextrx);
        !           466:                if (m != NULL) {
        !           467:                        m->m_pkthdr.rcvif = ifp;
        !           468:                        m->m_pkthdr.len = m->m_len = len;
        !           469:                        eh = mtod(m, struct ether_header *);
        !           470: #if NBPFILTER > 0
        !           471:                        if (ifp->if_bpf) {
        !           472:                                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           473:                                if ((ifp->if_flags & IFF_PROMISC) != 0 &&
        !           474:                                    ((eh->ether_dhost[0] & 1) == 0) &&
        !           475:                                    bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
        !           476:                                    ETHER_ADDR_LEN) != 0) {
        !           477:                                        m_freem(m);
        !           478:                                        continue;
        !           479:                                }
        !           480:                        }
        !           481: #endif
        !           482:                        /*
        !           483:                         * ALLMULTI means PROMISC in this driver.
        !           484:                         */
        !           485:                        if ((ifp->if_flags & IFF_ALLMULTI) &&
        !           486:                            ((eh->ether_dhost[0] & 1) == 0) &&
        !           487:                            bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
        !           488:                            ETHER_ADDR_LEN)) {
        !           489:                                m_freem(m);
        !           490:                                continue;
        !           491:                        }
        !           492:                        ether_input_mbuf(ifp, m);
        !           493:                }
        !           494:                if (++sc->sc_nextrx == RXDESCS)
        !           495:                        sc->sc_nextrx = 0;
        !           496:        }
        !           497: }
        !           498:
        !           499: void
        !           500: sgec_txintr(struct ze_softc *sc)
        !           501: {
        !           502:        struct ze_cdata *zc = sc->sc_zedata;
        !           503:        struct ifnet *ifp = &sc->sc_if;
        !           504:        u_short tdes0;
        !           505:
        !           506:        while ((zc->zc_xmit[sc->sc_lastack].ze_tdr & ZE_TDR_OW) == 0) {
        !           507:                int idx = sc->sc_lastack;
        !           508:
        !           509:                if (sc->sc_lastack == sc->sc_nexttx)
        !           510:                        break;
        !           511:                sc->sc_inq--;
        !           512:                if (++sc->sc_lastack == TXDESCS)
        !           513:                        sc->sc_lastack = 0;
        !           514:
        !           515:                if ((zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_DT) ==
        !           516:                    ZE_TDES1_DT_SETUP) {
        !           517:                        continue;
        !           518:                }
        !           519:
        !           520:                tdes0 = zc->zc_xmit[idx].ze_tdes0;
        !           521:                if (tdes0 & ZE_TDES0_ES) {
        !           522:                        if (tdes0 & ZE_TDES0_TO)
        !           523:                                printf("%s: transmit watchdog timeout\n",
        !           524:                                    sc->sc_dev.dv_xname);
        !           525:                        if (tdes0 & (ZE_TDES0_LO | ZE_TDES0_NC))
        !           526:                                printf("%s: no carrier\n",
        !           527:                                    sc->sc_dev.dv_xname);
        !           528:                        if (tdes0 & ZE_TDES0_EC) {
        !           529:                                printf("%s: excessive collisions, tdr %d\n",
        !           530:                                    sc->sc_dev.dv_xname,
        !           531:                                    zc->zc_xmit[idx].ze_tdr & ~ZE_TDR_OW);
        !           532:                                ifp->if_collisions += 16;
        !           533:                        } else if (tdes0 & ZE_TDES0_LC)
        !           534:                                ifp->if_collisions +=
        !           535:                                    (tdes0 & ZE_TDES0_CC) >> 3;
        !           536:                        if (tdes0 & ZE_TDES0_UF)
        !           537:                                printf("%s: underflow\n", sc->sc_dev.dv_xname);
        !           538:                        ifp->if_oerrors++;
        !           539:                        if (tdes0 & (ZE_TDES0_TO | ZE_TDES0_UF))
        !           540:                                zeinit(sc);
        !           541:                } else {
        !           542:                        if (zc->zc_xmit[idx].ze_tdes1 & ZE_TDES1_LS)
        !           543:                                ifp->if_opackets++;
        !           544:                        bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
        !           545:                        if (sc->sc_txmbuf[idx]) {
        !           546:                                m_freem(sc->sc_txmbuf[idx]);
        !           547:                                sc->sc_txmbuf[idx] = 0;
        !           548:                        }
        !           549:                }
        !           550:        }
        !           551:        if (sc->sc_inq == 0)
        !           552:                ifp->if_timer = 0;
        !           553:        ifp->if_flags &= ~IFF_OACTIVE;
        !           554:        zestart(ifp); /* Put in more in queue */
        !           555: }
        !           556:
        !           557: int
        !           558: sgec_intr(sc)
        !           559:        struct ze_softc *sc;
        !           560: {
        !           561:        int s, csr;
        !           562:
        !           563:        csr = ZE_RCSR(ZE_CSR5);
        !           564:        if ((csr & ZE_NICSR5_IS) == 0) /* Wasn't we */
        !           565:                return 0;
        !           566:
        !           567:        /*
        !           568:         * On some systems, interrupts are handled at spl4, this can end up
        !           569:         * in pool corruption.
        !           570:         */
        !           571:        s = splnet();
        !           572:
        !           573:        ZE_WCSR(ZE_CSR5, csr);
        !           574:
        !           575:        if (csr & ZE_NICSR5_ME) {
        !           576:                printf("%s: memory error, resetting\n", sc->sc_dev.dv_xname);
        !           577:                zeinit(sc);
        !           578:                return (1);
        !           579:        }
        !           580:
        !           581:        if (csr & ZE_NICSR5_RI)
        !           582:                sgec_rxintr(sc);
        !           583:
        !           584:        if (csr & ZE_NICSR5_TI)
        !           585:                sgec_txintr(sc);
        !           586:
        !           587:        splx(s);
        !           588:
        !           589:        return 1;
        !           590: }
        !           591:
        !           592: /*
        !           593:  * Process an ioctl request.
        !           594:  */
        !           595: int
        !           596: zeioctl(ifp, cmd, data)
        !           597:        struct ifnet *ifp;
        !           598:        u_long cmd;
        !           599:        caddr_t data;
        !           600: {
        !           601:        struct ze_softc *sc = ifp->if_softc;
        !           602:        struct ifreq *ifr = (struct ifreq *)data;
        !           603:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           604:        int s = splnet(), error = 0;
        !           605:
        !           606:        switch (cmd) {
        !           607:
        !           608:        case SIOCSIFADDR:
        !           609:                ifp->if_flags |= IFF_UP;
        !           610:                switch(ifa->ifa_addr->sa_family) {
        !           611: #ifdef INET
        !           612:                case AF_INET:
        !           613:                        zeinit(sc);
        !           614:                        arp_ifinit(&sc->sc_ac, ifa);
        !           615:                        break;
        !           616: #endif
        !           617:                }
        !           618:                break;
        !           619:
        !           620:        case SIOCSIFFLAGS:
        !           621:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           622:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           623:                        /*
        !           624:                         * If interface is marked down and it is running,
        !           625:                         * stop it. (by disabling receive mechanism).
        !           626:                         */
        !           627:                        ZE_WCSR(ZE_CSR6, ZE_RCSR(ZE_CSR6) &
        !           628:                            ~(ZE_NICSR6_ST|ZE_NICSR6_SR));
        !           629:                        ifp->if_flags &= ~IFF_RUNNING;
        !           630:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           631:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !           632:                        /*
        !           633:                         * If interface it marked up and it is stopped, then
        !           634:                         * start it.
        !           635:                         */
        !           636:                        zeinit(sc);
        !           637:                } else if ((ifp->if_flags & IFF_UP) != 0) {
        !           638:                        /*
        !           639:                         * Send a new setup packet to match any new changes.
        !           640:                         * (Like IFF_PROMISC etc)
        !           641:                         */
        !           642:                        ze_setup(sc);
        !           643:                }
        !           644:                break;
        !           645:
        !           646:        case SIOCADDMULTI:
        !           647:        case SIOCDELMULTI:
        !           648:                /*
        !           649:                 * Update our multicast list.
        !           650:                 */
        !           651:                error = (cmd == SIOCADDMULTI) ?
        !           652:                        ether_addmulti(ifr, &sc->sc_ac):
        !           653:                        ether_delmulti(ifr, &sc->sc_ac);
        !           654:
        !           655:                if (error == ENETRESET) {
        !           656:                        /*
        !           657:                         * Multicast list has changed; set the hardware filter
        !           658:                         * accordingly.
        !           659:                         */
        !           660:                        if (ifp->if_flags & IFF_RUNNING)
        !           661:                                ze_setup(sc);
        !           662:                        error = 0;
        !           663:                }
        !           664:                break;
        !           665:
        !           666:        default:
        !           667:                error = EINVAL;
        !           668:
        !           669:        }
        !           670:        splx(s);
        !           671:        return (error);
        !           672: }
        !           673:
        !           674: /*
        !           675:  * Add a receive buffer to the indicated descriptor.
        !           676:  */
        !           677: int
        !           678: ze_add_rxbuf(sc, i)
        !           679:        struct ze_softc *sc;
        !           680:        int i;
        !           681: {
        !           682:        struct mbuf *m;
        !           683:        struct ze_rdes *rp;
        !           684:        int error;
        !           685:
        !           686:        splassert(IPL_NET);
        !           687:
        !           688:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           689:        if (m == NULL)
        !           690:                return (ENOBUFS);
        !           691:
        !           692:        MCLGET(m, M_DONTWAIT);
        !           693:        if ((m->m_flags & M_EXT) == 0) {
        !           694:                m_freem(m);
        !           695:                return (ENOBUFS);
        !           696:        }
        !           697:
        !           698:        if (sc->sc_rxmbuf[i] != NULL)
        !           699:                bus_dmamap_unload(sc->sc_dmat, sc->sc_rcvmap[i]);
        !           700:
        !           701:        error = bus_dmamap_load(sc->sc_dmat, sc->sc_rcvmap[i],
        !           702:            m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
        !           703:        if (error)
        !           704:                panic("%s: can't load rx DMA map %d, error = %d",
        !           705:                    sc->sc_dev.dv_xname, i, error);
        !           706:        sc->sc_rxmbuf[i] = m;
        !           707:
        !           708:        bus_dmamap_sync(sc->sc_dmat, sc->sc_rcvmap[i], 0,
        !           709:            sc->sc_rcvmap[i]->dm_mapsize, BUS_DMASYNC_PREREAD);
        !           710:
        !           711:        /*
        !           712:         * We know that the mbuf cluster is page aligned. Also, be sure
        !           713:         * that the IP header will be longword aligned.
        !           714:         */
        !           715:        m->m_data += 2;
        !           716:        rp = &sc->sc_zedata->zc_recv[i];
        !           717:        rp->ze_bufsize = (m->m_ext.ext_size - 2);
        !           718:        rp->ze_bufaddr = (char *)sc->sc_rcvmap[i]->dm_segs[0].ds_addr + 2;
        !           719:        rp->ze_framelen = ZE_FRAMELEN_OW;
        !           720:
        !           721:        return (0);
        !           722: }
        !           723:
        !           724: /*
        !           725:  * Create a setup packet and put in queue for sending.
        !           726:  */
        !           727: void
        !           728: ze_setup(sc)
        !           729:        struct ze_softc *sc;
        !           730: {
        !           731:        struct ether_multi *enm;
        !           732:        struct ether_multistep step;
        !           733:        struct ze_cdata *zc = sc->sc_zedata;
        !           734:        struct ifnet *ifp = &sc->sc_if;
        !           735:        u_int8_t *enaddr = sc->sc_ac.ac_enaddr;
        !           736:        int j, idx, s, reg;
        !           737:
        !           738:        s = splnet();
        !           739:        if (sc->sc_inq == (TXDESCS - 1)) {
        !           740:                SET(sc->sc_flags, SGECF_SETUP);
        !           741:                splx(s);
        !           742:                return;
        !           743:        }
        !           744:        CLR(sc->sc_flags, SGECF_SETUP);
        !           745:
        !           746:        /*
        !           747:         * Init the setup packet with valid info.
        !           748:         */
        !           749:        memset(zc->zc_setup, 0xff, sizeof(zc->zc_setup)); /* Broadcast */
        !           750:        bcopy(enaddr, zc->zc_setup, ETHER_ADDR_LEN);
        !           751:
        !           752:        /*
        !           753:         * Multicast handling. The SGEC can handle up to 16 direct
        !           754:         * ethernet addresses.
        !           755:         */
        !           756:        j = 16;
        !           757:        ifp->if_flags &= ~IFF_ALLMULTI;
        !           758:        ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
        !           759:        while (enm != NULL) {
        !           760:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 6)) {
        !           761:                        ifp->if_flags |= IFF_ALLMULTI;
        !           762:                        break;
        !           763:                }
        !           764:                bcopy(enm->enm_addrlo, &zc->zc_setup[j], ETHER_ADDR_LEN);
        !           765:                j += 8;
        !           766:                ETHER_NEXT_MULTI(step, enm);
        !           767:                if ((enm != NULL)&& (j == 128)) {
        !           768:                        ifp->if_flags |= IFF_ALLMULTI;
        !           769:                        break;
        !           770:                }
        !           771:        }
        !           772:
        !           773:        /*
        !           774:         * Fiddle with the receive logic.
        !           775:         */
        !           776:        reg = ZE_RCSR(ZE_CSR6);
        !           777:        DELAY(10);
        !           778:        ZE_WCSR(ZE_CSR6, reg & ~ZE_NICSR6_SR); /* Stop rx */
        !           779:        while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_RS) != ZE_NICSR5_RS_STOP)
        !           780:                DELAY(10);
        !           781:        reg &= ~ZE_NICSR6_AF;
        !           782:        if (ifp->if_flags & IFF_PROMISC)
        !           783:                reg |= ZE_NICSR6_AF_PROM;
        !           784:        else if (ifp->if_flags & IFF_ALLMULTI)
        !           785:                reg |= ZE_NICSR6_AF_ALLM;
        !           786:        DELAY(10);
        !           787:        ZE_WCSR(ZE_CSR6, reg);
        !           788:        while ((ZE_RCSR(ZE_CSR5) & ZE_NICSR5_RS) == ZE_NICSR5_RS_STOP)
        !           789:                DELAY(10);
        !           790:        /*
        !           791:         * Only send a setup packet if needed.
        !           792:         */
        !           793:        if ((ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) == 0) {
        !           794:                idx = sc->sc_nexttx;
        !           795:                zc->zc_xmit[idx].ze_tdes1 = ZE_TDES1_DT_SETUP;
        !           796:                zc->zc_xmit[idx].ze_bufsize = 128;
        !           797:                zc->zc_xmit[idx].ze_bufaddr = sc->sc_pzedata->zc_setup;
        !           798:                zc->zc_xmit[idx].ze_tdr = ZE_TDR_OW;
        !           799:
        !           800:                zekick(sc);
        !           801:
        !           802:                sc->sc_inq++;
        !           803:                if (++sc->sc_nexttx == TXDESCS)
        !           804:                        sc->sc_nexttx = 0;
        !           805:        }
        !           806:        splx(s);
        !           807: }
        !           808:
        !           809: /*
        !           810:  * Check for dead transmit logic.
        !           811:  */
        !           812: void
        !           813: zetimeout(ifp)
        !           814:        struct ifnet *ifp;
        !           815: {
        !           816:        struct ze_softc *sc = ifp->if_softc;
        !           817:
        !           818:        if (sc->sc_inq == 0)
        !           819:                return;
        !           820:
        !           821:        printf("%s: xmit logic died, resetting...\n", sc->sc_dev.dv_xname);
        !           822:        /*
        !           823:         * Do a reset of interface, to get it going again.
        !           824:         * Will it work by just restart the transmit logic?
        !           825:         */
        !           826:        zeinit(sc);
        !           827: }
        !           828:
        !           829: /*
        !           830:  * Reset chip:
        !           831:  * Set/reset the reset flag.
        !           832:  *  Write interrupt vector.
        !           833:  *  Write ring buffer addresses.
        !           834:  *  Write SBR.
        !           835:  */
        !           836: int
        !           837: zereset(sc)
        !           838:        struct ze_softc *sc;
        !           839: {
        !           840:        int reg, i, s;
        !           841:
        !           842:        ZE_WCSR(ZE_CSR6, ZE_NICSR6_RE);
        !           843:        DELAY(50000);
        !           844:        if (ZE_RCSR(ZE_CSR5) & ZE_NICSR5_SF) {
        !           845:                printf("%s: selftest failed\n", sc->sc_dev.dv_xname);
        !           846:                return 1;
        !           847:        }
        !           848:
        !           849:        /*
        !           850:         * Get the vector that were set at match time, and remember it.
        !           851:         * WHICH VECTOR TO USE? Take one unused. XXX
        !           852:         * Funny way to set vector described in the programmers manual.
        !           853:         */
        !           854:        reg = ZE_NICSR0_IPL14 | sc->sc_intvec | ZE_NICSR0_MBO; /* SYNC/ASYNC??? */
        !           855:        i = 10;
        !           856:        s = splnet();
        !           857:        do {
        !           858:                if (i-- == 0) {
        !           859:                        printf("Failing SGEC CSR0 init\n");
        !           860:                        splx(s);
        !           861:                        return 1;
        !           862:                }
        !           863:                ZE_WCSR(ZE_CSR0, reg);
        !           864:        } while (ZE_RCSR(ZE_CSR0) != reg);
        !           865:        splx(s);
        !           866:
        !           867:        ZE_WCSR(ZE_CSR3, (vaddr_t)sc->sc_pzedata->zc_recv);
        !           868:        ZE_WCSR(ZE_CSR4, (vaddr_t)sc->sc_pzedata->zc_xmit);
        !           869:        return 0;
        !           870: }

CVSweb