[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.28.2.5

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

CVSweb <webmaster@jp.NetBSD.org>