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

Annotation of src/sys/dev/ic/lance.c, Revision 1.7.2.1

1.7.2.1 ! perry       1: /*     $NetBSD: lance.c,v 1.8 1999/04/30 18:15:04 thorpej Exp $        */
1.1       drochner    2:
                      3: /*-
1.3       mycroft     4:  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
1.1       drochner    5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.3       mycroft     8:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
                      9:  * Simulation Facility, NASA Ames Research Center.
1.1       drochner   10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*-
                     41:  * Copyright (c) 1992, 1993
                     42:  *     The Regents of the University of California.  All rights reserved.
                     43:  *
                     44:  * This code is derived from software contributed to Berkeley by
                     45:  * Ralph Campbell and Rick Macklem.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed by the University of
                     58:  *     California, Berkeley and its contributors.
                     59:  * 4. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  *
                     75:  *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
                     76:  */
                     77:
                     78: #include "opt_inet.h"
                     79: #include "opt_ccitt.h"
                     80: #include "opt_llc.h"
                     81: #include "opt_ns.h"
                     82: #include "bpfilter.h"
                     83: #include "rnd.h"
                     84:
                     85: #include <sys/param.h>
                     86: #include <sys/systm.h>
                     87: #include <sys/mbuf.h>
                     88: #include <sys/syslog.h>
                     89: #include <sys/socket.h>
                     90: #include <sys/device.h>
                     91: #include <sys/malloc.h>
                     92: #include <sys/ioctl.h>
                     93: #include <sys/errno.h>
                     94: #if NRND > 0
                     95: #include <sys/rnd.h>
                     96: #endif
                     97:
                     98: #include <net/if.h>
                     99: #include <net/if_dl.h>
                    100: #include <net/if_ether.h>
                    101: #include <net/if_media.h>
                    102:
                    103: #ifdef INET
                    104: #include <netinet/in.h>
                    105: #include <netinet/if_inarp.h>
                    106: #include <netinet/in_systm.h>
                    107: #include <netinet/in_var.h>
                    108: #include <netinet/ip.h>
                    109: #endif
                    110:
                    111: #ifdef NS
                    112: #include <netns/ns.h>
                    113: #include <netns/ns_if.h>
                    114: #endif
                    115:
                    116: #if defined(CCITT) && defined(LLC)
                    117: #include <sys/socketvar.h>
                    118: #include <netccitt/x25.h>
                    119: #include <netccitt/pk.h>
                    120: #include <netccitt/pk_var.h>
                    121: #include <netccitt/pk_extern.h>
                    122: #endif
                    123:
                    124: #if NBPFILTER > 0
                    125: #include <net/bpf.h>
                    126: #include <net/bpfdesc.h>
                    127: #endif
                    128:
                    129: #include <dev/ic/lancereg.h>
                    130: #include <dev/ic/lancevar.h>
                    131:
                    132: #if defined(_KERNEL) && !defined(_LKM)
                    133: #include "opt_ddb.h"
                    134: #endif
                    135:
                    136: #ifdef DDB
                    137: #define        integrate
                    138: #define hide
                    139: #else
                    140: #define        integrate       static __inline
                    141: #define hide           static
                    142: #endif
                    143:
                    144: integrate struct mbuf *lance_get __P((struct lance_softc *, int, int));
                    145:
                    146: hide void lance_shutdown __P((void *));
                    147:
                    148: int lance_mediachange __P((struct ifnet *));
                    149: void lance_mediastatus __P((struct ifnet *, struct ifmediareq *));
                    150:
                    151: static inline u_int16_t ether_cmp __P((void *, void *));
                    152:
                    153: void lance_stop __P((struct lance_softc *));
                    154: int lance_ioctl __P((struct ifnet *, u_long, caddr_t));
                    155: void lance_watchdog __P((struct ifnet *));
                    156:
                    157: /*
                    158:  * Compare two Ether/802 addresses for equality, inlined and
                    159:  * unrolled for speed.  Use this like bcmp().
                    160:  *
                    161:  * XXX: Add <machine/inlines.h> for stuff like this?
                    162:  * XXX: or maybe add it to libkern.h instead?
                    163:  *
                    164:  * "I'd love to have an inline assembler version of this."
                    165:  * XXX: Who wanted that? mycroft?  I wrote one, but this
                    166:  * version in C is as good as hand-coded assembly. -gwr
                    167:  *
                    168:  * Please do NOT tweak this without looking at the actual
                    169:  * assembly code generated before and after your tweaks!
                    170:  */
                    171: static inline u_int16_t
                    172: ether_cmp(one, two)
                    173:        void *one, *two;
                    174: {
                    175:        register u_int16_t *a = (u_short *) one;
                    176:        register u_int16_t *b = (u_short *) two;
                    177:        register u_int16_t diff;
                    178:
                    179: #ifdef m68k
                    180:        /*
                    181:         * The post-increment-pointer form produces the best
                    182:         * machine code for m68k.  This was carefully tuned
                    183:         * so it compiles to just 8 short (2-byte) op-codes!
                    184:         */
                    185:        diff  = *a++ - *b++;
                    186:        diff |= *a++ - *b++;
                    187:        diff |= *a++ - *b++;
                    188: #else
                    189:        /*
                    190:         * Most modern CPUs do better with a single expresion.
                    191:         * Note that short-cut evaluation is NOT helpful here,
                    192:         * because it just makes the code longer, not faster!
                    193:         */
                    194:        diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
                    195: #endif
                    196:
                    197:        return (diff);
                    198: }
                    199:
                    200: #define ETHER_CMP      ether_cmp
                    201:
                    202: #ifdef LANCE_REVC_BUG
                    203: /* Make sure this is short-aligned, for ether_cmp(). */
                    204: static u_int16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
                    205: #endif
                    206:
                    207: #define        ifp     (&sc->sc_ethercom.ec_if)
                    208:
                    209: void
                    210: lance_config(sc)
                    211:        struct lance_softc *sc;
                    212: {
                    213:        int i;
                    214:
                    215:        /* Make sure the chip is stopped. */
                    216:        lance_stop(sc);
                    217:
                    218:        /* Initialize ifnet structure. */
                    219:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    220:        ifp->if_softc = sc;
                    221:        ifp->if_start = sc->sc_start;
                    222:        ifp->if_ioctl = lance_ioctl;
                    223:        ifp->if_watchdog = lance_watchdog;
                    224:        ifp->if_flags =
                    225:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    226: #ifdef LANCE_REVC_BUG
                    227:        ifp->if_flags &= ~IFF_MULTICAST;
                    228: #endif
                    229:
                    230:        /* Initialize ifmedia structures. */
                    231:        ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus);
                    232:        if (sc->sc_supmedia != NULL) {
                    233:                for (i = 0; i < sc->sc_nsupmedia; i++)
                    234:                        ifmedia_add(&sc->sc_media, sc->sc_supmedia[i],
                    235:                           0, NULL);
                    236:                ifmedia_set(&sc->sc_media, sc->sc_defaultmedia);
                    237:        } else {
                    238:                ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
                    239:                ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
                    240:        }
                    241:
                    242:        /* Attach the interface. */
                    243:        if_attach(ifp);
                    244:        ether_ifattach(ifp, sc->sc_enaddr);
                    245:
                    246: #if NBPFILTER > 0
                    247:        bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
                    248: #endif
                    249:
                    250:        switch (sc->sc_memsize) {
                    251:        case 8192:
                    252:                sc->sc_nrbuf = 4;
                    253:                sc->sc_ntbuf = 1;
                    254:                break;
                    255:        case 16384:
                    256:                sc->sc_nrbuf = 8;
                    257:                sc->sc_ntbuf = 2;
                    258:                break;
                    259:        case 32768:
                    260:                sc->sc_nrbuf = 16;
                    261:                sc->sc_ntbuf = 4;
                    262:                break;
                    263:        case 65536:
                    264:                sc->sc_nrbuf = 32;
                    265:                sc->sc_ntbuf = 8;
                    266:                break;
                    267:        case 131072:
                    268:                sc->sc_nrbuf = 64;
                    269:                sc->sc_ntbuf = 16;
1.4       leo       270:                break;
                    271:        case 262144:
                    272:                sc->sc_nrbuf = 128;
                    273:                sc->sc_ntbuf = 32;
1.1       drochner  274:                break;
                    275:        default:
                    276:                panic("lance_config: weird memory size");
                    277:        }
                    278:
                    279:        printf(": address %s\n", ether_sprintf(sc->sc_enaddr));
                    280:        printf("%s: %d receive buffers, %d transmit buffers\n",
                    281:            sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
                    282:
                    283:        sc->sc_sh = shutdownhook_establish(lance_shutdown, sc);
                    284:        if (sc->sc_sh == NULL)
                    285:                panic("lance_config: can't establish shutdownhook");
                    286:        sc->sc_rbufaddr = malloc(sc->sc_nrbuf * sizeof(int), M_DEVBUF,
                    287:                                        M_WAITOK);
                    288:        sc->sc_tbufaddr = malloc(sc->sc_ntbuf * sizeof(int), M_DEVBUF,
                    289:                                        M_WAITOK);
                    290:
                    291: #if NRND > 0
                    292:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
1.7       explorer  293:                          RND_TYPE_NET, 0);
1.1       drochner  294: #endif
                    295: }
                    296:
                    297: void
                    298: lance_reset(sc)
                    299:        struct lance_softc *sc;
                    300: {
                    301:        int s;
                    302:
1.2       mycroft   303:        s = splnet();
1.1       drochner  304:        lance_init(sc);
                    305:        splx(s);
                    306: }
                    307:
                    308: void
                    309: lance_stop(sc)
                    310:        struct lance_softc *sc;
                    311: {
                    312:
                    313:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
                    314: }
                    315:
                    316: /*
                    317:  * Initialization of interface; set up initialization block
                    318:  * and transmit/receive descriptor rings.
                    319:  */
                    320: void
                    321: lance_init(sc)
                    322:        register struct lance_softc *sc;
                    323: {
                    324:        register int timo;
                    325:        u_long a;
                    326:
                    327:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
                    328:        DELAY(100);
                    329:
                    330:        /* Newer LANCE chips have a reset register */
                    331:        if (sc->sc_hwreset)
                    332:                (*sc->sc_hwreset)(sc);
                    333:
                    334:        /* Set the correct byte swapping mode, etc. */
                    335:        (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
                    336:
                    337:        /* Set up LANCE init block. */
                    338:        (*sc->sc_meminit)(sc);
                    339:
                    340:        /* Give LANCE the physical address of its init block. */
                    341:        a = sc->sc_addr + LE_INITADDR(sc);
                    342:        (*sc->sc_wrcsr)(sc, LE_CSR1, a);
                    343:        (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
                    344:
                    345:        /* Try to initialize the LANCE. */
                    346:        DELAY(100);
                    347:        (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
                    348:
                    349:        /* Wait for initialization to finish. */
                    350:        for (timo = 100000; timo; timo--)
                    351:                if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
                    352:                        break;
                    353:
                    354:        if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
                    355:                /* Start the LANCE. */
                    356:                (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
                    357:                    LE_C0_IDON);
                    358:                ifp->if_flags |= IFF_RUNNING;
                    359:                ifp->if_flags &= ~IFF_OACTIVE;
                    360:                ifp->if_timer = 0;
                    361:                (*sc->sc_start)(ifp);
                    362:        } else
                    363:                printf("%s: controller failed to initialize\n",
                    364:                        sc->sc_dev.dv_xname);
                    365:        if (sc->sc_hwinit)
                    366:                (*sc->sc_hwinit)(sc);
                    367: }
                    368:
                    369: /*
                    370:  * Routine to copy from mbuf chain to transmit buffer in
                    371:  * network buffer memory.
                    372:  */
                    373: int
                    374: lance_put(sc, boff, m)
                    375:        struct lance_softc *sc;
                    376:        int boff;
                    377:        register struct mbuf *m;
                    378: {
                    379:        register struct mbuf *n;
                    380:        register int len, tlen = 0;
                    381:
                    382:        for (; m; m = n) {
                    383:                len = m->m_len;
                    384:                if (len == 0) {
                    385:                        MFREE(m, n);
                    386:                        continue;
                    387:                }
                    388:                (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
                    389:                boff += len;
                    390:                tlen += len;
                    391:                MFREE(m, n);
                    392:        }
                    393:        if (tlen < LEMINSIZE) {
                    394:                (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
                    395:                tlen = LEMINSIZE;
                    396:        }
                    397:        return (tlen);
                    398: }
                    399:
                    400: /*
                    401:  * Pull data off an interface.
                    402:  * Len is length of data, with local net header stripped.
                    403:  * We copy the data into mbufs.  When full cluster sized units are present
                    404:  * we copy into clusters.
                    405:  */
                    406: integrate struct mbuf *
                    407: lance_get(sc, boff, totlen)
                    408:        struct lance_softc *sc;
                    409:        int boff, totlen;
                    410: {
1.5       mycroft   411:        struct mbuf *m, *m0, *newm;
1.1       drochner  412:        int len;
                    413:
1.5       mycroft   414:        MGETHDR(m0, M_DONTWAIT, MT_DATA);
                    415:        if (m0 == 0)
1.1       drochner  416:                return (0);
1.5       mycroft   417:        m0->m_pkthdr.rcvif = ifp;
                    418:        m0->m_pkthdr.len = totlen;
1.1       drochner  419:        len = MHLEN;
1.5       mycroft   420:        m = m0;
1.1       drochner  421:
                    422:        while (totlen > 0) {
                    423:                if (totlen >= MINCLSIZE) {
                    424:                        MCLGET(m, M_DONTWAIT);
1.5       mycroft   425:                        if ((m->m_flags & M_EXT) == 0)
                    426:                                goto bad;
1.1       drochner  427:                        len = MCLBYTES;
                    428:                }
1.5       mycroft   429:
                    430:                if (m == m0) {
                    431:                        caddr_t newdata = (caddr_t)
                    432:                            ALIGN(m->m_data + sizeof(struct ether_header)) -
                    433:                            sizeof(struct ether_header);
                    434:                        len -= newdata - m->m_data;
                    435:                        m->m_data = newdata;
1.1       drochner  436:                }
1.5       mycroft   437:
1.1       drochner  438:                m->m_len = len = min(totlen, len);
                    439:                (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
                    440:                boff += len;
1.5       mycroft   441:
1.1       drochner  442:                totlen -= len;
1.5       mycroft   443:                if (totlen > 0) {
                    444:                        MGET(newm, M_DONTWAIT, MT_DATA);
                    445:                        if (newm == 0)
                    446:                                goto bad;
                    447:                        len = MLEN;
                    448:                        m = m->m_next = newm;
                    449:                }
1.1       drochner  450:        }
                    451:
1.5       mycroft   452:        return (m0);
                    453:
                    454: bad:
                    455:        m_freem(m0);
                    456:        return (0);
1.1       drochner  457: }
                    458:
                    459: /*
                    460:  * Pass a packet to the higher levels.
                    461:  */
                    462: void
                    463: lance_read(sc, boff, len)
                    464:        register struct lance_softc *sc;
                    465:        int boff, len;
                    466: {
                    467:        struct mbuf *m;
                    468:        struct ether_header *eh;
                    469:
                    470:        if (len <= sizeof(struct ether_header) ||
                    471:            len > ETHERMTU + sizeof(struct ether_header)) {
                    472: #ifdef LEDEBUG
                    473:                printf("%s: invalid packet size %d; dropping\n",
                    474:                    sc->sc_dev.dv_xname, len);
                    475: #endif
                    476:                ifp->if_ierrors++;
                    477:                return;
                    478:        }
                    479:
                    480:        /* Pull packet off interface. */
                    481:        m = lance_get(sc, boff, len);
                    482:        if (m == 0) {
                    483:                ifp->if_ierrors++;
                    484:                return;
                    485:        }
                    486:
                    487:        ifp->if_ipackets++;
                    488:
                    489:        /* We assume that the header fit entirely in one mbuf. */
                    490:        eh = mtod(m, struct ether_header *);
                    491:
                    492: #if NBPFILTER > 0
                    493:        /*
                    494:         * Check if there's a BPF listener on this interface.
                    495:         * If so, hand off the raw packet to BPF.
                    496:         */
                    497:        if (ifp->if_bpf) {
                    498:                bpf_mtap(ifp->if_bpf, m);
                    499:
                    500: #ifndef LANCE_REVC_BUG
                    501:                /*
                    502:                 * Note that the interface cannot be in promiscuous mode if
                    503:                 * there are no BPF listeners.  And if we are in promiscuous
                    504:                 * mode, we have to check if this packet is really ours.
                    505:                 */
                    506:                if ((ifp->if_flags & IFF_PROMISC) != 0 &&
                    507:                    (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
                    508:                    ETHER_CMP(eh->ether_dhost, sc->sc_enaddr)) {
                    509:                        m_freem(m);
                    510:                        return;
                    511:                }
                    512: #endif
                    513:        }
                    514: #endif
                    515:
                    516: #ifdef LANCE_REVC_BUG
                    517:        /*
                    518:         * The old LANCE (Rev. C) chips have a bug which causes
                    519:         * garbage to be inserted in front of the received packet.
                    520:         * The work-around is to ignore packets with an invalid
                    521:         * destination address (garbage will usually not match).
                    522:         * Of course, this precludes multicast support...
                    523:         */
                    524:        if (ETHER_CMP(eh->ether_dhost, sc->sc_enaddr) &&
                    525:            ETHER_CMP(eh->ether_dhost, bcast_enaddr)) {
                    526:                m_freem(m);
                    527:                return;
                    528:        }
                    529: #endif
                    530:
                    531:        /* Pass the packet up, with the ether header sort-of removed. */
                    532:        m_adj(m, sizeof(struct ether_header));
                    533:        ether_input(ifp, eh, m);
                    534: }
                    535:
                    536: #undef ifp
                    537:
                    538: void
                    539: lance_watchdog(ifp)
                    540:        struct ifnet *ifp;
                    541: {
                    542:        struct lance_softc *sc = ifp->if_softc;
                    543:
                    544:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    545:        ++ifp->if_oerrors;
                    546:
                    547:        lance_reset(sc);
                    548: }
                    549:
                    550: int
                    551: lance_mediachange(ifp)
                    552:        struct ifnet *ifp;
                    553: {
                    554:        struct lance_softc *sc = ifp->if_softc;
                    555:
                    556:        if (sc->sc_mediachange)
                    557:                return ((*sc->sc_mediachange)(sc));
1.7.2.1 ! perry     558:        return (0);
1.1       drochner  559: }
                    560:
                    561: void
                    562: lance_mediastatus(ifp, ifmr)
                    563:        struct ifnet *ifp;
                    564:        struct ifmediareq *ifmr;
                    565: {
                    566:        struct lance_softc *sc = ifp->if_softc;
                    567:
                    568:        if ((ifp->if_flags & IFF_UP) == 0)
                    569:                return;
                    570:
                    571:        ifmr->ifm_status = IFM_AVALID;
                    572:        if (sc->sc_havecarrier)
                    573:                ifmr->ifm_status |= IFM_ACTIVE;
                    574:
                    575:        if (sc->sc_mediastatus)
                    576:                (*sc->sc_mediastatus)(sc, ifmr);
                    577: }
                    578:
                    579: /*
                    580:  * Process an ioctl request.
                    581:  */
                    582: int
                    583: lance_ioctl(ifp, cmd, data)
                    584:        register struct ifnet *ifp;
                    585:        u_long cmd;
                    586:        caddr_t data;
                    587: {
                    588:        register struct lance_softc *sc = ifp->if_softc;
                    589:        struct ifaddr *ifa = (struct ifaddr *)data;
                    590:        struct ifreq *ifr = (struct ifreq *)data;
                    591:        int s, error = 0;
                    592:
1.2       mycroft   593:        s = splnet();
1.1       drochner  594:
                    595:        switch (cmd) {
                    596:
                    597:        case SIOCSIFADDR:
                    598:                ifp->if_flags |= IFF_UP;
                    599:
                    600:                switch (ifa->ifa_addr->sa_family) {
                    601: #ifdef INET
                    602:                case AF_INET:
                    603:                        lance_init(sc);
                    604:                        arp_ifinit(ifp, ifa);
                    605:                        break;
                    606: #endif
                    607: #ifdef NS
                    608:                case AF_NS:
                    609:                    {
                    610:                        register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
                    611:
                    612:                        if (ns_nullhost(*ina))
                    613:                                ina->x_host =
                    614:                                    *(union ns_host *)LLADDR(ifp->if_sadl);
                    615:                        else {
                    616:                                bcopy(ina->x_host.c_host,
                    617:                                    LLADDR(ifp->if_sadl),
                    618:                                    sizeof(sc->sc_enaddr));
                    619:                        }
                    620:                        /* Set new address. */
                    621:                        lance_init(sc);
                    622:                        break;
                    623:                    }
                    624: #endif
                    625:                default:
                    626:                        lance_init(sc);
                    627:                        break;
                    628:                }
                    629:                break;
                    630:
                    631: #if defined(CCITT) && defined(LLC)
                    632:        case SIOCSIFCONF_X25:
                    633:                ifp->if_flags |= IFF_UP;
                    634:                ifa->ifa_rtrequest = cons_rtrequest; /* XXX */
                    635:                error = x25_llcglue(PRC_IFUP, ifa->ifa_addr);
                    636:                if (error == 0)
                    637:                        lance_init(sc);
                    638:                break;
                    639: #endif /* CCITT && LLC */
                    640:
                    641:        case SIOCSIFFLAGS:
                    642:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    643:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    644:                        /*
                    645:                         * If interface is marked down and it is running, then
                    646:                         * stop it.
                    647:                         */
                    648:                        lance_stop(sc);
                    649:                        ifp->if_flags &= ~IFF_RUNNING;
                    650:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    651:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                    652:                        /*
                    653:                         * If interface is marked up and it is stopped, then
                    654:                         * start it.
                    655:                         */
                    656:                        lance_init(sc);
1.6       thorpej   657:                } else if ((ifp->if_flags & IFF_UP) != 0) {
1.1       drochner  658:                        /*
                    659:                         * Reset the interface to pick up changes in any other
                    660:                         * flags that affect hardware registers.
                    661:                         */
                    662:                        /*lance_stop(sc);*/
                    663:                        lance_init(sc);
                    664:                }
                    665: #ifdef LEDEBUG
                    666:                if (ifp->if_flags & IFF_DEBUG)
                    667:                        sc->sc_debug = 1;
                    668:                else
                    669:                        sc->sc_debug = 0;
                    670: #endif
                    671:                break;
                    672:
                    673:        case SIOCADDMULTI:
                    674:        case SIOCDELMULTI:
                    675:                error = (cmd == SIOCADDMULTI) ?
                    676:                    ether_addmulti(ifr, &sc->sc_ethercom) :
                    677:                    ether_delmulti(ifr, &sc->sc_ethercom);
                    678:
                    679:                if (error == ENETRESET) {
                    680:                        /*
                    681:                         * Multicast list has changed; set the hardware filter
                    682:                         * accordingly.
                    683:                         */
                    684:                        lance_reset(sc);
                    685:                        error = 0;
                    686:                }
                    687:                break;
                    688:
                    689:        case SIOCGIFMEDIA:
                    690:        case SIOCSIFMEDIA:
                    691:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                    692:                break;
                    693:
                    694:        default:
                    695:                error = EINVAL;
                    696:                break;
                    697:        }
                    698:
                    699:        splx(s);
                    700:        return (error);
                    701: }
                    702:
                    703: hide void
                    704: lance_shutdown(arg)
                    705:        void *arg;
                    706: {
                    707:
                    708:        lance_stop((struct lance_softc *)arg);
                    709: }
                    710:
                    711: /*
                    712:  * Set up the logical address filter.
                    713:  */
                    714: void
                    715: lance_setladrf(ac, af)
                    716:        struct ethercom *ac;
                    717:        u_int16_t *af;
                    718: {
                    719:        struct ifnet *ifp = &ac->ec_if;
                    720:        struct ether_multi *enm;
                    721:        register u_char *cp;
                    722:        register u_int32_t crc;
                    723:        static const u_int32_t crctab[] = {
                    724:                0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
                    725:                0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
                    726:                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
                    727:                0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
                    728:        };
                    729:        register int len;
                    730:        struct ether_multistep step;
                    731:
                    732:        /*
                    733:         * Set up multicast address filter by passing all multicast addresses
                    734:         * through a crc generator, and then using the high order 6 bits as an
                    735:         * index into the 64 bit logical address filter.  The high order bit
                    736:         * selects the word, while the rest of the bits select the bit within
                    737:         * the word.
                    738:         */
                    739:
                    740:        if (ifp->if_flags & IFF_PROMISC)
                    741:                goto allmulti;
                    742:
                    743:        af[0] = af[1] = af[2] = af[3] = 0x0000;
                    744:        ETHER_FIRST_MULTI(step, ac, enm);
                    745:        while (enm != NULL) {
                    746:                if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
                    747:                        /*
                    748:                         * We must listen to a range of multicast addresses.
                    749:                         * For now, just accept all multicasts, rather than
                    750:                         * trying to set only those filter bits needed to match
                    751:                         * the range.  (At this time, the only use of address
                    752:                         * ranges is for IP multicast routing, for which the
                    753:                         * range is big enough to require all bits set.)
                    754:                         */
                    755:                        goto allmulti;
                    756:                }
                    757:
                    758:                cp = enm->enm_addrlo;
                    759:                crc = 0xffffffff;
                    760:                for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
                    761:                        crc ^= *cp++;
                    762:                        crc = (crc >> 4) ^ crctab[crc & 0xf];
                    763:                        crc = (crc >> 4) ^ crctab[crc & 0xf];
                    764:                }
                    765:                /* Just want the 6 most significant bits. */
                    766:                crc >>= 26;
                    767:
                    768:                /* Set the corresponding bit in the filter. */
                    769:                af[crc >> 4] |= 1 << (crc & 0xf);
                    770:
                    771:                ETHER_NEXT_MULTI(step, enm);
                    772:        }
                    773:        ifp->if_flags &= ~IFF_ALLMULTI;
                    774:        return;
                    775:
                    776: allmulti:
                    777:        ifp->if_flags |= IFF_ALLMULTI;
                    778:        af[0] = af[1] = af[2] = af[3] = 0xffff;
                    779: }
                    780:
                    781: /*
                    782:  * Routines for accessing the transmit and receive buffers.
                    783:  * The various CPU and adapter configurations supported by this
                    784:  * driver require three different access methods for buffers
                    785:  * and descriptors:
                    786:  *     (1) contig (contiguous data; no padding),
                    787:  *     (2) gap2 (two bytes of data followed by two bytes of padding),
                    788:  *     (3) gap16 (16 bytes of data followed by 16 bytes of padding).
                    789:  */
                    790:
                    791: /*
                    792:  * contig: contiguous data with no padding.
                    793:  *
                    794:  * Buffers may have any alignment.
                    795:  */
                    796:
                    797: void
                    798: lance_copytobuf_contig(sc, from, boff, len)
                    799:        struct lance_softc *sc;
                    800:        void *from;
                    801:        int boff, len;
                    802: {
                    803:        volatile caddr_t buf = sc->sc_mem;
                    804:
                    805:        /*
                    806:         * Just call bcopy() to do the work.
                    807:         */
                    808:        bcopy(from, buf + boff, len);
                    809: }
                    810:
                    811: void
                    812: lance_copyfrombuf_contig(sc, to, boff, len)
                    813:        struct lance_softc *sc;
                    814:        void *to;
                    815:        int boff, len;
                    816: {
                    817:        volatile caddr_t buf = sc->sc_mem;
                    818:
                    819:        /*
                    820:         * Just call bcopy() to do the work.
                    821:         */
                    822:        bcopy(buf + boff, to, len);
                    823: }
                    824:
                    825: void
                    826: lance_zerobuf_contig(sc, boff, len)
                    827:        struct lance_softc *sc;
                    828:        int boff, len;
                    829: {
                    830:        volatile caddr_t buf = sc->sc_mem;
                    831:
                    832:        /*
                    833:         * Just let bzero() do the work
                    834:         */
                    835:        bzero(buf + boff, len);
                    836: }
                    837:
                    838: #if 0
                    839: /*
                    840:  * Examples only; duplicate these and tweak (if necessary) in
                    841:  * machine-specific front-ends.
                    842:  */
                    843:
                    844: /*
                    845:  * gap2: two bytes of data followed by two bytes of pad.
                    846:  *
                    847:  * Buffers must be 4-byte aligned.  The code doesn't worry about
                    848:  * doing an extra byte.
                    849:  */
                    850:
                    851: void
                    852: lance_copytobuf_gap2(sc, fromv, boff, len)
                    853:        struct lance_softc *sc;
                    854:        void *fromv;
                    855:        int boff;
                    856:        register int len;
                    857: {
                    858:        volatile caddr_t buf = sc->sc_mem;
                    859:        register caddr_t from = fromv;
                    860:        register volatile u_int16_t *bptr;
                    861:
                    862:        if (boff & 0x1) {
                    863:                /* handle unaligned first byte */
                    864:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                    865:                *bptr = (*from++ << 8) | (*bptr & 0xff);
                    866:                bptr += 2;
                    867:                len--;
                    868:        } else
                    869:                bptr = ((volatile u_int16_t *)buf) + boff;
                    870:        while (len > 1) {
                    871:                *bptr = (from[1] << 8) | (from[0] & 0xff);
                    872:                bptr += 2;
                    873:                from += 2;
                    874:                len -= 2;
                    875:        }
                    876:        if (len == 1)
                    877:                *bptr = (u_int16_t)*from;
                    878: }
                    879:
                    880: void
                    881: lance_copyfrombuf_gap2(sc, tov, boff, len)
                    882:        struct lance_softc *sc;
                    883:        void *tov;
                    884:        int boff, len;
                    885: {
                    886:        volatile caddr_t buf = sc->sc_mem;
                    887:        register caddr_t to = tov;
                    888:        register volatile u_int16_t *bptr;
                    889:        register u_int16_t tmp;
                    890:
                    891:        if (boff & 0x1) {
                    892:                /* handle unaligned first byte */
                    893:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                    894:                *to++ = (*bptr >> 8) & 0xff;
                    895:                bptr += 2;
                    896:                len--;
                    897:        } else
                    898:                bptr = ((volatile u_int16_t *)buf) + boff;
                    899:        while (len > 1) {
                    900:                tmp = *bptr;
                    901:                *to++ = tmp & 0xff;
                    902:                *to++ = (tmp >> 8) & 0xff;
                    903:                bptr += 2;
                    904:                len -= 2;
                    905:        }
                    906:        if (len == 1)
                    907:                *to = *bptr & 0xff;
                    908: }
                    909:
                    910: void
                    911: lance_zerobuf_gap2(sc, boff, len)
                    912:        struct lance_softc *sc;
                    913:        int boff, len;
                    914: {
                    915:        volatile caddr_t buf = sc->sc_mem;
                    916:        register volatile u_int16_t *bptr;
                    917:
                    918:        if ((unsigned)boff & 0x1) {
                    919:                bptr = ((volatile u_int16_t *)buf) + (boff - 1);
                    920:                *bptr &= 0xff;
                    921:                bptr += 2;
                    922:                len--;
                    923:        } else
                    924:                bptr = ((volatile u_int16_t *)buf) + boff;
                    925:        while (len > 0) {
                    926:                *bptr = 0;
                    927:                bptr += 2;
                    928:                len -= 2;
                    929:        }
                    930: }
                    931:
                    932: /*
                    933:  * gap16: 16 bytes of data followed by 16 bytes of pad.
                    934:  *
                    935:  * Buffers must be 32-byte aligned.
                    936:  */
                    937:
                    938: void
                    939: lance_copytobuf_gap16(sc, fromv, boff, len)
                    940:        struct lance_softc *sc;
                    941:        void *fromv;
                    942:        int boff;
                    943:        register int len;
                    944: {
                    945:        volatile caddr_t buf = sc->sc_mem;
                    946:        register caddr_t from = fromv;
                    947:        register caddr_t bptr;
                    948:        register int xfer;
                    949:
                    950:        bptr = buf + ((boff << 1) & ~0x1f);
                    951:        boff &= 0xf;
                    952:        xfer = min(len, 16 - boff);
                    953:        while (len > 0) {
                    954:                bcopy(from, bptr + boff, xfer);
                    955:                from += xfer;
                    956:                bptr += 32;
                    957:                boff = 0;
                    958:                len -= xfer;
                    959:                xfer = min(len, 16);
                    960:        }
                    961: }
                    962:
                    963: void
                    964: lance_copyfrombuf_gap16(sc, tov, boff, len)
                    965:        struct lance_softc *sc;
                    966:        void *tov;
                    967:        int boff, len;
                    968: {
                    969:        volatile caddr_t buf = sc->sc_mem;
                    970:        register caddr_t to = tov;
                    971:        register caddr_t bptr;
                    972:        register int xfer;
                    973:
                    974:        bptr = buf + ((boff << 1) & ~0x1f);
                    975:        boff &= 0xf;
                    976:        xfer = min(len, 16 - boff);
                    977:        while (len > 0) {
                    978:                bcopy(bptr + boff, to, xfer);
                    979:                to += xfer;
                    980:                bptr += 32;
                    981:                boff = 0;
                    982:                len -= xfer;
                    983:                xfer = min(len, 16);
                    984:        }
                    985: }
                    986:
                    987: void
                    988: lance_zerobuf_gap16(sc, boff, len)
                    989:        struct lance_softc *sc;
                    990:        int boff, len;
                    991: {
                    992:        volatile caddr_t buf = sc->sc_mem;
                    993:        register caddr_t bptr;
                    994:        register int xfer;
                    995:
                    996:        bptr = buf + ((boff << 1) & ~0x1f);
                    997:        boff &= 0xf;
                    998:        xfer = min(len, 16 - boff);
                    999:        while (len > 0) {
                   1000:                bzero(bptr + boff, xfer);
                   1001:                bptr += 32;
                   1002:                boff = 0;
                   1003:                len -= xfer;
                   1004:                xfer = min(len, 16);
                   1005:        }
                   1006: }
                   1007: #endif /* Example only */

CVSweb <webmaster@jp.NetBSD.org>