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

Annotation of sys/dev/isa/if_ie.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_ie.c,v 1.33 2006/04/16 00:46:32 pascoe Exp $       */
                      2: /*     $NetBSD: if_ie.c,v 1.51 1996/05/12 23:52:48 mycroft Exp $       */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1993, 1994, 1995 Charles Hannum.
                      6:  * Copyright (c) 1992, 1993, University of Vermont and State
                      7:  *  Agricultural College.
                      8:  * Copyright (c) 1992, 1993, Garrett A. Wollman.
                      9:  *
                     10:  * Portions:
                     11:  * Copyright (c) 1993, 1994, 1995, Rodney W. Grimes
                     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 82586 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:  * Intel EtherExpress 16 support taken from FreeBSD's if_ix.c, written
                     61:  * by Rodney W. Grimes.
                     62:  *
                     63:  * Majorly cleaned up and 3C507 code merged by Charles Hannum.
                     64:  */
                     65:
                     66: /*
                     67:  * The i82586 is a very versatile chip, found in many implementations.
                     68:  * Programming this chip is mostly the same, but certain details differ
                     69:  * from card to card.  This driver is written so that different cards
                     70:  * can be automatically detected at run-time.
                     71:  */
                     72:
                     73: /*
                     74: Mode of operation:
                     75:
                     76: We run the 82586 in a standard Ethernet mode.  We keep NFRAMES received frame
                     77: descriptors around for the receiver to use, and NRXBUF associated receive
                     78: buffer descriptors, both in a circular list.  Whenever a frame is received, we
                     79: rotate both lists as necessary.  (The 586 treats both lists as a simple
                     80: queue.)  We also keep a transmit command around so that packets can be sent
                     81: off quickly.
                     82:
                     83: We configure the adapter in AL-LOC = 1 mode, which means that the
                     84: Ethernet/802.3 MAC header is placed at the beginning of the receive buffer
                     85: rather than being split off into various fields in the RFD.  This also means
                     86: that we must include this header in the transmit buffer as well.
                     87:
                     88: By convention, all transmit commands, and only transmit commands, shall have
                     89: the I (IE_CMD_INTR) bit set in the command.  This way, when an interrupt
                     90: arrives at ieintr(), it is immediately possible to tell what precisely caused
                     91: it.  ANY OTHER command-sending routines should run at splnet(), and should
                     92: post an acknowledgement to every interrupt they generate.
                     93:
                     94: The 82586 has a 24-bit address space internally, and the adaptor's memory is
                     95: located at the top of this region.  However, the value we are given in
                     96: configuration is the CPU's idea of where the adaptor RAM is.  So, we must go
                     97: through a few gyrations to come up with a kernel virtual address which
                     98: represents the actual beginning of the 586 address space.  First, we autosize
                     99: the RAM by running through several possible sizes and trying to initialize the
                    100: adapter under the assumption that the selected size is correct.  Then, knowing
                    101: the correct RAM size, we set up our pointers in the softc.  `sc_maddr'
                    102: represents the computed base of the 586 address space.  `iomembot' represents
                    103: the actual configured base of adapter RAM.  Finally, `sc_msize' represents the
                    104: calculated size of 586 RAM.  Then, when laying out commands, we use the
                    105: interval [sc_maddr, sc_maddr + sc_msize); to make 24-pointers, we subtract
                    106: iomem, and to make 16-pointers, we subtract sc_maddr and and with 0xffff.
                    107: */
                    108:
                    109: #include "bpfilter.h"
                    110:
                    111: #include <sys/param.h>
                    112: #include <sys/systm.h>
                    113: #include <sys/mbuf.h>
                    114: #include <sys/buf.h>
                    115: #include <sys/protosw.h>
                    116: #include <sys/socket.h>
                    117: #include <sys/ioctl.h>
                    118: #include <sys/errno.h>
                    119: #include <sys/syslog.h>
                    120: #include <sys/device.h>
                    121: #include <sys/timeout.h>
                    122:
                    123: #include <net/if.h>
                    124: #include <net/if_types.h>
                    125: #include <net/if_dl.h>
                    126: #include <net/netisr.h>
                    127: #include <net/route.h>
                    128:
                    129: #if NBPFILTER > 0
                    130: #include <net/bpf.h>
                    131: #endif
                    132:
                    133: #ifdef INET
                    134: #include <netinet/in.h>
                    135: #include <netinet/in_systm.h>
                    136: #include <netinet/in_var.h>
                    137: #include <netinet/ip.h>
                    138: #include <netinet/if_ether.h>
                    139: #endif
                    140:
                    141: #include <machine/cpu.h>
                    142: #include <machine/bus.h>
                    143: #include <machine/intr.h>
                    144:
                    145: #include <dev/isa/isareg.h>
                    146: #include <dev/isa/isavar.h>
                    147: #include <i386/isa/isa_machdep.h>      /* XXX USES ISA HOLE DIRECTLY */
                    148: #include <dev/ic/i82586reg.h>
                    149: #include <dev/isa/if_ieatt.h>
                    150: #include <dev/isa/if_ie507.h>
                    151: #include <dev/isa/if_iee16.h>
                    152: #include <dev/isa/elink.h>
                    153:
                    154: #define        IED_RINT        0x01
                    155: #define        IED_TINT        0x02
                    156: #define        IED_RNR         0x04
                    157: #define        IED_CNA         0x08
                    158: #define        IED_READFRAME   0x10
                    159: #define        IED_ENQ         0x20
                    160: #define        IED_XMIT        0x40
                    161: #define        IED_ALL         0x7f
                    162:
                    163: /*
                    164: sizeof(iscp) == 1+1+2+4 == 8
                    165: sizeof(scb) == 2+2+2+2+2+2+2+2 == 16
                    166: NFRAMES * sizeof(rfd) == NFRAMES*(2+2+2+2+6+6+2+2) == NFRAMES*24 == 384
                    167: sizeof(xmit_cmd) == 2+2+2+2+6+2 == 18
                    168: sizeof(transmit buffer) == ETHER_MAX_LEN == 1518
                    169: sizeof(transmit buffer desc) == 8
                    170: -----
                    171: 1952
                    172:
                    173: NRXBUF * sizeof(rbd) == NRXBUF*(2+2+4+2+2) == NRXBUF*12
                    174: NRXBUF * IE_RBUF_SIZE == NRXBUF*256
                    175:
                    176: NRXBUF should be (16384 - 1952) / (256 + 12) == 14432 / 268 == 53
                    177:
                    178: With NRXBUF == 48, this leaves us 1568 bytes for another command or
                    179: more buffers.  Another transmit command would be 18+8+1518 == 1544
                    180: ---just barely fits!
                    181:
                    182: Obviously all these would have to be reduced for smaller memory sizes.
                    183: With a larger memory, it would be possible to roughly double the number of
                    184: both transmit and receive buffers.
                    185: */
                    186:
                    187: #define        NFRAMES         16              /* number of receive frames */
                    188: #define        NRXBUF          48              /* number of buffers to allocate */
                    189: #define        IE_RBUF_SIZE    256             /* size of each receive buffer;
                    190:                                                MUST BE POWER OF TWO */
                    191: #define        NTXBUF          2               /* number of transmit commands */
                    192: #define        IE_TBUF_SIZE    ETHER_MAX_LEN   /* length of transmit buffer */
                    193:
                    194:
                    195: enum ie_hardware {
                    196:        IE_STARLAN10,
                    197:        IE_EN100,
                    198:        IE_SLFIBER,
                    199:        IE_3C507,
                    200:        IE_EE16,
                    201:        IE_UNKNOWN
                    202: };
                    203:
                    204: const char *ie_hardware_names[] = {
                    205:        "StarLAN 10",
                    206:        "EN100",
                    207:        "StarLAN Fiber",
                    208:        "3C507",
                    209:        "EtherExpress 16",
                    210:        "Unknown"
                    211: };
                    212:
                    213: /*
                    214:  * Ethernet status, per interface.
                    215:  */
                    216: struct ie_softc {
                    217:        struct device sc_dev;
                    218:        void *sc_ih;
                    219:
                    220:        int sc_iobase;
                    221:        caddr_t sc_maddr;
                    222:        u_int sc_msize;
                    223:
                    224:        struct arpcom sc_arpcom;
                    225:
                    226:        void (*reset_586)(struct ie_softc *);
                    227:        void (*chan_attn)(struct ie_softc *);
                    228:
                    229:        enum ie_hardware hard_type;
                    230:        int hard_vers;
                    231:
                    232:        int want_mcsetup;
                    233:        int promisc;
                    234:        volatile struct ie_int_sys_conf_ptr *iscp;
                    235:        volatile struct ie_sys_ctl_block *scb;
                    236:
                    237:        int rfhead, rftail, rbhead, rbtail;
                    238:        volatile struct ie_recv_frame_desc *rframes[NFRAMES];
                    239:        volatile struct ie_recv_buf_desc *rbuffs[NRXBUF];
                    240:        volatile char *cbuffs[NRXBUF];
                    241:
                    242:        int xmit_busy;
                    243:        int xchead, xctail;
                    244:        volatile struct ie_xmit_cmd *xmit_cmds[NTXBUF];
                    245:        volatile struct ie_xmit_buf *xmit_buffs[NTXBUF];
                    246:        u_char *xmit_cbuffs[NTXBUF];
                    247:
                    248:        struct ie_en_addr mcast_addrs[MAXMCAST + 1];
                    249:        int mcast_count;
                    250:
                    251:        u_short irq_encoded;            /* encoded interrupt on IEE16 */
                    252:
                    253: #ifdef IEDEBUG
                    254:        int sc_debug;
                    255: #endif
                    256: };
                    257:
                    258: void iewatchdog(struct ifnet *);
                    259: int ieintr(void *);
                    260: void iestop(struct ie_softc *);
                    261: int ieinit(struct ie_softc *);
                    262: int ieioctl(struct ifnet *, u_long, caddr_t);
                    263: void iestart(struct ifnet *);
                    264: static void el_reset_586(struct ie_softc *);
                    265: static void sl_reset_586(struct ie_softc *);
                    266: static void el_chan_attn(struct ie_softc *);
                    267: static void sl_chan_attn(struct ie_softc *);
                    268: static void slel_get_address(struct ie_softc *);
                    269:
                    270: static void ee16_reset_586(struct ie_softc *);
                    271: static void ee16_chan_attn(struct ie_softc *);
                    272: static void ee16_interrupt_enable(struct ie_softc *);
                    273: void ee16_eeprom_outbits(struct ie_softc *, int, int);
                    274: void ee16_eeprom_clock(struct ie_softc *, int);
                    275: u_short ee16_read_eeprom(struct ie_softc *, int);
                    276: int ee16_eeprom_inbits(struct ie_softc *);
                    277:
                    278: void iereset(struct ie_softc *);
                    279: void ie_readframe(struct ie_softc *, int);
                    280: void ie_drop_packet_buffer(struct ie_softc *);
                    281: void ie_find_mem_size(struct ie_softc *);
                    282: static int command_and_wait(struct ie_softc *, int,
                    283:     void volatile *, int);
                    284: void ierint(struct ie_softc *);
                    285: void ietint(struct ie_softc *);
                    286: void iexmit(struct ie_softc *);
                    287: struct mbuf *ieget(struct ie_softc *,
                    288:     struct ether_header *, int *);
                    289: void iememinit(void *, struct ie_softc *);
                    290: static int mc_setup(struct ie_softc *, void *);
                    291: static void mc_reset(struct ie_softc *);
                    292:
                    293: #ifdef IEDEBUG
                    294: void print_rbd(volatile struct ie_recv_buf_desc *);
                    295:
                    296: int in_ierint = 0;
                    297: int in_ietint = 0;
                    298: #endif
                    299:
                    300: int    ieprobe(struct device *, void *, void *);
                    301: void   ieattach(struct device *, struct device *, void *);
                    302: int    sl_probe(struct ie_softc *, struct isa_attach_args *);
                    303: int    el_probe(struct ie_softc *, struct isa_attach_args *);
                    304: int    ee16_probe(struct ie_softc *, struct isa_attach_args *);
                    305: int    check_ie_present(struct ie_softc *, caddr_t, u_int);
                    306:
                    307: static __inline void ie_setup_config(volatile struct ie_config_cmd *,
                    308:     int, int);
                    309: static __inline void ie_ack(struct ie_softc *, u_int);
                    310: static __inline int ether_equal(u_char *, u_char *);
                    311: static __inline int check_eh(struct ie_softc *, struct ether_header *,
                    312:     int *);
                    313: static __inline int ie_buflen(struct ie_softc *, int);
                    314: static __inline int ie_packet_len(struct ie_softc *);
                    315:
                    316: static void run_tdr(struct ie_softc *, struct ie_tdr_cmd *);
                    317:
                    318: struct cfattach ie_isa_ca = {
                    319:        sizeof(struct ie_softc), ieprobe, ieattach
                    320: };
                    321:
                    322: struct cfdriver ie_cd = {
                    323:        NULL, "ie", DV_IFNET
                    324: };
                    325:
                    326: #define MK_24(base, ptr) ((caddr_t)((u_long)ptr - (u_long)base))
                    327: #define MK_16(base, ptr) ((u_short)(u_long)MK_24(base, ptr))
                    328:
                    329: #define PORT   sc->sc_iobase
                    330: #define MEM    sc->sc_maddr
                    331:
                    332: /*
                    333:  * Here are a few useful functions.  We could have done these as macros, but
                    334:  * since we have the inline facility, it makes sense to use that instead.
                    335:  */
                    336: static __inline void
                    337: ie_setup_config(cmd, promiscuous, manchester)
                    338:        volatile struct ie_config_cmd *cmd;
                    339:        int promiscuous, manchester;
                    340: {
                    341:
                    342:        cmd->ie_config_count = 0x0c;
                    343:        cmd->ie_fifo = 8;
                    344:        cmd->ie_save_bad = 0x40;
                    345:        cmd->ie_addr_len = 0x2e;
                    346:        cmd->ie_priority = 0;
                    347:        cmd->ie_ifs = 0x60;
                    348:        cmd->ie_slot_low = 0;
                    349:        cmd->ie_slot_high = 0xf2;
                    350:        cmd->ie_promisc = promiscuous | manchester << 2;
                    351:        cmd->ie_crs_cdt = 0;
                    352:        cmd->ie_min_len = 64;
                    353:        cmd->ie_junk = 0xff;
                    354: }
                    355:
                    356: static __inline void
                    357: ie_ack(sc, mask)
                    358:        struct ie_softc *sc;
                    359:        u_int mask;
                    360: {
                    361:        volatile struct ie_sys_ctl_block *scb = sc->scb;
                    362:
                    363:        scb->ie_command = scb->ie_status & mask;
                    364:        (sc->chan_attn)(sc);
                    365:
                    366:        while (scb->ie_command)
                    367:                ;               /* Spin Lock */
                    368: }
                    369:
                    370: int
                    371: ieprobe(parent, match, aux)
                    372:        struct device *parent;
                    373:        void *match, *aux;
                    374: {
                    375:        struct ie_softc *sc = match;
                    376:        struct isa_attach_args *ia = aux;
                    377:
                    378:        if (sl_probe(sc, ia))
                    379:                return 1;
                    380:        if (el_probe(sc, ia))
                    381:                return 1;
                    382:        if (ee16_probe(sc, ia))
                    383:                return 1;
                    384:        return 0;
                    385: }
                    386:
                    387: int
                    388: sl_probe(sc, ia)
                    389:        struct ie_softc *sc;
                    390:        struct isa_attach_args *ia;
                    391: {
                    392:        u_char c;
                    393:
                    394:        sc->sc_iobase = ia->ia_iobase;
                    395:
                    396:        /* Need this for part of the probe. */
                    397:        sc->reset_586 = sl_reset_586;
                    398:        sc->chan_attn = sl_chan_attn;
                    399:
                    400:        c = inb(PORT + IEATT_REVISION);
                    401:        switch (SL_BOARD(c)) {
                    402:        case SL10_BOARD:
                    403:                sc->hard_type = IE_STARLAN10;
                    404:                break;
                    405:        case EN100_BOARD:
                    406:                sc->hard_type = IE_EN100;
                    407:                break;
                    408:        case SLFIBER_BOARD:
                    409:                sc->hard_type = IE_SLFIBER;
                    410:                break;
                    411:
                    412:        default:
                    413:                /* Anything else is not recognized or cannot be used. */
                    414: #if 0
                    415:                printf("%s: unknown AT&T board type code %d\n",
                    416:                    sc->sc_dev.dv_xname, SL_BOARD(c));
                    417: #endif
                    418:                return 0;
                    419:        }
                    420:
                    421:        sc->hard_vers = SL_REV(c);
                    422:
                    423:        if (ia->ia_irq == IRQUNK || ia->ia_maddr == MADDRUNK) {
                    424:                printf("%s: %s does not have soft configuration\n",
                    425:                    sc->sc_dev.dv_xname, ie_hardware_names[sc->hard_type]);
                    426:                return 0;
                    427:        }
                    428:
                    429:        /*
                    430:         * Divine memory size on-board the card.  Ususally 16k.
                    431:         */
                    432:        sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);
                    433:        ie_find_mem_size(sc);
                    434:
                    435:        if (!sc->sc_msize) {
                    436:                printf("%s: can't find shared memory\n", sc->sc_dev.dv_xname);
                    437:                return 0;
                    438:        }
                    439:
                    440:        if (!ia->ia_msize)
                    441:                ia->ia_msize = sc->sc_msize;
                    442:        else if (ia->ia_msize != sc->sc_msize) {
                    443:                printf("%s: msize mismatch; kernel configured %d != board configured %d\n",
                    444:                    sc->sc_dev.dv_xname, ia->ia_msize, sc->sc_msize);
                    445:                return 0;
                    446:        }
                    447:
                    448:        slel_get_address(sc);
                    449:
                    450:        ia->ia_iosize = 16;
                    451:        return 1;
                    452: }
                    453:
                    454: int
                    455: el_probe(sc, ia)
                    456:        struct ie_softc *sc;
                    457:        struct isa_attach_args *ia;
                    458: {
                    459:        bus_space_tag_t iot = ia->ia_iot;
                    460:        bus_space_handle_t ioh;
                    461:        u_char c;
                    462:        int i, rval = 0;
                    463:        u_char signature[] = "*3COM*";
                    464:
                    465:        sc->sc_iobase = ia->ia_iobase;
                    466:
                    467:        /* Need this for part of the probe. */
                    468:        sc->reset_586 = el_reset_586;
                    469:        sc->chan_attn = el_chan_attn;
                    470:
                    471:        /*
                    472:         * Map the Etherlink ID port for the probe sequence.
                    473:         */
                    474:        if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh)) {
                    475:                printf("3c507 probe: can't map Etherlink ID port\n");
                    476:                return 0;
                    477:        }
                    478:
                    479:        /*
                    480:         * Reset and put card in CONFIG state without changing address.
                    481:         * XXX Indirect brokenness here!
                    482:         */
                    483:        elink_reset(iot, ioh, sc->sc_dev.dv_parent->dv_unit);
                    484:        elink_idseq(iot, ioh, ELINK_507_POLY);
                    485:        elink_idseq(iot, ioh, ELINK_507_POLY);
                    486:        outb(ELINK_ID_PORT, 0xff);
                    487:
                    488:        /* Check for 3COM signature before proceeding. */
                    489:        outb(PORT + IE507_CTRL, inb(PORT + IE507_CTRL) & 0xfc); /* XXX */
                    490:        for (i = 0; i < 6; i++)
                    491:                if (inb(PORT + i) != signature[i])
                    492:                        goto out;
                    493:
                    494:        c = inb(PORT + IE507_MADDR);
                    495:        if (c & 0x20) {
                    496:                printf("%s: can't map 3C507 RAM in high memory\n",
                    497:                    sc->sc_dev.dv_xname);
                    498:                goto out;
                    499:        }
                    500:
                    501:        /* Go to RUN state. */
                    502:        outb(ELINK_ID_PORT, 0x00);
                    503:        elink_idseq(iot, ioh, ELINK_507_POLY);
                    504:        outb(ELINK_ID_PORT, 0x00);
                    505:
                    506:        /* Set bank 2 for version info and read BCD version byte. */
                    507:        outb(PORT + IE507_CTRL, EL_CTRL_NRST | EL_CTRL_BNK2);
                    508:        i = inb(PORT + 3);
                    509:
                    510:        sc->hard_type = IE_3C507;
                    511:        sc->hard_vers = 10*(i / 16) + (i % 16) - 1;
                    512:
                    513:        i = inb(PORT + IE507_IRQ) & 0x0f;
                    514:
                    515:        if (ia->ia_irq != IRQUNK) {
                    516:                if (ia->ia_irq != i) {
                    517:                        printf("%s: irq mismatch; kernel configured %d != board configured %d\n",
                    518:                            sc->sc_dev.dv_xname, ia->ia_irq, i);
                    519:                        goto out;
                    520:                }
                    521:        } else
                    522:                ia->ia_irq = i;
                    523:
                    524:        i = ((inb(PORT + IE507_MADDR) & 0x1c) << 12) + 0xc0000;
                    525:
                    526:        if (ia->ia_maddr != MADDRUNK) {
                    527:                if (ia->ia_maddr != i) {
                    528:                        printf("%s: maddr mismatch; kernel configured %x != board configured %x\n",
                    529:                            sc->sc_dev.dv_xname, ia->ia_maddr, i);
                    530:                        goto out;
                    531:                }
                    532:        } else
                    533:                ia->ia_maddr = i;
                    534:
                    535:        outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
                    536:
                    537:        /*
                    538:         * Divine memory size on-board the card.
                    539:         */
                    540:        sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);
                    541:        ie_find_mem_size(sc);
                    542:
                    543:        if (!sc->sc_msize) {
                    544:                printf("%s: can't find shared memory\n", sc->sc_dev.dv_xname);
                    545:                outb(PORT + IE507_CTRL, EL_CTRL_NRST);
                    546:                goto out;
                    547:        }
                    548:
                    549:        if (!ia->ia_msize)
                    550:                ia->ia_msize = sc->sc_msize;
                    551:        else if (ia->ia_msize != sc->sc_msize) {
                    552:                printf("%s: msize mismatch; kernel configured %d != board configured %d\n",
                    553:                    sc->sc_dev.dv_xname, ia->ia_msize, sc->sc_msize);
                    554:                outb(PORT + IE507_CTRL, EL_CTRL_NRST);
                    555:                goto out;
                    556:        }
                    557:
                    558:        slel_get_address(sc);
                    559:
                    560:        /* Clear the interrupt latch just in case. */
                    561:        outb(PORT + IE507_ICTRL, 1);
                    562:
                    563:        ia->ia_iosize = 16;
                    564:        rval = 1;
                    565:
                    566:  out:
                    567:        bus_space_unmap(iot, ioh, 1);
                    568:        return rval;
                    569: }
                    570:
                    571: /* Taken almost exactly from Rod's if_ix.c. */
                    572:
                    573: int
                    574: ee16_probe(sc, ia)
                    575:        struct ie_softc *sc;
                    576:        struct isa_attach_args *ia;
                    577: {
                    578:        int i;
                    579:        u_short board_id, id_var1, id_var2, checksum = 0;
                    580:        u_short eaddrtemp, irq;
                    581:         u_short pg, adjust, decode, edecode;
                    582:        u_char  bart_config;
                    583:
                    584:        short   irq_translate[] = {0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0};
                    585:
                    586:        /* Need this for part of the probe. */
                    587:        sc->reset_586 = ee16_reset_586;
                    588:        sc->chan_attn = ee16_chan_attn;
                    589:
                    590:        /* reset any ee16 at the current iobase */
                    591:        outb(ia->ia_iobase + IEE16_ECTRL, IEE16_RESET_ASIC);
                    592:        outb(ia->ia_iobase + IEE16_ECTRL, 0);
                    593:        delay(240);
                    594:
                    595:        /* now look for ee16. */
                    596:        board_id = id_var1 = id_var2 = 0;
                    597:        for (i=0; i<4 ; i++) {
                    598:                id_var1 = inb(ia->ia_iobase + IEE16_ID_PORT);
                    599:                id_var2 = ((id_var1 & 0x03) << 2);
                    600:                board_id |= (( id_var1 >> 4)  << id_var2);
                    601:                }
                    602:
                    603:        if (board_id != IEE16_ID)
                    604:                return 0;
                    605:
                    606:        /* need sc->sc_iobase for ee16_read_eeprom */
                    607:        sc->sc_iobase = ia->ia_iobase;
                    608:        sc->hard_type = IE_EE16;
                    609:
                    610:        /*
                    611:         * If ia->maddr == MADDRUNK, use value in eeprom location 6.
                    612:         *
                    613:         * The shared RAM location on the EE16 is encoded into bits
                    614:         * 3-7 of EEPROM location 6.  We zero the upper byte, and
                    615:         * shift the 5 bits right 3.  The resulting number tells us
                    616:         * the RAM location.  Because the EE16 supports either 16k or 32k
                    617:         * of shared RAM, we only worry about the 32k locations.
                    618:         *
                    619:         * NOTE: if a 64k EE16 exists, it should be added to this switch.
                    620:         *       then the ia->ia_msize would need to be set per case statement.
                    621:         *
                    622:         *      value   msize   location
                    623:         *      =====   =====   ========
                    624:         *      0x03    0x8000  0xCC000
                    625:         *      0x06    0x8000  0xD0000
                    626:         *      0x0C    0x8000  0xD4000
                    627:         *      0x18    0x8000  0xD8000
                    628:         *
                    629:         */
                    630:
                    631:        if ((ia->ia_maddr == MADDRUNK) || (ia->ia_msize == 0)) {
                    632:                i = (ee16_read_eeprom(sc, 6) & 0x00ff ) >> 3;
                    633:                switch(i) {
                    634:                        case 0x03:
                    635:                                ia->ia_maddr = 0xCC000;
                    636:                                break;
                    637:                        case 0x06:
                    638:                                ia->ia_maddr = 0xD0000;
                    639:                                break;
                    640:                        case 0x0c:
                    641:                                ia->ia_maddr = 0xD4000;
                    642:                                break;
                    643:                        case 0x18:
                    644:                                ia->ia_maddr = 0xD8000;
                    645:                                break;
                    646:                        default:
                    647:                                return 0 ;
                    648:                                break; /* NOTREACHED */
                    649:                }
                    650:                ia->ia_msize = 0x8000;
                    651:        }
                    652:
                    653:        /* need to set these after checking for MADDRUNK */
                    654:        sc->sc_maddr = ISA_HOLE_VADDR(ia->ia_maddr);
                    655:        sc->sc_msize = ia->ia_msize;
                    656:
                    657:        /* need to put the 586 in RESET, and leave it */
                    658:        outb( PORT + IEE16_ECTRL, IEE16_RESET_586);
                    659:
                    660:        /* read the eeprom and checksum it, should == IEE16_ID */
                    661:        for(i=0 ; i< 0x40 ; i++)
                    662:                checksum += ee16_read_eeprom(sc, i);
                    663:
                    664:        if (checksum != IEE16_ID)
                    665:                return 0;
                    666:
                    667:        /*
                    668:         * Size and test the memory on the board.  The size of the memory
                    669:         * can be one of 16k, 32k, 48k or 64k.  It can be located in the
                    670:         * address range 0xC0000 to 0xEFFFF on 16k boundaries.
                    671:         *
                    672:         * If the size does not match the passed in memory allocation size
                    673:         * issue a warning, but continue with the minimum of the two sizes.
                    674:         */
                    675:
                    676:        switch (ia->ia_msize) {
                    677:                case 65536:
                    678:                case 32768: /* XXX Only support 32k and 64k right now */
                    679:                        break;
                    680:                case 16384:
                    681:                case 49512:
                    682:                default:
                    683:                        printf("ieprobe mapped memory size out of range\n");
                    684:                        return 0;
                    685:                        break; /* NOTREACHED */
                    686:        }
                    687:
                    688:        if ((kvtop(sc->sc_maddr) < 0xC0000) ||
                    689:            (kvtop(sc->sc_maddr) + sc->sc_msize > 0xF0000)) {
                    690:                printf("ieprobe mapped memory address out of range\n");
                    691:                return 0;
                    692:        }
                    693:
                    694:        pg = (kvtop(sc->sc_maddr) & 0x3C000) >> 14;
                    695:        adjust = IEE16_MCTRL_FMCS16 | (pg & 0x3) << 2;
                    696:        decode = ((1 << (sc->sc_msize / 16384)) - 1) << pg;
                    697:        edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
                    698:
                    699:        /* ZZZ This should be checked against eeprom location 6, low byte */
                    700:        outb(PORT + IEE16_MEMDEC, decode & 0xFF);
                    701:        /* ZZZ This should be checked against eeprom location 1, low byte */
                    702:        outb(PORT + IEE16_MCTRL, adjust);
                    703:        /* ZZZ Now if I could find this one I would have it made */
                    704:        outb(PORT + IEE16_MPCTRL, (~decode & 0xFF));
                    705:        /* ZZZ I think this is location 6, high byte */
                    706:        outb(PORT + IEE16_MECTRL, edecode); /*XXX disable Exxx */
                    707:
                    708:        /*
                    709:         * first prime the stupid bart DRAM controller so that it
                    710:         * works, then zero out all of memory.
                    711:         */
                    712:        bzero(sc->sc_maddr, 32);
                    713:        bzero(sc->sc_maddr, sc->sc_msize);
                    714:
                    715:        /*
                    716:         * Get the encoded interrupt number from the EEPROM, check it
                    717:         * against the passed in IRQ.  Issue a warning if they do not
                    718:         * match, and fail the probe.  If irq is 'IRQUNK' then we
                    719:         * use the EEPROM irq, and continue.
                    720:         */
                    721:        irq = ee16_read_eeprom(sc, IEE16_EEPROM_CONFIG1);
                    722:        irq = (irq & IEE16_EEPROM_IRQ) >> IEE16_EEPROM_IRQ_SHIFT;
                    723:        sc->irq_encoded = irq;
                    724:        irq = irq_translate[irq];
                    725:        if (ia->ia_irq != IRQUNK) {
                    726:                if (irq != ia->ia_irq) {
                    727: #ifdef DIAGNOSTIC
                    728:                        printf("\nie%d: fatal: board IRQ %d does not match kernel\n", sc->sc_dev.dv_unit, irq);
                    729: #endif /* DIAGNOSTIC */
                    730:                        return 0;       /* _must_ match or probe fails */
                    731:                }
                    732:        } else
                    733:                ia->ia_irq = irq;
                    734:
                    735:        /*
                    736:         * Get the hardware ethernet address from the EEPROM and
                    737:         * save it in the softc for use by the 586 setup code.
                    738:         */
                    739:        eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_HIGH);
                    740:        sc->sc_arpcom.ac_enaddr[1] = eaddrtemp & 0xFF;
                    741:        sc->sc_arpcom.ac_enaddr[0] = eaddrtemp >> 8;
                    742:        eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_MID);
                    743:        sc->sc_arpcom.ac_enaddr[3] = eaddrtemp & 0xFF;
                    744:        sc->sc_arpcom.ac_enaddr[2] = eaddrtemp >> 8;
                    745:        eaddrtemp = ee16_read_eeprom(sc, IEE16_EEPROM_ENET_LOW);
                    746:        sc->sc_arpcom.ac_enaddr[5] = eaddrtemp & 0xFF;
                    747:        sc->sc_arpcom.ac_enaddr[4] = eaddrtemp >> 8;
                    748:
                    749:        /* disable the board interrupts */
                    750:        outb(PORT + IEE16_IRQ, sc->irq_encoded);
                    751:
                    752:        /* enable loopback to keep bad packets off the wire */
                    753:        if(sc->hard_type == IE_EE16) {
                    754:                bart_config = inb(PORT + IEE16_CONFIG);
                    755:                bart_config |= IEE16_BART_LOOPBACK;
                    756:                bart_config |= IEE16_BART_MCS16_TEST; /* inb doesn't get bit! */
                    757:                outb(PORT + IEE16_CONFIG, bart_config);
                    758:                bart_config = inb(PORT + IEE16_CONFIG);
                    759:        }
                    760:
                    761:        outb(PORT + IEE16_ECTRL, 0);
                    762:        delay(100);
                    763:        if (!check_ie_present(sc, sc->sc_maddr, sc->sc_msize))
                    764:                return 0;
                    765:
                    766:        ia->ia_iosize = 16;     /* the number of I/O ports */
                    767:        return 1;               /* found */
                    768: }
                    769:
                    770: /*
                    771:  * Taken almost exactly from Bill's if_is.c, then modified beyond recognition.
                    772:  */
                    773: void
                    774: ieattach(parent, self, aux)
                    775:        struct device *parent, *self;
                    776:        void *aux;
                    777: {
                    778:        struct ie_softc *sc = (void *)self;
                    779:        struct isa_attach_args *ia = aux;
                    780:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    781:
                    782:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    783:        ifp->if_softc = sc;
                    784:        ifp->if_start = iestart;
                    785:        ifp->if_ioctl = ieioctl;
                    786:        ifp->if_watchdog = iewatchdog;
                    787:        ifp->if_flags =
                    788:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    789:        IFQ_SET_READY(&ifp->if_snd);
                    790:
                    791:        /* Attach the interface. */
                    792:        if_attach(ifp);
                    793:        ether_ifattach(ifp);
                    794:
                    795:        printf(": address %s, type %s R%d\n",
                    796:            ether_sprintf(sc->sc_arpcom.ac_enaddr),
                    797:            ie_hardware_names[sc->hard_type], sc->hard_vers + 1);
                    798:
                    799:        sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
                    800:            IPL_NET, ieintr, sc, sc->sc_dev.dv_xname);
                    801: }
                    802:
                    803: /*
                    804:  * Device timeout/watchdog routine.  Entered if the device neglects to generate
                    805:  * an interrupt after a transmit has been started on it.
                    806:  */
                    807: void
                    808: iewatchdog(ifp)
                    809:        struct ifnet *ifp;
                    810: {
                    811:        struct ie_softc *sc = ifp->if_softc;
                    812:
                    813:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    814:        ++sc->sc_arpcom.ac_if.if_oerrors;
                    815:        iereset(sc);
                    816: }
                    817:
                    818: /*
                    819:  * What to do upon receipt of an interrupt.
                    820:  */
                    821: int
                    822: ieintr(arg)
                    823:        void *arg;
                    824: {
                    825:        struct ie_softc *sc = arg;
                    826:        register u_short status;
                    827:
                    828:        /* Clear the interrupt latch on the 3C507. */
                    829:        if (sc->hard_type == IE_3C507)
                    830:                outb(PORT + IE507_ICTRL, 1);
                    831:
                    832:        /* disable interrupts on the EE16. */
                    833:        if (sc->hard_type == IE_EE16)
                    834:                outb(PORT + IEE16_IRQ, sc->irq_encoded);
                    835:
                    836:        status = sc->scb->ie_status & IE_ST_WHENCE;
                    837:        if (status == 0)
                    838:                return 0;
                    839:
                    840: loop:
                    841:        /* Ack interrupts FIRST in case we receive more during the ISR. */
                    842:        ie_ack(sc, status);
                    843:
                    844:        if (status & (IE_ST_FR | IE_ST_RNR)) {
                    845: #ifdef IEDEBUG
                    846:                in_ierint++;
                    847:                if (sc->sc_debug & IED_RINT)
                    848:                        printf("%s: rint\n", sc->sc_dev.dv_xname);
                    849: #endif
                    850:                ierint(sc);
                    851: #ifdef IEDEBUG
                    852:                in_ierint--;
                    853: #endif
                    854:        }
                    855:
                    856:        if (status & IE_ST_CX) {
                    857: #ifdef IEDEBUG
                    858:                in_ietint++;
                    859:                if (sc->sc_debug & IED_TINT)
                    860:                        printf("%s: tint\n", sc->sc_dev.dv_xname);
                    861: #endif
                    862:                ietint(sc);
                    863: #ifdef IEDEBUG
                    864:                in_ietint--;
                    865: #endif
                    866:        }
                    867:
                    868:        if (status & IE_ST_RNR) {
                    869:                printf("%s: receiver not ready\n", sc->sc_dev.dv_xname);
                    870:                sc->sc_arpcom.ac_if.if_ierrors++;
                    871:                iereset(sc);
                    872:        }
                    873:
                    874: #ifdef IEDEBUG
                    875:        if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))
                    876:                printf("%s: cna\n", sc->sc_dev.dv_xname);
                    877: #endif
                    878:
                    879:        /* Clear the interrupt latch on the 3C507. */
                    880:        if (sc->hard_type == IE_3C507)
                    881:                outb(PORT + IE507_ICTRL, 1);
                    882:
                    883:        status = sc->scb->ie_status & IE_ST_WHENCE;
                    884:        if (status == 0) {
                    885:                /* enable interrupts on the EE16. */
                    886:                if (sc->hard_type == IE_EE16)
                    887:                    outb(PORT + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
                    888:                return 1;
                    889:        }
                    890:
                    891:        goto loop;
                    892: }
                    893:
                    894: /*
                    895:  * Process a received-frame interrupt.
                    896:  */
                    897: void
                    898: ierint(sc)
                    899:        struct ie_softc *sc;
                    900: {
                    901:        volatile struct ie_sys_ctl_block *scb = sc->scb;
                    902:        int i, status;
                    903:        static int timesthru = 1024;
                    904:
                    905:        i = sc->rfhead;
                    906:        for (;;) {
                    907:                status = sc->rframes[i]->ie_fd_status;
                    908:
                    909:                if ((status & IE_FD_COMPLETE) && (status & IE_FD_OK)) {
                    910:                        if (!--timesthru) {
                    911:                                sc->sc_arpcom.ac_if.if_ierrors +=
                    912:                                    scb->ie_err_crc + scb->ie_err_align +
                    913:                                    scb->ie_err_resource + scb->ie_err_overrun;
                    914:                                scb->ie_err_crc = scb->ie_err_align =
                    915:                                    scb->ie_err_resource = scb->ie_err_overrun =
                    916:                                    0;
                    917:                                timesthru = 1024;
                    918:                        }
                    919:                        ie_readframe(sc, i);
                    920:                } else {
                    921:                        if ((status & IE_FD_RNR) != 0 &&
                    922:                            (scb->ie_status & IE_RU_READY) == 0) {
                    923:                                sc->rframes[0]->ie_fd_buf_desc =
                    924:                                                MK_16(MEM, sc->rbuffs[0]);
                    925:                                scb->ie_recv_list = MK_16(MEM, sc->rframes[0]);
                    926:                                command_and_wait(sc, IE_RU_START, 0, 0);
                    927:                        }
                    928:                        break;
                    929:                }
                    930:                i = (i + 1) % NFRAMES;
                    931:        }
                    932: }
                    933:
                    934: /*
                    935:  * Process a command-complete interrupt.  These are only generated by the
                    936:  * transmission of frames.  This routine is deceptively simple, since most of
                    937:  * the real work is done by iestart().
                    938:  */
                    939: void
                    940: ietint(sc)
                    941:        struct ie_softc *sc;
                    942: {
                    943:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    944:        int status;
                    945:
                    946:        ifp->if_timer = 0;
                    947:        ifp->if_flags &= ~IFF_OACTIVE;
                    948:
                    949:        status = sc->xmit_cmds[sc->xctail]->ie_xmit_status;
                    950:
                    951:        if (!(status & IE_STAT_COMPL) || (status & IE_STAT_BUSY))
                    952:                printf("ietint: command still busy!\n");
                    953:
                    954:        if (status & IE_STAT_OK) {
                    955:                ifp->if_opackets++;
                    956:                ifp->if_collisions += status & IE_XS_MAXCOLL;
                    957:        } else {
                    958:                ifp->if_oerrors++;
                    959:                /*
                    960:                 * XXX
                    961:                 * Check SQE and DEFERRED?
                    962:                 * What if more than one bit is set?
                    963:                 */
                    964:                if (status & IE_STAT_ABORT)
                    965:                        printf("%s: send aborted\n", sc->sc_dev.dv_xname);
                    966:                else if (status & IE_XS_LATECOLL)
                    967:                        printf("%s: late collision\n", sc->sc_dev.dv_xname);
                    968:                else if (status & IE_XS_NOCARRIER)
                    969:                        printf("%s: no carrier\n", sc->sc_dev.dv_xname);
                    970:                else if (status & IE_XS_LOSTCTS)
                    971:                        printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
                    972:                else if (status & IE_XS_UNDERRUN)
                    973:                        printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
                    974:                else if (status & IE_XS_EXCMAX) {
                    975:                        printf("%s: too many collisions\n", sc->sc_dev.dv_xname);
                    976:                        ifp->if_collisions += 16;
                    977:                }
                    978:        }
                    979:
                    980:        /*
                    981:         * If multicast addresses were added or deleted while transmitting,
                    982:         * mc_reset() set the want_mcsetup flag indicating that we should do
                    983:         * it.
                    984:         */
                    985:        if (sc->want_mcsetup) {
                    986:                mc_setup(sc, (caddr_t)sc->xmit_cbuffs[sc->xctail]);
                    987:                sc->want_mcsetup = 0;
                    988:        }
                    989:
                    990:        /* Done with the buffer. */
                    991:        sc->xmit_busy--;
                    992:        sc->xctail = (sc->xctail + 1) % NTXBUF;
                    993:
                    994:        /* Start the next packet, if any, transmitting. */
                    995:        if (sc->xmit_busy > 0)
                    996:                iexmit(sc);
                    997:
                    998:        iestart(ifp);
                    999: }
                   1000:
                   1001: /*
                   1002:  * Compare two Ether/802 addresses for equality, inlined and unrolled for
                   1003:  * speed.  I'd love to have an inline assembler version of this...
                   1004:  */
                   1005: static __inline int
                   1006: ether_equal(one, two)
                   1007:        u_char *one, *two;
                   1008: {
                   1009:
                   1010:        if (one[0] != two[0] || one[1] != two[1] || one[2] != two[2] ||
                   1011:            one[3] != two[3] || one[4] != two[4] || one[5] != two[5])
                   1012:                return 0;
                   1013:        return 1;
                   1014: }
                   1015:
                   1016: /*
                   1017:  * Check for a valid address.  to_bpf is filled in with one of the following:
                   1018:  *   0 -> BPF doesn't get this packet
                   1019:  *   1 -> BPF does get this packet
                   1020:  *   2 -> BPF does get this packet, but we don't
                   1021:  * Return value is true if the packet is for us, and false otherwise.
                   1022:  *
                   1023:  * This routine is a mess, but it's also critical that it be as fast
                   1024:  * as possible.  It could be made cleaner if we can assume that the
                   1025:  * only client which will fiddle with IFF_PROMISC is BPF.  This is
                   1026:  * probably a good assumption, but we do not make it here.  (Yet.)
                   1027:  */
                   1028: static __inline int
                   1029: check_eh(sc, eh, to_bpf)
                   1030:        struct ie_softc *sc;
                   1031:        struct ether_header *eh;
                   1032:        int *to_bpf;
                   1033: {
                   1034:        int i;
                   1035:
                   1036:        switch (sc->promisc) {
                   1037:        case IFF_ALLMULTI:
                   1038:                /*
                   1039:                 * Receiving all multicasts, but no unicasts except those
                   1040:                 * destined for us.
                   1041:                 */
                   1042: #if NBPFILTER > 0
                   1043:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0); /* BPF gets this packet if anybody cares */
                   1044: #endif
                   1045:                if (eh->ether_dhost[0] & 1)
                   1046:                        return 1;
                   1047:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1048:                        return 1;
                   1049:                return 0;
                   1050:
                   1051:        case IFF_PROMISC:
                   1052:                /*
                   1053:                 * Receiving all packets.  These need to be passed on to BPF.
                   1054:                 */
                   1055: #if NBPFILTER > 0
                   1056:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0) ||
                   1057:                    (sc->sc_arpcom.ac_if.if_bridge != NULL);
                   1058: #else
                   1059:                *to_bpf = (sc->sc_arpcom.ac_if.if_bridge != NULL);
                   1060: #endif
                   1061:                /* If for us, accept and hand up to BPF */
                   1062:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1063:                        return 1;
                   1064:
                   1065: #if NBPFILTER > 0
                   1066:                if (*to_bpf && sc->sc_arpcom.ac_if.if_bridge == NULL)
                   1067:                        *to_bpf = 2; /* we don't need to see it */
                   1068: #endif
                   1069:
                   1070:                /*
                   1071:                 * Not a multicast, so BPF wants to see it but we don't.
                   1072:                 */
                   1073:                if (!(eh->ether_dhost[0] & 1))
                   1074:                        return 1;
                   1075:
                   1076:                /*
                   1077:                 * If it's one of our multicast groups, accept it and pass it
                   1078:                 * up.
                   1079:                 */
                   1080:                for (i = 0; i < sc->mcast_count; i++) {
                   1081:                        if (ether_equal(eh->ether_dhost, (u_char *)&sc->mcast_addrs[i])) {
                   1082: #if NBPFILTER > 0
                   1083:                                if (*to_bpf)
                   1084:                                        *to_bpf = 1;
                   1085: #endif
                   1086:                                return 1;
                   1087:                        }
                   1088:                }
                   1089:                return 1;
                   1090:
                   1091:        case IFF_ALLMULTI | IFF_PROMISC:
                   1092:                /*
                   1093:                 * Acting as a multicast router, and BPF running at the same
                   1094:                 * time.  Whew!  (Hope this is a fast machine...)
                   1095:                 */
                   1096: #if NBPFILTER > 0
                   1097:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0) ||
                   1098:                    (sc->sc_arpcom.ac_if.if_bridge != NULL);
                   1099: #else
                   1100:                *to_bpf = (sc->sc_arpcom.ac_if.if_bridge != NULL);
                   1101: #endif
                   1102:                /* We want to see multicasts. */
                   1103:                if (eh->ether_dhost[0] & 1)
                   1104:                        return 1;
                   1105:
                   1106:                /* We want to see our own packets */
                   1107:                if (ether_equal(eh->ether_dhost, sc->sc_arpcom.ac_enaddr))
                   1108:                        return 1;
                   1109:
                   1110:                /* Anything else goes to BPF but nothing else. */
                   1111: #if NBPFILTER > 0
                   1112:                if (*to_bpf && sc->sc_arpcom.ac_if.if_bridge == NULL)
                   1113:                        *to_bpf = 2;
                   1114: #endif
                   1115:                return 1;
                   1116:
                   1117:        case 0:
                   1118:                /*
                   1119:                 * Only accept unicast packets destined for us, or multicasts
                   1120:                 * for groups that we belong to.  For now, we assume that the
                   1121:                 * '586 will only return packets that we asked it for.  This
                   1122:                 * isn't strictly true (it uses hashing for the multicast
                   1123:                 * filter), but it will do in this case, and we want to get out
                   1124:                 * of here as quickly as possible.
                   1125:                 */
                   1126: #if NBPFILTER > 0
                   1127:                *to_bpf = (sc->sc_arpcom.ac_if.if_bpf != 0);
                   1128: #endif
                   1129:                return 1;
                   1130:        }
                   1131:
                   1132: #ifdef DIAGNOSTIC
                   1133:        panic("check_eh: impossible");
                   1134: #endif
                   1135:        return 0;
                   1136: }
                   1137:
                   1138: /*
                   1139:  * We want to isolate the bits that have meaning...  This assumes that
                   1140:  * IE_RBUF_SIZE is an even power of two.  If somehow the act_len exceeds
                   1141:  * the size of the buffer, then we are screwed anyway.
                   1142:  */
                   1143: static __inline int
                   1144: ie_buflen(sc, head)
                   1145:        struct ie_softc *sc;
                   1146:        int head;
                   1147: {
                   1148:
                   1149:        return (sc->rbuffs[head]->ie_rbd_actual
                   1150:            & (IE_RBUF_SIZE | (IE_RBUF_SIZE - 1)));
                   1151: }
                   1152:
                   1153: static __inline int
                   1154: ie_packet_len(sc)
                   1155:        struct ie_softc *sc;
                   1156: {
                   1157:        int i;
                   1158:        int head = sc->rbhead;
                   1159:        int acc = 0;
                   1160:
                   1161:        do {
                   1162:                if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED))
                   1163:                        return -1;
                   1164:
                   1165:                i = sc->rbuffs[head]->ie_rbd_actual & IE_RBD_LAST;
                   1166:
                   1167:                acc += ie_buflen(sc, head);
                   1168:                head = (head + 1) % NRXBUF;
                   1169:        } while (!i);
                   1170:
                   1171:        return acc;
                   1172: }
                   1173:
                   1174: /*
                   1175:  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
                   1176:  * command to the chip to be executed.  On the way, if we have a BPF listener
                   1177:  * also give him a copy.
                   1178:  */
                   1179: void
                   1180: iexmit(sc)
                   1181:        struct ie_softc *sc;
                   1182: {
                   1183:
                   1184: #ifdef IEDEBUG
                   1185:        if (sc->sc_debug & IED_XMIT)
                   1186:                printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname,
                   1187:                    sc->xctail);
                   1188: #endif
                   1189:
                   1190: #if NBPFILTER > 0
                   1191:        /*
                   1192:         * If BPF is listening on this interface, let it see the packet before
                   1193:         * we push it on the wire.
                   1194:         */
                   1195:        if (sc->sc_arpcom.ac_if.if_bpf)
                   1196:                bpf_tap(sc->sc_arpcom.ac_if.if_bpf,
                   1197:                    sc->xmit_cbuffs[sc->xctail],
                   1198:                    sc->xmit_buffs[sc->xctail]->ie_xmit_flags,
                   1199:                    BPF_DIRECTION_OUT);
                   1200: #endif
                   1201:
                   1202:        sc->xmit_buffs[sc->xctail]->ie_xmit_flags |= IE_XMIT_LAST;
                   1203:        sc->xmit_buffs[sc->xctail]->ie_xmit_next = 0xffff;
                   1204:        sc->xmit_buffs[sc->xctail]->ie_xmit_buf =
                   1205:            MK_24(MEM, sc->xmit_cbuffs[sc->xctail]);
                   1206:
                   1207:        sc->xmit_cmds[sc->xctail]->com.ie_cmd_link = 0xffff;
                   1208:        sc->xmit_cmds[sc->xctail]->com.ie_cmd_cmd =
                   1209:            IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST;
                   1210:
                   1211:        sc->xmit_cmds[sc->xctail]->ie_xmit_status = 0;
                   1212:        sc->xmit_cmds[sc->xctail]->ie_xmit_desc =
                   1213:            MK_16(MEM, sc->xmit_buffs[sc->xctail]);
                   1214:
                   1215:        sc->scb->ie_command_list = MK_16(MEM, sc->xmit_cmds[sc->xctail]);
                   1216:        command_and_wait(sc, IE_CU_START, 0, 0);
                   1217:
                   1218:        sc->sc_arpcom.ac_if.if_timer = 5;
                   1219: }
                   1220:
                   1221: /*
                   1222:  * Read data off the interface, and turn it into an mbuf chain.
                   1223:  *
                   1224:  * This code is DRAMATICALLY different from the previous version; this version
                   1225:  * tries to allocate the entire mbuf chain up front, given the length of the
                   1226:  * data available.  This enables us to allocate mbuf clusters in many
                   1227:  * situations where before we would have had a long chain of partially-full
                   1228:  * mbufs.  This should help to speed up the operation considerably.  (Provided
                   1229:  * that it works, of course.)
                   1230:  */
                   1231: struct mbuf *
                   1232: ieget(sc, ehp, to_bpf)
                   1233:        struct ie_softc *sc;
                   1234:        struct ether_header *ehp;
                   1235:        int *to_bpf;
                   1236: {
                   1237:        struct mbuf *top, **mp, *m;
                   1238:        int len, totlen, resid;
                   1239:        int thisrboff, thismboff;
                   1240:        int head;
                   1241:
                   1242:        resid = totlen = ie_packet_len(sc);
                   1243:        if (totlen <= 0)
                   1244:                return 0;
                   1245:
                   1246:        head = sc->rbhead;
                   1247:
                   1248:        /*
                   1249:         * Snarf the Ethernet header.
                   1250:         */
                   1251:        bcopy((caddr_t)sc->cbuffs[head], (caddr_t)ehp, sizeof *ehp);
                   1252:
                   1253:        /*
                   1254:         * As quickly as possible, check if this packet is for us.
                   1255:         * If not, don't waste a single cycle copying the rest of the
                   1256:         * packet in.
                   1257:         * This is only a consideration when FILTER is defined; i.e., when
                   1258:         * we are either running BPF or doing multicasting.
                   1259:         */
                   1260:        if (!check_eh(sc, ehp, to_bpf)) {
                   1261:                sc->sc_arpcom.ac_if.if_ierrors--; /* just this case, it's not an error */
                   1262:                return 0;
                   1263:        }
                   1264:
                   1265:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1266:        if (m == 0)
                   1267:                return 0;
                   1268:        m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
                   1269:        m->m_pkthdr.len = totlen;
                   1270:        len = MHLEN;
                   1271:        top = 0;
                   1272:        mp = &top;
                   1273:
                   1274:        /*
                   1275:         * This loop goes through and allocates mbufs for all the data we will
                   1276:         * be copying in.  It does not actually do the copying yet.
                   1277:         */
                   1278:        while (totlen > 0) {
                   1279:                if (top) {
                   1280:                        MGET(m, M_DONTWAIT, MT_DATA);
                   1281:                        if (m == 0) {
                   1282:                                m_freem(top);
                   1283:                                return 0;
                   1284:                        }
                   1285:                        len = MLEN;
                   1286:                }
                   1287:                if (totlen >= MINCLSIZE) {
                   1288:                        MCLGET(m, M_DONTWAIT);
                   1289:                        if (m->m_flags & M_EXT)
                   1290:                                len = MCLBYTES;
                   1291:                }
                   1292:                m->m_len = len = min(totlen, len);
                   1293:                totlen -= len;
                   1294:                *mp = m;
                   1295:                mp = &m->m_next;
                   1296:        }
                   1297:
                   1298:        m = top;
                   1299:        thisrboff = 0;
                   1300:        thismboff = 0;
                   1301:
                   1302:        /*
                   1303:         * Now we take the mbuf chain (hopefully only one mbuf most of the
                   1304:         * time) and stuff the data into it.  There are no possible failures at
                   1305:         * or after this point.
                   1306:         */
                   1307:        while (resid > 0) {
                   1308:                int thisrblen = ie_buflen(sc, head) - thisrboff,
                   1309:                    thismblen = m->m_len - thismboff;
                   1310:                len = min(thisrblen, thismblen);
                   1311:
                   1312:                bcopy((caddr_t)(sc->cbuffs[head] + thisrboff),
                   1313:                    mtod(m, caddr_t) + thismboff, (u_int)len);
                   1314:                resid -= len;
                   1315:
                   1316:                if (len == thismblen) {
                   1317:                        m = m->m_next;
                   1318:                        thismboff = 0;
                   1319:                } else
                   1320:                        thismboff += len;
                   1321:
                   1322:                if (len == thisrblen) {
                   1323:                        head = (head + 1) % NRXBUF;
                   1324:                        thisrboff = 0;
                   1325:                } else
                   1326:                        thisrboff += len;
                   1327:        }
                   1328:
                   1329:        /*
                   1330:         * Unless something changed strangely while we were doing the copy, we
                   1331:         * have now copied everything in from the shared memory.
                   1332:         * This means that we are done.
                   1333:         */
                   1334:        return top;
                   1335: }
                   1336:
                   1337: /*
                   1338:  * Read frame NUM from unit UNIT (pre-cached as IE).
                   1339:  *
                   1340:  * This routine reads the RFD at NUM, and copies in the buffers from the list
                   1341:  * of RBD, then rotates the RBD and RFD lists so that the receiver doesn't
                   1342:  * start complaining.  Trailers are DROPPED---there's no point in wasting time
                   1343:  * on confusing code to deal with them.  Hopefully, this machine will never ARP
                   1344:  * for trailers anyway.
                   1345:  */
                   1346: void
                   1347: ie_readframe(sc, num)
                   1348:        struct ie_softc *sc;
                   1349:        int num;                        /* frame number to read */
                   1350: {
                   1351:        int status;
                   1352:        struct mbuf *m = 0;
                   1353:        struct ether_header eh;
                   1354: #if NBPFILTER > 0
                   1355:        int bpf_gets_it = 0;
                   1356: #endif
                   1357:
                   1358:        status = sc->rframes[num]->ie_fd_status;
                   1359:
                   1360:        /* Advance the RFD list, since we're done with this descriptor. */
                   1361:        sc->rframes[num]->ie_fd_status = 0;
                   1362:        sc->rframes[num]->ie_fd_last |= IE_FD_LAST;
                   1363:        sc->rframes[sc->rftail]->ie_fd_last &= ~IE_FD_LAST;
                   1364:        sc->rftail = (sc->rftail + 1) % NFRAMES;
                   1365:        sc->rfhead = (sc->rfhead + 1) % NFRAMES;
                   1366:
                   1367:        if (status & IE_FD_OK) {
                   1368: #if NBPFILTER > 0
                   1369:                m = ieget(sc, &eh, &bpf_gets_it);
                   1370: #else
                   1371:                m = ieget(sc, &eh, 0);
                   1372: #endif
                   1373:                ie_drop_packet_buffer(sc);
                   1374:        }
                   1375:        if (m == 0) {
                   1376:                sc->sc_arpcom.ac_if.if_ierrors++;
                   1377:                return;
                   1378:        }
                   1379:
                   1380: #ifdef IEDEBUG
                   1381:        if (sc->sc_debug & IED_READFRAME)
                   1382:                printf("%s: frame from ether %s type %x\n", sc->sc_dev.dv_xname,
                   1383:                    ether_sprintf(eh.ether_shost), (u_int)eh.ether_type);
                   1384: #endif
                   1385:
                   1386: #if NBPFILTER > 0
                   1387:        /* Check for a BPF filter; if so, hand it up. */
                   1388:        if (bpf_gets_it) {
                   1389:                /* Pass it up. */
                   1390:                bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m, BPF_DIRECTION_IN);
                   1391:
                   1392:                /*
                   1393:                 * A signal passed up from the filtering code indicating that
                   1394:                 * the packet is intended for BPF but not for the protocol
                   1395:                 * machinery.  We can save a few cycles by not handing it off
                   1396:                 * to them.
                   1397:                 */
                   1398:                if (bpf_gets_it == 2) {
                   1399:                        m_freem(m);
                   1400:                        return;
                   1401:                }
                   1402:        }
                   1403: #endif /* NBPFILTER > 0 */
                   1404:
                   1405:        /*
                   1406:         * In here there used to be code to check destination addresses upon
                   1407:         * receipt of a packet.  We have deleted that code, and replaced it
                   1408:         * with code to check the address much earlier in the cycle, before
                   1409:         * copying the data in; this saves us valuable cycles when operating
                   1410:         * as a multicast router or when using BPF.
                   1411:         */
                   1412:
                   1413:        /*
                   1414:         * Finally pass this packet up to higher layers.
                   1415:         */
                   1416:        ether_input_mbuf(&sc->sc_arpcom.ac_if, m);
                   1417:        sc->sc_arpcom.ac_if.if_ipackets++;
                   1418: }
                   1419:
                   1420: void
                   1421: ie_drop_packet_buffer(sc)
                   1422:        struct ie_softc *sc;
                   1423: {
                   1424:        int i;
                   1425:
                   1426:        do {
                   1427:                /*
                   1428:                 * This means we are somehow out of sync.  So, we reset the
                   1429:                 * adapter.
                   1430:                 */
                   1431:                if (!(sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_USED)) {
                   1432: #ifdef IEDEBUG
                   1433:                        print_rbd(sc->rbuffs[sc->rbhead]);
                   1434: #endif
                   1435:                        log(LOG_ERR, "%s: receive descriptors out of sync at %d\n",
                   1436:                            sc->sc_dev.dv_xname, sc->rbhead);
                   1437:                        iereset(sc);
                   1438:                        return;
                   1439:                }
                   1440:
                   1441:                i = sc->rbuffs[sc->rbhead]->ie_rbd_actual & IE_RBD_LAST;
                   1442:
                   1443:                sc->rbuffs[sc->rbhead]->ie_rbd_length |= IE_RBD_LAST;
                   1444:                sc->rbuffs[sc->rbhead]->ie_rbd_actual = 0;
                   1445:                sc->rbhead = (sc->rbhead + 1) % NRXBUF;
                   1446:                sc->rbuffs[sc->rbtail]->ie_rbd_length &= ~IE_RBD_LAST;
                   1447:                sc->rbtail = (sc->rbtail + 1) % NRXBUF;
                   1448:        } while (!i);
                   1449: }
                   1450:
                   1451: /*
                   1452:  * Start transmission on an interface.
                   1453:  */
                   1454: void
                   1455: iestart(ifp)
                   1456:        struct ifnet *ifp;
                   1457: {
                   1458:        struct ie_softc *sc = ifp->if_softc;
                   1459:        struct mbuf *m0, *m;
                   1460:        u_char *buffer;
                   1461:        u_short len;
                   1462:
                   1463:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                   1464:                return;
                   1465:
                   1466:        for (;;) {
                   1467:                if (sc->xmit_busy == NTXBUF) {
                   1468:                        ifp->if_flags |= IFF_OACTIVE;
                   1469:                        break;
                   1470:                }
                   1471:
                   1472:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                   1473:                if (m0 == 0)
                   1474:                        break;
                   1475:
                   1476:                /* We need to use m->m_pkthdr.len, so require the header */
                   1477:                if ((m0->m_flags & M_PKTHDR) == 0)
                   1478:                        panic("iestart: no header mbuf");
                   1479:
                   1480: #if NBPFILTER > 0
                   1481:                /* Tap off here if there is a BPF listener. */
                   1482:                if (ifp->if_bpf)
                   1483:                        bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
                   1484: #endif
                   1485:
                   1486: #ifdef IEDEBUG
                   1487:                if (sc->sc_debug & IED_ENQ)
                   1488:                        printf("%s: fill buffer %d\n", sc->sc_dev.dv_xname,
                   1489:                            sc->xchead);
                   1490: #endif
                   1491:
                   1492:                len = 0;
                   1493:                buffer = sc->xmit_cbuffs[sc->xchead];
                   1494:
                   1495:                for (m = m0; m != NULL && (len + m->m_len) < IE_TBUF_SIZE;
                   1496:                    m = m->m_next) {
                   1497:                        bcopy(mtod(m, caddr_t), buffer, m->m_len);
                   1498:                        buffer += m->m_len;
                   1499:                        len += m->m_len;
                   1500:                }
                   1501:                if (m != NULL)
                   1502:                        printf("%s: tbuf overflow\n", sc->sc_dev.dv_xname);
                   1503:
                   1504:                m_freem(m0);
                   1505:
                   1506:                if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
                   1507:                        bzero(buffer, ETHER_MIN_LEN - ETHER_CRC_LEN - len);
                   1508:                        len = ETHER_MIN_LEN - ETHER_CRC_LEN;
                   1509:                        buffer += ETHER_MIN_LEN - ETHER_CRC_LEN;
                   1510:                }
                   1511:
                   1512:                sc->xmit_buffs[sc->xchead]->ie_xmit_flags = len;
                   1513:
                   1514:                /* Start the first packet transmitting. */
                   1515:                if (sc->xmit_busy == 0)
                   1516:                        iexmit(sc);
                   1517:
                   1518:                sc->xchead = (sc->xchead + 1) % NTXBUF;
                   1519:                sc->xmit_busy++;
                   1520:        }
                   1521: }
                   1522:
                   1523: /*
                   1524:  * Check to see if there's an 82586 out there.
                   1525:  */
                   1526: int
                   1527: check_ie_present(sc, where, size)
                   1528:        struct ie_softc *sc;
                   1529:        caddr_t where;
                   1530:        u_int size;
                   1531: {
                   1532:        volatile struct ie_sys_conf_ptr *scp;
                   1533:        volatile struct ie_int_sys_conf_ptr *iscp;
                   1534:        volatile struct ie_sys_ctl_block *scb;
                   1535:        u_long realbase;
                   1536:        int s;
                   1537:
                   1538:        s = splnet();
                   1539:
                   1540:        realbase = (u_long)where + size - (1 << 24);
                   1541:
                   1542:        scp = (volatile struct ie_sys_conf_ptr *)(realbase + IE_SCP_ADDR);
                   1543:        bzero((char *)scp, sizeof *scp);
                   1544:
                   1545:        /*
                   1546:         * First we put the ISCP at the bottom of memory; this tests to make
                   1547:         * sure that our idea of the size of memory is the same as the
                   1548:         * controller's.  This is NOT where the ISCP will be in normal
                   1549:         * operation.
                   1550:         */
                   1551:        iscp = (volatile struct ie_int_sys_conf_ptr *)where;
                   1552:        bzero((char *)iscp, sizeof *iscp);
                   1553:
                   1554:        scb = (volatile struct ie_sys_ctl_block *)where;
                   1555:        bzero((char *)scb, sizeof *scb);
                   1556:
                   1557:        scp->ie_bus_use = 0;            /* 16-bit */
                   1558:        scp->ie_iscp_ptr = (caddr_t)((volatile caddr_t)iscp -
                   1559:            (volatile caddr_t)realbase);
                   1560:
                   1561:        iscp->ie_busy = 1;
                   1562:        iscp->ie_scb_offset = MK_16(realbase, scb) + 256;
                   1563:
                   1564:        (sc->reset_586)(sc);
                   1565:        (sc->chan_attn)(sc);
                   1566:
                   1567:        delay(100);                     /* wait a while... */
                   1568:
                   1569:        if (iscp->ie_busy) {
                   1570:                splx(s);
                   1571:                return 0;
                   1572:        }
                   1573:
                   1574:        /*
                   1575:         * Now relocate the ISCP to its real home, and reset the controller
                   1576:         * again.
                   1577:         */
                   1578:        iscp = (void *)ALIGN(realbase + IE_SCP_ADDR - sizeof(*iscp));
                   1579:        bzero((char *)iscp, sizeof *iscp);
                   1580:
                   1581:        scp->ie_iscp_ptr = (caddr_t)((caddr_t)iscp - (caddr_t)realbase);
                   1582:
                   1583:        iscp->ie_busy = 1;
                   1584:        iscp->ie_scb_offset = MK_16(realbase, scb);
                   1585:
                   1586:        (sc->reset_586)(sc);
                   1587:        (sc->chan_attn)(sc);
                   1588:
                   1589:        delay(100);
                   1590:
                   1591:        if (iscp->ie_busy) {
                   1592:                splx(s);
                   1593:                return 0;
                   1594:        }
                   1595:
                   1596:        sc->sc_msize = size;
                   1597:        sc->sc_maddr = (caddr_t)realbase;
                   1598:
                   1599:        sc->iscp = iscp;
                   1600:        sc->scb = scb;
                   1601:
                   1602:        /*
                   1603:         * Acknowledge any interrupts we may have caused...
                   1604:         */
                   1605:        ie_ack(sc, IE_ST_WHENCE);
                   1606:        splx(s);
                   1607:
                   1608:        return 1;
                   1609: }
                   1610:
                   1611: /*
                   1612:  * Divine the memory size of ie board UNIT.
                   1613:  * Better hope there's nothing important hiding just below the ie card...
                   1614:  */
                   1615: void
                   1616: ie_find_mem_size(sc)
                   1617:        struct ie_softc *sc;
                   1618: {
                   1619:        u_int size;
                   1620:
                   1621:        sc->sc_msize = 0;
                   1622:
                   1623:        for (size = 65536; size >= 16384; size -= 16384)
                   1624:                if (check_ie_present(sc, sc->sc_maddr, size))
                   1625:                        return;
                   1626:
                   1627:        return;
                   1628: }
                   1629:
                   1630: void
                   1631: el_reset_586(sc)
                   1632:        struct ie_softc *sc;
                   1633: {
                   1634:
                   1635:        outb(PORT + IE507_CTRL, EL_CTRL_RESET);
                   1636:        delay(100);
                   1637:        outb(PORT + IE507_CTRL, EL_CTRL_NORMAL);
                   1638:        delay(100);
                   1639: }
                   1640:
                   1641: void
                   1642: sl_reset_586(sc)
                   1643:        struct ie_softc *sc;
                   1644: {
                   1645:
                   1646:        outb(PORT + IEATT_RESET, 0);
                   1647: }
                   1648:
                   1649: void
                   1650: ee16_reset_586(sc)
                   1651:        struct ie_softc *sc;
                   1652: {
                   1653:
                   1654:        outb(PORT + IEE16_ECTRL, IEE16_RESET_586);
                   1655:        delay(100);
                   1656:        outb(PORT + IEE16_ECTRL, 0);
                   1657:        delay(100);
                   1658: }
                   1659:
                   1660: void
                   1661: el_chan_attn(sc)
                   1662:        struct ie_softc *sc;
                   1663: {
                   1664:
                   1665:        outb(PORT + IE507_ATTN, 1);
                   1666: }
                   1667:
                   1668: void
                   1669: sl_chan_attn(sc)
                   1670:        struct ie_softc *sc;
                   1671: {
                   1672:
                   1673:        outb(PORT + IEATT_ATTN, 0);
                   1674: }
                   1675:
                   1676: void
                   1677: ee16_chan_attn(sc)
                   1678:        struct ie_softc *sc;
                   1679: {
                   1680:        outb(PORT + IEE16_ATTN, 0);
                   1681: }
                   1682:
                   1683: u_short
                   1684: ee16_read_eeprom(sc, location)
                   1685:        struct ie_softc *sc;
                   1686:        int location;
                   1687: {
                   1688:        int ectrl, edata;
                   1689:
                   1690:        ectrl = inb(PORT + IEE16_ECTRL);
                   1691:        ectrl &= IEE16_ECTRL_MASK;
                   1692:        ectrl |= IEE16_ECTRL_EECS;
                   1693:        outb(PORT + IEE16_ECTRL, ectrl);
                   1694:
                   1695:        ee16_eeprom_outbits(sc, IEE16_EEPROM_READ, IEE16_EEPROM_OPSIZE1);
                   1696:        ee16_eeprom_outbits(sc, location, IEE16_EEPROM_ADDR_SIZE);
                   1697:        edata = ee16_eeprom_inbits(sc);
                   1698:        ectrl = inb(PORT + IEE16_ECTRL);
                   1699:        ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EEDI | IEE16_ECTRL_EECS);
                   1700:        outb(PORT + IEE16_ECTRL, ectrl);
                   1701:        ee16_eeprom_clock(sc, 1);
                   1702:        ee16_eeprom_clock(sc, 0);
                   1703:        return edata;
                   1704: }
                   1705:
                   1706: void
                   1707: ee16_eeprom_outbits(sc, edata, count)
                   1708:        struct ie_softc *sc;
                   1709:        int edata, count;
                   1710: {
                   1711:        int ectrl, i;
                   1712:
                   1713:        ectrl = inb(PORT + IEE16_ECTRL);
                   1714:        ectrl &= ~IEE16_RESET_ASIC;
                   1715:        for (i = count - 1; i >= 0; i--) {
                   1716:                ectrl &= ~IEE16_ECTRL_EEDI;
                   1717:                if (edata & (1 << i)) {
                   1718:                        ectrl |= IEE16_ECTRL_EEDI;
                   1719:                }
                   1720:                outb(PORT + IEE16_ECTRL, ectrl);
                   1721:                delay(1);       /* eeprom data must be setup for 0.4 uSec */
                   1722:                ee16_eeprom_clock(sc, 1);
                   1723:                ee16_eeprom_clock(sc, 0);
                   1724:        }
                   1725:        ectrl &= ~IEE16_ECTRL_EEDI;
                   1726:        outb(PORT + IEE16_ECTRL, ectrl);
                   1727:        delay(1);               /* eeprom data must be held for 0.4 uSec */
                   1728: }
                   1729:
                   1730: int
                   1731: ee16_eeprom_inbits(sc)
                   1732:        struct ie_softc *sc;
                   1733: {
                   1734:        int ectrl, edata, i;
                   1735:
                   1736:        ectrl = inb(PORT + IEE16_ECTRL);
                   1737:        ectrl &= ~IEE16_RESET_ASIC;
                   1738:        for (edata = 0, i = 0; i < 16; i++) {
                   1739:                edata = edata << 1;
                   1740:                ee16_eeprom_clock(sc, 1);
                   1741:                ectrl = inb(PORT + IEE16_ECTRL);
                   1742:                if (ectrl & IEE16_ECTRL_EEDO) {
                   1743:                        edata |= 1;
                   1744:                }
                   1745:                ee16_eeprom_clock(sc, 0);
                   1746:        }
                   1747:        return (edata);
                   1748: }
                   1749:
                   1750: void
                   1751: ee16_eeprom_clock(sc, state)
                   1752:        struct ie_softc *sc;
                   1753:        int state;
                   1754: {
                   1755:        int ectrl;
                   1756:
                   1757:        ectrl = inb(PORT + IEE16_ECTRL);
                   1758:        ectrl &= ~(IEE16_RESET_ASIC | IEE16_ECTRL_EESK);
                   1759:        if (state) {
                   1760:                ectrl |= IEE16_ECTRL_EESK;
                   1761:        }
                   1762:        outb(PORT + IEE16_ECTRL, ectrl);
                   1763:        delay(9);               /* EESK must be stable for 8.38 uSec */
                   1764: }
                   1765:
                   1766: static inline void
                   1767: ee16_interrupt_enable(sc)
                   1768:        struct ie_softc *sc;
                   1769: {
                   1770:        delay(100);
                   1771:        outb(PORT + IEE16_IRQ, sc->irq_encoded | IEE16_IRQ_ENABLE);
                   1772:        delay(100);
                   1773: }
                   1774: void
                   1775: slel_get_address(sc)
                   1776:        struct ie_softc *sc;
                   1777: {
                   1778:        u_char *addr = sc->sc_arpcom.ac_enaddr;
                   1779:        int i;
                   1780:
                   1781:        for (i = 0; i < ETHER_ADDR_LEN; i++)
                   1782:                addr[i] = inb(PORT + i);
                   1783: }
                   1784:
                   1785: void
                   1786: iereset(sc)
                   1787:        struct ie_softc *sc;
                   1788: {
                   1789:        int s = splnet();
                   1790:
                   1791:        iestop(sc);
                   1792:
                   1793:        /*
                   1794:         * Stop i82586 dead in its tracks.
                   1795:         */
                   1796:        if (command_and_wait(sc, IE_RU_ABORT | IE_CU_ABORT, 0, 0))
                   1797:                printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
                   1798:
                   1799:        if (command_and_wait(sc, IE_RU_DISABLE | IE_CU_STOP, 0, 0))
                   1800:                printf("%s: disable commands timed out\n", sc->sc_dev.dv_xname);
                   1801:
                   1802:        ieinit(sc);
                   1803:
                   1804:        splx(s);
                   1805: }
                   1806:
                   1807: /*
                   1808:  * Send a command to the controller and wait for it to either complete or be
                   1809:  * accepted, depending on the command.  If the command pointer is null, then
                   1810:  * pretend that the command is not an action command.  If the command pointer
                   1811:  * is not null, and the command is an action command, wait for
                   1812:  * ((volatile struct ie_cmd_common *)pcmd)->ie_cmd_status & MASK
                   1813:  * to become true.
                   1814:  */
                   1815: static int
                   1816: command_and_wait(sc, cmd, pcmd, mask)
                   1817:        struct ie_softc *sc;
                   1818:        int cmd;
                   1819:        volatile void *pcmd;
                   1820:        int mask;
                   1821: {
                   1822:        volatile struct ie_cmd_common *cc = pcmd;
                   1823:        volatile struct ie_sys_ctl_block *scb = sc->scb;
                   1824:        int i;
                   1825:
                   1826:        scb->ie_command = (u_short)cmd;
                   1827:
                   1828:        if (IE_ACTION_COMMAND(cmd) && pcmd) {
                   1829:                (sc->chan_attn)(sc);
                   1830:
                   1831:                /*
                   1832:                 * According to the packet driver, the minimum timeout should
                   1833:                 * be .369 seconds, which we round up to .4.
                   1834:                 *
                   1835:                 * Now spin-lock waiting for status.  This is not a very nice
                   1836:                 * thing to do, but I haven't figured out how, or indeed if, we
                   1837:                 * can put the process waiting for action to sleep.  (We may
                   1838:                 * be getting called through some other timeout running in the
                   1839:                 * kernel.)
                   1840:                 */
                   1841:                for (i = 36900; i--; DELAY(10))
                   1842:                        if ((cc->ie_cmd_status & mask))
                   1843:                                break;
                   1844:
                   1845:                return i < 0;
                   1846:        } else {
                   1847:                /*
                   1848:                 * Otherwise, just wait for the command to be accepted.
                   1849:                 */
                   1850:                (sc->chan_attn)(sc);
                   1851:
                   1852:                while (scb->ie_command)
                   1853:                        ;                               /* spin lock */
                   1854:
                   1855:                return 0;
                   1856:        }
                   1857: }
                   1858:
                   1859: /*
                   1860:  * Run the time-domain reflectometer.
                   1861:  */
                   1862: static void
                   1863: run_tdr(sc, cmd)
                   1864:        struct ie_softc *sc;
                   1865:        struct ie_tdr_cmd *cmd;
                   1866: {
                   1867:        int result;
                   1868:
                   1869:        cmd->com.ie_cmd_status = 0;
                   1870:        cmd->com.ie_cmd_cmd = IE_CMD_TDR | IE_CMD_LAST;
                   1871:        cmd->com.ie_cmd_link = 0xffff;
                   1872:
                   1873:        sc->scb->ie_command_list = MK_16(MEM, cmd);
                   1874:        cmd->ie_tdr_time = 0;
                   1875:
                   1876:        if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
                   1877:            !(cmd->com.ie_cmd_status & IE_STAT_OK))
                   1878:                result = 0x10000;
                   1879:        else
                   1880:                result = cmd->ie_tdr_time;
                   1881:
                   1882:        ie_ack(sc, IE_ST_WHENCE);
                   1883:
                   1884:        if (result & IE_TDR_SUCCESS)
                   1885:                return;
                   1886:
                   1887:        if (result & 0x10000)
                   1888:                printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
                   1889:        else if (result & IE_TDR_XCVR)
                   1890:                printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
                   1891:        else if (result & IE_TDR_OPEN)
                   1892:                printf("%s: TDR detected an open %d clocks away\n",
                   1893:                    sc->sc_dev.dv_xname, result & IE_TDR_TIME);
                   1894:        else if (result & IE_TDR_SHORT)
                   1895:                printf("%s: TDR detected a short %d clocks away\n",
                   1896:                    sc->sc_dev.dv_xname, result & IE_TDR_TIME);
                   1897:        else
                   1898:                printf("%s: TDR returned unknown status %x\n",
                   1899:                    sc->sc_dev.dv_xname, result);
                   1900: }
                   1901:
                   1902: #define        _ALLOC(p, n)    (bzero(p, n), p += n, p - n)
                   1903: #define        ALLOC(p, n)     _ALLOC(p, ALIGN(n))
                   1904:
                   1905: /*
                   1906:  * Here is a helper routine for ieinit().  This sets up the buffers.
                   1907:  */
                   1908: void
                   1909: iememinit(ptr, sc)
                   1910:        void *ptr;
                   1911:        struct ie_softc *sc;
                   1912: {
                   1913:        int i;
                   1914:
                   1915:        /* First lay them out. */
                   1916:        for (i = 0; i < NFRAMES; i++)
                   1917:                sc->rframes[i] = ALLOC(ptr, sizeof(*sc->rframes[i]));
                   1918:
                   1919:        /* Now link them together. */
                   1920:        for (i = 0; i < NFRAMES; i++)
                   1921:                sc->rframes[i]->ie_fd_next =
                   1922:                    MK_16(MEM, sc->rframes[(i + 1) % NFRAMES]);
                   1923:
                   1924:        /* Finally, set the EOL bit on the last one. */
                   1925:        sc->rframes[NFRAMES - 1]->ie_fd_last |= IE_FD_LAST;
                   1926:
                   1927:        /*
                   1928:         * Now lay out some buffers for the incoming frames.  Note that we set
                   1929:         * aside a bit of slop in each buffer, to make sure that we have enough
                   1930:         * space to hold a single frame in every buffer.
                   1931:         */
                   1932:        for (i = 0; i < NRXBUF; i++) {
                   1933:                sc->rbuffs[i] = ALLOC(ptr, sizeof(*sc->rbuffs[i]));
                   1934:                sc->rbuffs[i]->ie_rbd_length = IE_RBUF_SIZE;
                   1935:                sc->rbuffs[i]->ie_rbd_buffer = MK_24(MEM, ptr);
                   1936:                sc->cbuffs[i] = ALLOC(ptr, IE_RBUF_SIZE);
                   1937:        }
                   1938:
                   1939:        /* Now link them together. */
                   1940:        for (i = 0; i < NRXBUF; i++)
                   1941:                sc->rbuffs[i]->ie_rbd_next =
                   1942:                    MK_16(MEM, sc->rbuffs[(i + 1) % NRXBUF]);
                   1943:
                   1944:        /* Tag EOF on the last one. */
                   1945:        sc->rbuffs[NRXBUF - 1]->ie_rbd_length |= IE_RBD_LAST;
                   1946:
                   1947:        /*
                   1948:         * We use the head and tail pointers on receive to keep track of the
                   1949:         * order in which RFDs and RBDs are used.
                   1950:         */
                   1951:        sc->rfhead = 0;
                   1952:        sc->rftail = NFRAMES - 1;
                   1953:        sc->rbhead = 0;
                   1954:        sc->rbtail = NRXBUF - 1;
                   1955:
                   1956:        sc->scb->ie_recv_list = MK_16(MEM, sc->rframes[0]);
                   1957:        sc->rframes[0]->ie_fd_buf_desc = MK_16(MEM, sc->rbuffs[0]);
                   1958:
                   1959:        /*
                   1960:         * Finally, the transmit command and buffer are the last little bit of
                   1961:         * work.
                   1962:         */
                   1963:        for (i = 0; i < NTXBUF; i++) {
                   1964:                sc->xmit_cmds[i] = ALLOC(ptr, sizeof(*sc->xmit_cmds[i]));
                   1965:                sc->xmit_buffs[i] = ALLOC(ptr, sizeof(*sc->xmit_buffs[i]));
                   1966:        }
                   1967:
                   1968:        for (i = 0; i < NTXBUF; i++)
                   1969:                sc->xmit_cbuffs[i] = ALLOC(ptr, IE_TBUF_SIZE);
                   1970:
                   1971:        /* Pointers to last packet sent and next available transmit buffer. */
                   1972:        sc->xchead = sc->xctail = 0;
                   1973:
                   1974:        /* Clear transmit-busy flag and set number of free transmit buffers. */
                   1975:        sc->xmit_busy = 0;
                   1976: }
                   1977:
                   1978: /*
                   1979:  * Run the multicast setup command.
                   1980:  * Called at splnet().
                   1981:  */
                   1982: static int
                   1983: mc_setup(sc, ptr)
                   1984:        struct ie_softc *sc;
                   1985:        void *ptr;
                   1986: {
                   1987:        volatile struct ie_mcast_cmd *cmd = ptr;
                   1988:
                   1989:        cmd->com.ie_cmd_status = 0;
                   1990:        cmd->com.ie_cmd_cmd = IE_CMD_MCAST | IE_CMD_LAST;
                   1991:        cmd->com.ie_cmd_link = 0xffff;
                   1992:
                   1993:        bcopy((caddr_t)sc->mcast_addrs, (caddr_t)cmd->ie_mcast_addrs,
                   1994:            sc->mcast_count * sizeof *sc->mcast_addrs);
                   1995:
                   1996:        cmd->ie_mcast_bytes = sc->mcast_count * ETHER_ADDR_LEN; /* grrr... */
                   1997:
                   1998:        sc->scb->ie_command_list = MK_16(MEM, cmd);
                   1999:        if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
                   2000:            !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
                   2001:                printf("%s: multicast address setup command failed\n",
                   2002:                    sc->sc_dev.dv_xname);
                   2003:                return 0;
                   2004:        }
                   2005:        return 1;
                   2006: }
                   2007:
                   2008: /*
                   2009:  * This routine takes the environment generated by check_ie_present() and adds
                   2010:  * to it all the other structures we need to operate the adapter.  This
                   2011:  * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
                   2012:  * the receiver unit, and clearing interrupts.
                   2013:  *
                   2014:  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
                   2015:  */
                   2016: int
                   2017: ieinit(sc)
                   2018:        struct ie_softc *sc;
                   2019: {
                   2020:        volatile struct ie_sys_ctl_block *scb = sc->scb;
                   2021:        void *ptr;
                   2022:
                   2023:        ptr = (void *)ALIGN(scb + 1);
                   2024:
                   2025:        /*
                   2026:         * Send the configure command first.
                   2027:         */
                   2028:        {
                   2029:                volatile struct ie_config_cmd *cmd = ptr;
                   2030:
                   2031:                scb->ie_command_list = MK_16(MEM, cmd);
                   2032:                cmd->com.ie_cmd_status = 0;
                   2033:                cmd->com.ie_cmd_cmd = IE_CMD_CONFIG | IE_CMD_LAST;
                   2034:                cmd->com.ie_cmd_link = 0xffff;
                   2035:
                   2036:                ie_setup_config(cmd, sc->promisc != 0,
                   2037:                    sc->hard_type == IE_STARLAN10);
                   2038:
                   2039:                if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
                   2040:                    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
                   2041:                        printf("%s: configure command failed\n",
                   2042:                            sc->sc_dev.dv_xname);
                   2043:                        return 0;
                   2044:                }
                   2045:        }
                   2046:
                   2047:        /*
                   2048:         * Now send the Individual Address Setup command.
                   2049:         */
                   2050:        {
                   2051:                volatile struct ie_iasetup_cmd *cmd = ptr;
                   2052:
                   2053:                scb->ie_command_list = MK_16(MEM, cmd);
                   2054:                cmd->com.ie_cmd_status = 0;
                   2055:                cmd->com.ie_cmd_cmd = IE_CMD_IASETUP | IE_CMD_LAST;
                   2056:                cmd->com.ie_cmd_link = 0xffff;
                   2057:
                   2058:                bcopy(sc->sc_arpcom.ac_enaddr, (caddr_t)&cmd->ie_address,
                   2059:                    sizeof cmd->ie_address);
                   2060:
                   2061:                if (command_and_wait(sc, IE_CU_START, cmd, IE_STAT_COMPL) ||
                   2062:                    !(cmd->com.ie_cmd_status & IE_STAT_OK)) {
                   2063:                        printf("%s: individual address setup command failed\n",
                   2064:                            sc->sc_dev.dv_xname);
                   2065:                        return 0;
                   2066:                }
                   2067:        }
                   2068:
                   2069:        /*
                   2070:         * Now run the time-domain reflectometer.
                   2071:         */
                   2072:        run_tdr(sc, ptr);
                   2073:
                   2074:        /*
                   2075:         * Acknowledge any interrupts we have generated thus far.
                   2076:         */
                   2077:        ie_ack(sc, IE_ST_WHENCE);
                   2078:
                   2079:        /*
                   2080:         * Set up the RFA.
                   2081:         */
                   2082:        iememinit(ptr, sc);
                   2083:
                   2084:        sc->sc_arpcom.ac_if.if_flags |= IFF_RUNNING;
                   2085:        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
                   2086:
                   2087:        sc->scb->ie_recv_list = MK_16(MEM, sc->rframes[0]);
                   2088:        command_and_wait(sc, IE_RU_START, 0, 0);
                   2089:
                   2090:        ie_ack(sc, IE_ST_WHENCE);
                   2091:
                   2092:        /* take the ee16 out of loopback */
                   2093:        {
                   2094:        u_char  bart_config;
                   2095:
                   2096:        if(sc->hard_type == IE_EE16) {
                   2097:                bart_config = inb(PORT + IEE16_CONFIG);
                   2098:                bart_config &= ~IEE16_BART_LOOPBACK;
                   2099:                bart_config |= IEE16_BART_MCS16_TEST; /* inb doesn't get bit! */
                   2100:                outb(PORT + IEE16_CONFIG, bart_config);
                   2101:                ee16_interrupt_enable(sc);
                   2102:                ee16_chan_attn(sc);
                   2103:                }
                   2104:        }
                   2105:        return 0;
                   2106: }
                   2107:
                   2108: void
                   2109: iestop(sc)
                   2110:        struct ie_softc *sc;
                   2111: {
                   2112:
                   2113:        command_and_wait(sc, IE_RU_DISABLE, 0, 0);
                   2114: }
                   2115:
                   2116: int
                   2117: ieioctl(ifp, cmd, data)
                   2118:        register struct ifnet *ifp;
                   2119:        u_long cmd;
                   2120:        caddr_t data;
                   2121: {
                   2122:        struct ie_softc *sc = ifp->if_softc;
                   2123:        struct ifaddr *ifa = (struct ifaddr *)data;
                   2124:        struct ifreq *ifr = (struct ifreq *)data;
                   2125:        int s, error = 0;
                   2126:
                   2127:        s = splnet();
                   2128:
                   2129:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
                   2130:                splx(s);
                   2131:                return error;
                   2132:        }
                   2133:
                   2134:        switch (cmd) {
                   2135:
                   2136:        case SIOCSIFADDR:
                   2137:                ifp->if_flags |= IFF_UP;
                   2138:
                   2139:                switch (ifa->ifa_addr->sa_family) {
                   2140: #ifdef INET
                   2141:                case AF_INET:
                   2142:                        ieinit(sc);
                   2143:                        arp_ifinit(&sc->sc_arpcom, ifa);
                   2144:                        break;
                   2145: #endif
                   2146:                default:
                   2147:                        ieinit(sc);
                   2148:                        break;
                   2149:                }
                   2150:                break;
                   2151:
                   2152:        case SIOCSIFFLAGS:
                   2153:                sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
                   2154:                if ((ifp->if_flags & IFF_UP) == 0 &&
                   2155:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                   2156:                        /*
                   2157:                         * If interface is marked down and it is running, then
                   2158:                         * stop it.
                   2159:                         */
                   2160:                        iestop(sc);
                   2161:                        ifp->if_flags &= ~IFF_RUNNING;
                   2162:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                   2163:                           (ifp->if_flags & IFF_RUNNING) == 0) {
                   2164:                        /*
                   2165:                         * If interface is marked up and it is stopped, then
                   2166:                         * start it.
                   2167:                         */
                   2168:                        ieinit(sc);
                   2169:                } else {
                   2170:                        /*
                   2171:                         * Reset the interface to pick up changes in any other
                   2172:                         * flags that affect hardware registers.
                   2173:                         */
                   2174:                        iestop(sc);
                   2175:                        ieinit(sc);
                   2176:                }
                   2177: #ifdef IEDEBUG
                   2178:                if (ifp->if_flags & IFF_DEBUG)
                   2179:                        sc->sc_debug = IED_ALL;
                   2180:                else
                   2181:                        sc->sc_debug = 0;
                   2182: #endif
                   2183:                break;
                   2184:
                   2185:        case SIOCADDMULTI:
                   2186:        case SIOCDELMULTI:
                   2187:                error = (cmd == SIOCADDMULTI) ?
                   2188:                    ether_addmulti(ifr, &sc->sc_arpcom):
                   2189:                    ether_delmulti(ifr, &sc->sc_arpcom);
                   2190:
                   2191:                if (error == ENETRESET) {
                   2192:                        /*
                   2193:                         * Multicast list has changed; set the hardware filter
                   2194:                         * accordingly.
                   2195:                         */
                   2196:                        if (ifp->if_flags & IFF_RUNNING)
                   2197:                                mc_reset(sc);
                   2198:                        error = 0;
                   2199:                }
                   2200:                break;
                   2201:
                   2202:        default:
                   2203:                error = EINVAL;
                   2204:        }
                   2205:        splx(s);
                   2206:        return error;
                   2207: }
                   2208:
                   2209: static void
                   2210: mc_reset(sc)
                   2211:        struct ie_softc *sc;
                   2212: {
                   2213:        struct ether_multi *enm;
                   2214:        struct ether_multistep step;
                   2215:
                   2216:        /*
                   2217:         * Step through the list of addresses.
                   2218:         */
                   2219:        sc->mcast_count = 0;
                   2220:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
                   2221:        while (enm) {
                   2222:                if (sc->mcast_count >= MAXMCAST ||
                   2223:                    bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
                   2224:                        sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
                   2225:                        ieioctl(&sc->sc_arpcom.ac_if, SIOCSIFFLAGS, (void *)0);
                   2226:                        goto setflag;
                   2227:                }
                   2228:
                   2229:                bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
                   2230:                sc->mcast_count++;
                   2231:                ETHER_NEXT_MULTI(step, enm);
                   2232:        }
                   2233: setflag:
                   2234:        sc->want_mcsetup = 1;
                   2235: }
                   2236:
                   2237: #ifdef IEDEBUG
                   2238: void
                   2239: print_rbd(rbd)
                   2240:        volatile struct ie_recv_buf_desc *rbd;
                   2241: {
                   2242:
                   2243:        printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
                   2244:            "length %04x, mbz %04x\n", (u_long)rbd, rbd->ie_rbd_actual,
                   2245:            rbd->ie_rbd_next, rbd->ie_rbd_buffer, rbd->ie_rbd_length,
                   2246:            rbd->mbz);
                   2247: }
                   2248: #endif
                   2249:

CVSweb