[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

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