[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

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