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

Annotation of sys/dev/ic/i82596.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: i82596.c,v 1.26 2006/03/25 22:41:43 djm Exp $ */
        !             2: /*     $NetBSD: i82586.c,v 1.18 1998/08/15 04:42:42 mycroft Exp $      */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Paul Kranenburg and Charles M. Hannum.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *        This product includes software developed by the NetBSD
        !            22:  *        Foundation, Inc. and its contributors.
        !            23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            24:  *    contributors may be used to endorse or promote products derived
        !            25:  *    from this software without specific prior written permission.
        !            26:  *
        !            27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            37:  * POSSIBILITY OF SUCH DAMAGE.
        !            38:  */
        !            39: /*-
        !            40:  * Copyright (c) 1997 Paul Kranenburg.
        !            41:  * Copyright (c) 1992, 1993, University of Vermont and State
        !            42:  *  Agricultural College.
        !            43:  * Copyright (c) 1992, 1993, Garrett A. Wollman.
        !            44:  *
        !            45:  * Portions:
        !            46:  * Copyright (c) 1994, 1995, Rafal K. Boni
        !            47:  * Copyright (c) 1990, 1991, William F. Jolitz
        !            48:  * Copyright (c) 1990, The Regents of the University of California
        !            49:  *
        !            50:  * All rights reserved.
        !            51:  *
        !            52:  * Redistribution and use in source and binary forms, with or without
        !            53:  * modification, are permitted provided that the following conditions
        !            54:  * are met:
        !            55:  * 1. Redistributions of source code must retain the above copyright
        !            56:  *    notice, this list of conditions and the following disclaimer.
        !            57:  * 2. Redistributions in binary form must reproduce the above copyright
        !            58:  *    notice, this list of conditions and the following disclaimer in the
        !            59:  *    documentation and/or other materials provided with the distribution.
        !            60:  * 3. All advertising materials mentioning features or use of this software
        !            61:  *    must display the following acknowledgement:
        !            62:  *     This product includes software developed by the University of Vermont
        !            63:  *     and State Agricultural College and Garrett A. Wollman, by William F.
        !            64:  *     Jolitz, and by the University of California, Berkeley, Lawrence
        !            65:  *     Berkeley Laboratory, and its contributors.
        !            66:  * 4. Neither the names of the Universities nor the names of the authors
        !            67:  *    may be used to endorse or promote products derived from this software
        !            68:  *    without specific prior written permission.
        !            69:  *
        !            70:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            71:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            72:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            73:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE
        !            74:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            75:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            76:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            77:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            78:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            79:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            80:  * SUCH DAMAGE.
        !            81:  */
        !            82: /*
        !            83:  * Intel 82586/82596 Ethernet chip
        !            84:  * Register, bit, and structure definitions.
        !            85:  *
        !            86:  * Original StarLAN driver written by Garrett Wollman with reference to the
        !            87:  * Clarkson Packet Driver code for this chip written by Russ Nelson and others.
        !            88:  *
        !            89:  * BPF support code taken from hpdev/if_le.c, supplied with tcpdump.
        !            90:  *
        !            91:  * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni.
        !            92:  *
        !            93:  * Majorly cleaned up and 3C507 code merged by Charles Hannum.
        !            94:  *
        !            95:  * Converted to SUN ie driver by Charles D. Cranor,
        !            96:  *             October 1994, January 1995.
        !            97:  * This sun version based on i386 version 1.30.
        !            98:  */
        !            99: /*
        !           100:  * The i82596 is a very painful chip, found in sun3's, sun-4/100's
        !           101:  * sun-4/200's, and VME based suns.  The byte order is all wrong for a
        !           102:  * SUN, making life difficult.  Programming this chip is mostly the same,
        !           103:  * but certain details differ from system to system.  This driver is
        !           104:  * written so that different "ie" interfaces can be controled by the same
        !           105:  * driver.
        !           106:  */
        !           107:
        !           108: /*
        !           109: Mode of operation:
        !           110:
        !           111:    We run the 82596 in a standard Ethernet mode.  We keep NFRAMES
        !           112:    received frame descriptors around for the receiver to use, and
        !           113:    NRXBUF associated receive buffer descriptors, both in a circular
        !           114:    list.  Whenever a frame is received, we rotate both lists as
        !           115:    necessary.  (The 596 treats both lists as a simple queue.)  We also
        !           116:    keep a transmit command around so that packets can be sent off
        !           117:    quickly.
        !           118:
        !           119:    We configure the adapter in AL-LOC = 1 mode, which means that the
        !           120:    Ethernet/802.3 MAC header is placed at the beginning of the receive
        !           121:    buffer rather than being split off into various fields in the RFD.
        !           122:    This also means that we must include this header in the transmit
        !           123:    buffer as well.
        !           124:
        !           125:    By convention, all transmit commands, and only transmit commands,
        !           126:    shall have the I (IE_CMD_INTR) bit set in the command.  This way,
        !           127:    when an interrupt arrives at i82596_intr(), it is immediately possible
        !           128:    to tell what precisely caused it.  ANY OTHER command-sending
        !           129:    routines should run at splnet(), and should post an acknowledgement
        !           130:    to every interrupt they generate.
        !           131:
        !           132:    To save the expense of shipping a command to 82596 every time we
        !           133:    want to send a frame, we use a linked list of commands consisting
        !           134:    of alternate XMIT and NOP commands. The links of these elements
        !           135:    are manipulated (in i82596_xmit()) such that the NOP command loops back
        !           136:    to itself whenever the following XMIT command is not yet ready to
        !           137:    go. Whenever an XMIT is ready, the preceding NOP link is pointed
        !           138:    at it, while its own link field points to the following NOP command.
        !           139:    Thus, a single transmit command sets off an interlocked traversal
        !           140:    of the xmit command chain, with the host processor in control of
        !           141:    the synchronization.
        !           142: */
        !           143:
        !           144: #include "bpfilter.h"
        !           145:
        !           146: #include <sys/param.h>
        !           147: #include <sys/systm.h>
        !           148: #include <sys/mbuf.h>
        !           149: #include <sys/socket.h>
        !           150: #include <sys/ioctl.h>
        !           151: #include <sys/errno.h>
        !           152: #include <sys/syslog.h>
        !           153: #include <sys/device.h>
        !           154:
        !           155: #include <net/if.h>
        !           156: #include <net/if_dl.h>
        !           157: #include <net/if_types.h>
        !           158: #include <net/if_media.h>
        !           159:
        !           160: #if NBPFILTER > 0
        !           161: #include <net/bpf.h>
        !           162: #endif
        !           163:
        !           164: #ifdef INET
        !           165: #include <netinet/in.h>
        !           166: #include <netinet/in_systm.h>
        !           167: #include <netinet/in_var.h>
        !           168: #include <netinet/ip.h>
        !           169: #include <netinet/if_ether.h>
        !           170: #endif
        !           171:
        !           172: #include <uvm/uvm_extern.h>
        !           173:
        !           174: #include <machine/bus.h>
        !           175:
        !           176: #include <dev/ic/i82596reg.h>
        !           177: #include <dev/ic/i82596var.h>
        !           178:
        !           179: static char *padbuf;
        !           180:
        !           181: void   i82596_reset(struct ie_softc *, int);
        !           182: void   i82596_watchdog(struct ifnet *);
        !           183: int    i82596_init(struct ie_softc *);
        !           184: int    i82596_ioctl(struct ifnet *, u_long, caddr_t);
        !           185: void   i82596_start(struct ifnet *);
        !           186:
        !           187: int    i82596_rint(struct ie_softc *, int);
        !           188: int    i82596_tint(struct ie_softc *, int);
        !           189:
        !           190: int    i82596_mediachange(struct ifnet *);
        !           191: void   i82596_mediastatus(struct ifnet *, struct ifmediareq *);
        !           192:
        !           193: int    i82596_readframe(struct ie_softc *, int);
        !           194: int    i82596_get_rbd_list(struct ie_softc *,
        !           195:                                             u_int16_t *, u_int16_t *, int *);
        !           196: void   i82596_release_rbd_list(struct ie_softc *, u_int16_t, u_int16_t);
        !           197: int    i82596_drop_frames(struct ie_softc *);
        !           198: int    i82596_chk_rx_ring(struct ie_softc *);
        !           199:
        !           200: void   i82596_start_transceiver(struct ie_softc *);
        !           201: void   i82596_stop(struct ie_softc *);
        !           202: void   i82596_xmit(struct ie_softc *);
        !           203:
        !           204: void   i82596_setup_bufs(struct ie_softc *);
        !           205: void   i82596_simple_command(struct ie_softc *, int, int);
        !           206: int    ie_cfg_setup(struct ie_softc *, int, int, int);
        !           207: int    ie_ia_setup(struct ie_softc *, int);
        !           208: void   ie_run_tdr(struct ie_softc *, int);
        !           209: int    ie_mc_setup(struct ie_softc *, int);
        !           210: void   ie_mc_reset(struct ie_softc *);
        !           211: int    i82596_cmd_wait(struct ie_softc *);
        !           212:
        !           213: #ifdef I82596_DEBUG
        !           214: void   print_rbd(struct ie_softc *, int);
        !           215: #endif
        !           216:
        !           217: struct cfdriver ie_cd = {
        !           218:        NULL, "ie", DV_IFNET
        !           219: };
        !           220:
        !           221: /*
        !           222:  * generic i82596 probe routine
        !           223:  */
        !           224: int
        !           225: i82596_probe(sc)
        !           226:        struct ie_softc *sc;
        !           227: {
        !           228:        int i;
        !           229:
        !           230:        sc->scp = sc->sc_msize - IE_SCP_SZ;
        !           231:        sc->iscp = 0;
        !           232:        sc->scb = 32;
        !           233:
        !           234:        (sc->ie_bus_write16)(sc, IE_ISCP_BUSY(sc->iscp), 1);
        !           235:        (sc->ie_bus_write16)(sc, IE_ISCP_SCB(sc->iscp), sc->scb);
        !           236:        (sc->ie_bus_write24)(sc, IE_ISCP_BASE(sc->iscp), sc->sc_maddr);
        !           237:        (sc->ie_bus_write24)(sc, IE_SCP_ISCP(sc->scp), sc->sc_maddr);
        !           238:        (sc->ie_bus_write16)(sc, IE_SCP_BUS_USE(sc->scp), sc->sysbus);
        !           239:
        !           240:        (sc->hwreset)(sc, IE_CARD_RESET);
        !           241:
        !           242:        if ((sc->ie_bus_read16)(sc, IE_ISCP_BUSY(sc->iscp))) {
        !           243: #ifdef I82596_DEBUG
        !           244:                printf("%s: ISCP set failed\n", sc->sc_dev.dv_xname);
        !           245: #endif
        !           246:                return 0;
        !           247:        }
        !           248:
        !           249:        if (sc->port) {
        !           250:                (sc->ie_bus_write24)(sc, sc->scp, 0);
        !           251:                (sc->ie_bus_write24)(sc, IE_SCP_TEST(sc->scp), -1);
        !           252:                (sc->port)(sc, IE_PORT_TEST);
        !           253:                for (i = 9000; i-- &&
        !           254:                             (sc->ie_bus_read16)(sc, IE_SCP_TEST(sc->scp));
        !           255:                     DELAY(100))
        !           256:                        ;
        !           257:        }
        !           258:
        !           259:        return 1;
        !           260: }
        !           261:
        !           262: /*
        !           263:  * Front-ends call this function to attach to the MI driver.
        !           264:  *
        !           265:  * The front-end has responsibility for managing the ICP and ISCP
        !           266:  * structures. Both of these are opaque to us.  Also, the front-end
        !           267:  * chooses a location for the SCB which is expected to be addressable
        !           268:  * (through `sc->scb') as an offset against the shared-memory bus handle.
        !           269:  *
        !           270:  * The following MD interface function must be setup by the front-end
        !           271:  * before calling here:
        !           272:  *
        !           273:  *     hwreset                 - board dependent reset
        !           274:  *     hwinit                  - board dependent initialization
        !           275:  *     chan_attn               - channel attention
        !           276:  *     intrhook                - board dependent interrupt processing
        !           277:  *     memcopyin               - shared memory copy: board to KVA
        !           278:  *     memcopyout              - shared memory copy: KVA to board
        !           279:  *     ie_bus_read16           - read a sixteen-bit i82596 pointer
        !           280:  *     ie_bus_write16          - write a sixteen-bit i82596 pointer
        !           281:  *     ie_bus_write24          - write a twenty-four-bit i82596 pointer
        !           282:  *
        !           283:  */
        !           284: void
        !           285: i82596_attach(sc, name, etheraddr, media, nmedia, defmedia)
        !           286:        struct ie_softc *sc;
        !           287:        const char *name;
        !           288:        u_int8_t *etheraddr;
        !           289:         int *media, nmedia, defmedia;
        !           290: {
        !           291:        int i;
        !           292:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           293:
        !           294:        /* Setup SCP+ISCP */
        !           295:        (sc->ie_bus_write16)(sc, IE_ISCP_BUSY(sc->iscp), 1);
        !           296:        (sc->ie_bus_write16)(sc, IE_ISCP_SCB(sc->iscp), sc->scb);
        !           297:        (sc->ie_bus_write24)(sc, IE_ISCP_BASE(sc->iscp), sc->sc_maddr);
        !           298:        (sc->ie_bus_write24)(sc, IE_SCP_ISCP(sc->scp), sc->sc_maddr +sc->iscp);
        !           299:        (sc->ie_bus_write16)(sc, IE_SCP_BUS_USE(sc->scp), sc->sysbus);
        !           300:        (sc->hwreset)(sc, IE_CARD_RESET);
        !           301:
        !           302:        /* Setup Iface */
        !           303:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           304:        ifp->if_softc = sc;
        !           305:        ifp->if_start = i82596_start;
        !           306:        ifp->if_ioctl = i82596_ioctl;
        !           307:        ifp->if_watchdog = i82596_watchdog;
        !           308:        ifp->if_flags =
        !           309: #ifdef I82596_DEBUG
        !           310:                IFF_DEBUG |
        !           311: #endif
        !           312:                IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
        !           313:        IFQ_SET_READY(&ifp->if_snd);
        !           314:
        !           315:         /* Initialize media goo. */
        !           316:         ifmedia_init(&sc->sc_media, 0, i82596_mediachange, i82596_mediastatus);
        !           317:         if (media != NULL) {
        !           318:                 for (i = 0; i < nmedia; i++)
        !           319:                         ifmedia_add(&sc->sc_media, media[i], 0, NULL);
        !           320:                 ifmedia_set(&sc->sc_media, defmedia);
        !           321:         } else {
        !           322:                 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
        !           323:                 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
        !           324:         }
        !           325:
        !           326:        if (padbuf == NULL) {
        !           327:                padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF,
        !           328:                    M_NOWAIT);
        !           329:                if (padbuf == NULL) {
        !           330:                        printf("%s: can't allocate pad buffer\n",
        !           331:                            sc->sc_dev.dv_xname);
        !           332:                        return;
        !           333:                }
        !           334:                bzero(padbuf, ETHER_MIN_LEN - ETHER_CRC_LEN);
        !           335:        }
        !           336:
        !           337:        /* Attach the interface. */
        !           338:        if_attach(ifp);
        !           339:        ether_ifattach(ifp);
        !           340:
        !           341:        printf(" %s v%d.%d, address %s\n", name, sc->sc_vers / 10,
        !           342:               sc->sc_vers % 10, ether_sprintf(etheraddr));
        !           343: }
        !           344:
        !           345:
        !           346: /*
        !           347:  * Device timeout/watchdog routine.
        !           348:  * Entered if the device neglects to generate an interrupt after a
        !           349:  * transmit has been started on it.
        !           350:  */
        !           351: void
        !           352: i82596_watchdog(ifp)
        !           353:        struct ifnet *ifp;
        !           354: {
        !           355:        struct ie_softc *sc = ifp->if_softc;
        !           356:
        !           357:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           358:        ++ifp->if_oerrors;
        !           359:
        !           360:        i82596_reset(sc, 1);
        !           361: }
        !           362:
        !           363: int
        !           364: i82596_cmd_wait(sc)
        !           365:        struct ie_softc *sc;
        !           366: {
        !           367:        /* spin on i82596 command acknowledge; wait at most 0.9 (!) seconds */
        !           368:        int i, off;
        !           369:
        !           370:        for (i = 180000; i--; DELAY(5)) {
        !           371:                /* Read the command word */
        !           372:                off = IE_SCB_CMD(sc->scb);
        !           373:                bus_space_barrier(sc->bt, sc->bh, off, 2,
        !           374:                                  BUS_SPACE_BARRIER_READ);
        !           375:                if ((sc->ie_bus_read16)(sc, off) == 0) {
        !           376: #ifdef I82596_DEBUG
        !           377:                        if (sc->sc_debug & IED_CMDS)
        !           378:                                printf("%s: cmd_wait after %d usec\n",
        !           379:                                    sc->sc_dev.dv_xname, (180000 - i) * 5);
        !           380: #endif
        !           381:                        return (0);
        !           382:                }
        !           383:        }
        !           384:
        !           385: #ifdef I82596_DEBUG
        !           386:        if (sc->sc_debug & IED_CMDS)
        !           387:                printf("i82596_cmd_wait: timo(%ssync): scb status: %b\n",
        !           388:                    sc->async_cmd_inprogress? "a" : "",
        !           389:                    sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb)),
        !           390:                    IE_STAT_BITS);
        !           391: #endif
        !           392:        return (1);     /* Timeout */
        !           393: }
        !           394:
        !           395: /*
        !           396:  * Send a command to the controller and wait for it to either complete
        !           397:  * or be accepted, depending on the command.  If the command pointer
        !           398:  * is null, then pretend that the command is not an action command.
        !           399:  * If the command pointer is not null, and the command is an action
        !           400:  * command, wait for one of the MASK bits to turn on in the command's
        !           401:  * status field.
        !           402:  * If ASYNC is set, we just call the chip's attention and return.
        !           403:  * We may have to wait for the command's acceptance later though.
        !           404:  */
        !           405: int
        !           406: i82596_start_cmd(sc, cmd, iecmdbuf, mask, async)
        !           407:        struct ie_softc *sc;
        !           408:        int cmd;
        !           409:        int iecmdbuf;
        !           410:        int mask;
        !           411:        int async;
        !           412: {
        !           413:        int i, off;
        !           414:
        !           415: #ifdef I82596_DEBUG
        !           416:        if (sc->sc_debug & IED_CMDS)
        !           417:                printf("start_cmd: %p, %x, %x, %b, %ssync\n",
        !           418:                       sc, cmd, iecmdbuf, mask, IE_STAT_BITS, async?"a":"");
        !           419: #endif
        !           420:        if (sc->async_cmd_inprogress != 0) {
        !           421:                /*
        !           422:                 * If previous command was issued asynchronously, wait
        !           423:                 * for it now.
        !           424:                 */
        !           425:                if (i82596_cmd_wait(sc) != 0)
        !           426:                        return (1);
        !           427:                sc->async_cmd_inprogress = 0;
        !           428:        }
        !           429:
        !           430:        off = IE_SCB_CMD(sc->scb);
        !           431:        (sc->ie_bus_write16)(sc, off, cmd);
        !           432:        bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
        !           433:        (sc->chan_attn)(sc);
        !           434:
        !           435:        if (async) {
        !           436:                sc->async_cmd_inprogress = 1;
        !           437:                return (0);
        !           438:        }
        !           439:
        !           440:        if (IE_ACTION_COMMAND(cmd) && iecmdbuf) {
        !           441:                int status;
        !           442:                /*
        !           443:                 * Now spin-lock waiting for status.  This is not a very nice
        !           444:                 * thing to do, and can kill performance pretty well...
        !           445:                 * According to the packet driver, the minimum timeout
        !           446:                 * should be .369 seconds.
        !           447:                 */
        !           448:                for (i = 73800; i--; DELAY(5)) {
        !           449:                        /* Read the command status */
        !           450:                        off = IE_CMD_COMMON_STATUS(iecmdbuf);
        !           451:                        bus_space_barrier(sc->bt, sc->bh, off, 2,
        !           452:                            BUS_SPACE_BARRIER_READ);
        !           453:                        status = (sc->ie_bus_read16)(sc, off);
        !           454:                        if (status & mask) {
        !           455: #ifdef I82596_DEBUG
        !           456:                                if (sc->sc_debug & IED_CMDS)
        !           457:                                        printf("%s: cmd status %b\n",
        !           458:                                            sc->sc_dev.dv_xname,
        !           459:                                            status, IE_STAT_BITS);
        !           460: #endif
        !           461:                                return (0);
        !           462:                        }
        !           463:                }
        !           464:
        !           465:        } else {
        !           466:                /*
        !           467:                 * Otherwise, just wait for the command to be accepted.
        !           468:                 */
        !           469:                return (i82596_cmd_wait(sc));
        !           470:        }
        !           471:
        !           472:        /* Timeout */
        !           473:        return (1);
        !           474: }
        !           475:
        !           476: /*
        !           477:  * Transfer accumulated chip error counters to IF.
        !           478:  */
        !           479: static __inline void
        !           480: i82596_count_errors(struct ie_softc *sc)
        !           481: {
        !           482:        int scb = sc->scb;
        !           483:
        !           484:        sc->sc_arpcom.ac_if.if_ierrors +=
        !           485:            sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) +
        !           486:            sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) +
        !           487:            sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) +
        !           488:            sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb));
        !           489:
        !           490:        /* Clear error counters */
        !           491:        sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0);
        !           492:        sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0);
        !           493:        sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0);
        !           494:        sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0);
        !           495: }
        !           496:
        !           497: static __inline void
        !           498: i82596_rx_errors(struct ie_softc *sc, int fn, int status)
        !           499: {
        !           500:        log(LOG_ERR, "%s: rx error (frame# %d): %b\n", sc->sc_dev.dv_xname, fn,
        !           501:            status, IE_FD_STATUSBITS);
        !           502: }
        !           503:
        !           504: /*
        !           505:  * i82596 interrupt entry point.
        !           506:  */
        !           507: int
        !           508: i82596_intr(v)
        !           509:        void *v;
        !           510: {
        !           511:        register struct ie_softc *sc = v;
        !           512:        register u_int status;
        !           513:        register int off;
        !           514:
        !           515:        off = IE_SCB_STATUS(sc->scb);
        !           516:        bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_READ);
        !           517:        status = sc->ie_bus_read16(sc, off) /* & IE_ST_WHENCE */;
        !           518:
        !           519:        if ((status & IE_ST_WHENCE) == 0) {
        !           520:                if (sc->intrhook)
        !           521:                        (sc->intrhook)(sc, IE_INTR_EXIT);
        !           522:
        !           523:                return (0);
        !           524:        }
        !           525:
        !           526: loop:
        !           527:        /* Ack interrupts FIRST in case we receive more during the ISR. */
        !           528:        i82596_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, 1);
        !           529:
        !           530:        if (status & (IE_ST_FR | IE_ST_RNR)) {
        !           531:                if (sc->intrhook)
        !           532:                        (sc->intrhook)(sc, IE_INTR_ENRCV);
        !           533:
        !           534:                if (i82596_rint(sc, status) != 0)
        !           535:                        goto reset;
        !           536:        }
        !           537:
        !           538:        if (status & IE_ST_CX) {
        !           539:                if (sc->intrhook)
        !           540:                        (sc->intrhook)(sc, IE_INTR_ENSND);
        !           541:
        !           542:                if (i82596_tint(sc, status) != 0)
        !           543:                        goto reset;
        !           544:        }
        !           545:
        !           546: #ifdef I82596_DEBUG
        !           547:        if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA))
        !           548:                printf("%s: cna; status=%b\n", sc->sc_dev.dv_xname,
        !           549:                        status, IE_ST_BITS);
        !           550: #endif
        !           551:        if (sc->intrhook)
        !           552:                (sc->intrhook)(sc, IE_INTR_LOOP);
        !           553:
        !           554:        /*
        !           555:         * Interrupt ACK was posted asynchronously; wait for
        !           556:         * completion here before reading SCB status again.
        !           557:         *
        !           558:         * If ACK fails, try to reset the chip, in hopes that
        !           559:         * it helps.
        !           560:         */
        !           561:        if (i82596_cmd_wait(sc))
        !           562:                goto reset;
        !           563:
        !           564:        bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_READ);
        !           565:        status = sc->ie_bus_read16(sc, off);
        !           566:        if ((status & IE_ST_WHENCE) != 0)
        !           567:                goto loop;
        !           568:
        !           569: out:
        !           570:        if (sc->intrhook)
        !           571:                (sc->intrhook)(sc, IE_INTR_EXIT);
        !           572:        return (1);
        !           573:
        !           574: reset:
        !           575:        i82596_cmd_wait(sc);
        !           576:        i82596_reset(sc, 1);
        !           577:        goto out;
        !           578: }
        !           579:
        !           580: /*
        !           581:  * Process a received-frame interrupt.
        !           582:  */
        !           583: int
        !           584: i82596_rint(sc, scbstatus)
        !           585:        struct  ie_softc *sc;
        !           586:        int     scbstatus;
        !           587: {
        !           588:        static int timesthru = 1024;
        !           589:        register int i, status, off;
        !           590:
        !           591: #ifdef I82596_DEBUG
        !           592:        if (sc->sc_debug & IED_RINT)
        !           593:                printf("%s: rint: status %b\n",
        !           594:                        sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS);
        !           595: #endif
        !           596:
        !           597:        for (;;) {
        !           598:                register int drop = 0;
        !           599:
        !           600:                i = sc->rfhead;
        !           601:                off = IE_RFRAME_STATUS(sc->rframes, i);
        !           602:                bus_space_barrier(sc->bt, sc->bh, off, 2,
        !           603:                                  BUS_SPACE_BARRIER_READ);
        !           604:                status = sc->ie_bus_read16(sc, off);
        !           605:
        !           606: #ifdef I82596_DEBUG
        !           607:                if (sc->sc_debug & IED_RINT)
        !           608:                        printf("%s: rint: frame(%d) status %b\n",
        !           609:                                sc->sc_dev.dv_xname, i, status, IE_ST_BITS);
        !           610: #endif
        !           611:                if ((status & IE_FD_COMPLETE) == 0) {
        !           612:                        if ((status & IE_FD_OK) != 0) {
        !           613:                                printf("%s: rint: weird: ",
        !           614:                                        sc->sc_dev.dv_xname);
        !           615:                                i82596_rx_errors(sc, i, status);
        !           616:                                break;
        !           617:                        }
        !           618:                        if (--timesthru == 0) {
        !           619:                                /* Account the accumulated errors */
        !           620:                                i82596_count_errors(sc);
        !           621:                                timesthru = 1024;
        !           622:                        }
        !           623:                        break;
        !           624:                } else if ((status & IE_FD_OK) == 0) {
        !           625:                        /*
        !           626:                         * If the chip is configured to automatically
        !           627:                         * discard bad frames, the only reason we can
        !           628:                         * get here is an "out-of-resource" condition.
        !           629:                         */
        !           630:                        i82596_rx_errors(sc, i, status);
        !           631:                        drop = 1;
        !           632:                }
        !           633:
        !           634: #ifdef I82596_DEBUG
        !           635:                if ((status & IE_FD_BUSY) != 0)
        !           636:                        printf("%s: rint: frame(%d) busy; status=%x\n",
        !           637:                                sc->sc_dev.dv_xname, i, status, IE_ST_BITS);
        !           638: #endif
        !           639:
        !           640:                /*
        !           641:                 * Advance the RFD list, since we're done with
        !           642:                 * this descriptor.
        !           643:                 */
        !           644:
        !           645:                /* Clear frame status */
        !           646:                sc->ie_bus_write16(sc, off, 0);
        !           647:
        !           648:                /* Put fence at this frame (the head) */
        !           649:                off = IE_RFRAME_LAST(sc->rframes, i);
        !           650:                sc->ie_bus_write16(sc, off, IE_FD_EOL|IE_FD_SUSP);
        !           651:
        !           652:                /* and clear RBD field */
        !           653:                off = IE_RFRAME_BUFDESC(sc->rframes, i);
        !           654:                sc->ie_bus_write16(sc, off, 0xffff);
        !           655:
        !           656:                /* Remove fence from current tail */
        !           657:                off = IE_RFRAME_LAST(sc->rframes, sc->rftail);
        !           658:                sc->ie_bus_write16(sc, off, 0);
        !           659:
        !           660:                if (++sc->rftail == sc->nframes)
        !           661:                        sc->rftail = 0;
        !           662:                if (++sc->rfhead == sc->nframes)
        !           663:                        sc->rfhead = 0;
        !           664:
        !           665:                /* Pull the frame off the board */
        !           666:                if (drop) {
        !           667:                        i82596_drop_frames(sc);
        !           668:                        if ((status & IE_FD_RNR) != 0)
        !           669:                                sc->rnr_expect = 1;
        !           670:                        sc->sc_arpcom.ac_if.if_ierrors++;
        !           671:                } else if (i82596_readframe(sc, i) != 0)
        !           672:                        return (1);
        !           673:        }
        !           674:
        !           675:        if ((scbstatus & IE_ST_RNR) != 0) {
        !           676:
        !           677:                /*
        !           678:                 * Receiver went "Not Ready". We try to figure out
        !           679:                 * whether this was an expected event based on past
        !           680:                 * frame status values.
        !           681:                 */
        !           682:
        !           683:                if ((scbstatus & IE_RUS_SUSPEND) != 0) {
        !           684:                        /*
        !           685:                         * We use the "suspend on last frame" flag.
        !           686:                         * Send a RU RESUME command in response, since
        !           687:                         * we should have dealt with all completed frames
        !           688:                         * by now.
        !           689:                         */
        !           690:                        printf("RINT: SUSPENDED; scbstatus=%b\n",
        !           691:                                scbstatus, IE_ST_BITS);
        !           692:                        if (i82596_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0)
        !           693:                                return (0);
        !           694:                        printf("%s: RU RESUME command timed out\n",
        !           695:                                sc->sc_dev.dv_xname);
        !           696:                        return (1);     /* Ask for a reset */
        !           697:                }
        !           698:
        !           699:                if (sc->rnr_expect != 0) {
        !           700:                        /*
        !           701:                         * The RNR condition was announced in the previously
        !           702:                         * completed frame.  Assume the receive ring is Ok,
        !           703:                         * so restart the receiver without further delay.
        !           704:                         */
        !           705:                        i82596_start_transceiver(sc);
        !           706:                        sc->rnr_expect = 0;
        !           707:                        return (0);
        !           708:
        !           709:                } else if ((scbstatus & IE_RUS_NOSPACE) != 0) {
        !           710:                        /*
        !           711:                         * We saw no previous IF_FD_RNR flag.
        !           712:                         * We check our ring invariants and, if ok,
        !           713:                         * just restart the receiver at the current
        !           714:                         * point in the ring.
        !           715:                         */
        !           716:                        if (i82596_chk_rx_ring(sc) != 0)
        !           717:                                return (1);
        !           718:
        !           719:                        i82596_start_transceiver(sc);
        !           720:                        sc->sc_arpcom.ac_if.if_ierrors++;
        !           721:                        return (0);
        !           722:                } else
        !           723:                        printf("%s: receiver not ready; scbstatus=%b\n",
        !           724:                                sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS);
        !           725:
        !           726:                sc->sc_arpcom.ac_if.if_ierrors++;
        !           727:                return (1);     /* Ask for a reset */
        !           728:        }
        !           729:
        !           730:        return (0);
        !           731: }
        !           732:
        !           733: /*
        !           734:  * Process a command-complete interrupt.  These are only generated by the
        !           735:  * transmission of frames.  This routine is deceptively simple, since most
        !           736:  * of the real work is done by i82596_start().
        !           737:  */
        !           738: int
        !           739: i82596_tint(sc, scbstatus)
        !           740:        struct ie_softc *sc;
        !           741:        int     scbstatus;
        !           742: {
        !           743:        register struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           744:        register int off, status;
        !           745:
        !           746:        ifp->if_timer = 0;
        !           747:        ifp->if_flags &= ~IFF_OACTIVE;
        !           748:
        !           749: #ifdef I82596_DEBUG
        !           750:        if (sc->xmit_busy <= 0) {
        !           751:                printf("%s: i82596_tint: WEIRD:"
        !           752:                       "xmit_busy=%d, xctail=%d, xchead=%d\n",
        !           753:                       sc->sc_dev.dv_xname,
        !           754:                       sc->xmit_busy, sc->xctail, sc->xchead);
        !           755:                return (0);
        !           756:        }
        !           757: #endif
        !           758:
        !           759:        off = IE_CMD_XMIT_STATUS(sc->xmit_cmds, sc->xctail);
        !           760:        status = sc->ie_bus_read16(sc, off);
        !           761:
        !           762: #ifdef I82596_DEBUG
        !           763:        if (sc->sc_debug & IED_TINT)
        !           764:                printf("%s: tint: SCB status %b; xmit status %b\n",
        !           765:                        sc->sc_dev.dv_xname, scbstatus, IE_ST_BITS,
        !           766:                        status, IE_XS_BITS);
        !           767: #endif
        !           768:
        !           769:        if ((status & (IE_STAT_COMPL|IE_STAT_BUSY)) == IE_STAT_BUSY) {
        !           770:                printf("%s: i82596_tint: command still busy;"
        !           771:                       "status=%b; tail=%d\n", sc->sc_dev.dv_xname,
        !           772:                       status, IE_XS_BITS, sc->xctail);
        !           773:                printf("iestatus = %b\n", scbstatus, IE_ST_BITS);
        !           774:        }
        !           775:
        !           776:        if (status & IE_STAT_OK) {
        !           777:                ifp->if_opackets++;
        !           778:                ifp->if_collisions += (status & IE_XS_MAXCOLL);
        !           779:        } else {
        !           780:                ifp->if_oerrors++;
        !           781:                /*
        !           782:                 * Check SQE and DEFERRED?
        !           783:                 * What if more than one bit is set?
        !           784:                 */
        !           785:                if (status & IE_STAT_ABORT)
        !           786:                        printf("%s: send aborted\n", sc->sc_dev.dv_xname);
        !           787:                else if (status & IE_XS_NOCARRIER)
        !           788:                        printf("%s: no carrier\n", sc->sc_dev.dv_xname);
        !           789:                else if (status & IE_XS_LOSTCTS)
        !           790:                        printf("%s: lost CTS\n", sc->sc_dev.dv_xname);
        !           791:                else if (status & IE_XS_UNDERRUN)
        !           792:                        printf("%s: DMA underrun\n", sc->sc_dev.dv_xname);
        !           793:                else if (status & IE_XS_EXCMAX) {
        !           794:                        printf("%s: too many collisions\n",
        !           795:                                sc->sc_dev.dv_xname);
        !           796:                        sc->sc_arpcom.ac_if.if_collisions += 16;
        !           797:                }
        !           798:        }
        !           799:
        !           800:        /*
        !           801:         * If multicast addresses were added or deleted while transmitting,
        !           802:         * ie_mc_reset() set the want_mcsetup flag indicating that we
        !           803:         * should do it.
        !           804:         */
        !           805:        if (sc->want_mcsetup) {
        !           806:                ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail));
        !           807:                sc->want_mcsetup = 0;
        !           808:        }
        !           809:
        !           810:        /* Done with the buffer. */
        !           811:        sc->xmit_busy--;
        !           812:        sc->xctail = (sc->xctail + 1) % NTXBUF;
        !           813:
        !           814:        /* Start the next packet, if any, transmitting. */
        !           815:        if (sc->xmit_busy > 0)
        !           816:                i82596_xmit(sc);
        !           817:
        !           818:        i82596_start(ifp);
        !           819:        return (0);
        !           820: }
        !           821:
        !           822: /*
        !           823:  * Get a range of receive buffer descriptors that represent one packet.
        !           824:  */
        !           825: int
        !           826: i82596_get_rbd_list(sc, start, end, pktlen)
        !           827:        struct ie_softc *sc;
        !           828:        u_int16_t       *start;
        !           829:        u_int16_t       *end;
        !           830:        int             *pktlen;
        !           831: {
        !           832:        int     off, rbbase = sc->rbds;
        !           833:        int     rbindex, count = 0;
        !           834:        int     plen = 0;
        !           835:        int     rbdstatus;
        !           836:
        !           837:        *start = rbindex = sc->rbhead;
        !           838:
        !           839:        do {
        !           840:                off = IE_RBD_STATUS(rbbase, rbindex);
        !           841:                bus_space_barrier(sc->bt, sc->bh, off, 2,
        !           842:                                  BUS_SPACE_BARRIER_READ);
        !           843:                rbdstatus = sc->ie_bus_read16(sc, off);
        !           844:                if ((rbdstatus & IE_RBD_USED) == 0) {
        !           845:                        /*
        !           846:                         * This means we are somehow out of sync.  So, we
        !           847:                         * reset the adapter.
        !           848:                         */
        !           849: #ifdef I82596_DEBUG
        !           850:                        print_rbd(sc, rbindex);
        !           851: #endif
        !           852:                        log(LOG_ERR,
        !           853:                            "%s: receive descriptors out of sync at %d\n",
        !           854:                            sc->sc_dev.dv_xname, rbindex);
        !           855:                        return (0);
        !           856:                }
        !           857:                plen += (rbdstatus & IE_RBD_CNTMASK);
        !           858:
        !           859:                if (++rbindex == sc->nrxbuf)
        !           860:                        rbindex = 0;
        !           861:
        !           862:                ++count;
        !           863:        } while ((rbdstatus & IE_RBD_LAST) == 0);
        !           864:        *end = rbindex;
        !           865:        *pktlen = plen;
        !           866:        return (count);
        !           867: }
        !           868:
        !           869:
        !           870: /*
        !           871:  * Release a range of receive buffer descriptors after we've copied the packet.
        !           872:  */
        !           873: void
        !           874: i82596_release_rbd_list(sc, start, end)
        !           875:        struct ie_softc *sc;
        !           876:        u_int16_t       start;
        !           877:        u_int16_t       end;
        !           878: {
        !           879:        register int    off, rbbase = sc->rbds;
        !           880:        register int    rbindex = start;
        !           881:
        !           882:        do {
        !           883:                /* Clear buffer status */
        !           884:                off = IE_RBD_STATUS(rbbase, rbindex);
        !           885:                sc->ie_bus_write16(sc, off, 0);
        !           886:                if (++rbindex == sc->nrxbuf)
        !           887:                        rbindex = 0;
        !           888:        } while (rbindex != end);
        !           889:
        !           890:        /* Mark EOL at new tail */
        !           891:        rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1;
        !           892:        off = IE_RBD_BUFLEN(rbbase, rbindex);
        !           893:        sc->ie_bus_write16(sc, off, IE_RBUF_SIZE|IE_RBD_EOL);
        !           894:
        !           895:        /* Remove EOL from current tail */
        !           896:        off = IE_RBD_BUFLEN(rbbase, sc->rbtail);
        !           897:        sc->ie_bus_write16(sc, off, IE_RBUF_SIZE);
        !           898:
        !           899:        /* New head & tail pointer */
        !           900: /* hmm, why have both? head is always (tail + 1) % NRXBUF */
        !           901:        sc->rbhead = end;
        !           902:        sc->rbtail = rbindex;
        !           903: }
        !           904:
        !           905: /*
        !           906:  * Drop the packet at the head of the RX buffer ring.
        !           907:  * Called if the frame descriptor reports an error on this packet.
        !           908:  * Returns 1 if the buffer descriptor ring appears to be corrupt;
        !           909:  * and 0 otherwise.
        !           910:  */
        !           911: int
        !           912: i82596_drop_frames(sc)
        !           913:        struct ie_softc *sc;
        !           914: {
        !           915:        u_int16_t bstart, bend;
        !           916:        int pktlen;
        !           917:
        !           918:        if (!i82596_get_rbd_list(sc, &bstart, &bend, &pktlen))
        !           919:                return (1);
        !           920:        i82596_release_rbd_list(sc, bstart, bend);
        !           921:        return (0);
        !           922: }
        !           923:
        !           924: /*
        !           925:  * Check the RX frame & buffer descriptor lists for our invariants,
        !           926:  * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer.
        !           927:  *
        !           928:  * Called when the receive unit has stopped unexpectedly.
        !           929:  * Returns 1 if an inconsistency is detected; 0 otherwise.
        !           930:  *
        !           931:  * The Receive Unit is expected to be NOT RUNNING.
        !           932:  */
        !           933: int
        !           934: i82596_chk_rx_ring(sc)
        !           935:        struct ie_softc *sc;
        !           936: {
        !           937:        int n, off, val;
        !           938:
        !           939:        for (n = 0; n < sc->nrxbuf; n++) {
        !           940:                off = IE_RBD_BUFLEN(sc->rbds, n);
        !           941:                val = sc->ie_bus_read16(sc, off);
        !           942:                if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) {
        !           943:                        /* `rbtail' and EOL flag out of sync */
        !           944:                        log(LOG_ERR,
        !           945:                            "%s: rx buffer descriptors out of sync at %d\n",
        !           946:                            sc->sc_dev.dv_xname, n);
        !           947:                        return (1);
        !           948:                }
        !           949:
        !           950:                /* Take the opportunity to clear the status fields here ? */
        !           951:        }
        !           952:
        !           953:        for (n = 0; n < sc->nframes; n++) {
        !           954:                off = IE_RFRAME_LAST(sc->rframes, n);
        !           955:                val = sc->ie_bus_read16(sc, off);
        !           956:                if ((n == sc->rftail) ^ ((val & (IE_FD_EOL|IE_FD_SUSP)) != 0)) {
        !           957:                        /* `rftail' and EOL flag out of sync */
        !           958:                        log(LOG_ERR,
        !           959:                            "%s: rx frame list out of sync at %d\n",
        !           960:                            sc->sc_dev.dv_xname, n);
        !           961:                        return (1);
        !           962:                }
        !           963:        }
        !           964:
        !           965:        return (0);
        !           966: }
        !           967:
        !           968: /*
        !           969:  * Read data off the interface, and turn it into an mbuf chain.
        !           970:  *
        !           971:  * This code is DRAMATICALLY different from the previous version; this
        !           972:  * version tries to allocate the entire mbuf chain up front, given the
        !           973:  * length of the data available.  This enables us to allocate mbuf
        !           974:  * clusters in many situations where before we would have had a long
        !           975:  * chain of partially-full mbufs.  This should help to speed up the
        !           976:  * operation considerably.  (Provided that it works, of course.)
        !           977:  */
        !           978: static __inline__ struct mbuf *
        !           979: i82596_get(struct ie_softc *sc, int head, int totlen)
        !           980: {
        !           981:        struct mbuf *m, *m0, *newm;
        !           982:        int off, len, resid;
        !           983:        int thisrboff, thismboff;
        !           984:        struct ether_header eh;
        !           985:
        !           986:        /*
        !           987:         * Snarf the Ethernet header.
        !           988:         */
        !           989:        (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head),
        !           990:            sizeof(struct ether_header));
        !           991:
        !           992:        resid = totlen;
        !           993:
        !           994:        MGETHDR(m0, M_DONTWAIT, MT_DATA);
        !           995:        if (m0 == 0)
        !           996:                return (0);
        !           997:        m0->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
        !           998:        m0->m_pkthdr.len = totlen;
        !           999:        len = MHLEN;
        !          1000:        m = m0;
        !          1001:
        !          1002:        /*
        !          1003:         * This loop goes through and allocates mbufs for all the data we will
        !          1004:         * be copying in.  It does not actually do the copying yet.
        !          1005:         */
        !          1006:        while (totlen > 0) {
        !          1007:                if (totlen >= MINCLSIZE) {
        !          1008:                        MCLGET(m, M_DONTWAIT);
        !          1009:                        if ((m->m_flags & M_EXT) == 0)
        !          1010:                                goto bad;
        !          1011:                        len = MCLBYTES;
        !          1012:                }
        !          1013:
        !          1014:                if (m == m0) {
        !          1015:                        caddr_t newdata = (caddr_t)
        !          1016:                            ALIGN(m->m_data + sizeof(struct ether_header)) -
        !          1017:                            sizeof(struct ether_header);
        !          1018:                        len -= newdata - m->m_data;
        !          1019:                        m->m_data = newdata;
        !          1020:                }
        !          1021:
        !          1022:                m->m_len = len = min(totlen, len);
        !          1023:
        !          1024:                totlen -= len;
        !          1025:                if (totlen > 0) {
        !          1026:                        MGET(newm, M_DONTWAIT, MT_DATA);
        !          1027:                        if (newm == 0)
        !          1028:                                goto bad;
        !          1029:                        len = MLEN;
        !          1030:                        m = m->m_next = newm;
        !          1031:                }
        !          1032:        }
        !          1033:
        !          1034:        m = m0;
        !          1035:        thismboff = 0;
        !          1036:
        !          1037:        /*
        !          1038:         * Copy the Ethernet header into the mbuf chain.
        !          1039:         */
        !          1040:        bcopy(&eh, mtod(m, caddr_t), sizeof(struct ether_header));
        !          1041:        thismboff = sizeof(struct ether_header);
        !          1042:        thisrboff = sizeof(struct ether_header);
        !          1043:        resid -= sizeof(struct ether_header);
        !          1044:
        !          1045:        /*
        !          1046:         * Now we take the mbuf chain (hopefully only one mbuf most of the
        !          1047:         * time) and stuff the data into it.  There are no possible failures
        !          1048:         * at or after this point.
        !          1049:         */
        !          1050:        while (resid > 0) {
        !          1051:                int thisrblen = IE_RBUF_SIZE - thisrboff,
        !          1052:                    thismblen = m->m_len - thismboff;
        !          1053:                len = min(thisrblen, thismblen);
        !          1054:
        !          1055:                off = IE_RBUF_ADDR(sc,head) + thisrboff;
        !          1056:                (sc->memcopyin)(sc, mtod(m, caddr_t) + thismboff, off, len);
        !          1057:                resid -= len;
        !          1058:
        !          1059:                if (len == thismblen) {
        !          1060:                        m = m->m_next;
        !          1061:                        thismboff = 0;
        !          1062:                } else
        !          1063:                        thismboff += len;
        !          1064:
        !          1065:                if (len == thisrblen) {
        !          1066:                        if (++head == sc->nrxbuf)
        !          1067:                                head = 0;
        !          1068:                        thisrboff = 0;
        !          1069:                } else
        !          1070:                        thisrboff += len;
        !          1071:        }
        !          1072:
        !          1073:        /*
        !          1074:         * Unless something changed strangely while we were doing the copy,
        !          1075:         * we have now copied everything in from the shared memory.
        !          1076:         * This means that we are done.
        !          1077:         */
        !          1078:        return (m0);
        !          1079:
        !          1080: bad:
        !          1081:        m_freem(m0);
        !          1082:        return (NULL);
        !          1083: }
        !          1084:
        !          1085: /*
        !          1086:  * Read frame NUM from unit UNIT (pre-cached as IE).
        !          1087:  *
        !          1088:  * This routine reads the RFD at NUM, and copies in the buffers from the list
        !          1089:  * of RBD, then rotates the RBD list so that the receiver doesn't start
        !          1090:  * complaining.  Trailers are DROPPED---there's no point in wasting time
        !          1091:  * on confusing code to deal with them.  Hopefully, this machine will
        !          1092:  * never ARP for trailers anyway.
        !          1093:  */
        !          1094: int
        !          1095: i82596_readframe(sc, num)
        !          1096:        struct ie_softc *sc;
        !          1097:        int num;                /* frame number to read */
        !          1098: {
        !          1099:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1100:        struct mbuf *m;
        !          1101:        u_int16_t bstart, bend;
        !          1102:        int pktlen;
        !          1103:
        !          1104:        if (i82596_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) {
        !          1105:                ifp->if_ierrors++;
        !          1106:                return (1);
        !          1107:        }
        !          1108:
        !          1109:        m = i82596_get(sc, bstart, pktlen);
        !          1110:        i82596_release_rbd_list(sc, bstart, bend);
        !          1111:
        !          1112:        if (m == 0) {
        !          1113:                sc->sc_arpcom.ac_if.if_ierrors++;
        !          1114:                return (0);
        !          1115:        }
        !          1116:
        !          1117: #ifdef I82596_DEBUG
        !          1118:        if (sc->sc_debug & IED_READFRAME) {
        !          1119:                struct ether_header *eh = mtod(m, struct ether_header *);
        !          1120:
        !          1121:                printf("%s: frame from ether %s type 0x%x len %d\n",
        !          1122:                    sc->sc_dev.dv_xname, ether_sprintf(eh->ether_shost),
        !          1123:                    (u_int)eh->ether_type, pktlen);
        !          1124:        }
        !          1125: #endif
        !          1126:
        !          1127: #if NBPFILTER > 0
        !          1128:        /* Check for a BPF filter; if so, hand it up. */
        !          1129:        if (ifp->if_bpf)
        !          1130:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !          1131: #endif /* NBPFILTER > 0 */
        !          1132:
        !          1133:        /*
        !          1134:         * Finally pass this packet up to higher layers.
        !          1135:         */
        !          1136:        ether_input_mbuf(ifp, m);
        !          1137:        ifp->if_ipackets++;
        !          1138:        return (0);
        !          1139: }
        !          1140:
        !          1141:
        !          1142: /*
        !          1143:  * Setup all necessary artifacts for an XMIT command, and then pass the XMIT
        !          1144:  * command to the chip to be executed.
        !          1145:  */
        !          1146: void
        !          1147: i82596_xmit(sc)
        !          1148:        struct ie_softc *sc;
        !          1149: {
        !          1150:        int off, cur, prev;
        !          1151:
        !          1152:        cur = sc->xctail;
        !          1153:
        !          1154: #ifdef I82596_DEBUG
        !          1155:        if (sc->sc_debug & IED_XMIT)
        !          1156:                printf("%s: xmit buffer %d\n", sc->sc_dev.dv_xname, cur);
        !          1157: #endif
        !          1158:
        !          1159:        /*
        !          1160:         * Setup the transmit command.
        !          1161:         */
        !          1162:        sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur),
        !          1163:                               IE_XBD_ADDR(sc->xbds, cur));
        !          1164:
        !          1165:        sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0);
        !          1166:
        !          1167:        if (sc->do_xmitnopchain) {
        !          1168:                /*
        !          1169:                 * Gate this XMIT command to the following NOP
        !          1170:                 */
        !          1171:                sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur),
        !          1172:                                       IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
        !          1173:                sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
        !          1174:                                       IE_CMD_XMIT | IE_CMD_INTR);
        !          1175:
        !          1176:                /*
        !          1177:                 * Loopback at following NOP
        !          1178:                 */
        !          1179:                sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0);
        !          1180:                sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur),
        !          1181:                                       IE_CMD_NOP_ADDR(sc->nop_cmds, cur));
        !          1182:
        !          1183:                /*
        !          1184:                 * Gate preceding NOP to this XMIT command
        !          1185:                 */
        !          1186:                prev = (cur + NTXBUF - 1) % NTXBUF;
        !          1187:                sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 0);
        !          1188:                sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev),
        !          1189:                                       IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
        !          1190:
        !          1191:                off = IE_SCB_STATUS(sc->scb);
        !          1192:                bus_space_barrier(sc->bt, sc->bh, off, 2,
        !          1193:                                  BUS_SPACE_BARRIER_READ);
        !          1194:                if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) {
        !          1195:                        printf("i82596_xmit: CU not active\n");
        !          1196:                        i82596_start_transceiver(sc);
        !          1197:                }
        !          1198:        } else {
        !          1199:                sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds,cur),
        !          1200:                                       0xffff);
        !          1201:
        !          1202:                sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur),
        !          1203:                                       IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST);
        !          1204:
        !          1205:                off = IE_SCB_CMDLST(sc->scb);
        !          1206:                sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur));
        !          1207:                bus_space_barrier(sc->bt, sc->bh, off, 2,
        !          1208:                                  BUS_SPACE_BARRIER_WRITE);
        !          1209:
        !          1210:                if (i82596_start_cmd(sc, IE_CUC_START, 0, 0, 1)) {
        !          1211: #ifdef I82596_DEBUG
        !          1212:                        if (sc->sc_debug & IED_XMIT)
        !          1213:                                printf("%s: i82596_xmit: "
        !          1214:                                    "start xmit command timed out\n",
        !          1215:                                       sc->sc_dev.dv_xname);
        !          1216: #endif
        !          1217:                }
        !          1218:        }
        !          1219:
        !          1220:        sc->sc_arpcom.ac_if.if_timer = 5;
        !          1221: }
        !          1222:
        !          1223:
        !          1224: /*
        !          1225:  * Start transmission on an interface.
        !          1226:  */
        !          1227: void
        !          1228: i82596_start(ifp)
        !          1229:        struct ifnet *ifp;
        !          1230: {
        !          1231:        struct ie_softc *sc = ifp->if_softc;
        !          1232:        struct mbuf *m0, *m;
        !          1233:        int     buffer, head, xbase;
        !          1234:        u_short len;
        !          1235:
        !          1236: #ifdef I82596_DEBUG
        !          1237:        if (sc->sc_debug & IED_ENQ)
        !          1238:                printf("i82596_start(%p)\n", ifp);
        !          1239: #endif
        !          1240:
        !          1241:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !          1242:                return;
        !          1243:
        !          1244:        for (;;) {
        !          1245:                if (sc->xmit_busy == NTXBUF) {
        !          1246:                        ifp->if_flags |= IFF_OACTIVE;
        !          1247:                        break;
        !          1248:                }
        !          1249:
        !          1250:                IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1251:                if (m0 == 0)
        !          1252:                        break;
        !          1253:
        !          1254:                /* We need to use m->m_pkthdr.len, so require the header */
        !          1255:                if ((m0->m_flags & M_PKTHDR) == 0)
        !          1256:                        panic("i82596_start: no header mbuf");
        !          1257:
        !          1258: #if NBPFILTER > 0
        !          1259:                /* Tap off here if there is a BPF listener. */
        !          1260:                if (ifp->if_bpf)
        !          1261:                        bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          1262: #endif
        !          1263:
        !          1264:                if (m0->m_pkthdr.len > IE_TBUF_SIZE)
        !          1265:                        printf("%s: tbuf overflow\n", sc->sc_dev.dv_xname);
        !          1266:
        !          1267:                head = sc->xchead;
        !          1268:                sc->xchead = (head + 1) % NTXBUF;
        !          1269:                buffer = IE_XBUF_ADDR(sc, head);
        !          1270:
        !          1271: #ifdef I82596_DEBUG
        !          1272:                if (sc->sc_debug & IED_ENQ)
        !          1273:                        printf("%s: fill buffer %d offset %x",
        !          1274:                            sc->sc_dev.dv_xname, head, buffer);
        !          1275: #endif
        !          1276:
        !          1277:                for (m = m0; m != 0; m = m->m_next) {
        !          1278: #ifdef I82596_DEBUG
        !          1279:                        if (sc->sc_debug & IED_ENQ) {
        !          1280:                                u_int8_t *e, *p = mtod(m, u_int8_t *);
        !          1281:                                static int i;
        !          1282:                                if (m == m0)
        !          1283:                                        i = 0;
        !          1284:                                for (e = p + m->m_len; p < e; i++, p += 2) {
        !          1285:                                        if (!(i % 8))
        !          1286:                                                printf("\n%s:",
        !          1287:                                                    sc->sc_dev.dv_xname);
        !          1288:                                        printf(" %02x%02x", p[0], p[1]);
        !          1289:                                }
        !          1290:                        }
        !          1291: #endif
        !          1292:                        (sc->memcopyout)(sc, mtod(m,caddr_t), buffer, m->m_len);
        !          1293:                        buffer += m->m_len;
        !          1294:                }
        !          1295:
        !          1296:                len = m0->m_pkthdr.len;
        !          1297:                if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) {
        !          1298:                        (sc->memcopyout)(sc, padbuf, buffer,
        !          1299:                            ETHER_MIN_LEN - ETHER_CRC_LEN - len);
        !          1300:                        buffer += ETHER_MIN_LEN - ETHER_CRC_LEN - len;
        !          1301:                        len = ETHER_MIN_LEN - ETHER_CRC_LEN;
        !          1302:                }
        !          1303:
        !          1304: #ifdef I82596_DEBUG
        !          1305:                if (sc->sc_debug & IED_ENQ)
        !          1306:                        printf("\n");
        !          1307: #endif
        !          1308:
        !          1309:                m_freem(m0);
        !          1310:
        !          1311:                /*
        !          1312:                 * Setup the transmit buffer descriptor here, while we
        !          1313:                 * know the packet's length.
        !          1314:                 */
        !          1315:                xbase = sc->xbds;
        !          1316:                sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head),
        !          1317:                                       len | IE_TBD_EOL);
        !          1318:                sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff);
        !          1319:                sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head),
        !          1320:                                       sc->sc_maddr + IE_XBUF_ADDR(sc, head));
        !          1321:
        !          1322:                /* Start the first packet transmitting. */
        !          1323:                if (sc->xmit_busy++ == 0)
        !          1324:                        i82596_xmit(sc);
        !          1325:        }
        !          1326: }
        !          1327:
        !          1328: /*
        !          1329:  * Probe IE's ram setup   [ Move all this into MD front-end!? ]
        !          1330:  * Use only if SCP and ISCP represent offsets into shared ram space.
        !          1331:  */
        !          1332: int
        !          1333: i82596_proberam(sc)
        !          1334:        struct ie_softc *sc;
        !          1335: {
        !          1336:        int result, off;
        !          1337:
        !          1338:        /* Put in 16-bit mode */
        !          1339:        off = IE_SCP_BUS_USE(sc->scp);
        !          1340:        (sc->ie_bus_write16)(sc, off, 0);
        !          1341:        bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
        !          1342:
        !          1343:        /* Set the ISCP `busy' bit */
        !          1344:        off = IE_ISCP_BUSY(sc->iscp);
        !          1345:        (sc->ie_bus_write16)(sc, off, 1);
        !          1346:        bus_space_barrier(sc->bt, sc->bh, off, 2, BUS_SPACE_BARRIER_WRITE);
        !          1347:
        !          1348:        if (sc->hwreset)
        !          1349:                (sc->hwreset)(sc, IE_CHIP_PROBE);
        !          1350:
        !          1351:        (sc->chan_attn) (sc);
        !          1352:
        !          1353:        DELAY(100);             /* wait a while... */
        !          1354:
        !          1355:        /* Read back the ISCP `busy' bit; it should be clear by now */
        !          1356:        off = IE_ISCP_BUSY(sc->iscp);
        !          1357:        bus_space_barrier(sc->bt, sc->bh, off, 1, BUS_SPACE_BARRIER_READ);
        !          1358:        result = (sc->ie_bus_read16)(sc, off) == 0;
        !          1359:
        !          1360:        /* Acknowledge any interrupts we may have caused. */
        !          1361:        ie_ack(sc, IE_ST_WHENCE);
        !          1362:
        !          1363:        return (result);
        !          1364: }
        !          1365:
        !          1366: void
        !          1367: i82596_reset(sc, hard)
        !          1368:        struct ie_softc *sc;
        !          1369:        int hard;
        !          1370: {
        !          1371:        int s = splnet();
        !          1372:
        !          1373: #ifdef I82596_DEBUG
        !          1374:        if (hard)
        !          1375:                printf("%s: reset\n", sc->sc_dev.dv_xname);
        !          1376: #endif
        !          1377:
        !          1378:        /* Clear OACTIVE in case we're called from watchdog (frozen xmit). */
        !          1379:        sc->sc_arpcom.ac_if.if_timer = 0;
        !          1380:        sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
        !          1381:
        !          1382:        /*
        !          1383:         * Stop i82596 dead in its tracks.
        !          1384:         */
        !          1385:        if (i82596_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0)) {
        !          1386: #ifdef I82596_DEBUG
        !          1387:                printf("%s: abort commands timed out\n", sc->sc_dev.dv_xname);
        !          1388: #endif
        !          1389:        }
        !          1390:
        !          1391:        /*
        !          1392:         * This can really slow down the i82596_reset() on some cards, but it's
        !          1393:         * necessary to unwedge other ones (eg, the Sun VME ones) from certain
        !          1394:         * lockups.
        !          1395:         */
        !          1396:        if (hard && sc->hwreset)
        !          1397:                (sc->hwreset)(sc, IE_CARD_RESET);
        !          1398:
        !          1399:        DELAY(100);
        !          1400:        ie_ack(sc, IE_ST_WHENCE);
        !          1401:
        !          1402:        if ((sc->sc_arpcom.ac_if.if_flags & IFF_UP) != 0) {
        !          1403:                int retries=0;  /* XXX - find out why init sometimes fails */
        !          1404:                while (retries++ < 2)
        !          1405:                        if (i82596_init(sc) == 1)
        !          1406:                                break;
        !          1407:        }
        !          1408:
        !          1409:        splx(s);
        !          1410: }
        !          1411:
        !          1412: void
        !          1413: i82596_simple_command(sc, cmd, cmdbuf)
        !          1414:        struct ie_softc *sc;
        !          1415:        int cmd;
        !          1416:        int cmdbuf;
        !          1417: {
        !          1418:        /* Setup a simple command */
        !          1419:        sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0);
        !          1420:        sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST);
        !          1421:        sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff);
        !          1422:
        !          1423:        /* Assign the command buffer to the SCB command list */
        !          1424:        sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf);
        !          1425: }
        !          1426:
        !          1427: /*
        !          1428:  * Run the time-domain reflectometer.
        !          1429:  */
        !          1430: void
        !          1431: ie_run_tdr(sc, cmd)
        !          1432:        struct ie_softc *sc;
        !          1433:        int cmd;
        !          1434: {
        !          1435:        int result, clocks;
        !          1436:
        !          1437:        i82596_simple_command(sc, IE_CMD_TDR, cmd);
        !          1438:        (sc->ie_bus_write16)(sc, IE_CMD_TDR_TIME(cmd), 0);
        !          1439:
        !          1440:        if (i82596_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) ||
        !          1441:            !(sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK))
        !          1442:                result = 0x10000; /* XXX */
        !          1443:        else
        !          1444:                result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd));
        !          1445:
        !          1446:        /* Squash any pending interrupts */
        !          1447:        ie_ack(sc, IE_ST_WHENCE);
        !          1448:
        !          1449:        if (result & IE_TDR_SUCCESS)
        !          1450:                return;
        !          1451:
        !          1452:        clocks = result & IE_TDR_TIME;
        !          1453:        if (result & 0x10000)
        !          1454:                printf("%s: TDR command failed\n", sc->sc_dev.dv_xname);
        !          1455:        else if (result & IE_TDR_XCVR)
        !          1456:                printf("%s: transceiver problem\n", sc->sc_dev.dv_xname);
        !          1457:        else if (result & IE_TDR_OPEN)
        !          1458:                printf("%s: TDR detected an open %d clock%s away\n",
        !          1459:                    sc->sc_dev.dv_xname, clocks, clocks == 1? "":"s");
        !          1460:        else if (result & IE_TDR_SHORT)
        !          1461:                printf("%s: TDR detected a short %d clock%s away\n",
        !          1462:                    sc->sc_dev.dv_xname, clocks, clocks == 1? "":"s");
        !          1463:        else
        !          1464:                printf("%s: TDR returned unknown status 0x%x\n",
        !          1465:                    sc->sc_dev.dv_xname, result);
        !          1466: }
        !          1467:
        !          1468: /*
        !          1469:  * i82596_setup_bufs: set up the buffers
        !          1470:  *
        !          1471:  * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz.
        !          1472:  * this is to be used for the buffers.  The chip indexs its control data
        !          1473:  * structures with 16 bit offsets, and it indexes actual buffers with
        !          1474:  * 24 bit addresses.   So we should allocate control buffers first so that
        !          1475:  * we don't overflow the 16 bit offset field.   The number of transmit
        !          1476:  * buffers is fixed at compile time.
        !          1477:  *
        !          1478:  */
        !          1479: void
        !          1480: i82596_setup_bufs(sc)
        !          1481:        struct ie_softc *sc;
        !          1482: {
        !          1483:        int n, r, ptr = sc->buf_area;   /* memory pool */
        !          1484:        int cl = 32;
        !          1485:
        !          1486:        /*
        !          1487:         * step 0: zero memory and figure out how many recv buffers and
        !          1488:         * frames we can have.
        !          1489:         */
        !          1490:        ptr = (ptr + cl - 1) & ~(cl - 1); /* set alignment and stick with it */
        !          1491:
        !          1492:        /*
        !          1493:         *  step 1: lay out data structures in the shared-memory area
        !          1494:         */
        !          1495:
        !          1496:        /* The no-op commands; used if "nop-chaining" is in effect */
        !          1497:        ptr += cl;
        !          1498:        sc->nop_cmds = ptr - 2;
        !          1499:        ptr += NTXBUF * 32;
        !          1500:
        !          1501:        /* The transmit commands */
        !          1502:        ptr += cl;
        !          1503:        sc->xmit_cmds = ptr - 2;
        !          1504:        ptr += NTXBUF * 32;
        !          1505:
        !          1506:        /* The transmit buffers descriptors */
        !          1507:        ptr += cl;
        !          1508:        sc->xbds = ptr - 2;
        !          1509:        ptr += NTXBUF * 32;
        !          1510:
        !          1511:        /* The transmit buffers */
        !          1512:        sc->xbufs = ptr;
        !          1513:        ptr += NTXBUF * IE_TBUF_SIZE;
        !          1514:
        !          1515:        ptr = (ptr + cl - 1) & ~(cl - 1);       /* re-align.. just in case */
        !          1516:
        !          1517:        /* Compute free space for RECV stuff */
        !          1518:        n = sc->buf_area_sz - (ptr - sc->buf_area);
        !          1519:
        !          1520:        /* Compute size of one RECV frame */
        !          1521:        r = 64 + ((32 + IE_RBUF_SIZE) * B_PER_F);
        !          1522:
        !          1523:        sc->nframes = n / r;
        !          1524:
        !          1525:        if (sc->nframes <= 8)
        !          1526:                panic("ie: bogus buffer calc");
        !          1527:
        !          1528:        sc->nrxbuf = sc->nframes * B_PER_F;
        !          1529:
        !          1530:        /* The receive frame descriptors */
        !          1531:        ptr += cl;
        !          1532:        sc->rframes = ptr - 2;
        !          1533:        ptr += sc->nframes * 64;
        !          1534:
        !          1535:        /* The receive buffer descriptors */
        !          1536:        ptr += cl;
        !          1537:        sc->rbds = ptr - 2;
        !          1538:        ptr += sc->nrxbuf * 32;
        !          1539:
        !          1540:        /* The receive buffers */
        !          1541:        sc->rbufs = ptr;
        !          1542:        ptr += sc->nrxbuf * IE_RBUF_SIZE;
        !          1543:
        !          1544: #ifdef I82596_DEBUG
        !          1545:        printf("%s: %d frames %d bufs\n", sc->sc_dev.dv_xname, sc->nframes,
        !          1546:                sc->nrxbuf);
        !          1547: #endif
        !          1548:
        !          1549:        /*
        !          1550:         * step 2: link together the recv frames and set EOL on last one
        !          1551:         */
        !          1552:        for (n = 0; n < sc->nframes; n++) {
        !          1553:                int m = (n == sc->nframes - 1) ? 0 : n + 1;
        !          1554:
        !          1555:                /* Clear status */
        !          1556:                sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes,n), 0);
        !          1557:
        !          1558:                /* RBD link = NULL */
        !          1559:                sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,n),
        !          1560:                                       0xffff);
        !          1561:
        !          1562:                /* Make a circular list */
        !          1563:                sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes,n),
        !          1564:                                       IE_RFRAME_ADDR(sc->rframes,m));
        !          1565:
        !          1566:                /* Mark last as EOL */
        !          1567:                sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes,n),
        !          1568:                                       ((m==0)? (IE_FD_EOL|IE_FD_SUSP) : 0));
        !          1569:        }
        !          1570:
        !          1571:        /*
        !          1572:         * step 3: link the RBDs and set EOL on last one
        !          1573:         */
        !          1574:        for (n = 0; n < sc->nrxbuf; n++) {
        !          1575:                int m = (n == sc->nrxbuf - 1) ? 0 : n + 1;
        !          1576:
        !          1577:                /* Clear status */
        !          1578:                sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds,n), 0);
        !          1579:
        !          1580:                /* Make a circular list */
        !          1581:                sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds,n),
        !          1582:                                       IE_RBD_ADDR(sc->rbds,m));
        !          1583:
        !          1584:                /* Link to data buffers */
        !          1585:                sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n),
        !          1586:                                       sc->sc_maddr + IE_RBUF_ADDR(sc, n));
        !          1587:                sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds,n),
        !          1588:                                       IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0));
        !          1589:        }
        !          1590:
        !          1591:        /*
        !          1592:         * step 4: all xmit no-op commands loopback onto themselves
        !          1593:         */
        !          1594:        for (n = 0; n < NTXBUF; n++) {
        !          1595:                (sc->ie_bus_write16)(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0);
        !          1596:
        !          1597:                (sc->ie_bus_write16)(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n),
        !          1598:                                         IE_CMD_NOP);
        !          1599:
        !          1600:                (sc->ie_bus_write16)(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n),
        !          1601:                                         IE_CMD_NOP_ADDR(sc->nop_cmds, n));
        !          1602:        }
        !          1603:
        !          1604:
        !          1605:        /*
        !          1606:         * step 6: set the head and tail pointers on receive to keep track of
        !          1607:         * the order in which RFDs and RBDs are used.
        !          1608:         */
        !          1609:
        !          1610:        /* Pointers to last packet sent and next available transmit buffer. */
        !          1611:        sc->xchead = sc->xctail = 0;
        !          1612:
        !          1613:        /* Clear transmit-busy flag and set number of free transmit buffers. */
        !          1614:        sc->xmit_busy = 0;
        !          1615:
        !          1616:        /*
        !          1617:         * Pointers to first and last receive frame.
        !          1618:         * The RFD pointed to by rftail is the only one that has EOL set.
        !          1619:         */
        !          1620:        sc->rfhead = 0;
        !          1621:        sc->rftail = sc->nframes - 1;
        !          1622:
        !          1623:        /*
        !          1624:         * Pointers to first and last receive descriptor buffer.
        !          1625:         * The RBD pointed to by rbtail is the only one that has EOL set.
        !          1626:         */
        !          1627:        sc->rbhead = 0;
        !          1628:        sc->rbtail = sc->nrxbuf - 1;
        !          1629:
        !          1630: /* link in recv frames * and buffer into the scb. */
        !          1631: #ifdef I82596_DEBUG
        !          1632:        printf("%s: reserved %d bytes\n",
        !          1633:                sc->sc_dev.dv_xname, ptr - sc->buf_area);
        !          1634: #endif
        !          1635: }
        !          1636:
        !          1637: int
        !          1638: ie_cfg_setup(sc, cmd, promiscuous, manchester)
        !          1639:        struct ie_softc *sc;
        !          1640:        int cmd;
        !          1641:        int promiscuous, manchester;
        !          1642: {
        !          1643:        int cmdresult, status;
        !          1644:
        !          1645:        i82596_simple_command(sc, IE_CMD_CONFIG, cmd);
        !          1646:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CNT(cmd), 0x0c);
        !          1647:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_FIFO(cmd), 8);
        !          1648:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SAVEBAD(cmd), 0x40);
        !          1649:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_ADDRLEN(cmd), 0x2e);
        !          1650:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PRIORITY(cmd), 0);
        !          1651:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_IFS(cmd), 0x60);
        !          1652:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_LOW(cmd), 0);
        !          1653:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_HIGH(cmd), 0xf2);
        !          1654:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PROMISC(cmd),
        !          1655:                                          !!promiscuous | manchester << 2);
        !          1656:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CRSCDT(cmd), 0);
        !          1657:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_MINLEN(cmd), 64);
        !          1658:        bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_JUNK(cmd), 0xff);
        !          1659:        bus_space_barrier(sc->bt, sc->bh, cmd, IE_CMD_CFG_SZ,
        !          1660:                          BUS_SPACE_BARRIER_WRITE);
        !          1661:
        !          1662:        cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0);
        !          1663:        status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd));
        !          1664:        if (cmdresult != 0) {
        !          1665:                printf("%s: configure command timed out; status %b\n",
        !          1666:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1667:                return (0);
        !          1668:        }
        !          1669:        if ((status & IE_STAT_OK) == 0) {
        !          1670:                printf("%s: configure command failed; status %b\n",
        !          1671:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1672:                return (0);
        !          1673:        }
        !          1674:
        !          1675:        /* Squash any pending interrupts */
        !          1676:        ie_ack(sc, IE_ST_WHENCE);
        !          1677:        return (1);
        !          1678: }
        !          1679:
        !          1680: int
        !          1681: ie_ia_setup(sc, cmdbuf)
        !          1682:        struct ie_softc *sc;
        !          1683:        int cmdbuf;
        !          1684: {
        !          1685:        int cmdresult, status;
        !          1686:
        !          1687:        i82596_simple_command(sc, IE_CMD_IASETUP, cmdbuf);
        !          1688:
        !          1689:        (sc->memcopyout)(sc, sc->sc_arpcom.ac_enaddr,
        !          1690:                         IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN);
        !          1691:
        !          1692:        cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
        !          1693:        status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
        !          1694:        if (cmdresult != 0) {
        !          1695:                printf("%s: individual address command timed out; status %b\n",
        !          1696:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1697:                return (0);
        !          1698:        }
        !          1699:        if ((status & IE_STAT_OK) == 0) {
        !          1700:                printf("%s: individual address command failed; status %b\n",
        !          1701:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1702:                return (0);
        !          1703:        }
        !          1704:
        !          1705:        /* Squash any pending interrupts */
        !          1706:        ie_ack(sc, IE_ST_WHENCE);
        !          1707:        return (1);
        !          1708: }
        !          1709:
        !          1710: /*
        !          1711:  * Run the multicast setup command.
        !          1712:  * Called at splnet().
        !          1713:  */
        !          1714: int
        !          1715: ie_mc_setup(sc, cmdbuf)
        !          1716:        struct ie_softc *sc;
        !          1717:        int cmdbuf;
        !          1718: {
        !          1719:        int cmdresult, status;
        !          1720:
        !          1721:        if (sc->mcast_count == 0)
        !          1722:                return (1);
        !          1723:
        !          1724:        i82596_simple_command(sc, IE_CMD_MCAST, cmdbuf);
        !          1725:
        !          1726:        (sc->memcopyout)(sc, (caddr_t)sc->mcast_addrs,
        !          1727:                         IE_CMD_MCAST_MADDR(cmdbuf),
        !          1728:                         sc->mcast_count * ETHER_ADDR_LEN);
        !          1729:
        !          1730:        sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf),
        !          1731:                               sc->mcast_count * ETHER_ADDR_LEN);
        !          1732:
        !          1733:        /* Start the command */
        !          1734:        cmdresult = i82596_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0);
        !          1735:        status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf));
        !          1736:        if (cmdresult != 0) {
        !          1737:                printf("%s: multicast setup command timed out; status %b\n",
        !          1738:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1739:                return (0);
        !          1740:        }
        !          1741:        if ((status & IE_STAT_OK) == 0) {
        !          1742:                printf("%s: multicast setup command failed; status %b\n",
        !          1743:                        sc->sc_dev.dv_xname, status, IE_STAT_BITS);
        !          1744:                return (0);
        !          1745:        }
        !          1746:
        !          1747:        /* Squash any pending interrupts */
        !          1748:        ie_ack(sc, IE_ST_WHENCE);
        !          1749:        return (1);
        !          1750: }
        !          1751:
        !          1752: /*
        !          1753:  * This routine takes the environment generated by check_ie_present() and adds
        !          1754:  * to it all the other structures we need to operate the adapter.  This
        !          1755:  * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting
        !          1756:  * the receiver unit, and clearing interrupts.
        !          1757:  *
        !          1758:  * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER.
        !          1759:  */
        !          1760: int
        !          1761: i82596_init(sc)
        !          1762:        struct ie_softc *sc;
        !          1763: {
        !          1764:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1765:        int cmd;
        !          1766:
        !          1767:        sc->async_cmd_inprogress = 0;
        !          1768:
        !          1769:        cmd = sc->buf_area;
        !          1770:
        !          1771:        /*
        !          1772:         * Send the configure command first.
        !          1773:         */
        !          1774:        if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0)
        !          1775:                return (0);
        !          1776:
        !          1777:        /*
        !          1778:         * Send the Individual Address Setup command.
        !          1779:         */
        !          1780:        if (ie_ia_setup(sc, cmd) == 0)
        !          1781:                return (0);
        !          1782:
        !          1783:        /*
        !          1784:         * Run the time-domain reflectometer.
        !          1785:         */
        !          1786:        ie_run_tdr(sc, cmd);
        !          1787:
        !          1788:        /*
        !          1789:         * Set the multi-cast filter, if any
        !          1790:         */
        !          1791:        if (ie_mc_setup(sc, cmd) == 0)
        !          1792:                return (0);
        !          1793:
        !          1794:        /*
        !          1795:         * Acknowledge any interrupts we have generated thus far.
        !          1796:         */
        !          1797:        ie_ack(sc, IE_ST_WHENCE);
        !          1798:
        !          1799:        /*
        !          1800:         * Set up the transmit and recv buffers.
        !          1801:         */
        !          1802:        i82596_setup_bufs(sc);
        !          1803:
        !          1804:        if (sc->hwinit)
        !          1805:                (sc->hwinit)(sc);
        !          1806:
        !          1807:        ifp->if_flags |= IFF_RUNNING;
        !          1808:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1809:
        !          1810:        if (NTXBUF < 2)
        !          1811:                sc->do_xmitnopchain = 0;
        !          1812:
        !          1813:        i82596_start_transceiver(sc);
        !          1814:        return (1);
        !          1815: }
        !          1816:
        !          1817: /*
        !          1818:  * Start the RU and possibly the CU unit
        !          1819:  */
        !          1820: void
        !          1821: i82596_start_transceiver(sc)
        !          1822:        struct ie_softc *sc;
        !          1823: {
        !          1824:
        !          1825:        /*
        !          1826:         * Start RU at current position in frame & RBD lists.
        !          1827:         */
        !          1828:        sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes,sc->rfhead),
        !          1829:                               IE_RBD_ADDR(sc->rbds, sc->rbhead));
        !          1830:
        !          1831:        sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb),
        !          1832:                               IE_RFRAME_ADDR(sc->rframes,sc->rfhead));
        !          1833:
        !          1834:        if (sc->do_xmitnopchain) {
        !          1835:                /* Stop transmit command chain */
        !          1836:                if (i82596_start_cmd(sc, IE_CUC_SUSPEND|IE_RUC_SUSPEND, 0, 0, 0))
        !          1837:                        printf("%s: CU/RU stop command timed out\n",
        !          1838:                                sc->sc_dev.dv_xname);
        !          1839:
        !          1840:                /* Start the receiver & transmitter chain */
        !          1841:                /* sc->scb->ie_command_list =
        !          1842:                        IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/
        !          1843:                sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb),
        !          1844:                                   IE_CMD_NOP_ADDR(
        !          1845:                                        sc->nop_cmds,
        !          1846:                                        (sc->xctail + NTXBUF - 1) % NTXBUF));
        !          1847:
        !          1848:                if (i82596_start_cmd(sc, IE_CUC_START|IE_RUC_START, 0, 0, 0))
        !          1849:                        printf("%s: CU/RU command timed out\n",
        !          1850:                                sc->sc_dev.dv_xname);
        !          1851:        } else {
        !          1852:                if (i82596_start_cmd(sc, IE_RUC_START, 0, 0, 0))
        !          1853:                        printf("%s: RU command timed out\n",
        !          1854:                                sc->sc_dev.dv_xname);
        !          1855:        }
        !          1856: }
        !          1857:
        !          1858: void
        !          1859: i82596_stop(sc)
        !          1860:        struct ie_softc *sc;
        !          1861: {
        !          1862:
        !          1863:        if (i82596_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0))
        !          1864:                printf("%s: i82596_stop: disable commands timed out\n",
        !          1865:                        sc->sc_dev.dv_xname);
        !          1866: }
        !          1867:
        !          1868: int
        !          1869: i82596_ioctl(ifp, cmd, data)
        !          1870:        register struct ifnet *ifp;
        !          1871:        u_long cmd;
        !          1872:        caddr_t data;
        !          1873: {
        !          1874:        struct ie_softc *sc = ifp->if_softc;
        !          1875:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          1876:        struct ifreq *ifr = (struct ifreq *)data;
        !          1877:        int s, error = 0;
        !          1878:
        !          1879:        s = splnet();
        !          1880:
        !          1881:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !          1882:                splx(s);
        !          1883:                return error;
        !          1884:        }
        !          1885:
        !          1886:        switch(cmd) {
        !          1887:
        !          1888:        case SIOCSIFADDR:
        !          1889:                ifp->if_flags |= IFF_UP;
        !          1890:
        !          1891:                switch(ifa->ifa_addr->sa_family) {
        !          1892: #ifdef INET
        !          1893:                case AF_INET:
        !          1894:                        i82596_init(sc);
        !          1895:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !          1896:                        break;
        !          1897: #endif
        !          1898:                default:
        !          1899:                        i82596_init(sc);
        !          1900:                        break;
        !          1901:                }
        !          1902:                break;
        !          1903:
        !          1904:        case SIOCSIFFLAGS:
        !          1905:                sc->promisc = ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI);
        !          1906:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !          1907:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !          1908:                        /*
        !          1909:                         * If interface is marked down and it is running, then
        !          1910:                         * stop it.
        !          1911:                         */
        !          1912:                        i82596_stop(sc);
        !          1913:                        ifp->if_flags &= ~IFF_RUNNING;
        !          1914:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !          1915:                           (ifp->if_flags & IFF_RUNNING) == 0) {
        !          1916:                        /*
        !          1917:                         * If interface is marked up and it is stopped, then
        !          1918:                         * start it.
        !          1919:                         */
        !          1920:                        i82596_init(sc);
        !          1921:                } else {
        !          1922:                        /*
        !          1923:                         * Reset the interface to pick up changes in any other
        !          1924:                         * flags that affect hardware registers.
        !          1925:                         */
        !          1926:                        i82596_stop(sc);
        !          1927:                        i82596_init(sc);
        !          1928:                }
        !          1929: #ifdef I82596_DEBUG
        !          1930:                if (ifp->if_flags & IFF_DEBUG)
        !          1931:                        sc->sc_debug = IED_ALL;
        !          1932:                else
        !          1933:                        sc->sc_debug = 0;
        !          1934: #endif
        !          1935:                break;
        !          1936:
        !          1937:        case SIOCADDMULTI:
        !          1938:        case SIOCDELMULTI:
        !          1939:                error = (cmd == SIOCADDMULTI) ?
        !          1940:                    ether_addmulti(ifr, &sc->sc_arpcom):
        !          1941:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !          1942:
        !          1943:                if (error == ENETRESET) {
        !          1944:                        /*
        !          1945:                         * Multicast list has changed; set the hardware filter
        !          1946:                         * accordingly.
        !          1947:                         */
        !          1948:                        if (ifp->if_flags & IFF_RUNNING)
        !          1949:                                ie_mc_reset(sc);
        !          1950:                        error = 0;
        !          1951:                }
        !          1952:                break;
        !          1953:
        !          1954:         case SIOCGIFMEDIA:
        !          1955:         case SIOCSIFMEDIA:
        !          1956:                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
        !          1957:                 break;
        !          1958:
        !          1959:        default:
        !          1960:                error = EINVAL;
        !          1961:        }
        !          1962:        splx(s);
        !          1963:        return (error);
        !          1964: }
        !          1965:
        !          1966: void
        !          1967: ie_mc_reset(sc)
        !          1968:        struct ie_softc *sc;
        !          1969: {
        !          1970:        struct ether_multi *enm;
        !          1971:        struct ether_multistep step;
        !          1972:        int size;
        !          1973:
        !          1974:        /*
        !          1975:         * Step through the list of addresses.
        !          1976:         */
        !          1977: again:
        !          1978:        size = 0;
        !          1979:        sc->mcast_count = 0;
        !          1980:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
        !          1981:        while (enm) {
        !          1982:                size += 6;
        !          1983:                if (sc->mcast_count >= IE_MAXMCAST ||
        !          1984:                    bcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) {
        !          1985:                        sc->sc_arpcom.ac_if.if_flags |= IFF_ALLMULTI;
        !          1986:                        i82596_ioctl(&sc->sc_arpcom.ac_if,
        !          1987:                                     SIOCSIFFLAGS, (void *)0);
        !          1988:                        return;
        !          1989:                }
        !          1990:                ETHER_NEXT_MULTI(step, enm);
        !          1991:        }
        !          1992:
        !          1993:        if (size > sc->mcast_addrs_size) {
        !          1994:                /* Need to allocate more space */
        !          1995:                if (sc->mcast_addrs_size)
        !          1996:                        free(sc->mcast_addrs, M_IFMADDR);
        !          1997:                sc->mcast_addrs = (char *)
        !          1998:                        malloc(size, M_IFMADDR, M_WAITOK);
        !          1999:                sc->mcast_addrs_size = size;
        !          2000:        }
        !          2001:
        !          2002:        /*
        !          2003:         * We've got the space; now copy the addresses
        !          2004:         */
        !          2005:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
        !          2006:        while (enm) {
        !          2007:                if (sc->mcast_count >= IE_MAXMCAST)
        !          2008:                        goto again; /* Just in case */
        !          2009:
        !          2010:                bcopy(enm->enm_addrlo, &sc->mcast_addrs[sc->mcast_count], 6);
        !          2011:                sc->mcast_count++;
        !          2012:                ETHER_NEXT_MULTI(step, enm);
        !          2013:        }
        !          2014:        sc->want_mcsetup = 1;
        !          2015: }
        !          2016:
        !          2017: /*
        !          2018:  * Media change callback.
        !          2019:  */
        !          2020: int
        !          2021: i82596_mediachange(ifp)
        !          2022:         struct ifnet *ifp;
        !          2023: {
        !          2024:         struct ie_softc *sc = ifp->if_softc;
        !          2025:
        !          2026:         if (sc->sc_mediachange)
        !          2027:                 return ((*sc->sc_mediachange)(sc));
        !          2028:         return (EINVAL);
        !          2029: }
        !          2030:
        !          2031: /*
        !          2032:  * Media status callback.
        !          2033:  */
        !          2034: void
        !          2035: i82596_mediastatus(ifp, ifmr)
        !          2036:         struct ifnet *ifp;
        !          2037:         struct ifmediareq *ifmr;
        !          2038: {
        !          2039:         struct ie_softc *sc = ifp->if_softc;
        !          2040:
        !          2041:         if (sc->sc_mediastatus)
        !          2042:                 (*sc->sc_mediastatus)(sc, ifmr);
        !          2043: }
        !          2044:
        !          2045: #ifdef I82596_DEBUG
        !          2046: void
        !          2047: print_rbd(sc, n)
        !          2048:        struct ie_softc *sc;
        !          2049:        int n;
        !          2050: {
        !          2051:
        !          2052:        printf("RBD at %08x:\n  status %b, next %04x, buffer %lx\n"
        !          2053:                "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds,n),
        !          2054:                sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds,n)), IE_STAT_BITS,
        !          2055:                sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds,n)),
        !          2056:                (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */
        !          2057:                sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds,n)));
        !          2058: }
        !          2059: #endif

CVSweb