[BACK]Return to if_ie.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme68k / dev

Annotation of sys/arch/mvme68k/dev/if_ie.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_ie.c,v 1.35 2006/04/16 00:46:32 pascoe Exp $ */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1999 Steve Murphree, Jr.
        !             5:  * Copyright (c) 1995 Theo de Raadt
        !             6:  * Copyright (c) 1993, 1994, 1995 Charles Hannum.
        !             7:  * Copyright (c) 1992, 1993, University of Vermont and State
        !             8:  *  Agricultural College.
        !             9:  * Copyright (c) 1992, 1993, Garrett A. Wollman.
        !            10:  *
        !            11:  * Portions:
        !            12:  * Copyright (c) 1994, 1995, Rafal K. Boni
        !            13:  * Copyright (c) 1990, 1991, William F. Jolitz
        !            14:  * Copyright (c) 1990, The Regents of the University of California
        !            15:  *
        !            16:  * All rights reserved.
        !            17:  *
        !            18:  * Redistribution and use in source and binary forms, with or without
        !            19:  * modification, are permitted provided that the following conditions
        !            20:  * are met:
        !            21:  * 1. Redistributions of source code must retain the above copyright
        !            22:  *    notice, this list of conditions and the following disclaimer.
        !            23:  * 2. Redistributions in binary form must reproduce the above copyright
        !            24:  *    notice, this list of conditions and the following disclaimer in the
        !            25:  *    documentation and/or other materials provided with the distribution.
        !            26:  * 3. All advertising materials mentioning features or use of this software
        !            27:  *    must display the following acknowledgement:
        !            28:  *     This product includes software developed by Charles Hannum, by the
        !            29:  *     University of Vermont and State Agricultural College and Garrett A.
        !            30:  *     Wollman, by William F. Jolitz, and by the University of California,
        !            31:  *     Berkeley, Lawrence Berkeley Laboratory, and its contributors.
        !            32:  * 4. Neither the names of the Universities nor the names of the authors
        !            33:  *    may be used to endorse or promote products derived from this software
        !            34:  *    without specific prior written permission.
        !            35:  *
        !            36:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            37:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            38:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            39:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
        !            40:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            41:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            42:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            44:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            45:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            46:  * SUCH DAMAGE.
        !            47:  */
        !            48:
        !            49: /*
        !            50:  * Intel 82596 Ethernet chip
        !            51:  * Register, bit, and structure definitions.
        !            52:  *
        !            53:  * Original StarLAN driver written by Garrett Wollman with reference to the
        !            54:  * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
        !            55:  *
        !            56:  * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
        !            57:  *
        !            58:  * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
        !            59:  *
        !            60:  * Majorly cleaned up and 3C507 code merged by Charles Hannum.
        !            61:  *
        !            62:  * Converted to SUN ie driver by Charles D. Cranor,
        !            63:  *             October 1994, January 1995.
        !            64:  * This sun version based on i386 version 1.30.
        !            65:  */
        !            66:
        !            67: extern void *etherbuf;
        !            68: extern int etherlen;
        !            69:
        !            70: /*
        !            71: Mode of operation:
        !            72:
        !            73:    We run the 82596 in a standard Ethernet mode.  We keep NFRAMES
        !            74:    received frame descriptors around for the receiver to use, and
        !            75:    NRXBUF associated receive buffer descriptors, both in a circular
        !            76:    list.  Whenever a frame is received, we rotate both lists as
        !            77:    necessary.  (The 596 treats both lists as a simple queue.)  We also
        !            78:    keep a transmit command around so that packets can be sent off
        !            79:    quickly.
        !            80:
        !            81:    We configure the adapter in AL-LOC = 1 mode, which means that the
        !            82:    Ethernet/802.3 MAC header is placed at the beginning of the receive
        !            83:    buffer rather than being split off into various fields in the RFD.
        !            84:    This also means that we must include this header in the transmit
        !            85:    buffer as well.
        !            86:
        !            87:    By convention, all transmit commands, and only transmit commands,
        !            88:    shall have the I (IE_CMD_INTR) bit set in the command.  This way,
        !            89:    when an interrupt arrives at ieintr(), it is immediately possible
        !            90:    to tell what precisely caused it.  ANY OTHER command-sending
        !            91:    routines should run at splnet(), and should post an acknowledgement
        !            92:    to every interrupt they generate.
        !            93:
        !            94: */
        !            95:
        !            96: #include "bpfilter.h"
        !            97:
        !            98: #include <sys/param.h>
        !            99: #include <sys/systm.h>
        !           100: #include <sys/mbuf.h>
        !           101: #include <sys/buf.h>
        !           102: #include <sys/protosw.h>
        !           103: #include <sys/socket.h>
        !           104: #include <sys/ioctl.h>
        !           105: #include <sys/errno.h>
        !           106: #include <sys/syslog.h>
        !           107: #include <sys/device.h>
        !           108:
        !           109: #include <net/if.h>
        !           110: #include <net/if_types.h>
        !           111: #include <net/if_dl.h>
        !           112: #include <net/netisr.h>
        !           113: #include <net/route.h>
        !           114:
        !           115: #if NBPFILTER > 0
        !           116: #include <net/bpf.h>
        !           117: #include <net/bpfdesc.h>
        !           118: #endif
        !           119:
        !           120: #ifdef INET
        !           121: #include <netinet/in.h>
        !           122: #include <netinet/in_systm.h>
        !           123: #include <netinet/in_var.h>
        !           124: #include <netinet/ip.h>
        !           125: #include <netinet/if_ether.h>
        !           126: #endif
        !           127:
        !           128: #include <uvm/uvm_extern.h>
        !           129:
        !           130: #include <machine/autoconf.h>
        !           131: #include <machine/cpu.h>
        !           132: #include <machine/pmap.h>
        !           133:
        !           134: #include "mc.h"
        !           135: #include "pcctwo.h"
        !           136:
        !           137: #if NMC > 0
        !           138: #include <mvme68k/dev/mcreg.h>
        !           139: #endif
        !           140: #if NPCCTWO > 0
        !           141: #include <mvme68k/dev/pcctworeg.h>
        !           142: #endif
        !           143:
        !           144: #include <mvme68k/dev/if_ie.h>
        !           145: #include <mvme68k/dev/i82596.h>
        !           146:
        !           147: static struct mbuf *last_not_for_us;
        !           148: struct vm_map *ie_map; /* for obio */
        !           149:
        !           150: #define        IED_RINT        0x01
        !           151: #define        IED_TINT        0x02
        !           152: #define        IED_RNR         0x04
        !           153: #define        IED_CNA         0x08
        !           154: #define        IED_READFRAME   0x10
        !           155: #define        IED_ALL         0x1f
        !           156:
        !           157: #define        ETHER_MIN_LEN   64
        !           158: #define        ETHER_MAX_LEN   1518
        !           159: #define        ETHER_ADDR_LEN  6
        !           160:
        !           161: #define B_PER_F         3               /* recv buffers per frame */
        !           162: #define MXFRAMES        300             /* max number of recv frames */
        !           163: #define        MXRXBUF         (MXFRAMES*B_PER_F) /* number of buffers to allocate */
        !           164: #define        IE_RBUF_SIZE    256             /* size of each receive buffer;
        !           165:                                                MUST BE POWER OF TWO */
        !           166: #define        NTXBUF          2               /* number of transmit commands */
        !           167: #define        IE_TBUF_SIZE    ETHER_MAX_LEN   /* length of transmit buffer */
        !           168:
        !           169: struct ie_softc {
        !           170:        struct device sc_dev;   /* device structure */
        !           171:        struct intrhand sc_ih, sc_failih;  /* interrupt info */
        !           172:        char    sc_failintrname[16 + 4];
        !           173:
        !           174:        caddr_t sc_iobase;      /* KVA of base of 24 bit addr space */
        !           175:        caddr_t sc_maddr;       /* KVA of base of chip's RAM (16bit addr sp.)*/
        !           176:        u_int sc_msize;         /* how much RAM we have/use */
        !           177:        vaddr_t sc_reg;         /* KVA of car's register */
        !           178:        int sc_bustype;
        !           179:
        !           180:        struct arpcom sc_arpcom;/* system arpcom structure */
        !           181:
        !           182:        void (*reset_596)(void *);      /* card dependent reset function */
        !           183:        void (*chan_attn)(void *);      /* card dependent attn function */
        !           184:        void (*run_596)(void *);        /* card dependent "go on-line" func */
        !           185:        void (*memcopy)(const void *, void *, size_t);
        !           186:                                /* card dependent memory copy function */
        !           187:         void (*memzero)(void *, size_t);
        !           188:                                /* card dependent memory zero function */
        !           189:        int want_mcsetup;       /* mcsetup flag */
        !           190:        int promisc;            /* are we in promisc mode? */
        !           191:
        !           192:        /*
        !           193:         * pointers to the 3 major control structures
        !           194:         */
        !           195:
        !           196:        volatile struct ie_sys_conf_ptr *scp;
        !           197:        volatile struct ie_int_sys_conf_ptr *iscp;
        !           198:        volatile struct ie_sys_ctl_block *scb;
        !           199:
        !           200:        /*
        !           201:         * pointer and size of a block of KVA where the buffers
        !           202:         * are to be allocated from
        !           203:         */
        !           204:
        !           205:        caddr_t buf_area;
        !           206:        int buf_area_sz;
        !           207:
        !           208:        /*
        !           209:         * the actual buffers (recv and xmit)
        !           210:         */
        !           211:
        !           212:        volatile struct ie_recv_frame_desc *rframes[MXFRAMES];
        !           213:        volatile struct ie_recv_buf_desc *rbuffs[MXRXBUF];
        !           214:        volatile char *cbuffs[MXRXBUF];
        !           215:         int rfhead, rftail, rbhead, rbtail;
        !           216:
        !           217:        volatile struct ie_xmit_cmd *xmit_cmds[NTXBUF];
        !           218:        volatile struct ie_xmit_buf *xmit_buffs[NTXBUF];
        !           219:        u_char *xmit_cbuffs[NTXBUF];
        !           220:        int xmit_busy;
        !           221:        int xmit_free;
        !           222:        int xchead, xctail;
        !           223:
        !           224:        struct ie_en_addr mcast_addrs[MAXMCAST + 1];
        !           225:        int mcast_count;
        !           226:
        !           227:        int nframes;      /* number of frames in use */
        !           228:        int nrxbuf;       /* number of recv buffs in use */
        !           229:
        !           230: #ifdef IEDEBUG
        !           231:        int sc_debug;
        !           232: #endif
        !           233: };
        !           234:
        !           235: void ie_obreset(void *);
        !           236: void ie_obattend(void *);
        !           237: void ie_obrun(void *);
        !           238:
        !           239: void iewatchdog(struct ifnet *);
        !           240: int ieintr(void *);
        !           241: int iefailintr(void *);
        !           242: int ieinit(struct ie_softc *);
        !           243: int ieioctl(struct ifnet *, u_long, caddr_t);
        !           244: void iestart(struct ifnet *);
        !           245: void iereset(struct ie_softc *);
        !           246: void ie_readframe(struct ie_softc *, int);
        !           247: void ie_drop_packet_buffer(struct ie_softc *);
        !           248: int command_and_wait(struct ie_softc *, int,
        !           249:     void volatile *, int);
        !           250: void ierint(struct ie_softc *);
        !           251: void ietint(struct ie_softc *);
        !           252: void setup_bufs(struct ie_softc *);
        !           253: int mc_setup(struct ie_softc *, void *);
        !           254: void mc_reset(struct ie_softc *);
        !           255:
        !           256: void ie_setup_config(volatile struct ie_config_cmd *, int, int);
        !           257: void ie_ack(struct ie_softc *, u_int);
        !           258: int ether_equal(u_char *, u_char *);
        !           259: int check_eh(struct ie_softc *, struct ether_header *, int *);
        !           260: int ie_buflen(struct ie_softc *, int);
        !           261: int ie_packet_len(struct ie_softc *);
        !           262: void iexmit(struct ie_softc *);
        !           263: int ieget(struct ie_softc *, struct mbuf **, struct ether_header *, int *);
        !           264: int ie_setupram(struct ie_softc *);
        !           265: void run_tdr(struct ie_softc *, struct ie_tdr_cmd *);
        !           266: void iestop(struct ie_softc *);
        !           267:
        !           268: #ifdef IEDEBUG
        !           269: void print_rbd(volatile struct ie_recv_buf_desc *);
        !           270:
        !           271: int in_ierint = 0;
        !           272: int in_ietint = 0;
        !           273: #endif
        !           274:
        !           275: int iematch(struct device *, void *, void *);
        !           276: void ieattach(struct device *, struct device *, void *);
        !           277:
        !           278: struct cfattach ie_ca = {
        !           279:        sizeof(struct ie_softc), iematch, ieattach
        !           280: };
        !           281:
        !           282: struct cfdriver ie_cd = {
        !           283:        NULL, "ie", DV_IFNET
        !           284: };
        !           285:
        !           286: /*
        !           287:  * address generation macros
        !           288:  */
        !           289: /* Make 32 bit value from swapped data (err counters access) */
        !           290: #define MK_32(ptr)     ((((u_int)(ptr) >> 16) & 0xffff) | ((u_int)(ptr) << 16))
        !           291:
        !           292: #define MKADR_32(ptr)  \
        !           293:                        ((caddr_t)((((u_int)(ptr) >> 16) & 0xffff) | \
        !           294:                                (((u_int)(ptr) << 16)) + UNCACHED_MEMORY_ADDR))
        !           295:
        !           296: /* *NOTE* The next macros also converts to physical address! */
        !           297: #define        ASWAP(ptr)      ((((u_int)(ptr) >> 16) & 0x1fff) | ((u_int)(ptr) << 16))
        !           298:
        !           299: #define SWT_32(to, from) { \
        !           300:                        u_int *t = (u_int *)&to; \
        !           301:                        *t = ((((u_int)from >> 16) & 0x1fff) | ((u_int)from << 16)); \
        !           302:                         }
        !           303: /*
        !           304:  * Here are a few useful functions.  We could have done these as macros, but
        !           305:  * since we have the inline facility, it makes sense to use that instead.
        !           306:  */
        !           307: void
        !           308: ie_setup_config(cmd, promiscuous, manchester)
        !           309:        volatile struct ie_config_cmd *cmd;
        !           310:        int promiscuous, manchester;
        !           311: {
        !           312:
        !           313:        cmd->ie_config_count = 0x0e;
        !           314:        cmd->ie_fifo = 0xc8;
        !           315:        cmd->ie_save_bad = 0x40;
        !           316:        cmd->ie_addr_len = 0x2e;
        !           317:        cmd->ie_priority = 0;
        !           318:        cmd->ie_ifs = 0x60;
        !           319:        cmd->ie_slot_low = 0;
        !           320:        cmd->ie_slot_high = 0xf2;
        !           321:        cmd->ie_promisc = !!promiscuous | manchester << 2;
        !           322:        cmd->ie_crs_cdt = 0;
        !           323:        cmd->ie_min_len = 64;
        !           324:        cmd->ie_junk = 0xff;
        !           325:        cmd->ie_dplx = 0x00;
        !           326:        cmd->ie_miabf = 0x3f;
        !           327: }
        !           328:
        !           329: void
        !           330: ie_ack(sc, mask)
        !           331:        struct ie_softc *sc;
        !           332:        u_int mask;
        !           333: {
        !           334:        volatile struct ie_sys_ctl_block *scb = sc->scb;
        !           335:
        !           336:        command_and_wait(sc, scb->ie_status & mask, 0, 0);
        !           337: }
        !           338:
        !           339: int
        !           340: iematch(parent, vcf, args)
        !           341:        struct device *parent;
        !           342:        void    *vcf, *args;
        !           343: {
        !           344:        struct confargs *ca = args;
        !           345:
        !           346:        return (!badvaddr((vaddr_t)ca->ca_vaddr, 4));
        !           347: }
        !           348:
        !           349: /*
        !           350:  * Deep Magic: reset it, then set SCP address again. Pray.
        !           351:  */
        !           352: void
        !           353: ie_obreset(arg)
        !           354:        void *arg;
        !           355: {
        !           356:        struct ie_softc *sc = (struct ie_softc *)arg;
        !           357:        volatile struct ieob *ieo = (struct ieob *)sc->sc_reg;
        !           358:        volatile int t;
        !           359:        u_long  a;
        !           360:
        !           361:        a = IE_PORT_RESET;
        !           362:        ieo->porthigh = a & 0xffff;
        !           363:        t = 0; t = 1;
        !           364:        ieo->portlow = a >> 16;
        !           365:        delay(1000);
        !           366:
        !           367:        pmap_extract(pmap_kernel(), (vaddr_t)sc->scp, &a);
        !           368:        a |= IE_PORT_NEWSCPADDR;
        !           369:        ieo->porthigh = a & 0xffff;
        !           370:        t = 0; t = 1;
        !           371:        ieo->portlow = a >> 16;
        !           372:        delay(1000);
        !           373: }
        !           374:
        !           375: void
        !           376: ie_obattend(arg)
        !           377:        void *arg;
        !           378: {
        !           379:        struct ie_softc *sc = (struct ie_softc *)arg;
        !           380:        volatile struct ieob *ieo = (struct ieob *)sc->sc_reg;
        !           381:
        !           382:        ieo->attn = 1;
        !           383: }
        !           384:
        !           385: /* ARGSUSED */
        !           386: void
        !           387: ie_obrun(arg)
        !           388:        void *arg;
        !           389: {
        !           390: }
        !           391:
        !           392: /*
        !           393:  * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
        !           394:  */
        !           395: void
        !           396: ieattach(parent, self, aux)
        !           397:        struct device *parent, *self;
        !           398:        void   *aux;
        !           399: {
        !           400:        struct ie_softc *sc = (void *) self;
        !           401:        struct confargs *ca = aux;
        !           402:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           403:        extern void myetheraddr(u_char *);      /* should be elsewhere */
        !           404:        int     pri = ca->ca_ipl;
        !           405:        volatile struct ieob *ieo;
        !           406:        paddr_t pa;
        !           407:
        !           408:        sc->reset_596 = ie_obreset;
        !           409:        sc->chan_attn = ie_obattend;
        !           410:        sc->run_596 = ie_obrun;
        !           411:        sc->memcopy = bcopy;
        !           412:        sc->memzero = bzero;
        !           413:        sc->sc_msize = etherlen;
        !           414:        sc->sc_reg = ca->ca_vaddr;
        !           415:        ieo = (volatile struct ieob *)sc->sc_reg;
        !           416:
        !           417:        /* get the first available etherbuf */
        !           418:        sc->sc_maddr = etherbuf;        /* maddr = vaddr */
        !           419:        if (sc->sc_maddr == NULL) panic("ie: too many ethernet boards");
        !           420:        if (pmap_extract(pmap_kernel(), (vaddr_t)sc->sc_maddr, &pa) == FALSE)
        !           421:                panic("ie: pmap_extract");
        !           422:        sc->sc_iobase = (caddr_t)pa;    /* iobase = paddr (24 bit) */
        !           423:
        !           424:        /*printf("maddrP %x iobaseV %x\n", sc->sc_maddr, sc->sc_iobase);*/
        !           425:
        !           426:        (sc->memzero)(sc->sc_maddr, sc->sc_msize);
        !           427:        sc->iscp = (volatile struct ie_int_sys_conf_ptr *)
        !           428:            sc->sc_maddr; /* @@ location zero */
        !           429:        sc->scb = (volatile struct ie_sys_ctl_block *)
        !           430:            roundup((int)sc->iscp + sizeof(struct ie_int_sys_conf_ptr), 16);
        !           431:        sc->scp = (struct ie_sys_conf_ptr *)
        !           432:            roundup((int)sc->scb + sizeof(struct ie_sys_ctl_block), 16);
        !           433:        /*printf("scpV %x iscpV %x scbV %x\n", sc->scp, sc->iscp, sc->scb);*/
        !           434:
        !           435:        sc->scp->ie_bus_use = 0x44;
        !           436:        pmap_extract(pmap_kernel(), (vaddr_t)sc->iscp, &pa);
        !           437:        SWT_32(sc->scp->ie_iscp_ptr, pa);
        !           438:        /*
        !           439:         * rest of first page is unused (wasted!), rest of ram
        !           440:         * for buffers
        !           441:         */
        !           442:        sc->buf_area = sc->sc_maddr + NBPG;
        !           443:        sc->buf_area_sz = sc->sc_msize - NBPG;
        !           444:        myetheraddr(sc->sc_arpcom.ac_enaddr);
        !           445:
        !           446:        if (ie_setupram(sc) == 0) {
        !           447:                printf(": RAM CONFIG FAILED!\n");
        !           448:                /* XXX should reclaim resources? */
        !           449:                return;
        !           450:        }
        !           451:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           452:        ifp->if_softc = sc;
        !           453:        ifp->if_start = iestart;
        !           454:        ifp->if_ioctl = ieioctl;
        !           455:        ifp->if_watchdog = iewatchdog;
        !           456:        ifp->if_flags =
        !           457:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
        !           458:
        !           459:        /* Attach the interface. */
        !           460:        if_attach(ifp);
        !           461:        ether_ifattach(ifp);
        !           462:
        !           463:        printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           464:
        !           465:        sc->sc_bustype = ca->ca_bustype;
        !           466:
        !           467:        sc->sc_ih.ih_fn = ieintr;
        !           468:        sc->sc_ih.ih_arg = sc;
        !           469:        sc->sc_ih.ih_ipl = pri;
        !           470:        sc->sc_failih.ih_fn = iefailintr;
        !           471:        sc->sc_failih.ih_arg = sc;
        !           472:        sc->sc_failih.ih_ipl = pri;
        !           473:
        !           474:        snprintf(sc->sc_failintrname, sizeof sc->sc_failintrname, "%s_err",                 self->dv_xname);
        !           475:
        !           476:        switch (sc->sc_bustype) {
        !           477: #if NMC > 0
        !           478:        case BUS_MC:
        !           479:                mcintr_establish(MCV_IE, &sc->sc_ih, self->dv_xname);
        !           480:                sys_mc->mc_ieirq = pri | MC_SC_SNOOP | MC_IRQ_IEN |
        !           481:                    MC_IRQ_ICLR;
        !           482:                mcintr_establish(MCV_IEFAIL, &sc->sc_failih,
        !           483:                    sc->sc_failintrname);
        !           484:                sys_mc->mc_iefailirq = pri | MC_IRQ_IEN | MC_IRQ_ICLR;
        !           485:                break;
        !           486: #endif
        !           487: #if NPCCTWO > 0
        !           488:        case BUS_PCCTWO:
        !           489:                pcctwointr_establish(PCC2V_IE, &sc->sc_ih, self->dv_xname);
        !           490:                switch (cputyp) {
        !           491: #ifdef MVME172
        !           492:                case CPU_172:
        !           493: #endif
        !           494: #ifdef MVME177
        !           495:                case CPU_177:
        !           496: #endif
        !           497: #if defined(MVME172) || defined(MVME177)
        !           498:                        /* no snooping on 68060 */
        !           499:                        sys_pcc2->pcc2_ieirq = pri | PCC2_SC_INHIBIT |
        !           500:                            PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
        !           501:                        break;
        !           502: #endif
        !           503:                default:
        !           504:                        sys_pcc2->pcc2_ieirq = pri | PCC2_SC_SNOOP |
        !           505:                            PCC2_IRQ_IEN | PCC2_IRQ_ICLR;
        !           506:                }
        !           507:                pcctwointr_establish(PCC2V_IEFAIL, &sc->sc_failih,
        !           508:                    sc->sc_failintrname);
        !           509:                sys_pcc2->pcc2_iefailirq = pri | PCC2_IRQ_IEN |
        !           510:                    PCC2_IRQ_ICLR;
        !           511:                break;
        !           512: #endif
        !           513:        }
        !           514: }
        !           515:
        !           516: /*
        !           517:  * Device timeout/watchdog routine.  Entered if the device neglects to generate
        !           518:  * an interrupt after a transmit has been started on it.
        !           519:  */
        !           520: void
        !           521: iewatchdog(ifp)
        !           522:        struct ifnet *ifp;
        !           523: {
        !           524:        struct ie_softc *sc = ifp->if_softc;
        !           525:
        !           526:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           527:        ++sc->sc_arpcom.ac_if.if_oerrors;
        !           528:
        !           529:        iereset(sc);
        !           530: }
        !           531:
        !           532: int
        !           533: iefailintr(v)
        !           534: void *v;
        !           535: {
        !           536:        struct ie_softc *sc = v;
        !           537:
        !           538:        switch (sc->sc_bustype) {
        !           539: #if NMC > 0
        !           540:        case BUS_MC:
        !           541:                sys_mc->mc_ieirq |= MC_IRQ_ICLR;                /* safe: clear irq */
        !           542:                sys_mc->mc_iefailirq |= MC_IRQ_ICLR;            /* clear failure */
        !           543:                sys_mc->mc_ieerr = MC_IEERR_SCLR;               /* reset error */
        !           544:                break;
        !           545: #endif
        !           546: #if NPCCTWO > 0
        !           547:        case BUS_PCCTWO:
        !           548:                sys_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR;          /* safe: clear irq */
        !           549:                sys_pcc2->pcc2_iefailirq |= PCC2_IRQ_ICLR;      /* clear failure */
        !           550:                sys_pcc2->pcc2_ieerr = PCC2_IEERR_SCLR;         /* reset error */
        !           551:                break;
        !           552: #endif
        !           553:        }
        !           554:
        !           555:        iereset(sc);
        !           556:        return (1);
        !           557: }
        !           558:
        !           559: /*
        !           560:  * What to do upon receipt of an interrupt.
        !           561:  */
        !           562: int
        !           563: ieintr(v)
        !           564: void *v;
        !           565: {
        !           566:        struct ie_softc *sc = v;
        !           567:        register u_short status;
        !           568:
        !           569:        status = sc->scb->ie_status;
        !           570: /*printf("I");*/
        !           571:
        !           572: loop:
        !           573:        /* Ack interrupts FIRST in case we receive more during the ISR. */
        !           574:        ie_ack(sc, IE_ST_WHENCE & status);
        !           575:        switch (sc->sc_bustype) {
        !           576: #if NMC > 0
        !           577:        case BUS_MC:
        !           578:                sys_mc->mc_ieirq |= MC_IRQ_ICLR;                /* clear irq */
        !           579:                break;
        !           580: #endif
        !           581: #if NPCCTWO > 0
        !           582:        case BUS_PCCTWO:
        !           583:                sys_pcc2->pcc2_ieirq |= PCC2_IRQ_ICLR;          /* clear irq */
        !           584:                break;
        !           585: #endif
        !           586:        }
        !           587:
        !           588:        if (status & (IE_ST_RECV | IE_ST_RNR)) {
        !           589: #ifdef IEDEBUG
        !           590:                in_ierint++;
        !           591:                if (sc->sc_debug & IED_RINT)
        !           592:                        printf("%s: rint\n", sc->sc_dev.dv_xname);
        !           593: #endif
        !           594:                ierint(sc);
        !           595: #ifdef IEDEBUG
        !           596:                in_ierint--;
        !           597: #endif
        !           598:        }
        !           599:
        !           600:        if (status & IE_ST_DONE) {
        !           601: #ifdef IEDEBUG
        !           602:                in_ietint++;
        !           603:                if (sc->sc_debug & IED_TINT)
        !           604:                        printf("%s: tint\n", sc->sc_dev.dv_xname);
        !           605: #endif
        !           606:                ietint(sc);
        !           607: #ifdef IEDEBUG
        !           608:                in_ietint--;
        !           609: #endif
        !           610:        }
        !           611:
        !           612:        if (status & IE_ST_RNR) {
        !           613:                printf("%s: receiver not ready\n", sc->sc_dev.dv_xname);
        !           614:                sc->sc_arpcom.ac_if.if_ierrors++;
        !           615:                iereset(sc);
        !           616:        }
        !           617:
        !           618: #ifdef IEDEBUG
        !           619:        if ((status & IE_ST_ALLDONE) && (sc->sc_debug & IED_CNA))
        !           620:                printf("%s: cna\n", sc->sc_dev.dv_xname);
        !           621: #endif
        !           622:
        !           623:        if ((status = sc->scb->ie_status) & IE_ST_WHENCE)
        !           624:                goto loop;
        !           625:
        !           626:        return 1;
        !           627: }
        !           628:
        !           629: /*
        !           630:  * Process a received-frame interrupt.
        !           631:  */
        !           632: void
        !           633: ierint(sc)
        !           634:        struct ie_softc *sc;
        !           635: {
        !           636:        volatile struct ie_sys_ctl_block *scb = sc->scb;
        !           637:        int i, status;
        !           638:        static int timesthru = 1024;
        !           639:
        !           640:        i = sc->rfhead;
        !           641:        for (;;) {
        !           642:                status = sc->rframes[i]->ie_fd_status;
        !           643:
        !           644:                if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
        !           645:                        sc->sc_arpcom.ac_if.if_ipackets++;
        !           646:                        if (!--timesthru) {
        !           647:                                sc->sc_arpcom.ac_if.if_ierrors +=
        !           648:                                    MK_32(scb->ie_err_crc) +
        !           649:                                    MK_32(scb->ie_err_align) +
        !           650:                                    MK_32(scb->ie_err_resource) +
        !           651:                                    MK_32(scb->ie_err_overrun) +
        !           652:                                    MK_32(scb->ie_err_coll) +
        !           653:                                    MK_32(scb->ie_err_short);
        !           654:                                scb->ie_err_crc = 0;
        !           655:                                scb->ie_err_align = 0;
        !           656:                                scb->ie_err_resource = 0;
        !           657:                                scb->ie_err_overrun = 0;
        !           658:                                scb->ie_err_coll = 0;
        !           659:                                scb->ie_err_short = 0;
        !           660:                                timesthru = 1024;
        !           661:                        }
        !           662:                        ie_readframe(sc, i);
        !           663:                } else {
        !           664:                        if ((status & IE_FD_RNR) != 0 &&
        !           665:                            (scb->ie_status & IE_RU_READY) == 0) {
        !           666:                                sc->rframes[0]->ie_fd_buf_desc = ASWAP(sc->rbuffs[0]);
        !           667:                                scb->ie_recv_list = ASWAP(sc->rframes[0]);
        !           668:                                command_and_wait(sc, IE_RU_START, 0, 0);
        !           669:                        }
        !           670:                        break;
        !           671:                }
        !           672:                i = (i + 1) % sc->nframes;
        !           673:        }
        !           674: }
        !           675:
        !           676: /*
        !           677:  * Process a command-complete interrupt.  These are only generated by the
        !           678:  * transmission of frames.  This routine is deceptively simple, since most of
        !           679:  * the real work is done by iestart().
        !           680:  */
        !           681: void
        !           682: ietint(sc)
        !           683:        struct ie_softc *sc;
        !           684: {
        !           685:        int status;
        !           686:
        !           687:        sc->sc_arpcom.ac_if.if_timer = 0;
        !           688:        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
        !           689:
        !           690:        status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
        !           691:
        !           692:        if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
        !           693:                printf("ietint: command still busy!\n");
        !           694:
        !           695:        if (status & IE_STAT_OK) {
        !           696:                sc->sc_arpcom.ac_if.if_opackets++;
        !           697:                sc->sc_arpcom.ac_if.if_collisions += status & IE_XS_MAXCOLL;
        !           698:        } else if (status & IE_STAT_ABORT) {
        !           699:                printf("%s: send aborted\n", sc->sc_dev.dv_xname);
        !           700:                sc->sc_arpcom.ac_if.if_oerrors++;
        !           701:        } else if (status & IE_XS_NOCARRIER) {
        !           702:                printf("%s: no carrier\n", sc->sc_dev.dv_xname);
        !           703:                sc->sc_arpcom.ac_if.if_oerrors++;
        !           704:        } else if (status & IE_XS_LOSTCTS) {
        !           705:                printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
        !           706:                sc->sc_arpcom.ac_if.if_oerrors++;
        !           707:        } else if (status & IE_XS_UNDERRUN) {
        !           708:                printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
        !           709:                sc->sc_arpcom.ac_if.if_oerrors++;
        !           710:        } else if (status & IE_XS_EXCMAX) {
        !           711:                printf("%s: too many collisions\n", sc->sc_dev.dv_xname);
        !           712:                sc->sc_arpcom.ac_if.if_collisions += 16;
        !           713:                sc->sc_arpcom.ac_if.if_oerrors++;
        !           714:        }
        !           715:
        !           716:        /*
        !           717:         * If multicast addresses were added or deleted while transmitting,
        !           718:         * mc_reset() set the want_mcsetup flag indicating that we should do
        !           719:         * it.
        !           720:         */
        !           721:        if (sc->want_mcsetup) {
        !           722:                mc_setup(sc, (caddr_t)sc->xmit_cbuffs[sc->xctail]);
        !           723:                sc->want_mcsetup = 0;
        !           724:        }
        !           725:
        !           726:        /* Done with the buffer. */
        !           727:        sc->xmit_free++;
        !           728:        sc->xmit_busy = 0;
        !           729:        sc->xctail = (sc->xctail + 1) % NTXBUF;
        !           730:
        !           731:        iestart(&sc->sc_arpcom.ac_if);
        !           732: }
        !           733:
        !           734: /*
        !           735:  * Compare two Ether/802 addresses for equality, inlined and unrolled for
        !           736:  * speed.  I'd love to have an inline assembler version of this...
        !           737:  */
        !           738: int
        !           739: ether_equal(one, two)
        !           740:        u_char *one, *two;
        !           741: {
        !           742:
        !           743:        if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||
        !           744:            one[3] != two[3] || one[4] != two[4] || one[5] != two[5])
        !           745:                return 0;
        !           746:        return 1;
        !           747: }
        !           748:
        !           749: /*
        !           750:  * Check for a valid address.  to_bpf is filled in with one of the following:
        !           751:  *   0 -> BPF doesn't get this packet
        !           752:  *   1 -> BPF does get this packet
        !           753:  *   2 -> BPF does get this packet, but we don't
        !           754:  * Return value is true if the packet is for us, and false otherwise.
        !           755:  *
        !           756:  * This routine is a mess, but it's also critical that it be as fast
        !           757:  * as possible.  It could be made cleaner if we can assume that the
        !           758:  * only client which will fiddle with IFF_PROMISC is BPF.  This is
        !           759:  * probably a good assumption, but we do not make it here.  (Yet.)
        !           760:  */
        !           761: int
        !           762: check_eh(sc, eh, to_bpf)
        !           763:        struct ie_softc *sc;
        !           764:        struct ether_header *eh;
        !           765:        int *to_bpf;
        !           766: {
        !           767:        int i;
        !           768:
        !           769:        switch(sc->promisc) {
        !           770:        case IFF_ALLMULTI:
        !           771:                /*
        !           772:                 * Receiving all multicasts, but no unicasts except those
        !           773:                 * destined for us.
        !           774:                 */
        !           775: #if NBPFILTER > 0
        !           776:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0); /* BPF gets this packet if anybody cares */
        !           777: #endif
        !           778:                if (eh->ether_dhost[0] & 1)
        !           779:                        return 1;
        !           780:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) return 1;
        !           781:                return 0;
        !           782:
        !           783:        case IFF_PROMISC:
        !           784:                /*
        !           785:                 * Receiving all packets.  These need to be passed on to BPF.
        !           786:                 */
        !           787: #if NBPFILTER > 0
        !           788:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0) ||
        !           789:                    (sc->sc_arpcom.ac_if.if_bridge != NULL);
        !           790: #else
        !           791:                *to_bpf = (sc->sc_arpcom.ac_if.if_bridge != NULL);
        !           792: #endif
        !           793:                /* If for us, accept and hand up to BPF */
        !           794:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr)) return 1;
        !           795:
        !           796: #if NBPFILTER > 0
        !           797:                if (*to_bpf && sc->sc_arpcom.ac_if.if_bridge == NULL)
        !           798:                        *to_bpf = 2; /* we don't need to see it */
        !           799: #endif
        !           800:
        !           801:                /*
        !           802:                 * Not a multicast, so BPF wants to see it but we don't.
        !           803:                 */
        !           804:                if (!(eh->ether_dhost[0] & 1))
        !           805:                        return 1;
        !           806:
        !           807:                /*
        !           808:                 * If it's one of our multicast groups, accept it and pass it
        !           809:                 * up.
        !           810:                 */
        !           811:                for (i = 0; i < sc->mcast_count; i++) {
        !           812:                        if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {
        !           813: #if NBPFILTER > 0
        !           814:                                if (*to_bpf)
        !           815:                                        *to_bpf = 1;
        !           816: #endif
        !           817:                                return 1;
        !           818:                        }
        !           819:                }
        !           820:                return 1;
        !           821:
        !           822:        case IFF_ALLMULTI | IFF_PROMISC:
        !           823:                /*
        !           824:                 * Acting as a multicast router, and BPF running at the same
        !           825:                 * time.  Whew!  (Hope this is a fast machine...)
        !           826:                 */
        !           827: #if NBPFILTER > 0
        !           828:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0) ||
        !           829:                    (sc->sc_arpcom.ac_if.if_bridge != NULL);
        !           830: #else
        !           831:                *to_bpf = (sc->sc_arpcom.ac_if.if_bridge != NULL);
        !           832: #endif
        !           833:                /* We want to see multicasts. */
        !           834:                if (eh->ether_dhost[0] & 1)
        !           835:                        return 1;
        !           836:
        !           837:                /* We want to see our own packets */
        !           838:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
        !           839:                        return 1;
        !           840:
        !           841:                /* Anything else goes to BPF but nothing else. */
        !           842: #if NBPFILTER > 0
        !           843:                if (*to_bpf && sc->sc_arpcom.ac_if.if_bridge == NULL)
        !           844:                        *to_bpf = 2;
        !           845: #endif
        !           846:                return 1;
        !           847:
        !           848:        default:
        !           849:                /*
        !           850:                 * Only accept unicast packets destined for us, or multicasts
        !           851:                 * for groups that we belong to.  For now, we assume that the
        !           852:                 * '596 will only return packets that we asked it for.  This
        !           853:                 * isn't strictly true (it uses hashing for the multicast
        !           854:                 * filter), but it will do in this case, and we want to get out
        !           855:                 * of here as quickly as possible.
        !           856:                 */
        !           857: #if NBPFILTER > 0
        !           858:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
        !           859: #endif
        !           860:                return 1;
        !           861:        }
        !           862:        return 0;
        !           863: }
        !           864:
        !           865: /*
        !           866:  * We want to isolate the bits that have meaning...  This assumes that
        !           867:  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
        !           868:  * the size of the buffer, then we are screwed anyway.
        !           869:  */
        !           870: int
        !           871: ie_buflen(sc, head)
        !           872:        struct ie_softc *sc;
        !           873:        int head;
        !           874: {
        !           875:
        !           876:        return (sc->rbuffs[head]->ie_rbd_actual & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
        !           877: }
        !           878:
        !           879: int
        !           880: ie_packet_len(sc)
        !           881:        struct ie_softc *sc;
        !           882: {
        !           883:        int i;
        !           884:        int head = sc->rbhead;
        !           885:        int acc = 0;
        !           886:
        !           887:        do {
        !           888:                if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
        !           889: #ifdef IEDEBUG
        !           890:                        print_rbd(sc->rbuffs[sc->rbhead]);
        !           891: #endif
        !           892:                        log(LOG_ERR, "%s: receive descriptors out of sync at %d\n",
        !           893:                            sc->sc_dev.dv_xname, sc->rbhead);
        !           894:                        iereset(sc);
        !           895:                        return -1;
        !           896:                }
        !           897:
        !           898:                i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
        !           899:
        !           900:                acc += ie_buflen(sc, head);
        !           901:                head = (head + 1) % sc->nrxbuf;
        !           902:        } while (!i);
        !           903:
        !           904:        return acc;
        !           905: }
        !           906:
        !           907: /*
        !           908:  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
        !           909:  * command to the chip to be executed.  On the way, if we have a BPF listener
        !           910:  * also give him a copy.
        !           911:  */
        !           912: void
        !           913: iexmit(sc)
        !           914:        struct ie_softc *sc;
        !           915: {
        !           916:
        !           917: #if NBPFILTER > 0
        !           918:        /*
        !           919:         * If BPF is listening on this interface, let it see the packet before
        !           920:         * we push it on the wire.
        !           921:         */
        !           922:        if (sc->sc_arpcom.ac_if.if_bpf)
        !           923:                bpf_tap(sc->sc_arpcom.ac_if.if_bpf,
        !           924:                    sc->xmit_cbuffs[sc->xctail],
        !           925:                    sc->xmit_buffs[sc->xctail]->ie_xmit_flags,
        !           926:                    BPF_DIRECTION_OUT);
        !           927: #endif
        !           928:
        !           929: #if 0
        !           930: printf("iexmit base %x cmd %x bfd %x to %x\n",
        !           931: sc->sc_maddr,
        !           932: sc->xmit_cmds[sc->xctail],
        !           933: sc->xmit_buffs[sc->xctail],
        !           934: sc->xmit_cbuffs[sc->xctail]);
        !           935: #endif
        !           936:        sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
        !           937:        sc->xmit_buffs[sc->xctail]->ie_xmit_next = 0xffffffff;
        !           938:        SWT_32(sc->xmit_buffs[sc->xctail]->ie_xmit_buf,
        !           939:                sc->xmit_cbuffs[sc->xctail]);
        !           940:
        !           941:        sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = 0xffffffff;
        !           942:        sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
        !           943:          IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST | IE_CMD_FLEX;
        !           944:
        !           945:        sc->xmit_cmds[sc->xctail]->ie_xmit_status = 0;
        !           946:        sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
        !           947:            ASWAP(sc->xmit_buffs[sc->xctail]);
        !           948:        sc->xmit_cmds[sc->xctail]->ie_xmit_count = 0;
        !           949:
        !           950:        sc->scb->ie_command_list =
        !           951:          ASWAP(sc->xmit_cmds[sc->xctail]);
        !           952:        command_and_wait(sc, IE_CU_START, 0, 0);
        !           953:
        !           954:        sc->xmit_busy = 1;
        !           955:        sc->sc_arpcom.ac_if.if_timer = 5;
        !           956: }
        !           957:
        !           958: /*
        !           959:  * Read data off the interface, and turn it into an mbuf chain.
        !           960:  *
        !           961:  * This code is DRAMATICALLY different from the previous version; this
        !           962:  * version tries to allocate the entire mbuf chain up front, given the
        !           963:  * length of the data available.  This enables us to allocate mbuf
        !           964:  * clusters in many situations where before we would have had a long
        !           965:  * chain of partially-full mbufs.  This should help to speed up the
        !           966:  * operation considerably.  (Provided that it works, of course.)
        !           967:  */
        !           968: int
        !           969: ieget(sc, mp, ehp, to_bpf)
        !           970:        struct ie_softc *sc;
        !           971:        struct mbuf **mp;
        !           972:        struct ether_header *ehp;
        !           973:        int *to_bpf;
        !           974: {
        !           975:        struct mbuf *m, *top, **mymp;
        !           976:        int i;
        !           977:        int offset = 0;
        !           978:        int totlen, resid;
        !           979:        int thismboff;
        !           980:        int head;
        !           981:
        !           982:        totlen = ie_packet_len(sc);
        !           983:        if (totlen <= 0)
        !           984:                return -1;
        !           985:
        !           986:        i = sc->rbhead;
        !           987:
        !           988:        /*
        !           989:         * Snarf the Ethernet header.
        !           990:         */
        !           991:        (sc->memcopy)((caddr_t)sc->cbuffs[i], (caddr_t)ehp, sizeof *ehp);
        !           992:
        !           993:        /*
        !           994:         * As quickly as possible, check if this packet is for us.
        !           995:         * If not, don't waste a single cycle copying the rest of the
        !           996:         * packet in.
        !           997:         * This is only a consideration when FILTER is defined; i.e., when
        !           998:         * we are either running BPF or doing multicasting.
        !           999:         */
        !          1000:        if (!check_eh(sc, ehp, to_bpf)) {
        !          1001:                ie_drop_packet_buffer(sc);
        !          1002:                sc->sc_arpcom.ac_if.if_ierrors--; /* just this case, it's not an error */
        !          1003:                return -1;
        !          1004:        }
        !          1005:
        !          1006:        MGETHDR(*mp, M_DONTWAIT, MT_DATA);
        !          1007:        if (!*mp) {
        !          1008:                ie_drop_packet_buffer(sc);
        !          1009:                return -1;
        !          1010:        }
        !          1011:
        !          1012:        m = *mp;
        !          1013:        m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
        !          1014:        m->m_len = MHLEN;
        !          1015:        resid = m->m_pkthdr.len = totlen;
        !          1016:        top = 0;
        !          1017:        mymp = &top;
        !          1018:
        !          1019:        /*
        !          1020:         * This loop goes through and allocates mbufs for all the data we will
        !          1021:         * be copying in.  It does not actually do the copying yet.
        !          1022:         */
        !          1023:        do {                            /* while (resid > 0) */
        !          1024:                /*
        !          1025:                 * Try to allocate an mbuf to hold the data that we have.  If
        !          1026:                 * we already allocated one, just get another one and stick it
        !          1027:                 * on the end (eventually).  If we don't already have one, try
        !          1028:                 * to allocate an mbuf cluster big enough to hold the whole
        !          1029:                 * packet, if we think it's reasonable, or a single mbuf which
        !          1030:                 * may or may not be big enough.
        !          1031:                 * Got that?
        !          1032:                 */
        !          1033:                if (top) {
        !          1034:                        MGET(m, M_DONTWAIT, MT_DATA);
        !          1035:                        if (!m) {
        !          1036:                                m_freem(top);
        !          1037:                                ie_drop_packet_buffer(sc);
        !          1038:                                return -1;
        !          1039:                        }
        !          1040:                        m->m_len = MLEN;
        !          1041:                }
        !          1042:
        !          1043:                if (resid >= MINCLSIZE) {
        !          1044:                        MCLGET(m, M_DONTWAIT);
        !          1045:                        if (m->m_flags & M_EXT)
        !          1046:                                m->m_len = min(resid, MCLBYTES);
        !          1047:                } else {
        !          1048:                        if (resid < m->m_len) {
        !          1049:                                if (!top && resid + max_linkhdr <= m->m_len)
        !          1050:                                        m->m_data += max_linkhdr;
        !          1051:                                m->m_len = resid;
        !          1052:                        }
        !          1053:                }
        !          1054:                resid -= m->m_len;
        !          1055:                *mymp = m;
        !          1056:                mymp = &m->m_next;
        !          1057:        } while (resid > 0);
        !          1058:
        !          1059:        resid = totlen;
        !          1060:        m = top;
        !          1061:        thismboff = 0;
        !          1062:        head = sc->rbhead;
        !          1063:
        !          1064:        /*
        !          1065:         * Now we take the mbuf chain (hopefully only one mbuf most of the
        !          1066:         * time) and stuff the data into it.  There are no possible failures at
        !          1067:         * or after this point.
        !          1068:         */
        !          1069:        while (resid > 0) {             /* while there's stuff left */
        !          1070:                int thislen = ie_buflen(sc, head) - offset;
        !          1071:
        !          1072:                /*
        !          1073:                 * If too much data for the current mbuf, then fill the current
        !          1074:                 * one up, go to the next one, and try again.
        !          1075:                 */
        !          1076:                if (thislen > m->m_len - thismboff) {
        !          1077:                        int newlen = m->m_len - thismboff;
        !          1078:                        (sc->memcopy)((caddr_t)(sc->cbuffs[head] + offset),
        !          1079:                            mtod(m, caddr_t) + thismboff, (u_int)newlen);
        !          1080:                        m = m->m_next;
        !          1081:                        thismboff = 0;          /* new mbuf, so no offset */
        !          1082:                        offset += newlen;       /* we are now this far
        !          1083:                                                        into the packet */
        !          1084:                        resid -= newlen;        /* so there is this much
        !          1085:                                                        left to get */
        !          1086:                        continue;
        !          1087:                }
        !          1088:
        !          1089:                /*
        !          1090:                 * If there is more than enough space in the mbuf to hold the
        !          1091:                 * contents of this buffer, copy everything in, advance
        !          1092:                 * pointers and so on.
        !          1093:                 */
        !          1094:                if (thislen < m->m_len - thismboff) {
        !          1095:                        (sc->memcopy)((caddr_t)(sc->cbuffs[head] + offset),
        !          1096:                            mtod(m, caddr_t) + thismboff, (u_int)thislen);
        !          1097:                        thismboff += thislen;   /* we are this far into the mbuf */
        !          1098:                        resid -= thislen;       /* and this much is left */
        !          1099:                        goto nextbuf;
        !          1100:                }
        !          1101:
        !          1102:                /*
        !          1103:                 * Otherwise, there is exactly enough space to put this
        !          1104:                 * buffer's contents into the current mbuf.  Do the combination
        !          1105:                 * of the above actions.
        !          1106:                 */
        !          1107:                (sc->memcopy)((caddr_t)(sc->cbuffs[head] + offset),
        !          1108:                    mtod(m, caddr_t) + thismboff, (u_int)thislen);
        !          1109:                m = m->m_next;
        !          1110:                thismboff = 0;          /* new mbuf, start at the beginning */
        !          1111:                resid -= thislen;       /* and we are this far through */
        !          1112:
        !          1113:                /*
        !          1114:                 * Advance all the pointers.  We can get here from either of
        !          1115:                 * the last two cases, but never the first.
        !          1116:                 */
        !          1117:        nextbuf:
        !          1118:                offset = 0;
        !          1119:                sc->rbuffs[head]->ie_rbd_actual = 0;
        !          1120:                sc->rbuffs[head]->ie_rbd_length |= IE_RBD_LAST;
        !          1121:                sc->rbhead = head = (head + 1) % sc->nrxbuf;
        !          1122:                sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
        !          1123:                sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
        !          1124:        }
        !          1125:
        !          1126:        /*
        !          1127:         * Unless something changed strangely while we were doing the copy, we
        !          1128:         * have now copied everything in from the shared memory.
        !          1129:         * This means that we are done.
        !          1130:         */
        !          1131:        return 0;
        !          1132: }
        !          1133:
        !          1134: /*
        !          1135:  * Read frame NUM from unit UNIT (pre-cached as IE).
        !          1136:  *
        !          1137:  * This routine reads the RFD at NUM, and copies in the buffers from the list
        !          1138:  * of RBD, then rotates the RBD and RFD lists so that the receiver doesn't
        !          1139:  * start complaining.  Trailers are DROPPED---there's no point in wasting time
        !          1140:  * on confusing code to deal with them.  Hopefully, this machine will never ARP
        !          1141:  * for trailers anyway.
        !          1142:  */
        !          1143: void
        !          1144: ie_readframe(sc, num)
        !          1145:        struct ie_softc *sc;
        !          1146:        int num;                        /* frame number to read */
        !          1147: {
        !          1148:        int status;
        !          1149:        struct mbuf *m = 0;
        !          1150:        struct ether_header eh;
        !          1151: #if NBPFILTER > 0
        !          1152:        int bpf_gets_it = 0;
        !          1153: #endif
        !          1154:
        !          1155:        status = sc->rframes[num]->ie_fd_status;
        !          1156:
        !          1157:        /* Immediately advance the RFD list, since we have copied ours now. */
        !          1158:        sc->rframes[num]->ie_fd_status = 0;
        !          1159:        sc->rframes[num]->ie_fd_actual = 0;
        !          1160:        sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
        !          1161:        sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
        !          1162:        sc->rftail = (sc->rftail + 1) % sc->nframes;
        !          1163:        sc->rfhead = (sc->rfhead + 1) % sc->nframes;
        !          1164:
        !          1165:        if (status & IE_FD_OK) {
        !          1166: #if NBPFILTER > 0
        !          1167:                if (ieget(sc, &m, &eh, &bpf_gets_it)) {
        !          1168: #else
        !          1169:                if (ieget(sc, &m, &eh, 0)) {
        !          1170: #endif
        !          1171:                        sc->sc_arpcom.ac_if.if_ierrors++;
        !          1172:                        return;
        !          1173:                }
        !          1174:        }
        !          1175:
        !          1176: #ifdef IEDEBUG
        !          1177:        if (sc->sc_debug & IED_READFRAME)
        !          1178:                printf("%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname,
        !          1179:                    ether_sprintf(eh.ether_shost), (u_int)eh.ether_type);
        !          1180: #endif
        !          1181:
        !          1182:        if (!m)
        !          1183:                return;
        !          1184:
        !          1185:        if (last_not_for_us) {
        !          1186:                m_freem(last_not_for_us);
        !          1187:                last_not_for_us = 0;
        !          1188:        }
        !          1189:
        !          1190: #if NBPFILTER > 0
        !          1191:        /* Check for a BPF filter; if so, hand it up. */
        !          1192:        if (bpf_gets_it)
        !          1193:                bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m, BPF_DIRECTION_IN);
        !          1194:
        !          1195:        /*
        !          1196:         * A signal passed up from the filtering code indicating that the
        !          1197:         * packet is intended for BPF but not for the protocol machinery.
        !          1198:         * We can save a few cycles by not handing it off to them.
        !          1199:         */
        !          1200:        if (bpf_gets_it == 2) {
        !          1201:                last_not_for_us = m;
        !          1202:                return;
        !          1203:        }
        !          1204: #endif /* NBPFILTER > 0 */
        !          1205:
        !          1206:        /*
        !          1207:         * In here there used to be code to check destination addresses upon
        !          1208:         * receipt of a packet.  We have deleted that code, and replaced it
        !          1209:         * with code to check the address much earlier in the cycle, before
        !          1210:         * copying the data in; this saves us valuable cycles when operating
        !          1211:         * as a multicast router or when using BPF.
        !          1212:         */
        !          1213:
        !          1214:        /*
        !          1215:         * Finally pass this packet up to higher layers.
        !          1216:         */
        !          1217:        ether_input_mbuf(&sc->sc_arpcom.ac_if, m);
        !          1218: }
        !          1219:
        !          1220: void
        !          1221: ie_drop_packet_buffer(sc)
        !          1222:        struct ie_softc *sc;
        !          1223: {
        !          1224:        int i;
        !          1225:
        !          1226:        do {
        !          1227:                /*
        !          1228:                 * This means we are somehow out of sync.  So, we reset the
        !          1229:                 * adapter.
        !          1230:                 */
        !          1231:                if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
        !          1232: #ifdef IEDEBUG
        !          1233:                        print_rbd(sc->rbuffs[sc->rbhead]);
        !          1234: #endif
        !          1235:                        log(LOG_ERR, "%s: receive descriptors out of sync at %d\n",
        !          1236:                            sc->sc_dev.dv_xname, sc->rbhead);
        !          1237:                        iereset(sc);
        !          1238:                        return;
        !          1239:                }
        !          1240:
        !          1241:                i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
        !          1242:
        !          1243:                sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
        !          1244:                sc->rbuffs[sc->rbhead]->ie_rbd_actual = 0;
        !          1245:                sc->rbhead = (sc->rbhead + 1) % sc->nrxbuf;
        !          1246:                sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
        !          1247:                sc->rbtail = (sc->rbtail + 1) % sc->nrxbuf;
        !          1248:        } while (!i);
        !          1249: }
        !          1250:
        !          1251:
        !          1252: /*
        !          1253:  * Start transmission on an interface.
        !          1254:  */
        !          1255: void
        !          1256: iestart(ifp)
        !          1257:        struct ifnet *ifp;
        !          1258: {
        !          1259:        struct ie_softc *sc = ifp->if_softc;
        !          1260:        struct mbuf *m0, *m;
        !          1261:        u_char *buffer;
        !          1262:        u_short len;
        !          1263:
        !          1264: /*printf("iestart\n");*/
        !          1265:        if ((ifp->if_flags & IFF_RUNNING) == 0)
        !          1266:                return;
        !          1267:
        !          1268:        if (sc->xmit_free == 0) {
        !          1269:                ifp->if_flags |= IFF_OACTIVE;
        !          1270:                if (!sc->xmit_busy)
        !          1271:                        iexmit(sc);
        !          1272:                return;
        !          1273:        }
        !          1274:
        !          1275:        do {
        !          1276:                IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
        !          1277:                if (!m)
        !          1278:                        break;
        !          1279:
        !          1280:                len = 0;
        !          1281:                buffer = sc->xmit_cbuffs[sc->xchead];
        !          1282:
        !          1283:                for (m0 = m; m && (len +m->m_len) < IE_TBUF_SIZE;
        !          1284:                                                           m = m->m_next) {
        !          1285:                        bcopy(mtod(m, caddr_t), buffer, m->m_len);
        !          1286:                        buffer += m->m_len;
        !          1287:                        len += m->m_len;
        !          1288:                }
        !          1289:                if (m)
        !          1290:                  printf("%s: tbuf overflow\n", sc->sc_dev.dv_xname);
        !          1291:
        !          1292:                m_freem(m0);
        !          1293:
        !          1294:                if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
        !          1295:                        bzero(buffer, ETHER_MIN_LEN - ETHER_CRC_LEN - len);
        !          1296:                        len = ETHER_MIN_LEN - ETHER_CRC_LEN;
        !          1297:                        buffer += ETHER_MIN_LEN - ETHER_CRC_LEN;
        !          1298:                }
        !          1299:
        !          1300:                sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len;
        !          1301:
        !          1302:                sc->xmit_free--;
        !          1303:                sc->xchead = (sc->xchead + 1) % NTXBUF;
        !          1304:        } while (sc->xmit_free > 0);
        !          1305:
        !          1306:        /* If we stuffed any packets into the card's memory, send now. */
        !          1307:        if ((sc->xmit_free < NTXBUF) && (!sc->xmit_busy))
        !          1308:                iexmit(sc);
        !          1309:
        !          1310:        return;
        !          1311: }
        !          1312:
        !          1313: /*
        !          1314:  * set up IE's ram space
        !          1315:  */
        !          1316: int
        !          1317: ie_setupram(sc)
        !          1318:        struct ie_softc *sc;
        !          1319: {
        !          1320:        volatile struct ie_int_sys_conf_ptr *iscp;
        !          1321:        volatile struct ie_sys_ctl_block *scb;
        !          1322:        int     s;
        !          1323:
        !          1324:        s = splnet();
        !          1325:
        !          1326:        iscp = sc->iscp;
        !          1327:        (sc->memzero)((char *) iscp, sizeof *iscp);
        !          1328:
        !          1329:        scb = sc->scb;
        !          1330:        (sc->memzero)((char *) scb, sizeof *scb);
        !          1331:        scb->ie_off_timer = 10;
        !          1332:        scb->ie_on_timer = 10000;
        !          1333:
        !          1334:        iscp->ie_busy = 1;      /* ie_busy == char */
        !          1335:        SWT_32(iscp->ie_base, sc->scb);
        !          1336:
        !          1337:        (sc->reset_596) (sc);
        !          1338:        (sc->chan_attn) (sc);
        !          1339:
        !          1340:        delay(100);             /* wait a while... */
        !          1341:
        !          1342:        if (iscp->ie_busy) {
        !          1343:                splx(s);
        !          1344:                return 0;
        !          1345:        }
        !          1346:        /*
        !          1347:         * Acknowledge any interrupts we may have caused...
        !          1348:         */
        !          1349:        ie_ack(sc, IE_ST_WHENCE);
        !          1350:        splx(s);
        !          1351:
        !          1352:        return 1;
        !          1353: }
        !          1354:
        !          1355: void
        !          1356: iereset(sc)
        !          1357:        struct ie_softc *sc;
        !          1358: {
        !          1359:        int s = splnet();
        !          1360:
        !          1361:        printf("%s: reset\n", sc->sc_dev.dv_xname);
        !          1362:
        !          1363:        /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */
        !          1364:        sc->sc_arpcom.ac_if.if_flags &= ~(IFF_UP | IFF_OACTIVE);
        !          1365:        ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, 0);
        !          1366:
        !          1367:        /*
        !          1368:         * Stop i82596 dead in its tracks.
        !          1369:         */
        !          1370:        if (command_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
        !          1371:                printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
        !          1372:
        !          1373:        if (command_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
        !          1374:                printf("%s: disable commands timed out\n", sc->sc_dev.dv_xname);
        !          1375:
        !          1376: #ifdef notdef
        !          1377:        if (!check_ie_present(sc, sc->sc_maddr, sc->sc_msize))
        !          1378:                panic("ie disappeared!");
        !          1379: #endif
        !          1380:
        !          1381:        sc->sc_arpcom.ac_if.if_flags |= IFF_UP;
        !          1382:        ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, 0);
        !          1383:
        !          1384:        splx(s);
        !          1385: }
        !          1386:
        !          1387: #if 0
        !          1388: /*
        !          1389:  * This is called if we time out.
        !          1390:  */
        !          1391: void
        !          1392: chan_attn_timeout(rock)
        !          1393:        caddr_t rock;
        !          1394: {
        !          1395:
        !          1396:        *(int *)rock = 1;
        !          1397: }
        !          1398: #endif
        !          1399:
        !          1400: /*
        !          1401:  * Send a command to the controller and wait for it to either complete
        !          1402:  * or be accepted, depending on the command.  If the command pointer
        !          1403:  * is null, then pretend that the command is not an action command.
        !          1404:  * If the command pointer is not null, and the command is an action
        !          1405:  * command, wait for
        !          1406:  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
        !          1407:  * to become true.
        !          1408:  */
        !          1409: int
        !          1410: command_and_wait(sc, cmd, pcmd, mask)
        !          1411:        struct ie_softc *sc;
        !          1412:        int cmd;
        !          1413:        volatile void *pcmd;
        !          1414:        int mask;
        !          1415: {
        !          1416:        volatile struct ie_cmd_common *cc = pcmd;
        !          1417:        volatile struct ie_sys_ctl_block *scb = sc->scb;
        !          1418:        volatile int timedout = 0;
        !          1419: #if 0
        !          1420:        struct timeout chan_tmo;
        !          1421:        extern int hz;
        !          1422: #endif
        !          1423:
        !          1424:        scb->ie_command = (u_short)cmd;
        !          1425:
        !          1426:        if (IE_ACTION_COMMAND(cmd) && pcmd) {
        !          1427:                (sc->chan_attn)(sc);
        !          1428:
        !          1429: #if 0
        !          1430:                 /*
        !          1431:                  * XXX
        !          1432:                  * I don't think this timeout works on suns.
        !          1433:                  * we are at splnet() in the loop, and the timeout
        !          1434:                  * stuff runs at software spl (so it is masked off?).
        !          1435:                  */
        !          1436:
        !          1437:                /*
        !          1438:                 * According to the packet driver, the minimum timeout should
        !          1439:                 * be .369 seconds, which we round up to .4.
        !          1440:                 */
        !          1441:                timeout_set(&chan_tmo, chan_attn_timeout, (caddr_t)&timedout);
        !          1442:                timeout_add(&chan_tmo, 2 * hz / 5);
        !          1443: #endif
        !          1444:
        !          1445:                /*
        !          1446:                 * Now spin-lock waiting for status.  This is not a very nice
        !          1447:                 * thing to do, but I haven't figured out how, or indeed if, we
        !          1448:                 * can put the process waiting for action to sleep.  (We may
        !          1449:                 * be getting called through some other timeout running in the
        !          1450:                 * kernel.)
        !          1451:                 */
        !          1452:                for (;;)
        !          1453:                        if ((cc->ie_cmd_status & mask) || timedout)
        !          1454:                                break;
        !          1455: #if 0
        !          1456:                timeout_del(&chan_tmo);
        !          1457: #endif
        !          1458:
        !          1459:                return timedout;
        !          1460:        } else {
        !          1461:                /*
        !          1462:                 * Otherwise, just wait for the command to be accepted.
        !          1463:                 */
        !          1464:                (sc->chan_attn)(sc);
        !          1465:
        !          1466:                while (scb->ie_command)
        !          1467:                        ;                               /* XXX spin lock */
        !          1468:
        !          1469:                return 0;
        !          1470:        }
        !          1471: }
        !          1472:
        !          1473: /*
        !          1474:  * Run the time-domain reflectometer.
        !          1475:  */
        !          1476: void
        !          1477: run_tdr(sc, cmd)
        !          1478:        struct ie_softc *sc;
        !          1479:        struct ie_tdr_cmd *cmd;
        !          1480: {
        !          1481:        int result;
        !          1482:
        !          1483:        cmd->com.ie_cmd_status = 0;
        !          1484:        cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
        !          1485:        cmd->com.ie_cmd_link = 0xffffffff;
        !          1486:
        !          1487:        sc->scb->ie_command_list = ASWAP(cmd);
        !          1488:        cmd->ie_tdr_time = 0;
        !          1489:
        !          1490:        if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
        !          1491:            !(cmd->com.ie_cmd_status & IE_STAT_OK))
        !          1492:                result = 0x10000; /* XXX */
        !          1493:        else
        !          1494:                result = cmd->ie_tdr_time;
        !          1495:
        !          1496:        ie_ack(sc, IE_ST_WHENCE);
        !          1497:
        !          1498:        if (result & IE_TDR_SUCCESS)
        !          1499:                return;
        !          1500:
        !          1501:        if (result & 0x10000)
        !          1502:                printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
        !          1503:        else if (result & IE_TDR_XCVR)
        !          1504:                printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
        !          1505:        else if (result & IE_TDR_OPEN)
        !          1506:                printf("%s: TDR detected an open %d clocks away\n",
        !          1507:                    sc->sc_dev.dv_xname, result & IE_TDR_TIME);
        !          1508:        else if (result & IE_TDR_SHORT)
        !          1509:                printf("%s: TDR detected a short %d clocks away\n",
        !          1510:                    sc->sc_dev.dv_xname, result & IE_TDR_TIME);
        !          1511:        else
        !          1512:                printf("%s: TDR returned unknown status %x\n",
        !          1513:                    sc->sc_dev.dv_xname, result);
        !          1514: }
        !          1515:
        !          1516: #ifdef notdef
        !          1517: /* ALIGN works on 8 byte boundaries.... but 4 byte boundaries are ok for sun */
        !          1518: #define        _ALLOC(p, n)    (bzero(p, n), p += n, p - n)
        !          1519: #define        ALLOC(p, n)     _ALLOC(p, ALIGN(n)) /* XXX convert to this? */
        !          1520: #endif
        !          1521:
        !          1522: #define        Align(ptr)      ((caddr_t)(((u_long)(ptr) + 3) & ~3L))
        !          1523:
        !          1524: /*
        !          1525:  * setup_bufs: set up the buffers
        !          1526:  *
        !          1527:  * we have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
        !          1528:  * this is to be used for the buffers.  the chip indexs its control data
        !          1529:  * structures with 16 bit offsets, and it indexes actual buffers with
        !          1530:  * 24 bit addresses.   so we should allocate control buffers first so that
        !          1531:  * we don't overflow the 16 bit offset field.   The number of transmit
        !          1532:  * buffers is fixed at compile time.
        !          1533:  *
        !          1534:  * note: this function was written to be easy to understand, rather than
        !          1535:  *       highly efficient (it isn't in the critical path).
        !          1536:  */
        !          1537: void
        !          1538: setup_bufs(sc)
        !          1539:        struct ie_softc *sc;
        !          1540: {
        !          1541:        caddr_t ptr = sc->buf_area;     /* memory pool */
        !          1542:        int     n, r;
        !          1543:
        !          1544:        /*
        !          1545:         * step 0: zero memory and figure out how many recv buffers and
        !          1546:         * frames we can have.   XXX CURRENTLY HARDWIRED AT MAX
        !          1547:         */
        !          1548:        (sc->memzero)(ptr, sc->buf_area_sz);
        !          1549:        ptr = Align(ptr);       /* set alignment and stick with it */
        !          1550:
        !          1551:        n = (int)Align(sizeof(struct ie_xmit_cmd)) +
        !          1552:            (int)Align(sizeof(struct ie_xmit_buf)) + IE_TBUF_SIZE;
        !          1553:        n *= NTXBUF;            /* n = total size of xmit area */
        !          1554:
        !          1555:        n = sc->buf_area_sz - n;/* n = free space for recv stuff */
        !          1556:
        !          1557:        r = (int)Align(sizeof(struct ie_recv_frame_desc)) +
        !          1558:            (((int)Align(sizeof(struct ie_recv_buf_desc)) + IE_RBUF_SIZE) * B_PER_F);
        !          1559:
        !          1560:        /* r = size of one R frame */
        !          1561:
        !          1562:        sc->nframes = n / r;
        !          1563:        if (sc->nframes <= 0)
        !          1564:                panic("ie: bogus buffer calc");
        !          1565:        if (sc->nframes > MXFRAMES)
        !          1566:                sc->nframes = MXFRAMES;
        !          1567:
        !          1568:        sc->nrxbuf = sc->nframes * B_PER_F;
        !          1569:
        !          1570: #ifdef IEDEBUG
        !          1571:        printf("IEDEBUG: %d frames %d bufs\n", sc->nframes, sc->nrxbuf);
        !          1572: #endif
        !          1573:
        !          1574:        /*
        !          1575:         *  step 1a: lay out and zero frame data structures for transmit and recv
        !          1576:         */
        !          1577:        for (n = 0; n < NTXBUF; n++) {
        !          1578:                sc->xmit_cmds[n] = (volatile struct ie_xmit_cmd *) ptr;
        !          1579:                ptr = Align(ptr + sizeof(struct ie_xmit_cmd));
        !          1580:        }
        !          1581:
        !          1582:        for (n = 0; n < sc->nframes; n++) {
        !          1583:                sc->rframes[n] = (volatile struct ie_recv_frame_desc *) ptr;
        !          1584:                ptr = Align(ptr + sizeof(struct ie_recv_frame_desc));
        !          1585:        }
        !          1586:
        !          1587:        /*
        !          1588:         * step 1b: link together the recv frames and set EOL on last one
        !          1589:         */
        !          1590:        for (n = 0; n < sc->nframes; n++) {
        !          1591:                sc->rframes[n]->ie_fd_last = IE_FD_FLEX;
        !          1592:                sc->rframes[n]->ie_fd_size = 0;
        !          1593:                sc->rframes[n]->ie_fd_next =
        !          1594:                    ASWAP(sc->rframes[(n + 1) % sc->nframes]);
        !          1595:        }
        !          1596:        sc->rframes[sc->nframes - 1]->ie_fd_last |= IE_FD_LAST;
        !          1597:
        !          1598:        /*
        !          1599:         * step 2a: lay out and zero frame buffer structures for xmit and recv
        !          1600:         */
        !          1601:        for (n = 0; n < NTXBUF; n++) {
        !          1602:                sc->xmit_buffs[n] = (volatile struct ie_xmit_buf *) ptr;
        !          1603:                ptr = Align(ptr + sizeof(struct ie_xmit_buf));
        !          1604:        }
        !          1605:
        !          1606:        for (n = 0; n < sc->nrxbuf; n++) {
        !          1607:                sc->rbuffs[n] = (volatile struct ie_recv_buf_desc *) ptr;
        !          1608:                ptr = Align(ptr + sizeof(struct ie_recv_buf_desc));
        !          1609:        }
        !          1610:
        !          1611:        /*
        !          1612:         * step 2b: link together recv bufs and set EOL on last one
        !          1613:         */
        !          1614:        for (n = 0; n < sc->nrxbuf; n++) {
        !          1615:                sc->rbuffs[n]->ie_rbd_next =
        !          1616:                    ASWAP(sc->rbuffs[(n + 1) % sc->nrxbuf]);
        !          1617:        }
        !          1618:        sc->rbuffs[sc->nrxbuf - 1]->ie_rbd_length |= IE_RBD_LAST;
        !          1619:
        !          1620:        /*
        !          1621:         * step 3: allocate the actual data buffers for xmit and recv
        !          1622:         * recv buffer gets linked into recv_buf_desc list here
        !          1623:         */
        !          1624:        for (n = 0; n < NTXBUF; n++) {
        !          1625:                sc->xmit_cbuffs[n] = (u_char *) ptr;
        !          1626:                ptr = Align(ptr + IE_TBUF_SIZE);
        !          1627:        }
        !          1628:
        !          1629:        /* Pointers to last packet sent and next available transmit buffer. */
        !          1630:        sc->xchead = sc->xctail = 0;
        !          1631:
        !          1632:        /* Clear transmit-busy flag and set number of free transmit buffers. */
        !          1633:        sc->xmit_busy = 0;
        !          1634:        sc->xmit_free = NTXBUF;
        !          1635:
        !          1636:        for (n = 0; n < sc->nrxbuf; n++) {
        !          1637:                sc->cbuffs[n] = (char *) ptr;   /* XXX why char vs uchar? */
        !          1638:                sc->rbuffs[n]->ie_rbd_length = IE_RBUF_SIZE;
        !          1639:                SWT_32(sc->rbuffs[n]->ie_rbd_buffer, ptr);
        !          1640:                ptr = Align(ptr + IE_RBUF_SIZE);
        !          1641:        }
        !          1642:
        !          1643:        /*
        !          1644:         * step 4: set the head and tail pointers on receive to keep track of
        !          1645:         * the order in which RFDs and RBDs are used.   link in recv frames
        !          1646:         * and buffer into the scb.
        !          1647:         */
        !          1648:
        !          1649:        sc->rfhead = 0;
        !          1650:        sc->rftail = sc->nframes - 1;
        !          1651:        sc->rbhead = 0;
        !          1652:        sc->rbtail = sc->nrxbuf - 1;
        !          1653:
        !          1654:        sc->scb->ie_recv_list = ASWAP(sc->rframes[0]);
        !          1655:        sc->rframes[0]->ie_fd_buf_desc = ASWAP(sc->rbuffs[0]);
        !          1656:
        !          1657: #ifdef IEDEBUG
        !          1658:        printf("IE_DEBUG: reserved %d bytes\n", ptr - sc->buf_area);
        !          1659: #endif
        !          1660: }
        !          1661:
        !          1662: /*
        !          1663:  * Run the multicast setup command.
        !          1664:  * Called at splnet().
        !          1665:  */
        !          1666: int
        !          1667: mc_setup(sc, ptr)
        !          1668:        struct ie_softc *sc;
        !          1669:        void *ptr;
        !          1670: {
        !          1671:        volatile struct ie_mcast_cmd *cmd = ptr;
        !          1672:
        !          1673:        cmd->com.ie_cmd_status = 0;
        !          1674:        cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
        !          1675:        cmd->com.ie_cmd_link = 0xffffffff;
        !          1676:
        !          1677:        (sc->memcopy)((caddr_t)sc->mcast_addrs, (caddr_t)cmd->ie_mcast_addrs,
        !          1678:            sc->mcast_count * sizeof *sc->mcast_addrs);
        !          1679:
        !          1680:        cmd->ie_mcast_bytes = sc->mcast_count * ETHER_ADDR_LEN; /* grrr... */
        !          1681:
        !          1682:        sc->scb->ie_command_list = ASWAP(cmd);
        !          1683:        if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
        !          1684:            !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
        !          1685:                printf("%s: multicast address setup command failed\n",
        !          1686:                    sc->sc_dev.dv_xname);
        !          1687:                return 0;
        !          1688:        }
        !          1689:        return 1;
        !          1690: }
        !          1691:
        !          1692: /*
        !          1693:  * This routine takes the environment generated by check_ie_present() and adds
        !          1694:  * to it all the other structures we need to operate the adapter.  This
        !          1695:  * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
        !          1696:  * the receiver unit, and clearing interrupts.
        !          1697:  *
        !          1698:  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
        !          1699:  */
        !          1700: int
        !          1701: ieinit(sc)
        !          1702:        struct ie_softc *sc;
        !          1703: {
        !          1704:        volatile struct ie_sys_ctl_block *scb = sc->scb;
        !          1705:        void *ptr;
        !          1706:
        !          1707:        ptr = sc->buf_area;
        !          1708:
        !          1709:        /*
        !          1710:         * Set up bus throttles.
        !          1711:         */
        !          1712:
        !          1713:        {
        !          1714:                if (command_and_wait(sc, IE_CU_THROTTLE, 0, 0)) {
        !          1715:                        printf("%s: throttle set command failed\n",
        !          1716:                            sc->sc_dev.dv_xname);
        !          1717:                        return 0;
        !          1718:                }
        !          1719:        }
        !          1720:
        !          1721:        /*
        !          1722:         * Send the configure command first.
        !          1723:         */
        !          1724:
        !          1725:        {
        !          1726:                volatile struct ie_config_cmd *cmd = ptr;
        !          1727:
        !          1728:                scb->ie_command_list = ASWAP(cmd);
        !          1729:                cmd->com.ie_cmd_status = 0;
        !          1730:                cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
        !          1731:                cmd->com.ie_cmd_link = 0xffffffff;
        !          1732:
        !          1733:                ie_setup_config(cmd, sc->promisc, 0);
        !          1734:
        !          1735:                if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
        !          1736:                    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
        !          1737:                        printf("%s: configure command failed\n",
        !          1738:                            sc->sc_dev.dv_xname);
        !          1739:                        return 0;
        !          1740:                }
        !          1741:        }
        !          1742:
        !          1743:        /*
        !          1744:         * Now send the Individual Address Setup command.
        !          1745:         */
        !          1746:        {
        !          1747:                volatile struct ie_iasetup_cmd *cmd = ptr;
        !          1748:
        !          1749:                scb->ie_command_list = ASWAP(cmd);
        !          1750:                cmd->com.ie_cmd_status = 0;
        !          1751:                cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
        !          1752:                cmd->com.ie_cmd_link = 0xffffffff;
        !          1753:
        !          1754:                (sc->memcopy)(sc->sc_arpcom.ac_enaddr,
        !          1755:                      (caddr_t)&cmd->ie_address, sizeof cmd->ie_address);
        !          1756:
        !          1757:                if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
        !          1758:                    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
        !          1759:                        printf("%s: individual address setup command failed\n",
        !          1760:                            sc->sc_dev.dv_xname);
        !          1761:                        return 0;
        !          1762:                }
        !          1763:        }
        !          1764:
        !          1765:        /*
        !          1766:         * Now run the time-domain reflectometer.
        !          1767:         */
        !          1768:        run_tdr(sc, ptr);
        !          1769:
        !          1770:        /*
        !          1771:         * Acknowledge any interrupts we have generated thus far.
        !          1772:         */
        !          1773:        ie_ack(sc, IE_ST_WHENCE);
        !          1774:
        !          1775:        /*
        !          1776:         * Set up the transmit and recv buffers.
        !          1777:         */
        !          1778:        setup_bufs(sc);
        !          1779:
        !          1780:        sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING; /* tell higher levels that we are here */
        !          1781:
        !          1782:        sc->scb->ie_recv_list = ASWAP(sc->rframes[0]);
        !          1783:        command_and_wait(sc, IE_RU_START, 0, 0);
        !          1784:
        !          1785:        ie_ack(sc, IE_ST_WHENCE);
        !          1786:
        !          1787:        if (sc->run_596)
        !          1788:          (sc->run_596)(sc);
        !          1789:
        !          1790:        return 0;
        !          1791: }
        !          1792:
        !          1793: void
        !          1794: iestop(sc)
        !          1795:        struct ie_softc *sc;
        !          1796: {
        !          1797:
        !          1798:        command_and_wait(sc, IE_RU_DISABLE, 0, 0);
        !          1799: }
        !          1800:
        !          1801: int
        !          1802: ieioctl(ifp, cmd, data)
        !          1803:        register struct ifnet *ifp;
        !          1804:        u_long cmd;
        !          1805:        caddr_t data;
        !          1806: {
        !          1807:        struct ie_softc *sc = ifp->if_softc;
        !          1808:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          1809:        struct ifreq *ifr = (struct ifreq *)data;
        !          1810:        int s, error = 0;
        !          1811:
        !          1812:        s = splnet();
        !          1813:
        !          1814:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !          1815:                splx(s);
        !          1816:                return error;
        !          1817:        }
        !          1818:
        !          1819:        switch(cmd) {
        !          1820:
        !          1821:        case SIOCSIFADDR:
        !          1822:                ifp->if_flags |= IFF_UP;
        !          1823:
        !          1824:                switch(ifa->ifa_addr->sa_family) {
        !          1825: #ifdef INET
        !          1826:                case AF_INET:
        !          1827:                        ieinit(sc);
        !          1828:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !          1829:                        break;
        !          1830: #endif
        !          1831:                default:
        !          1832:                        ieinit(sc);
        !          1833:                        break;
        !          1834:                }
        !          1835:                break;
        !          1836:
        !          1837:        case SIOCSIFFLAGS:
        !          1838:                sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
        !          1839:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !          1840:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !          1841:                        /*
        !          1842:                         * If interface is marked down and it is running, then
        !          1843:                         * stop it.
        !          1844:                         */
        !          1845:                        iestop(sc);
        !          1846:                        ifp->if_flags &= ~IFF_RUNNING;
        !          1847:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !          1848:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !          1849:                        /*
        !          1850:                         * If interface is marked up and it is stopped, then
        !          1851:                         * start it.
        !          1852:                         */
        !          1853:                        ieinit(sc);
        !          1854:                } else {
        !          1855:                        /*
        !          1856:                         * Reset the interface to pick up changes in any other
        !          1857:                         * flags that affect hardware registers.
        !          1858:                         */
        !          1859:                        iestop(sc);
        !          1860:                        ieinit(sc);
        !          1861:                }
        !          1862: #ifdef IEDEBUG
        !          1863:                if (ifp->if_flags & IFF_DEBUG)
        !          1864:                        sc->sc_debug = IED_ALL;
        !          1865:                else
        !          1866:                        sc->sc_debug = 0;
        !          1867: #endif
        !          1868:                break;
        !          1869:
        !          1870:        case SIOCADDMULTI:
        !          1871:        case SIOCDELMULTI:
        !          1872:                error = (cmd == SIOCADDMULTI) ?
        !          1873:                    ether_addmulti(ifr, &sc->sc_arpcom):
        !          1874:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !          1875:
        !          1876:                if (error == ENETRESET) {
        !          1877:                        /*
        !          1878:                         * Multicast list has changed; set the hardware filter
        !          1879:                         * accordingly.
        !          1880:                         */
        !          1881:                        if (ifp->if_flags & IFF_RUNNING)
        !          1882:                                mc_reset(sc);
        !          1883:                        error = 0;
        !          1884:                }
        !          1885:                break;
        !          1886:
        !          1887:        default:
        !          1888:                error = EINVAL;
        !          1889:        }
        !          1890:        splx(s);
        !          1891:        return error;
        !          1892: }
        !          1893:
        !          1894: void
        !          1895: mc_reset(sc)
        !          1896:        struct ie_softc *sc;
        !          1897: {
        !          1898:        struct ether_multi *enm;
        !          1899:        struct ether_multistep step;
        !          1900:
        !          1901:        /*
        !          1902:         * Step through the list of addresses.
        !          1903:         */
        !          1904:        sc->mcast_count = 0;
        !          1905:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
        !          1906:        while (enm) {
        !          1907:                if (sc->mcast_count >= MAXMCAST ||
        !          1908:                    bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
        !          1909:                        sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
        !          1910:                        ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
        !          1911:                        goto setflag;
        !          1912:                }
        !          1913:
        !          1914:                bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
        !          1915:                sc->mcast_count++;
        !          1916:                ETHER_NEXT_MULTI(step, enm);
        !          1917:        }
        !          1918: setflag:
        !          1919:        sc->want_mcsetup = 1;
        !          1920: }
        !          1921:
        !          1922: #ifdef IEDEBUG
        !          1923: void
        !          1924: print_rbd(rbd)
        !          1925:        volatile struct ie_recv_buf_desc *rbd;
        !          1926: {
        !          1927:
        !          1928:        printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
        !          1929:            "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
        !          1930:            rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
        !          1931:            rbd->mbz);
        !          1932: }
        !          1933: #endif

CVSweb