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

Annotation of sys/dev/isa/if_el.c, Revision 1.1

1.1     ! nbrk        1: /*    $OpenBSD: if_el.c,v 1.20 2006/03/25 22:41:44 djm Exp $       */
        !             2: /*     $NetBSD: if_el.c,v 1.39 1996/05/12 23:52:32 mycroft Exp $       */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994, Matthew E. Kimmel.  Permission is hereby granted
        !             6:  * to use, copy, modify and distribute this software provided that both
        !             7:  * the copyright notice and this permission notice appear in all copies
        !             8:  * of the software, derivative works or modified versions, and any
        !             9:  * portions thereof.
        !            10:  */
        !            11:
        !            12: /*
        !            13:  * 3COM Etherlink 3C501 device driver
        !            14:  */
        !            15:
        !            16: /*
        !            17:  * Bugs/possible improvements:
        !            18:  *     - Does not currently support DMA
        !            19:  *     - Does not currently support multicasts
        !            20:  */
        !            21:
        !            22: #include "bpfilter.h"
        !            23:
        !            24: #include <sys/param.h>
        !            25: #include <sys/systm.h>
        !            26: #include <sys/errno.h>
        !            27: #include <sys/ioctl.h>
        !            28: #include <sys/mbuf.h>
        !            29: #include <sys/socket.h>
        !            30: #include <sys/syslog.h>
        !            31: #include <sys/device.h>
        !            32:
        !            33: #include <net/if.h>
        !            34: #include <net/if_dl.h>
        !            35: #include <net/if_types.h>
        !            36:
        !            37: #ifdef INET
        !            38: #include <netinet/in.h>
        !            39: #include <netinet/in_systm.h>
        !            40: #include <netinet/in_var.h>
        !            41: #include <netinet/ip.h>
        !            42: #include <netinet/if_ether.h>
        !            43: #endif
        !            44:
        !            45: #if NBPFILTER > 0
        !            46: #include <net/bpf.h>
        !            47: #endif
        !            48:
        !            49: #include <machine/cpu.h>
        !            50: #include <machine/intr.h>
        !            51: #include <machine/pio.h>
        !            52:
        !            53: #include <dev/isa/isavar.h>
        !            54: #include <dev/isa/if_elreg.h>
        !            55:
        !            56: /* for debugging convenience */
        !            57: #ifdef EL_DEBUG
        !            58: #define dprintf(x) printf x
        !            59: #else
        !            60: #define dprintf(x)
        !            61: #endif
        !            62:
        !            63: /*
        !            64:  * per-line info and status
        !            65:  */
        !            66: struct el_softc {
        !            67:        struct device sc_dev;
        !            68:        void *sc_ih;
        !            69:
        !            70:        struct arpcom sc_arpcom;        /* ethernet common */
        !            71:        int sc_iobase;                  /* base I/O addr */
        !            72: };
        !            73:
        !            74: /*
        !            75:  * prototypes
        !            76:  */
        !            77: int elintr(void *);
        !            78: void elinit(struct el_softc *);
        !            79: int elioctl(struct ifnet *, u_long, caddr_t);
        !            80: void elstart(struct ifnet *);
        !            81: void elwatchdog(struct ifnet *);
        !            82: void elreset(struct el_softc *);
        !            83: void elstop(struct el_softc *);
        !            84: static int el_xmit(struct el_softc *);
        !            85: void elread(struct el_softc *, int);
        !            86: struct mbuf *elget(struct el_softc *sc, int);
        !            87: static inline void el_hardreset(struct el_softc *);
        !            88:
        !            89: int elprobe(struct device *, void *, void *);
        !            90: void elattach(struct device *, struct device *, void *);
        !            91:
        !            92: struct cfattach el_ca = {
        !            93:        sizeof(struct el_softc), elprobe, elattach
        !            94: };
        !            95:
        !            96: struct cfdriver el_cd = {
        !            97:        NULL, "el", DV_IFNET
        !            98: };
        !            99:
        !           100: /*
        !           101:  * Probe routine.
        !           102:  *
        !           103:  * See if the card is there and at the right place.
        !           104:  * (XXX - cgd -- needs help)
        !           105:  */
        !           106: int
        !           107: elprobe(parent, match, aux)
        !           108:        struct device *parent;
        !           109:        void *match, *aux;
        !           110: {
        !           111:        struct el_softc *sc = match;
        !           112:        struct isa_attach_args *ia = aux;
        !           113:        int iobase = ia->ia_iobase;
        !           114:        u_char station_addr[ETHER_ADDR_LEN];
        !           115:        int i;
        !           116:
        !           117:        /* First check the base. */
        !           118:        if (iobase < 0x280 || iobase > 0x3f0)
        !           119:                return 0;
        !           120:
        !           121:        /* Grab some info for our structure. */
        !           122:        sc->sc_iobase = iobase;
        !           123:
        !           124:        /*
        !           125:         * Now attempt to grab the station address from the PROM and see if it
        !           126:         * contains the 3com vendor code.
        !           127:         */
        !           128:        dprintf(("Probing 3c501 at 0x%x...\n", iobase));
        !           129:
        !           130:        /* Reset the board. */
        !           131:        dprintf(("Resetting board...\n"));
        !           132:        outb(iobase+EL_AC, EL_AC_RESET);
        !           133:        delay(5);
        !           134:        outb(iobase+EL_AC, 0);
        !           135:
        !           136:        /* Now read the address. */
        !           137:        dprintf(("Reading station address...\n"));
        !           138:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !           139:                outb(iobase+EL_GPBL, i);
        !           140:                station_addr[i] = inb(iobase+EL_EAW);
        !           141:        }
        !           142:        dprintf(("Address is %s\n", ether_sprintf(station_addr)));
        !           143:
        !           144:        /*
        !           145:         * If the vendor code is ok, return a 1.  We'll assume that whoever
        !           146:         * configured this system is right about the IRQ.
        !           147:         */
        !           148:        if (station_addr[0] != 0x02 || station_addr[1] != 0x60 ||
        !           149:            station_addr[2] != 0x8c) {
        !           150:                dprintf(("Bad vendor code.\n"));
        !           151:                return 0;
        !           152:        }
        !           153:
        !           154:        dprintf(("Vendor code ok.\n"));
        !           155:        /* Copy the station address into the arpcom structure. */
        !           156:        bcopy(station_addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           157:
        !           158:        ia->ia_iosize = 4;      /* XXX */
        !           159:        ia->ia_msize = 0;
        !           160:        return 1;
        !           161: }
        !           162:
        !           163: /*
        !           164:  * Attach the interface to the kernel data structures.  By the time this is
        !           165:  * called, we know that the card exists at the given I/O address.  We still
        !           166:  * assume that the IRQ given is correct.
        !           167:  */
        !           168: void
        !           169: elattach(parent, self, aux)
        !           170:        struct device *parent, *self;
        !           171:        void *aux;
        !           172: {
        !           173:        struct el_softc *sc = (void *)self;
        !           174:        struct isa_attach_args *ia = aux;
        !           175:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           176:
        !           177:        dprintf(("Attaching %s...\n", sc->sc_dev.dv_xname));
        !           178:
        !           179:        /* Stop the board. */
        !           180:        elstop(sc);
        !           181:
        !           182:        /* Initialize ifnet structure. */
        !           183:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           184:        ifp->if_softc = sc;
        !           185:        ifp->if_start = elstart;
        !           186:        ifp->if_ioctl = elioctl;
        !           187:        ifp->if_watchdog = elwatchdog;
        !           188:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
        !           189:        IFQ_SET_READY(&ifp->if_snd);
        !           190:
        !           191:        /* Now we can attach the interface. */
        !           192:        dprintf(("Attaching interface...\n"));
        !           193:        if_attach(ifp);
        !           194:        ether_ifattach(ifp);
        !           195:
        !           196:        /* Print out some information for the user. */
        !           197:        printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           198:
        !           199:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
        !           200:            IPL_NET, elintr, sc, sc->sc_dev.dv_xname);
        !           201:
        !           202:        dprintf(("elattach() finished.\n"));
        !           203: }
        !           204:
        !           205: /*
        !           206:  * Reset interface.
        !           207:  */
        !           208: void
        !           209: elreset(sc)
        !           210:        struct el_softc *sc;
        !           211: {
        !           212:        int s;
        !           213:
        !           214:        dprintf(("elreset()\n"));
        !           215:        s = splnet();
        !           216:        elstop(sc);
        !           217:        elinit(sc);
        !           218:        splx(s);
        !           219: }
        !           220:
        !           221: /*
        !           222:  * Stop interface.
        !           223:  */
        !           224: void
        !           225: elstop(sc)
        !           226:        struct el_softc *sc;
        !           227: {
        !           228:
        !           229:        outb(sc->sc_iobase+EL_AC, 0);
        !           230: }
        !           231:
        !           232: /*
        !           233:  * Do a hardware reset of the board, and upload the ethernet address again in
        !           234:  * case the board forgets.
        !           235:  */
        !           236: static inline void
        !           237: el_hardreset(sc)
        !           238:        struct el_softc *sc;
        !           239: {
        !           240:        int iobase = sc->sc_iobase;
        !           241:        int i;
        !           242:
        !           243:        outb(iobase+EL_AC, EL_AC_RESET);
        !           244:        delay(5);
        !           245:        outb(iobase+EL_AC, 0);
        !           246:
        !           247:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !           248:                outb(iobase+i, sc->sc_arpcom.ac_enaddr[i]);
        !           249: }
        !           250:
        !           251: /*
        !           252:  * Initialize interface.
        !           253:  */
        !           254: void
        !           255: elinit(sc)
        !           256:        struct el_softc *sc;
        !           257: {
        !           258:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           259:        int iobase = sc->sc_iobase;
        !           260:
        !           261:        /* First, reset the board. */
        !           262:        el_hardreset(sc);
        !           263:
        !           264:        /* Configure rx. */
        !           265:        dprintf(("Configuring rx...\n"));
        !           266:        if (ifp->if_flags & IFF_PROMISC)
        !           267:                outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
        !           268:        else
        !           269:                outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
        !           270:        outb(iobase+EL_RBC, 0);
        !           271:
        !           272:        /* Configure TX. */
        !           273:        dprintf(("Configuring tx...\n"));
        !           274:        outb(iobase+EL_TXC, 0);
        !           275:
        !           276:        /* Start reception. */
        !           277:        dprintf(("Starting reception...\n"));
        !           278:        outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
        !           279:
        !           280:        /* Set flags appropriately. */
        !           281:        ifp->if_flags |= IFF_RUNNING;
        !           282:        ifp->if_flags &= ~IFF_OACTIVE;
        !           283:
        !           284:        /* And start output. */
        !           285:        elstart(ifp);
        !           286: }
        !           287:
        !           288: /*
        !           289:  * Start output on interface.  Get datagrams from the queue and output them,
        !           290:  * giving the receiver a chance between datagrams.  Call only from splnet or
        !           291:  * interrupt level!
        !           292:  */
        !           293: void
        !           294: elstart(ifp)
        !           295:        struct ifnet *ifp;
        !           296: {
        !           297:        struct el_softc *sc = ifp->if_softc;
        !           298:        int iobase = sc->sc_iobase;
        !           299:        struct mbuf *m, *m0;
        !           300:        int s, i, off, retries;
        !           301:
        !           302:        dprintf(("elstart()...\n"));
        !           303:        s = splnet();
        !           304:
        !           305:        /* Don't do anything if output is active. */
        !           306:        if ((ifp->if_flags & IFF_OACTIVE) != 0) {
        !           307:                splx(s);
        !           308:                return;
        !           309:        }
        !           310:
        !           311:        ifp->if_flags |= IFF_OACTIVE;
        !           312:
        !           313:        /*
        !           314:         * The main loop.  They warned me against endless loops, but would I
        !           315:         * listen?  NOOO....
        !           316:         */
        !           317:        for (;;) {
        !           318:                /* Dequeue the next datagram. */
        !           319:                IFQ_DEQUEUE(&ifp->if_snd, m0);
        !           320:
        !           321:                /* If there's nothing to send, return. */
        !           322:                if (m0 == 0)
        !           323:                        break;
        !           324:
        !           325: #if NBPFILTER > 0
        !           326:                /* Give the packet to the bpf, if any. */
        !           327:                if (ifp->if_bpf)
        !           328:                        bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !           329: #endif
        !           330:
        !           331:                /* Disable the receiver. */
        !           332:                outb(iobase+EL_AC, EL_AC_HOST);
        !           333:                outb(iobase+EL_RBC, 0);
        !           334:
        !           335:                /* Transfer datagram to board. */
        !           336:                dprintf(("el: xfr pkt length=%d...\n", m0->m_pkthdr.len));
        !           337:                off = EL_BUFSIZ - max(m0->m_pkthdr.len, ETHER_MIN_LEN);
        !           338:                outb(iobase+EL_GPBL, off);
        !           339:                outb(iobase+EL_GPBH, off >> 8);
        !           340:
        !           341:                /* Copy the datagram to the buffer. */
        !           342:                for (m = m0; m != 0; m = m->m_next)
        !           343:                        outsb(iobase+EL_BUF, mtod(m, caddr_t), m->m_len);
        !           344:                for (i = 0;
        !           345:                    i < ETHER_MIN_LEN - ETHER_CRC_LEN - m0->m_pkthdr.len; i++)
        !           346:                        outb(iobase+EL_BUF, 0);
        !           347:
        !           348:                m_freem(m0);
        !           349:
        !           350:                /* Now transmit the datagram. */
        !           351:                retries = 0;
        !           352:                for (;;) {
        !           353:                        outb(iobase+EL_GPBL, off);
        !           354:                        outb(iobase+EL_GPBH, off >> 8);
        !           355:                        if (el_xmit(sc)) {
        !           356:                                ifp->if_oerrors++;
        !           357:                                break;
        !           358:                        }
        !           359:                        /* Check out status. */
        !           360:                        i = inb(iobase+EL_TXS);
        !           361:                        dprintf(("tx status=0x%x\n", i));
        !           362:                        if ((i & EL_TXS_READY) == 0) {
        !           363:                                dprintf(("el: err txs=%x\n", i));
        !           364:                                if (i & (EL_TXS_COLL | EL_TXS_COLL16)) {
        !           365:                                        ifp->if_collisions++;
        !           366:                                        if ((i & EL_TXC_DCOLL16) == 0 &&
        !           367:                                            retries < 15) {
        !           368:                                                retries++;
        !           369:                                                outb(iobase+EL_AC, EL_AC_HOST);
        !           370:                                        }
        !           371:                                } else {
        !           372:                                        ifp->if_oerrors++;
        !           373:                                        break;
        !           374:                                }
        !           375:                        } else {
        !           376:                                ifp->if_opackets++;
        !           377:                                break;
        !           378:                        }
        !           379:                }
        !           380:
        !           381:                /*
        !           382:                 * Now give the card a chance to receive.
        !           383:                 * Gotta love 3c501s...
        !           384:                 */
        !           385:                (void)inb(iobase+EL_AS);
        !           386:                outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
        !           387:                splx(s);
        !           388:                /* Interrupt here. */
        !           389:                s = splnet();
        !           390:        }
        !           391:
        !           392:        (void)inb(iobase+EL_AS);
        !           393:        outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
        !           394:        ifp->if_flags &= ~IFF_OACTIVE;
        !           395:        splx(s);
        !           396: }
        !           397:
        !           398: /*
        !           399:  * This function actually attempts to transmit a datagram downloaded to the
        !           400:  * board.  Call at splnet or interrupt, after downloading data!  Returns 0 on
        !           401:  * success, non-0 on failure.
        !           402:  */
        !           403: static int
        !           404: el_xmit(sc)
        !           405:        struct el_softc *sc;
        !           406: {
        !           407:        int iobase = sc->sc_iobase;
        !           408:        int i;
        !           409:
        !           410:        /*
        !           411:         * XXX
        !           412:         * This busy-waits for the tx completion.  Can we get an interrupt
        !           413:         * instead?
        !           414:         */
        !           415:
        !           416:        dprintf(("el: xmit..."));
        !           417:        outb(iobase+EL_AC, EL_AC_TXFRX);
        !           418:        i = 20000;
        !           419:        while ((inb(iobase+EL_AS) & EL_AS_TXBUSY) && (i > 0))
        !           420:                i--;
        !           421:        if (i == 0) {
        !           422:                dprintf(("tx not ready\n"));
        !           423:                return -1;
        !           424:        }
        !           425:        dprintf(("%d cycles.\n", 20000 - i));
        !           426:        return 0;
        !           427: }
        !           428:
        !           429: /*
        !           430:  * Controller interrupt.
        !           431:  */
        !           432: int
        !           433: elintr(arg)
        !           434:        void *arg;
        !           435: {
        !           436:        register struct el_softc *sc = arg;
        !           437:        int iobase = sc->sc_iobase;
        !           438:        int rxstat, len;
        !           439:
        !           440:        dprintf(("elintr: "));
        !           441:
        !           442:        /* Check board status. */
        !           443:        if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0) {
        !           444:                (void)inb(iobase+EL_RXC);
        !           445:                outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
        !           446:                return 0;
        !           447:        }
        !           448:
        !           449:        for (;;) {
        !           450:                rxstat = inb(iobase+EL_RXS);
        !           451:                if (rxstat & EL_RXS_STALE)
        !           452:                        break;
        !           453:
        !           454:                /* If there's an overflow, reinit the board. */
        !           455:                if ((rxstat & EL_RXS_NOFLOW) == 0) {
        !           456:                        dprintf(("overflow.\n"));
        !           457:                        el_hardreset(sc);
        !           458:                        /* Put board back into receive mode. */
        !           459:                        if (sc->sc_arpcom.ac_if.if_flags & IFF_PROMISC)
        !           460:                                outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC);
        !           461:                        else
        !           462:                                outb(iobase+EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD);
        !           463:                        (void)inb(iobase+EL_AS);
        !           464:                        outb(iobase+EL_RBC, 0);
        !           465:                        break;
        !           466:                }
        !           467:
        !           468:                /* Incoming packet. */
        !           469:                len = inb(iobase+EL_RBL);
        !           470:                len |= inb(iobase+EL_RBH) << 8;
        !           471:                dprintf(("receive len=%d rxstat=%x ", len, rxstat));
        !           472:                outb(iobase+EL_AC, EL_AC_HOST);
        !           473:
        !           474:                /* Pass data up to upper levels. */
        !           475:                elread(sc, len);
        !           476:
        !           477:                /* Is there another packet? */
        !           478:                if ((inb(iobase+EL_AS) & EL_AS_RXBUSY) != 0)
        !           479:                        break;
        !           480:
        !           481:                dprintf(("<rescan> "));
        !           482:        }
        !           483:
        !           484:        (void)inb(iobase+EL_RXC);
        !           485:        outb(iobase+EL_AC, EL_AC_IRQE | EL_AC_RX);
        !           486:        return 1;
        !           487: }
        !           488:
        !           489: /*
        !           490:  * Pass a packet to the higher levels.
        !           491:  */
        !           492: void
        !           493: elread(sc, len)
        !           494:        register struct el_softc *sc;
        !           495:        int len;
        !           496: {
        !           497:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           498:        struct mbuf *m;
        !           499:
        !           500:        if (len <= sizeof(struct ether_header) ||
        !           501:            len > ETHER_MAX_LEN) {
        !           502:                printf("%s: invalid packet size %d; dropping\n",
        !           503:                    sc->sc_dev.dv_xname, len);
        !           504:                ifp->if_ierrors++;
        !           505:                return;
        !           506:        }
        !           507:
        !           508:        /* Pull packet off interface. */
        !           509:        m = elget(sc, len);
        !           510:        if (m == 0) {
        !           511:                ifp->if_ierrors++;
        !           512:                return;
        !           513:        }
        !           514:
        !           515:        ifp->if_ipackets++;
        !           516:
        !           517: #if NBPFILTER > 0
        !           518:        /*
        !           519:         * Check if there's a BPF listener on this interface.
        !           520:         * If so, hand off the raw packet to BPF.
        !           521:         */
        !           522:        if (ifp->if_bpf)
        !           523:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           524: #endif
        !           525:
        !           526:        ether_input_mbuf(ifp, m);
        !           527: }
        !           528:
        !           529: /*
        !           530:  * Pull read data off a interface.  Len is length of data, with local net
        !           531:  * header stripped.  We copy the data into mbufs.  When full cluster sized
        !           532:  * units are present we copy into clusters.
        !           533:  */
        !           534: struct mbuf *
        !           535: elget(sc, totlen)
        !           536:        struct el_softc *sc;
        !           537:        int totlen;
        !           538: {
        !           539:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           540:        int iobase = sc->sc_iobase;
        !           541:        struct mbuf *top, **mp, *m;
        !           542:        int len;
        !           543:
        !           544:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           545:        if (m == 0)
        !           546:                return 0;
        !           547:        m->m_pkthdr.rcvif = ifp;
        !           548:        m->m_pkthdr.len = totlen;
        !           549:        len = MHLEN;
        !           550:        top = 0;
        !           551:        mp = &top;
        !           552:
        !           553:        outb(iobase+EL_GPBL, 0);
        !           554:        outb(iobase+EL_GPBH, 0);
        !           555:
        !           556:        while (totlen > 0) {
        !           557:                if (top) {
        !           558:                        MGET(m, M_DONTWAIT, MT_DATA);
        !           559:                        if (m == 0) {
        !           560:                                m_freem(top);
        !           561:                                return 0;
        !           562:                        }
        !           563:                        len = MLEN;
        !           564:                }
        !           565:                if (totlen >= MINCLSIZE) {
        !           566:                        MCLGET(m, M_DONTWAIT);
        !           567:                        if (m->m_flags & M_EXT)
        !           568:                                len = MCLBYTES;
        !           569:                }
        !           570:                m->m_len = len = min(totlen, len);
        !           571:                insb(iobase+EL_BUF, mtod(m, caddr_t), len);
        !           572:                totlen -= len;
        !           573:                *mp = m;
        !           574:                mp = &m->m_next;
        !           575:        }
        !           576:
        !           577:        outb(iobase+EL_RBC, 0);
        !           578:        outb(iobase+EL_AC, EL_AC_RX);
        !           579:
        !           580:        return top;
        !           581: }
        !           582:
        !           583: /*
        !           584:  * Process an ioctl request. This code needs some work - it looks pretty ugly.
        !           585:  */
        !           586: int
        !           587: elioctl(ifp, cmd, data)
        !           588:        register struct ifnet *ifp;
        !           589:        u_long cmd;
        !           590:        caddr_t data;
        !           591: {
        !           592:        struct el_softc *sc = ifp->if_softc;
        !           593:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           594:        int s, error = 0;
        !           595:
        !           596:        s = splnet();
        !           597:
        !           598:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !           599:                splx(s);
        !           600:                return error;
        !           601:        }
        !           602:
        !           603:        switch (cmd) {
        !           604:
        !           605:        case SIOCSIFADDR:
        !           606:                ifp->if_flags |= IFF_UP;
        !           607:
        !           608:                switch (ifa->ifa_addr->sa_family) {
        !           609: #ifdef INET
        !           610:                case AF_INET:
        !           611:                        elinit(sc);
        !           612:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           613:                        break;
        !           614: #endif
        !           615:                default:
        !           616:                        elinit(sc);
        !           617:                        break;
        !           618:                }
        !           619:                break;
        !           620:
        !           621:        case SIOCSIFFLAGS:
        !           622:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           623:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           624:                        /*
        !           625:                         * If interface is marked down and it is running, then
        !           626:                         * stop it.
        !           627:                         */
        !           628:                        elstop(sc);
        !           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 is marked up and it is stopped, then
        !           634:                         * start it.
        !           635:                         */
        !           636:                        elinit(sc);
        !           637:                } else {
        !           638:                        /*
        !           639:                         * Some other important flag might have changed, so
        !           640:                         * reset.
        !           641:                         */
        !           642:                        elreset(sc);
        !           643:                }
        !           644:                break;
        !           645:
        !           646:        default:
        !           647:                error = EINVAL;
        !           648:                break;
        !           649:        }
        !           650:
        !           651:        splx(s);
        !           652:        return error;
        !           653: }
        !           654:
        !           655: /*
        !           656:  * Device timeout routine.
        !           657:  */
        !           658: void
        !           659: elwatchdog(ifp)
        !           660:        struct ifnet *ifp;
        !           661: {
        !           662:        struct el_softc *sc = ifp->if_softc;
        !           663:
        !           664:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           665:        sc->sc_arpcom.ac_if.if_oerrors++;
        !           666:
        !           667:        elreset(sc);
        !           668: }

CVSweb