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

Annotation of sys/dev/pci/if_nge.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_nge.c,v 1.56 2006/10/25 02:37:50 brad Exp $        */
        !             2: /*
        !             3:  * Copyright (c) 2001 Wind River Systems
        !             4:  * Copyright (c) 1997, 1998, 1999, 2000, 2001
        !             5:  *     Bill Paul <wpaul@bsdi.com>.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Bill Paul.
        !            18:  * 4. Neither the name of the author nor the names of any co-contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
        !            26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            32:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  *
        !            34:  * $FreeBSD: if_nge.c,v 1.35 2002/08/08 18:33:28 ambrisko Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * National Semiconductor DP83820/DP83821 gigabit ethernet driver
        !            39:  * for FreeBSD. Datasheets are available from:
        !            40:  *
        !            41:  * http://www.national.com/ds/DP/DP83820.pdf
        !            42:  * http://www.national.com/ds/DP/DP83821.pdf
        !            43:  *
        !            44:  * These chips are used on several low cost gigabit ethernet NICs
        !            45:  * sold by D-Link, Addtron, SMC and Asante. Both parts are
        !            46:  * virtually the same, except the 83820 is a 64-bit/32-bit part,
        !            47:  * while the 83821 is 32-bit only.
        !            48:  *
        !            49:  * Many cards also use National gigE transceivers, such as the
        !            50:  * DP83891, DP83861 and DP83862 gigPHYTER parts. The DP83861 datasheet
        !            51:  * contains a full register description that applies to all of these
        !            52:  * components:
        !            53:  *
        !            54:  * http://www.national.com/ds/DP/DP83861.pdf
        !            55:  *
        !            56:  * Written by Bill Paul <wpaul@bsdi.com>
        !            57:  * BSDi Open Source Solutions
        !            58:  */
        !            59:
        !            60: /*
        !            61:  * The NatSemi DP83820 and 83821 controllers are enhanced versions
        !            62:  * of the NatSemi MacPHYTER 10/100 devices. They support 10, 100
        !            63:  * and 1000Mbps speeds with 1000baseX (ten bit interface), MII and GMII
        !            64:  * ports. Other features include 8K TX FIFO and 32K RX FIFO, TCP/IP
        !            65:  * hardware checksum offload (IPv4 only), VLAN tagging and filtering,
        !            66:  * priority TX and RX queues, a 2048 bit multicast hash filter, 4 RX pattern
        !            67:  * matching buffers, one perfect address filter buffer and interrupt
        !            68:  * moderation. The 83820 supports both 64-bit and 32-bit addressing
        !            69:  * and data transfers: the 64-bit support can be toggled on or off
        !            70:  * via software. This affects the size of certain fields in the DMA
        !            71:  * descriptors.
        !            72:  *
        !            73:  * There are two bugs/misfeatures in the 83820/83821 that I have
        !            74:  * discovered so far:
        !            75:  *
        !            76:  * - Receive buffers must be aligned on 64-bit boundaries, which means
        !            77:  *   you must resort to copying data in order to fix up the payload
        !            78:  *   alignment.
        !            79:  *
        !            80:  * - In order to transmit jumbo frames larger than 8170 bytes, you have
        !            81:  *   to turn off transmit checksum offloading, because the chip can't
        !            82:  *   compute the checksum on an outgoing frame unless it fits entirely
        !            83:  *   within the TX FIFO, which is only 8192 bytes in size. If you have
        !            84:  *   TX checksum offload enabled and you transmit attempt to transmit a
        !            85:  *   frame larger than 8170 bytes, the transmitter will wedge.
        !            86:  *
        !            87:  * To work around the latter problem, TX checksum offload is disabled
        !            88:  * if the user selects an MTU larger than 8152 (8170 - 18).
        !            89:  */
        !            90:
        !            91: #include "bpfilter.h"
        !            92: #include "vlan.h"
        !            93:
        !            94: #include <sys/param.h>
        !            95: #include <sys/systm.h>
        !            96: #include <sys/sockio.h>
        !            97: #include <sys/mbuf.h>
        !            98: #include <sys/malloc.h>
        !            99: #include <sys/kernel.h>
        !           100: #include <sys/device.h>
        !           101: #include <sys/socket.h>
        !           102:
        !           103: #include <net/if.h>
        !           104: #include <net/if_dl.h>
        !           105: #include <net/if_media.h>
        !           106:
        !           107: #ifdef INET
        !           108: #include <netinet/in.h>
        !           109: #include <netinet/in_systm.h>
        !           110: #include <netinet/in_var.h>
        !           111: #include <netinet/ip.h>
        !           112: #include <netinet/if_ether.h>
        !           113: #endif
        !           114:
        !           115: #if NVLAN > 0
        !           116: #include <net/if_types.h>
        !           117: #include <net/if_vlan_var.h>
        !           118: #endif
        !           119:
        !           120: #if NBPFILTER > 0
        !           121: #include <net/bpf.h>
        !           122: #endif
        !           123:
        !           124: #include <uvm/uvm_extern.h>              /* for vtophys */
        !           125: #define        VTOPHYS(v)      vtophys((vaddr_t)(v))
        !           126:
        !           127: #include <dev/pci/pcireg.h>
        !           128: #include <dev/pci/pcivar.h>
        !           129: #include <dev/pci/pcidevs.h>
        !           130:
        !           131: #include <dev/mii/mii.h>
        !           132: #include <dev/mii/miivar.h>
        !           133:
        !           134: #define NGE_USEIOSPACE
        !           135:
        !           136: #include <dev/pci/if_ngereg.h>
        !           137:
        !           138: int nge_probe(struct device *, void *, void *);
        !           139: void nge_attach(struct device *, struct device *, void *);
        !           140:
        !           141: int nge_alloc_jumbo_mem(struct nge_softc *);
        !           142: void *nge_jalloc(struct nge_softc *);
        !           143: void nge_jfree(caddr_t, u_int, void *);
        !           144:
        !           145: int nge_newbuf(struct nge_softc *, struct nge_desc *,
        !           146:                             struct mbuf *);
        !           147: int nge_encap(struct nge_softc *, struct mbuf *, u_int32_t *);
        !           148: void nge_rxeof(struct nge_softc *);
        !           149: void nge_txeof(struct nge_softc *);
        !           150: int nge_intr(void *);
        !           151: void nge_tick(void *);
        !           152: void nge_start(struct ifnet *);
        !           153: int nge_ioctl(struct ifnet *, u_long, caddr_t);
        !           154: void nge_init(void *);
        !           155: void nge_stop(struct nge_softc *);
        !           156: void nge_watchdog(struct ifnet *);
        !           157: void nge_shutdown(void *);
        !           158: int nge_ifmedia_mii_upd(struct ifnet *);
        !           159: void nge_ifmedia_mii_sts(struct ifnet *, struct ifmediareq *);
        !           160: int nge_ifmedia_tbi_upd(struct ifnet *);
        !           161: void nge_ifmedia_tbi_sts(struct ifnet *, struct ifmediareq *);
        !           162:
        !           163: void nge_delay(struct nge_softc *);
        !           164: void nge_eeprom_idle(struct nge_softc *);
        !           165: void nge_eeprom_putbyte(struct nge_softc *, int);
        !           166: void nge_eeprom_getword(struct nge_softc *, int, u_int16_t *);
        !           167: void nge_read_eeprom(struct nge_softc *, caddr_t, int, int, int);
        !           168:
        !           169: void nge_mii_sync(struct nge_softc *);
        !           170: void nge_mii_send(struct nge_softc *, u_int32_t, int);
        !           171: int nge_mii_readreg(struct nge_softc *, struct nge_mii_frame *);
        !           172: int nge_mii_writereg(struct nge_softc *, struct nge_mii_frame *);
        !           173:
        !           174: int nge_miibus_readreg(struct device *, int, int);
        !           175: void nge_miibus_writereg(struct device *, int, int, int);
        !           176: void nge_miibus_statchg(struct device *);
        !           177:
        !           178: void nge_setmulti(struct nge_softc *);
        !           179: void nge_reset(struct nge_softc *);
        !           180: int nge_list_rx_init(struct nge_softc *);
        !           181: int nge_list_tx_init(struct nge_softc *);
        !           182:
        !           183: #ifdef NGE_USEIOSPACE
        !           184: #define NGE_RES                        SYS_RES_IOPORT
        !           185: #define NGE_RID                        NGE_PCI_LOIO
        !           186: #else
        !           187: #define NGE_RES                        SYS_RES_MEMORY
        !           188: #define NGE_RID                        NGE_PCI_LOMEM
        !           189: #endif
        !           190:
        !           191: #ifdef NGE_DEBUG
        !           192: #define DPRINTF(x)     if (ngedebug) printf x
        !           193: #define DPRINTFN(n,x)  if (ngedebug >= (n)) printf x
        !           194: int    ngedebug = 0;
        !           195: #else
        !           196: #define DPRINTF(x)
        !           197: #define DPRINTFN(n,x)
        !           198: #endif
        !           199:
        !           200: #define NGE_SETBIT(sc, reg, x)                         \
        !           201:        CSR_WRITE_4(sc, reg,                            \
        !           202:                CSR_READ_4(sc, reg) | (x))
        !           203:
        !           204: #define NGE_CLRBIT(sc, reg, x)                         \
        !           205:        CSR_WRITE_4(sc, reg,                            \
        !           206:                CSR_READ_4(sc, reg) & ~(x))
        !           207:
        !           208: #define SIO_SET(x)                                     \
        !           209:        CSR_WRITE_4(sc, NGE_MEAR, CSR_READ_4(sc, NGE_MEAR) | (x))
        !           210:
        !           211: #define SIO_CLR(x)                                     \
        !           212:        CSR_WRITE_4(sc, NGE_MEAR, CSR_READ_4(sc, NGE_MEAR) & ~(x))
        !           213:
        !           214: void
        !           215: nge_delay(sc)
        !           216:        struct nge_softc        *sc;
        !           217: {
        !           218:        int                     idx;
        !           219:
        !           220:        for (idx = (300 / 33) + 1; idx > 0; idx--)
        !           221:                CSR_READ_4(sc, NGE_CSR);
        !           222: }
        !           223:
        !           224: void
        !           225: nge_eeprom_idle(sc)
        !           226:        struct nge_softc        *sc;
        !           227: {
        !           228:        int             i;
        !           229:
        !           230:        SIO_SET(NGE_MEAR_EE_CSEL);
        !           231:        nge_delay(sc);
        !           232:        SIO_SET(NGE_MEAR_EE_CLK);
        !           233:        nge_delay(sc);
        !           234:
        !           235:        for (i = 0; i < 25; i++) {
        !           236:                SIO_CLR(NGE_MEAR_EE_CLK);
        !           237:                nge_delay(sc);
        !           238:                SIO_SET(NGE_MEAR_EE_CLK);
        !           239:                nge_delay(sc);
        !           240:        }
        !           241:
        !           242:        SIO_CLR(NGE_MEAR_EE_CLK);
        !           243:        nge_delay(sc);
        !           244:        SIO_CLR(NGE_MEAR_EE_CSEL);
        !           245:        nge_delay(sc);
        !           246:        CSR_WRITE_4(sc, NGE_MEAR, 0x00000000);
        !           247: }
        !           248:
        !           249: /*
        !           250:  * Send a read command and address to the EEPROM, check for ACK.
        !           251:  */
        !           252: void
        !           253: nge_eeprom_putbyte(sc, addr)
        !           254:        struct nge_softc        *sc;
        !           255:        int                     addr;
        !           256: {
        !           257:        int                     d, i;
        !           258:
        !           259:        d = addr | NGE_EECMD_READ;
        !           260:
        !           261:        /*
        !           262:         * Feed in each bit and strobe the clock.
        !           263:         */
        !           264:        for (i = 0x400; i; i >>= 1) {
        !           265:                if (d & i) {
        !           266:                        SIO_SET(NGE_MEAR_EE_DIN);
        !           267:                } else {
        !           268:                        SIO_CLR(NGE_MEAR_EE_DIN);
        !           269:                }
        !           270:                nge_delay(sc);
        !           271:                SIO_SET(NGE_MEAR_EE_CLK);
        !           272:                nge_delay(sc);
        !           273:                SIO_CLR(NGE_MEAR_EE_CLK);
        !           274:                nge_delay(sc);
        !           275:        }
        !           276: }
        !           277:
        !           278: /*
        !           279:  * Read a word of data stored in the EEPROM at address 'addr.'
        !           280:  */
        !           281: void
        !           282: nge_eeprom_getword(sc, addr, dest)
        !           283:        struct nge_softc        *sc;
        !           284:        int                     addr;
        !           285:        u_int16_t               *dest;
        !           286: {
        !           287:        int                     i;
        !           288:        u_int16_t               word = 0;
        !           289:
        !           290:        /* Force EEPROM to idle state. */
        !           291:        nge_eeprom_idle(sc);
        !           292:
        !           293:        /* Enter EEPROM access mode. */
        !           294:        nge_delay(sc);
        !           295:        SIO_CLR(NGE_MEAR_EE_CLK);
        !           296:        nge_delay(sc);
        !           297:        SIO_SET(NGE_MEAR_EE_CSEL);
        !           298:        nge_delay(sc);
        !           299:
        !           300:        /*
        !           301:         * Send address of word we want to read.
        !           302:         */
        !           303:        nge_eeprom_putbyte(sc, addr);
        !           304:
        !           305:        /*
        !           306:         * Start reading bits from EEPROM.
        !           307:         */
        !           308:        for (i = 0x8000; i; i >>= 1) {
        !           309:                SIO_SET(NGE_MEAR_EE_CLK);
        !           310:                nge_delay(sc);
        !           311:                if (CSR_READ_4(sc, NGE_MEAR) & NGE_MEAR_EE_DOUT)
        !           312:                        word |= i;
        !           313:                nge_delay(sc);
        !           314:                SIO_CLR(NGE_MEAR_EE_CLK);
        !           315:                nge_delay(sc);
        !           316:        }
        !           317:
        !           318:        /* Turn off EEPROM access mode. */
        !           319:        nge_eeprom_idle(sc);
        !           320:
        !           321:        *dest = word;
        !           322: }
        !           323:
        !           324: /*
        !           325:  * Read a sequence of words from the EEPROM.
        !           326:  */
        !           327: void
        !           328: nge_read_eeprom(sc, dest, off, cnt, swap)
        !           329:        struct nge_softc        *sc;
        !           330:        caddr_t                 dest;
        !           331:        int                     off;
        !           332:        int                     cnt;
        !           333:        int                     swap;
        !           334: {
        !           335:        int                     i;
        !           336:        u_int16_t               word = 0, *ptr;
        !           337:
        !           338:        for (i = 0; i < cnt; i++) {
        !           339:                nge_eeprom_getword(sc, off + i, &word);
        !           340:                ptr = (u_int16_t *)(dest + (i * 2));
        !           341:                if (swap)
        !           342:                        *ptr = ntohs(word);
        !           343:                else
        !           344:                        *ptr = word;
        !           345:        }
        !           346: }
        !           347:
        !           348: /*
        !           349:  * Sync the PHYs by setting data bit and strobing the clock 32 times.
        !           350:  */
        !           351: void
        !           352: nge_mii_sync(sc)
        !           353:        struct nge_softc                *sc;
        !           354: {
        !           355:        int                     i;
        !           356:
        !           357:        SIO_SET(NGE_MEAR_MII_DIR|NGE_MEAR_MII_DATA);
        !           358:
        !           359:        for (i = 0; i < 32; i++) {
        !           360:                SIO_SET(NGE_MEAR_MII_CLK);
        !           361:                DELAY(1);
        !           362:                SIO_CLR(NGE_MEAR_MII_CLK);
        !           363:                DELAY(1);
        !           364:        }
        !           365: }
        !           366:
        !           367: /*
        !           368:  * Clock a series of bits through the MII.
        !           369:  */
        !           370: void
        !           371: nge_mii_send(sc, bits, cnt)
        !           372:        struct nge_softc                *sc;
        !           373:        u_int32_t               bits;
        !           374:        int                     cnt;
        !           375: {
        !           376:        int                     i;
        !           377:
        !           378:        SIO_CLR(NGE_MEAR_MII_CLK);
        !           379:
        !           380:        for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
        !           381:                 if (bits & i) {
        !           382:                        SIO_SET(NGE_MEAR_MII_DATA);
        !           383:                 } else {
        !           384:                        SIO_CLR(NGE_MEAR_MII_DATA);
        !           385:                 }
        !           386:                DELAY(1);
        !           387:                SIO_CLR(NGE_MEAR_MII_CLK);
        !           388:                DELAY(1);
        !           389:                SIO_SET(NGE_MEAR_MII_CLK);
        !           390:        }
        !           391: }
        !           392:
        !           393: /*
        !           394:  * Read an PHY register through the MII.
        !           395:  */
        !           396: int
        !           397: nge_mii_readreg(sc, frame)
        !           398:        struct nge_softc                *sc;
        !           399:        struct nge_mii_frame    *frame;
        !           400: {
        !           401:        int                     i, ack, s;
        !           402:
        !           403:        s = splnet();
        !           404:
        !           405:        /*
        !           406:         * Set up frame for RX.
        !           407:         */
        !           408:        frame->mii_stdelim = NGE_MII_STARTDELIM;
        !           409:        frame->mii_opcode = NGE_MII_READOP;
        !           410:        frame->mii_turnaround = 0;
        !           411:        frame->mii_data = 0;
        !           412:
        !           413:        CSR_WRITE_4(sc, NGE_MEAR, 0);
        !           414:
        !           415:        /*
        !           416:         * Turn on data xmit.
        !           417:         */
        !           418:        SIO_SET(NGE_MEAR_MII_DIR);
        !           419:
        !           420:        nge_mii_sync(sc);
        !           421:
        !           422:        /*
        !           423:         * Send command/address info.
        !           424:         */
        !           425:        nge_mii_send(sc, frame->mii_stdelim, 2);
        !           426:        nge_mii_send(sc, frame->mii_opcode, 2);
        !           427:        nge_mii_send(sc, frame->mii_phyaddr, 5);
        !           428:        nge_mii_send(sc, frame->mii_regaddr, 5);
        !           429:
        !           430:        /* Idle bit */
        !           431:        SIO_CLR((NGE_MEAR_MII_CLK|NGE_MEAR_MII_DATA));
        !           432:        DELAY(1);
        !           433:        SIO_SET(NGE_MEAR_MII_CLK);
        !           434:        DELAY(1);
        !           435:
        !           436:        /* Turn off xmit. */
        !           437:        SIO_CLR(NGE_MEAR_MII_DIR);
        !           438:        /* Check for ack */
        !           439:        SIO_CLR(NGE_MEAR_MII_CLK);
        !           440:        DELAY(1);
        !           441:        ack = CSR_READ_4(sc, NGE_MEAR) & NGE_MEAR_MII_DATA;
        !           442:        SIO_SET(NGE_MEAR_MII_CLK);
        !           443:        DELAY(1);
        !           444:
        !           445:        /*
        !           446:         * Now try reading data bits. If the ack failed, we still
        !           447:         * need to clock through 16 cycles to keep the PHY(s) in sync.
        !           448:         */
        !           449:        if (ack) {
        !           450:                for(i = 0; i < 16; i++) {
        !           451:                        SIO_CLR(NGE_MEAR_MII_CLK);
        !           452:                        DELAY(1);
        !           453:                        SIO_SET(NGE_MEAR_MII_CLK);
        !           454:                        DELAY(1);
        !           455:                }
        !           456:                goto fail;
        !           457:        }
        !           458:
        !           459:        for (i = 0x8000; i; i >>= 1) {
        !           460:                SIO_CLR(NGE_MEAR_MII_CLK);
        !           461:                DELAY(1);
        !           462:                if (!ack) {
        !           463:                        if (CSR_READ_4(sc, NGE_MEAR) & NGE_MEAR_MII_DATA)
        !           464:                                frame->mii_data |= i;
        !           465:                        DELAY(1);
        !           466:                }
        !           467:                SIO_SET(NGE_MEAR_MII_CLK);
        !           468:                DELAY(1);
        !           469:        }
        !           470:
        !           471: fail:
        !           472:
        !           473:        SIO_CLR(NGE_MEAR_MII_CLK);
        !           474:        DELAY(1);
        !           475:        SIO_SET(NGE_MEAR_MII_CLK);
        !           476:        DELAY(1);
        !           477:
        !           478:        splx(s);
        !           479:
        !           480:        if (ack)
        !           481:                return(1);
        !           482:        return(0);
        !           483: }
        !           484:
        !           485: /*
        !           486:  * Write to a PHY register through the MII.
        !           487:  */
        !           488: int
        !           489: nge_mii_writereg(sc, frame)
        !           490:        struct nge_softc                *sc;
        !           491:        struct nge_mii_frame    *frame;
        !           492: {
        !           493:        int                     s;
        !           494:
        !           495:        s = splnet();
        !           496:        /*
        !           497:         * Set up frame for TX.
        !           498:         */
        !           499:
        !           500:        frame->mii_stdelim = NGE_MII_STARTDELIM;
        !           501:        frame->mii_opcode = NGE_MII_WRITEOP;
        !           502:        frame->mii_turnaround = NGE_MII_TURNAROUND;
        !           503:
        !           504:        /*
        !           505:         * Turn on data output.
        !           506:         */
        !           507:        SIO_SET(NGE_MEAR_MII_DIR);
        !           508:
        !           509:        nge_mii_sync(sc);
        !           510:
        !           511:        nge_mii_send(sc, frame->mii_stdelim, 2);
        !           512:        nge_mii_send(sc, frame->mii_opcode, 2);
        !           513:        nge_mii_send(sc, frame->mii_phyaddr, 5);
        !           514:        nge_mii_send(sc, frame->mii_regaddr, 5);
        !           515:        nge_mii_send(sc, frame->mii_turnaround, 2);
        !           516:        nge_mii_send(sc, frame->mii_data, 16);
        !           517:
        !           518:        /* Idle bit. */
        !           519:        SIO_SET(NGE_MEAR_MII_CLK);
        !           520:        DELAY(1);
        !           521:        SIO_CLR(NGE_MEAR_MII_CLK);
        !           522:        DELAY(1);
        !           523:
        !           524:        /*
        !           525:         * Turn off xmit.
        !           526:         */
        !           527:        SIO_CLR(NGE_MEAR_MII_DIR);
        !           528:
        !           529:        splx(s);
        !           530:
        !           531:        return(0);
        !           532: }
        !           533:
        !           534: int
        !           535: nge_miibus_readreg(dev, phy, reg)
        !           536:        struct device           *dev;
        !           537:        int                     phy, reg;
        !           538: {
        !           539:        struct nge_softc        *sc = (struct nge_softc *)dev;
        !           540:        struct nge_mii_frame    frame;
        !           541:
        !           542:        DPRINTFN(9, ("%s: nge_miibus_readreg\n", sc->sc_dv.dv_xname));
        !           543:
        !           544:        bzero((char *)&frame, sizeof(frame));
        !           545:
        !           546:        frame.mii_phyaddr = phy;
        !           547:        frame.mii_regaddr = reg;
        !           548:        nge_mii_readreg(sc, &frame);
        !           549:
        !           550:        return(frame.mii_data);
        !           551: }
        !           552:
        !           553: void
        !           554: nge_miibus_writereg(dev, phy, reg, data)
        !           555:        struct device           *dev;
        !           556:        int                     phy, reg, data;
        !           557: {
        !           558:        struct nge_softc        *sc = (struct nge_softc *)dev;
        !           559:        struct nge_mii_frame    frame;
        !           560:
        !           561:
        !           562:        DPRINTFN(9, ("%s: nge_miibus_writereg\n", sc->sc_dv.dv_xname));
        !           563:
        !           564:        bzero((char *)&frame, sizeof(frame));
        !           565:
        !           566:        frame.mii_phyaddr = phy;
        !           567:        frame.mii_regaddr = reg;
        !           568:        frame.mii_data = data;
        !           569:        nge_mii_writereg(sc, &frame);
        !           570: }
        !           571:
        !           572: void
        !           573: nge_miibus_statchg(dev)
        !           574:        struct device           *dev;
        !           575: {
        !           576:        struct nge_softc        *sc = (struct nge_softc *)dev;
        !           577:        struct mii_data         *mii = &sc->nge_mii;
        !           578:        u_int32_t               txcfg, rxcfg;
        !           579:
        !           580:        txcfg = CSR_READ_4(sc, NGE_TX_CFG);
        !           581:        rxcfg = CSR_READ_4(sc, NGE_RX_CFG);
        !           582:
        !           583:        DPRINTFN(4, ("%s: nge_miibus_statchg txcfg=%#x, rxcfg=%#x\n",
        !           584:                     sc->sc_dv.dv_xname, txcfg, rxcfg));
        !           585:
        !           586:        if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
        !           587:                txcfg |= (NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR);
        !           588:                rxcfg |= (NGE_RXCFG_RX_FDX);
        !           589:        } else {
        !           590:                txcfg &= ~(NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR);
        !           591:                rxcfg &= ~(NGE_RXCFG_RX_FDX);
        !           592:        }
        !           593:
        !           594:        txcfg |= NGE_TXCFG_AUTOPAD;
        !           595:
        !           596:        CSR_WRITE_4(sc, NGE_TX_CFG, txcfg);
        !           597:        CSR_WRITE_4(sc, NGE_RX_CFG, rxcfg);
        !           598:
        !           599:        /* If we have a 1000Mbps link, set the mode_1000 bit. */
        !           600:        if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T)
        !           601:                NGE_SETBIT(sc, NGE_CFG, NGE_CFG_MODE_1000);
        !           602:        else
        !           603:                NGE_CLRBIT(sc, NGE_CFG, NGE_CFG_MODE_1000);
        !           604: }
        !           605:
        !           606: void
        !           607: nge_setmulti(sc)
        !           608:        struct nge_softc        *sc;
        !           609: {
        !           610:        struct arpcom           *ac = &sc->arpcom;
        !           611:        struct ifnet            *ifp = &ac->ac_if;
        !           612:        struct ether_multi      *enm;
        !           613:        struct ether_multistep  step;
        !           614:        u_int32_t               h = 0, i, filtsave;
        !           615:        int                     bit, index;
        !           616:
        !           617: allmulti:
        !           618:        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
        !           619:                NGE_CLRBIT(sc, NGE_RXFILT_CTL,
        !           620:                    NGE_RXFILTCTL_MCHASH|NGE_RXFILTCTL_UCHASH);
        !           621:                NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_ALLMULTI);
        !           622:                return;
        !           623:        }
        !           624:
        !           625:        /*
        !           626:         * We have to explicitly enable the multicast hash table
        !           627:         * on the NatSemi chip if we want to use it, which we do.
        !           628:         * We also have to tell it that we don't want to use the
        !           629:         * hash table for matching unicast addresses.
        !           630:         */
        !           631:        NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_MCHASH);
        !           632:        NGE_CLRBIT(sc, NGE_RXFILT_CTL,
        !           633:            NGE_RXFILTCTL_ALLMULTI|NGE_RXFILTCTL_UCHASH);
        !           634:
        !           635:        filtsave = CSR_READ_4(sc, NGE_RXFILT_CTL);
        !           636:
        !           637:        /* first, zot all the existing hash bits */
        !           638:        for (i = 0; i < NGE_MCAST_FILTER_LEN; i += 2) {
        !           639:                CSR_WRITE_4(sc, NGE_RXFILT_CTL, NGE_FILTADDR_MCAST_LO + i);
        !           640:                CSR_WRITE_4(sc, NGE_RXFILT_DATA, 0);
        !           641:        }
        !           642:
        !           643:        /*
        !           644:         * From the 11 bits returned by the crc routine, the top 7
        !           645:         * bits represent the 16-bit word in the mcast hash table
        !           646:         * that needs to be updated, and the lower 4 bits represent
        !           647:         * which bit within that byte needs to be set.
        !           648:         */
        !           649:        ETHER_FIRST_MULTI(step, ac, enm);
        !           650:        while (enm != NULL) {
        !           651:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !           652:                        ifp->if_flags |= IFF_ALLMULTI;
        !           653:                        goto allmulti;
        !           654:                }
        !           655:                h = (ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 21) &
        !           656:                    0x00000FFF;
        !           657:                index = (h >> 4) & 0x7F;
        !           658:                bit = h & 0xF;
        !           659:                CSR_WRITE_4(sc, NGE_RXFILT_CTL,
        !           660:                    NGE_FILTADDR_MCAST_LO + (index * 2));
        !           661:                NGE_SETBIT(sc, NGE_RXFILT_DATA, (1 << bit));
        !           662:                ETHER_NEXT_MULTI(step, enm);
        !           663:        }
        !           664:
        !           665:        CSR_WRITE_4(sc, NGE_RXFILT_CTL, filtsave);
        !           666: }
        !           667:
        !           668: void
        !           669: nge_reset(sc)
        !           670:        struct nge_softc        *sc;
        !           671: {
        !           672:        int                     i;
        !           673:
        !           674:        NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RESET);
        !           675:
        !           676:        for (i = 0; i < NGE_TIMEOUT; i++) {
        !           677:                if (!(CSR_READ_4(sc, NGE_CSR) & NGE_CSR_RESET))
        !           678:                        break;
        !           679:        }
        !           680:
        !           681:        if (i == NGE_TIMEOUT)
        !           682:                printf("%s: reset never completed\n", sc->sc_dv.dv_xname);
        !           683:
        !           684:        /* Wait a little while for the chip to get its brains in order. */
        !           685:        DELAY(1000);
        !           686:
        !           687:        /*
        !           688:         * If this is a NetSemi chip, make sure to clear
        !           689:         * PME mode.
        !           690:         */
        !           691:        CSR_WRITE_4(sc, NGE_CLKRUN, NGE_CLKRUN_PMESTS);
        !           692:        CSR_WRITE_4(sc, NGE_CLKRUN, 0);
        !           693: }
        !           694:
        !           695: /*
        !           696:  * Probe for an NatSemi chip. Check the PCI vendor and device
        !           697:  * IDs against our list and return a device name if we find a match.
        !           698:  */
        !           699: int
        !           700: nge_probe(parent, match, aux)
        !           701:        struct device *parent;
        !           702:        void *match;
        !           703:        void *aux;
        !           704: {
        !           705:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           706:
        !           707:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS &&
        !           708:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NS_DP83820)
        !           709:                return (1);
        !           710:
        !           711:        return (0);
        !           712: }
        !           713:
        !           714: /*
        !           715:  * Attach the interface. Allocate softc structures, do ifmedia
        !           716:  * setup and ethernet/BPF attach.
        !           717:  */
        !           718: void
        !           719: nge_attach(parent, self, aux)
        !           720:        struct device *parent, *self;
        !           721:        void *aux;
        !           722: {
        !           723:        struct nge_softc        *sc = (struct nge_softc *)self;
        !           724:        struct pci_attach_args  *pa = aux;
        !           725:        pci_chipset_tag_t       pc = pa->pa_pc;
        !           726:        pci_intr_handle_t       ih;
        !           727:        const char              *intrstr = NULL;
        !           728:        bus_size_t              size;
        !           729:        bus_dma_segment_t       seg;
        !           730:        bus_dmamap_t            dmamap;
        !           731:        int                     rseg;
        !           732:        u_char                  eaddr[ETHER_ADDR_LEN];
        !           733:        pcireg_t                command;
        !           734: #ifndef NGE_USEIOSPACE
        !           735:        pcireg_t                memtype;
        !           736: #endif
        !           737:        struct ifnet            *ifp;
        !           738:        caddr_t                 kva;
        !           739:
        !           740:        /*
        !           741:         * Handle power management nonsense.
        !           742:         */
        !           743:        DPRINTFN(5, ("%s: preparing for conf read\n", sc->sc_dv.dv_xname));
        !           744:        command = pci_conf_read(pc, pa->pa_tag, NGE_PCI_CAPID) & 0x000000FF;
        !           745:        if (command == 0x01) {
        !           746:                command = pci_conf_read(pc, pa->pa_tag, NGE_PCI_PWRMGMTCTRL);
        !           747:                if (command & NGE_PSTATE_MASK) {
        !           748:                        pcireg_t        iobase, membase, irq;
        !           749:
        !           750:                        /* Save important PCI config data. */
        !           751:                        iobase = pci_conf_read(pc, pa->pa_tag, NGE_PCI_LOIO);
        !           752:                        membase = pci_conf_read(pc, pa->pa_tag, NGE_PCI_LOMEM);
        !           753:                        irq = pci_conf_read(pc, pa->pa_tag, NGE_PCI_INTLINE);
        !           754:
        !           755:                        /* Reset the power state. */
        !           756:                        printf("%s: chip is in D%d power mode "
        !           757:                               "-- setting to D0\n", sc->sc_dv.dv_xname,
        !           758:                               command & NGE_PSTATE_MASK);
        !           759:                        command &= 0xFFFFFFFC;
        !           760:                        pci_conf_write(pc, pa->pa_tag,
        !           761:                                       NGE_PCI_PWRMGMTCTRL, command);
        !           762:
        !           763:                        /* Restore PCI config data. */
        !           764:                        pci_conf_write(pc, pa->pa_tag, NGE_PCI_LOIO, iobase);
        !           765:                        pci_conf_write(pc, pa->pa_tag, NGE_PCI_LOMEM, membase);
        !           766:                        pci_conf_write(pc, pa->pa_tag, NGE_PCI_INTLINE, irq);
        !           767:                }
        !           768:        }
        !           769:
        !           770:        /*
        !           771:         * Map control/status registers.
        !           772:         */
        !           773:        DPRINTFN(5, ("%s: map control/status regs\n", sc->sc_dv.dv_xname));
        !           774:
        !           775: #ifdef NGE_USEIOSPACE
        !           776:        DPRINTFN(5, ("%s: pci_mapreg_map\n", sc->sc_dv.dv_xname));
        !           777:        if (pci_mapreg_map(pa, NGE_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
        !           778:            &sc->nge_btag, &sc->nge_bhandle, NULL, &size, 0)) {
        !           779:                printf(": can't map i/o space\n");
        !           780:                return;
        !           781:        }
        !           782: #else
        !           783:        DPRINTFN(5, ("%s: pci_mapreg_map\n", sc->sc_dv.dv_xname));
        !           784:        memtype = pci_mapreg_type(pc, pa->pa_tag, NGE_PCI_LOMEM);
        !           785:        switch (memtype) {
        !           786:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !           787:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !           788:                if (pci_mapreg_map(pa, NGE_PCI_LOMEM,
        !           789:                                   memtype, 0, &sc->nge_btag, &sc->nge_bhandle,
        !           790:                                   NULL, &size, 0) == 0)
        !           791:                        break;
        !           792:        default:
        !           793:                printf(": can't map mem space\n");
        !           794:                return;
        !           795:        }
        !           796: #endif
        !           797:
        !           798:        /* Disable all interrupts */
        !           799:        CSR_WRITE_4(sc, NGE_IER, 0);
        !           800:
        !           801:        DPRINTFN(5, ("%s: pci_intr_map\n", sc->sc_dv.dv_xname));
        !           802:        if (pci_intr_map(pa, &ih)) {
        !           803:                printf(": couldn't map interrupt\n");
        !           804:                goto fail_1;
        !           805:        }
        !           806:
        !           807:        DPRINTFN(5, ("%s: pci_intr_string\n", sc->sc_dv.dv_xname));
        !           808:        intrstr = pci_intr_string(pc, ih);
        !           809:        DPRINTFN(5, ("%s: pci_intr_establish\n", sc->sc_dv.dv_xname));
        !           810:        sc->nge_intrhand = pci_intr_establish(pc, ih, IPL_NET, nge_intr, sc,
        !           811:                                              sc->sc_dv.dv_xname);
        !           812:        if (sc->nge_intrhand == NULL) {
        !           813:                printf(": couldn't establish interrupt");
        !           814:                if (intrstr != NULL)
        !           815:                        printf(" at %s", intrstr);
        !           816:                printf("\n");
        !           817:                goto fail_1;
        !           818:        }
        !           819:        printf(": %s", intrstr);
        !           820:
        !           821:        /* Reset the adapter. */
        !           822:        DPRINTFN(5, ("%s: nge_reset\n", sc->sc_dv.dv_xname));
        !           823:        nge_reset(sc);
        !           824:
        !           825:        /*
        !           826:         * Get station address from the EEPROM.
        !           827:         */
        !           828:        DPRINTFN(5, ("%s: nge_read_eeprom\n", sc->sc_dv.dv_xname));
        !           829:        nge_read_eeprom(sc, (caddr_t)&eaddr[4], NGE_EE_NODEADDR, 1, 0);
        !           830:        nge_read_eeprom(sc, (caddr_t)&eaddr[2], NGE_EE_NODEADDR + 1, 1, 0);
        !           831:        nge_read_eeprom(sc, (caddr_t)&eaddr[0], NGE_EE_NODEADDR + 2, 1, 0);
        !           832:
        !           833:        /*
        !           834:         * A NatSemi chip was detected. Inform the world.
        !           835:         */
        !           836:        printf(", address %s\n", ether_sprintf(eaddr));
        !           837:
        !           838:        bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           839:
        !           840:        sc->sc_dmatag = pa->pa_dmat;
        !           841:        DPRINTFN(5, ("%s: bus_dmamem_alloc\n", sc->sc_dv.dv_xname));
        !           842:        if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct nge_list_data),
        !           843:                             PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !           844:                printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
        !           845:                goto fail_2;
        !           846:        }
        !           847:        DPRINTFN(5, ("%s: bus_dmamem_map\n", sc->sc_dv.dv_xname));
        !           848:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
        !           849:                           sizeof(struct nge_list_data), &kva,
        !           850:                           BUS_DMA_NOWAIT)) {
        !           851:                printf("%s: can't map dma buffers (%d bytes)\n",
        !           852:                       sc->sc_dv.dv_xname, sizeof(struct nge_list_data));
        !           853:                goto fail_3;
        !           854:        }
        !           855:        DPRINTFN(5, ("%s: bus_dmamem_create\n", sc->sc_dv.dv_xname));
        !           856:        if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct nge_list_data), 1,
        !           857:                              sizeof(struct nge_list_data), 0,
        !           858:                              BUS_DMA_NOWAIT, &dmamap)) {
        !           859:                printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
        !           860:                goto fail_4;
        !           861:        }
        !           862:        DPRINTFN(5, ("%s: bus_dmamem_load\n", sc->sc_dv.dv_xname));
        !           863:        if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva,
        !           864:                            sizeof(struct nge_list_data), NULL,
        !           865:                            BUS_DMA_NOWAIT)) {
        !           866:                goto fail_5;
        !           867:        }
        !           868:
        !           869:        DPRINTFN(5, ("%s: bzero\n", sc->sc_dv.dv_xname));
        !           870:        sc->nge_ldata = (struct nge_list_data *)kva;
        !           871:        bzero(sc->nge_ldata, sizeof(struct nge_list_data));
        !           872:
        !           873:        /* Try to allocate memory for jumbo buffers. */
        !           874:        DPRINTFN(5, ("%s: nge_alloc_jumbo_mem\n", sc->sc_dv.dv_xname));
        !           875:        if (nge_alloc_jumbo_mem(sc)) {
        !           876:                printf("%s: jumbo buffer allocation failed\n",
        !           877:                       sc->sc_dv.dv_xname);
        !           878:                goto fail_5;
        !           879:        }
        !           880:
        !           881:        ifp = &sc->arpcom.ac_if;
        !           882:        ifp->if_softc = sc;
        !           883:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           884:        ifp->if_ioctl = nge_ioctl;
        !           885:        ifp->if_start = nge_start;
        !           886:        ifp->if_watchdog = nge_watchdog;
        !           887:        ifp->if_baudrate = 1000000000;
        !           888:        ifp->if_hardmtu = NGE_JUMBO_MTU;
        !           889:        IFQ_SET_MAXLEN(&ifp->if_snd, NGE_TX_LIST_CNT - 1);
        !           890:        IFQ_SET_READY(&ifp->if_snd);
        !           891:        DPRINTFN(5, ("%s: bcopy\n", sc->sc_dv.dv_xname));
        !           892:        bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           893:
        !           894:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !           895:
        !           896: #ifdef NGE_VLAN
        !           897:        ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
        !           898: #endif
        !           899:
        !           900:        /*
        !           901:         * Do MII setup.
        !           902:         */
        !           903:        DPRINTFN(5, ("%s: mii setup\n", sc->sc_dv.dv_xname));
        !           904:        if (CSR_READ_4(sc, NGE_CFG) & NGE_CFG_TBI_EN) {
        !           905:                DPRINTFN(5, ("%s: TBI mode\n", sc->sc_dv.dv_xname));
        !           906:                sc->nge_tbi = 1;
        !           907:
        !           908:                ifmedia_init(&sc->nge_ifmedia, 0, nge_ifmedia_tbi_upd,
        !           909:                             nge_ifmedia_tbi_sts);
        !           910:
        !           911:                ifmedia_add(&sc->nge_ifmedia, IFM_ETHER|IFM_NONE, 0, NULL),
        !           912:                ifmedia_add(&sc->nge_ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL);
        !           913:                ifmedia_add(&sc->nge_ifmedia, IFM_ETHER|IFM_1000_SX|IFM_FDX,
        !           914:                            0, NULL);
        !           915:                ifmedia_add(&sc->nge_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
        !           916:
        !           917:                ifmedia_set(&sc->nge_ifmedia, IFM_ETHER|IFM_AUTO);
        !           918:
        !           919:                CSR_WRITE_4(sc, NGE_GPIO, CSR_READ_4(sc, NGE_GPIO)
        !           920:                            | NGE_GPIO_GP4_OUT
        !           921:                            | NGE_GPIO_GP1_OUTENB | NGE_GPIO_GP2_OUTENB
        !           922:                            | NGE_GPIO_GP3_OUTENB | NGE_GPIO_GP4_OUTENB
        !           923:                            | NGE_GPIO_GP5_OUTENB);
        !           924:
        !           925:                NGE_SETBIT(sc, NGE_CFG, NGE_CFG_MODE_1000);
        !           926:        } else {
        !           927:                sc->nge_mii.mii_ifp = ifp;
        !           928:                sc->nge_mii.mii_readreg = nge_miibus_readreg;
        !           929:                sc->nge_mii.mii_writereg = nge_miibus_writereg;
        !           930:                sc->nge_mii.mii_statchg = nge_miibus_statchg;
        !           931:
        !           932:                ifmedia_init(&sc->nge_mii.mii_media, 0, nge_ifmedia_mii_upd,
        !           933:                             nge_ifmedia_mii_sts);
        !           934:                mii_attach(&sc->sc_dv, &sc->nge_mii, 0xffffffff, MII_PHY_ANY,
        !           935:                           MII_OFFSET_ANY, 0);
        !           936:
        !           937:                if (LIST_FIRST(&sc->nge_mii.mii_phys) == NULL) {
        !           938:
        !           939:                        printf("%s: no PHY found!\n", sc->sc_dv.dv_xname);
        !           940:                        ifmedia_add(&sc->nge_mii.mii_media,
        !           941:                                    IFM_ETHER|IFM_MANUAL, 0, NULL);
        !           942:                        ifmedia_set(&sc->nge_mii.mii_media,
        !           943:                                    IFM_ETHER|IFM_MANUAL);
        !           944:                }
        !           945:                else
        !           946:                        ifmedia_set(&sc->nge_mii.mii_media,
        !           947:                                    IFM_ETHER|IFM_AUTO);
        !           948:        }
        !           949:
        !           950:        /*
        !           951:         * Call MI attach routine.
        !           952:         */
        !           953:        DPRINTFN(5, ("%s: if_attach\n", sc->sc_dv.dv_xname));
        !           954:        if_attach(ifp);
        !           955:        DPRINTFN(5, ("%s: ether_ifattach\n", sc->sc_dv.dv_xname));
        !           956:        ether_ifattach(ifp);
        !           957:        DPRINTFN(5, ("%s: timeout_set\n", sc->sc_dv.dv_xname));
        !           958:        timeout_set(&sc->nge_timeout, nge_tick, sc);
        !           959:        timeout_add(&sc->nge_timeout, hz);
        !           960:        return;
        !           961:
        !           962: fail_5:
        !           963:        bus_dmamap_destroy(sc->sc_dmatag, dmamap);
        !           964:
        !           965: fail_4:
        !           966:        bus_dmamem_unmap(sc->sc_dmatag, kva,
        !           967:            sizeof(struct nge_list_data));
        !           968:
        !           969: fail_3:
        !           970:        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !           971:
        !           972: fail_2:
        !           973:        pci_intr_disestablish(pc, sc->nge_intrhand);
        !           974:
        !           975: fail_1:
        !           976:        bus_space_unmap(sc->nge_btag, sc->nge_bhandle, size);
        !           977: }
        !           978:
        !           979: /*
        !           980:  * Initialize the transmit descriptors.
        !           981:  */
        !           982: int
        !           983: nge_list_tx_init(sc)
        !           984:        struct nge_softc        *sc;
        !           985: {
        !           986:        struct nge_list_data    *ld;
        !           987:        struct nge_ring_data    *cd;
        !           988:        int                     i;
        !           989:
        !           990:        cd = &sc->nge_cdata;
        !           991:        ld = sc->nge_ldata;
        !           992:
        !           993:        for (i = 0; i < NGE_TX_LIST_CNT; i++) {
        !           994:                if (i == (NGE_TX_LIST_CNT - 1)) {
        !           995:                        ld->nge_tx_list[i].nge_nextdesc =
        !           996:                            &ld->nge_tx_list[0];
        !           997:                        ld->nge_tx_list[i].nge_next =
        !           998:                            VTOPHYS(&ld->nge_tx_list[0]);
        !           999:                } else {
        !          1000:                        ld->nge_tx_list[i].nge_nextdesc =
        !          1001:                            &ld->nge_tx_list[i + 1];
        !          1002:                        ld->nge_tx_list[i].nge_next =
        !          1003:                            VTOPHYS(&ld->nge_tx_list[i + 1]);
        !          1004:                }
        !          1005:                ld->nge_tx_list[i].nge_mbuf = NULL;
        !          1006:                ld->nge_tx_list[i].nge_ptr = 0;
        !          1007:                ld->nge_tx_list[i].nge_ctl = 0;
        !          1008:        }
        !          1009:
        !          1010:        cd->nge_tx_prod = cd->nge_tx_cons = cd->nge_tx_cnt = 0;
        !          1011:
        !          1012:        return(0);
        !          1013: }
        !          1014:
        !          1015:
        !          1016: /*
        !          1017:  * Initialize the RX descriptors and allocate mbufs for them. Note that
        !          1018:  * we arrange the descriptors in a closed ring, so that the last descriptor
        !          1019:  * points back to the first.
        !          1020:  */
        !          1021: int
        !          1022: nge_list_rx_init(sc)
        !          1023:        struct nge_softc        *sc;
        !          1024: {
        !          1025:        struct nge_list_data    *ld;
        !          1026:        struct nge_ring_data    *cd;
        !          1027:        int                     i;
        !          1028:
        !          1029:        ld = sc->nge_ldata;
        !          1030:        cd = &sc->nge_cdata;
        !          1031:
        !          1032:        for (i = 0; i < NGE_RX_LIST_CNT; i++) {
        !          1033:                if (nge_newbuf(sc, &ld->nge_rx_list[i], NULL) == ENOBUFS)
        !          1034:                        return(ENOBUFS);
        !          1035:                if (i == (NGE_RX_LIST_CNT - 1)) {
        !          1036:                        ld->nge_rx_list[i].nge_nextdesc =
        !          1037:                            &ld->nge_rx_list[0];
        !          1038:                        ld->nge_rx_list[i].nge_next =
        !          1039:                            VTOPHYS(&ld->nge_rx_list[0]);
        !          1040:                } else {
        !          1041:                        ld->nge_rx_list[i].nge_nextdesc =
        !          1042:                            &ld->nge_rx_list[i + 1];
        !          1043:                        ld->nge_rx_list[i].nge_next =
        !          1044:                            VTOPHYS(&ld->nge_rx_list[i + 1]);
        !          1045:                }
        !          1046:        }
        !          1047:
        !          1048:        cd->nge_rx_prod = 0;
        !          1049:
        !          1050:        return(0);
        !          1051: }
        !          1052:
        !          1053: /*
        !          1054:  * Initialize an RX descriptor and attach an MBUF cluster.
        !          1055:  */
        !          1056: int
        !          1057: nge_newbuf(sc, c, m)
        !          1058:        struct nge_softc        *sc;
        !          1059:        struct nge_desc         *c;
        !          1060:        struct mbuf             *m;
        !          1061: {
        !          1062:        struct mbuf             *m_new = NULL;
        !          1063:
        !          1064:        if (m == NULL) {
        !          1065:                caddr_t buf = NULL;
        !          1066:
        !          1067:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !          1068:                if (m_new == NULL)
        !          1069:                        return (ENOBUFS);
        !          1070:
        !          1071:                /* Allocate the jumbo buffer */
        !          1072:                buf = nge_jalloc(sc);
        !          1073:                if (buf == NULL) {
        !          1074:                        m_freem(m_new);
        !          1075:                        return (ENOBUFS);
        !          1076:                }
        !          1077:
        !          1078:                /* Attach the buffer to the mbuf */
        !          1079:                m_new->m_len = m_new->m_pkthdr.len = NGE_MCLBYTES;
        !          1080:                MEXTADD(m_new, buf, NGE_MCLBYTES, 0, nge_jfree, sc);
        !          1081:        } else {
        !          1082:                /*
        !          1083:                 * We're re-using a previously allocated mbuf;
        !          1084:                 * be sure to re-init pointers and lengths to
        !          1085:                 * default values.
        !          1086:                 */
        !          1087:                m_new = m;
        !          1088:                m_new->m_len = m_new->m_pkthdr.len = NGE_MCLBYTES;
        !          1089:                m_new->m_data = m_new->m_ext.ext_buf;
        !          1090:        }
        !          1091:
        !          1092:        m_adj(m_new, sizeof(u_int64_t));
        !          1093:
        !          1094:        c->nge_mbuf = m_new;
        !          1095:        c->nge_ptr = VTOPHYS(mtod(m_new, caddr_t));
        !          1096:        DPRINTFN(7,("%s: c->nge_ptr=%#x\n", sc->sc_dv.dv_xname,
        !          1097:                    c->nge_ptr));
        !          1098:        c->nge_ctl = m_new->m_len;
        !          1099:        c->nge_extsts = 0;
        !          1100:
        !          1101:        return(0);
        !          1102: }
        !          1103:
        !          1104: int
        !          1105: nge_alloc_jumbo_mem(sc)
        !          1106:        struct nge_softc        *sc;
        !          1107: {
        !          1108:        caddr_t                 ptr, kva;
        !          1109:        bus_dma_segment_t       seg;
        !          1110:        bus_dmamap_t            dmamap;
        !          1111:        int                     i, rseg, state, error;
        !          1112:        struct nge_jpool_entry  *entry;
        !          1113:
        !          1114:        state = error = 0;
        !          1115:
        !          1116:        if (bus_dmamem_alloc(sc->sc_dmatag, NGE_JMEM, PAGE_SIZE, 0,
        !          1117:                             &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !          1118:                printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
        !          1119:                return (ENOBUFS);
        !          1120:        }
        !          1121:
        !          1122:        state = 1;
        !          1123:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, NGE_JMEM, &kva,
        !          1124:                           BUS_DMA_NOWAIT)) {
        !          1125:                printf("%s: can't map dma buffers (%d bytes)\n",
        !          1126:                       sc->sc_dv.dv_xname, NGE_JMEM);
        !          1127:                error = ENOBUFS;
        !          1128:                goto out;
        !          1129:        }
        !          1130:
        !          1131:        state = 2;
        !          1132:        if (bus_dmamap_create(sc->sc_dmatag, NGE_JMEM, 1,
        !          1133:                              NGE_JMEM, 0, BUS_DMA_NOWAIT, &dmamap)) {
        !          1134:                printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
        !          1135:                error = ENOBUFS;
        !          1136:                goto out;
        !          1137:        }
        !          1138:
        !          1139:        state = 3;
        !          1140:        if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva, NGE_JMEM,
        !          1141:                            NULL, BUS_DMA_NOWAIT)) {
        !          1142:                printf("%s: can't load dma map\n", sc->sc_dv.dv_xname);
        !          1143:                error = ENOBUFS;
        !          1144:                goto out;
        !          1145:         }
        !          1146:
        !          1147:        state = 4;
        !          1148:        sc->nge_cdata.nge_jumbo_buf = (caddr_t)kva;
        !          1149:        DPRINTFN(1,("%s: nge_jumbo_buf=%#x, NGE_MCLBYTES=%#x\n",
        !          1150:                    sc->sc_dv.dv_xname , sc->nge_cdata.nge_jumbo_buf,
        !          1151:                    NGE_MCLBYTES));
        !          1152:
        !          1153:        LIST_INIT(&sc->nge_jfree_listhead);
        !          1154:        LIST_INIT(&sc->nge_jinuse_listhead);
        !          1155:
        !          1156:        /*
        !          1157:         * Now divide it up into 9K pieces and save the addresses
        !          1158:         * in an array. Note that we play an evil trick here by using
        !          1159:         * the first few bytes in the buffer to hold the address
        !          1160:         * of the softc structure for this interface. This is because
        !          1161:         * nge_jfree() needs it, but it is called by the mbuf management
        !          1162:         * code which will not pass it to us explicitly.
        !          1163:         */
        !          1164:        ptr = sc->nge_cdata.nge_jumbo_buf;
        !          1165:        for (i = 0; i < NGE_JSLOTS; i++) {
        !          1166:                sc->nge_cdata.nge_jslots[i].nge_buf = ptr;
        !          1167:                sc->nge_cdata.nge_jslots[i].nge_inuse = 0;
        !          1168:                ptr += NGE_MCLBYTES;
        !          1169:                entry = malloc(sizeof(struct nge_jpool_entry),
        !          1170:                               M_DEVBUF, M_NOWAIT);
        !          1171:                if (entry == NULL) {
        !          1172:                        sc->nge_cdata.nge_jumbo_buf = NULL;
        !          1173:                        printf("%s: no memory for jumbo buffer queue!\n",
        !          1174:                               sc->sc_dv.dv_xname);
        !          1175:                        error = ENOBUFS;
        !          1176:                        goto out;
        !          1177:                }
        !          1178:                entry->slot = i;
        !          1179:                LIST_INSERT_HEAD(&sc->nge_jfree_listhead, entry,
        !          1180:                                 jpool_entries);
        !          1181:        }
        !          1182: out:
        !          1183:        if (error != 0) {
        !          1184:                switch (state) {
        !          1185:                case 4:
        !          1186:                        bus_dmamap_unload(sc->sc_dmatag, dmamap);
        !          1187:                case 3:
        !          1188:                        bus_dmamap_destroy(sc->sc_dmatag, dmamap);
        !          1189:                case 2:
        !          1190:                        bus_dmamem_unmap(sc->sc_dmatag, kva, NGE_JMEM);
        !          1191:                case 1:
        !          1192:                        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !          1193:                        break;
        !          1194:                default:
        !          1195:                        break;
        !          1196:                }
        !          1197:        }
        !          1198:
        !          1199:        return (error);
        !          1200: }
        !          1201:
        !          1202: /*
        !          1203:  * Allocate a jumbo buffer.
        !          1204:  */
        !          1205: void *
        !          1206: nge_jalloc(sc)
        !          1207:        struct nge_softc        *sc;
        !          1208: {
        !          1209:        struct nge_jpool_entry   *entry;
        !          1210:
        !          1211:        entry = LIST_FIRST(&sc->nge_jfree_listhead);
        !          1212:
        !          1213:        if (entry == NULL)
        !          1214:                return (NULL);
        !          1215:
        !          1216:        LIST_REMOVE(entry, jpool_entries);
        !          1217:        LIST_INSERT_HEAD(&sc->nge_jinuse_listhead, entry, jpool_entries);
        !          1218:        sc->nge_cdata.nge_jslots[entry->slot].nge_inuse = 1;
        !          1219:        return(sc->nge_cdata.nge_jslots[entry->slot].nge_buf);
        !          1220: }
        !          1221:
        !          1222: /*
        !          1223:  * Release a jumbo buffer.
        !          1224:  */
        !          1225: void
        !          1226: nge_jfree(buf, size, arg)
        !          1227:        caddr_t         buf;
        !          1228:        u_int           size;
        !          1229:        void            *arg;
        !          1230: {
        !          1231:        struct nge_softc        *sc;
        !          1232:        int                     i;
        !          1233:        struct nge_jpool_entry *entry;
        !          1234:
        !          1235:        /* Extract the softc struct pointer. */
        !          1236:        sc = (struct nge_softc *)arg;
        !          1237:
        !          1238:        if (sc == NULL)
        !          1239:                panic("nge_jfree: can't find softc pointer!");
        !          1240:
        !          1241:        /* calculate the slot this buffer belongs to */
        !          1242:
        !          1243:        i = ((vaddr_t)buf - (vaddr_t)sc->nge_cdata.nge_jumbo_buf)
        !          1244:          / NGE_MCLBYTES;
        !          1245:
        !          1246:        if ((i < 0) || (i >= NGE_JSLOTS))
        !          1247:                panic("nge_jfree: asked to free buffer that we don't manage!");
        !          1248:        else if (sc->nge_cdata.nge_jslots[i].nge_inuse == 0)
        !          1249:                panic("nge_jfree: buffer already free!");
        !          1250:        else {
        !          1251:                sc->nge_cdata.nge_jslots[i].nge_inuse--;
        !          1252:                if(sc->nge_cdata.nge_jslots[i].nge_inuse == 0) {
        !          1253:                        entry = LIST_FIRST(&sc->nge_jinuse_listhead);
        !          1254:                        if (entry == NULL)
        !          1255:                                panic("nge_jfree: buffer not in use!");
        !          1256:                        entry->slot = i;
        !          1257:                        LIST_REMOVE(entry, jpool_entries);
        !          1258:                        LIST_INSERT_HEAD(&sc->nge_jfree_listhead,
        !          1259:                                         entry, jpool_entries);
        !          1260:                }
        !          1261:        }
        !          1262: }
        !          1263:
        !          1264: /*
        !          1265:  * A frame has been uploaded: pass the resulting mbuf chain up to
        !          1266:  * the higher level protocols.
        !          1267:  */
        !          1268: void
        !          1269: nge_rxeof(sc)
        !          1270:        struct nge_softc        *sc;
        !          1271: {
        !          1272:         struct mbuf            *m;
        !          1273:         struct ifnet           *ifp;
        !          1274:        struct nge_desc         *cur_rx;
        !          1275:        int                     i, total_len = 0;
        !          1276:        u_int32_t               rxstat;
        !          1277:
        !          1278:        ifp = &sc->arpcom.ac_if;
        !          1279:        i = sc->nge_cdata.nge_rx_prod;
        !          1280:
        !          1281:        while(NGE_OWNDESC(&sc->nge_ldata->nge_rx_list[i])) {
        !          1282:                struct mbuf             *m0 = NULL;
        !          1283:                u_int32_t               extsts;
        !          1284:
        !          1285:                cur_rx = &sc->nge_ldata->nge_rx_list[i];
        !          1286:                rxstat = cur_rx->nge_rxstat;
        !          1287:                extsts = cur_rx->nge_extsts;
        !          1288:                m = cur_rx->nge_mbuf;
        !          1289:                cur_rx->nge_mbuf = NULL;
        !          1290:                total_len = NGE_RXBYTES(cur_rx);
        !          1291:                NGE_INC(i, NGE_RX_LIST_CNT);
        !          1292:
        !          1293:                /*
        !          1294:                 * If an error occurs, update stats, clear the
        !          1295:                 * status word and leave the mbuf cluster in place:
        !          1296:                 * it should simply get re-used next time this descriptor
        !          1297:                 * comes up in the ring.
        !          1298:                 */
        !          1299:                if (!(rxstat & NGE_CMDSTS_PKT_OK)) {
        !          1300:                        ifp->if_ierrors++;
        !          1301:                        nge_newbuf(sc, cur_rx, m);
        !          1302:                        continue;
        !          1303:                }
        !          1304:
        !          1305:                /*
        !          1306:                 * Ok. NatSemi really screwed up here. This is the
        !          1307:                 * only gigE chip I know of with alignment constraints
        !          1308:                 * on receive buffers. RX buffers must be 64-bit aligned.
        !          1309:                 */
        !          1310: #ifndef __STRICT_ALIGNMENT
        !          1311:                /*
        !          1312:                 * By popular demand, ignore the alignment problems
        !          1313:                 * on the Intel x86 platform. The performance hit
        !          1314:                 * incurred due to unaligned accesses is much smaller
        !          1315:                 * than the hit produced by forcing buffer copies all
        !          1316:                 * the time, especially with jumbo frames. We still
        !          1317:                 * need to fix up the alignment everywhere else though.
        !          1318:                 */
        !          1319:                if (nge_newbuf(sc, cur_rx, NULL) == ENOBUFS) {
        !          1320: #endif
        !          1321:                        m0 = m_devget(mtod(m, char *), total_len,
        !          1322:                            ETHER_ALIGN, ifp, NULL);
        !          1323:                        nge_newbuf(sc, cur_rx, m);
        !          1324:                        if (m0 == NULL) {
        !          1325:                                ifp->if_ierrors++;
        !          1326:                                continue;
        !          1327:                        }
        !          1328:                        m_adj(m0, ETHER_ALIGN);
        !          1329:                        m = m0;
        !          1330: #ifndef __STRICT_ALIGNMENT
        !          1331:                } else {
        !          1332:                        m->m_pkthdr.rcvif = ifp;
        !          1333:                        m->m_pkthdr.len = m->m_len = total_len;
        !          1334:                }
        !          1335: #endif
        !          1336:
        !          1337:                ifp->if_ipackets++;
        !          1338:
        !          1339: #if NBPFILTER > 0
        !          1340:                /*
        !          1341:                 * Handle BPF listeners. Let the BPF user see the packet.
        !          1342:                 */
        !          1343:                if (ifp->if_bpf)
        !          1344:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !          1345: #endif
        !          1346:
        !          1347:                /* Do IP checksum checking. */
        !          1348:                if (extsts & NGE_RXEXTSTS_IPPKT) {
        !          1349:                        if (!(extsts & NGE_RXEXTSTS_IPCSUMERR))
        !          1350:                                m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
        !          1351:                        if ((extsts & NGE_RXEXTSTS_TCPPKT) &&
        !          1352:                            (!(extsts & NGE_RXEXTSTS_TCPCSUMERR)))
        !          1353:                                m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
        !          1354:                        else if ((extsts & NGE_RXEXTSTS_UDPPKT) &&
        !          1355:                                 (!(extsts & NGE_RXEXTSTS_UDPCSUMERR)))
        !          1356:                                m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
        !          1357:                }
        !          1358:
        !          1359:                ether_input_mbuf(ifp, m);
        !          1360:        }
        !          1361:
        !          1362:        sc->nge_cdata.nge_rx_prod = i;
        !          1363: }
        !          1364:
        !          1365: /*
        !          1366:  * A frame was downloaded to the chip. It's safe for us to clean up
        !          1367:  * the list buffers.
        !          1368:  */
        !          1369:
        !          1370: void
        !          1371: nge_txeof(sc)
        !          1372:        struct nge_softc        *sc;
        !          1373: {
        !          1374:        struct nge_desc         *cur_tx;
        !          1375:        struct ifnet            *ifp;
        !          1376:        u_int32_t               idx;
        !          1377:
        !          1378:        ifp = &sc->arpcom.ac_if;
        !          1379:
        !          1380:        /*
        !          1381:         * Go through our tx list and free mbufs for those
        !          1382:         * frames that have been transmitted.
        !          1383:         */
        !          1384:        idx = sc->nge_cdata.nge_tx_cons;
        !          1385:        while (idx != sc->nge_cdata.nge_tx_prod) {
        !          1386:                cur_tx = &sc->nge_ldata->nge_tx_list[idx];
        !          1387:
        !          1388:                if (NGE_OWNDESC(cur_tx))
        !          1389:                        break;
        !          1390:
        !          1391:                if (cur_tx->nge_ctl & NGE_CMDSTS_MORE) {
        !          1392:                        sc->nge_cdata.nge_tx_cnt--;
        !          1393:                        NGE_INC(idx, NGE_TX_LIST_CNT);
        !          1394:                        continue;
        !          1395:                }
        !          1396:
        !          1397:                if (!(cur_tx->nge_ctl & NGE_CMDSTS_PKT_OK)) {
        !          1398:                        ifp->if_oerrors++;
        !          1399:                        if (cur_tx->nge_txstat & NGE_TXSTAT_EXCESSCOLLS)
        !          1400:                                ifp->if_collisions++;
        !          1401:                        if (cur_tx->nge_txstat & NGE_TXSTAT_OUTOFWINCOLL)
        !          1402:                                ifp->if_collisions++;
        !          1403:                }
        !          1404:
        !          1405:                ifp->if_collisions +=
        !          1406:                    (cur_tx->nge_txstat & NGE_TXSTAT_COLLCNT) >> 16;
        !          1407:
        !          1408:                ifp->if_opackets++;
        !          1409:                if (cur_tx->nge_mbuf != NULL) {
        !          1410:                        m_freem(cur_tx->nge_mbuf);
        !          1411:                        cur_tx->nge_mbuf = NULL;
        !          1412:                        ifp->if_flags &= ~IFF_OACTIVE;
        !          1413:                }
        !          1414:
        !          1415:                sc->nge_cdata.nge_tx_cnt--;
        !          1416:                NGE_INC(idx, NGE_TX_LIST_CNT);
        !          1417:        }
        !          1418:
        !          1419:        sc->nge_cdata.nge_tx_cons = idx;
        !          1420:
        !          1421:        if (idx == sc->nge_cdata.nge_tx_prod)
        !          1422:                ifp->if_timer = 0;
        !          1423: }
        !          1424:
        !          1425: void
        !          1426: nge_tick(xsc)
        !          1427:        void                    *xsc;
        !          1428: {
        !          1429:        struct nge_softc        *sc = xsc;
        !          1430:        struct mii_data         *mii = &sc->nge_mii;
        !          1431:        struct ifnet            *ifp = &sc->arpcom.ac_if;
        !          1432:        int                     s;
        !          1433:
        !          1434:        s = splnet();
        !          1435:
        !          1436:        DPRINTFN(10, ("%s: nge_tick: link=%d\n", sc->sc_dv.dv_xname,
        !          1437:                      sc->nge_link));
        !          1438:
        !          1439:        timeout_add(&sc->nge_timeout, hz);
        !          1440:        if (sc->nge_link) {
        !          1441:                splx(s);
        !          1442:                return;
        !          1443:        }
        !          1444:
        !          1445:        if (sc->nge_tbi) {
        !          1446:                if (IFM_SUBTYPE(sc->nge_ifmedia.ifm_cur->ifm_media)
        !          1447:                    == IFM_AUTO) {
        !          1448:                        u_int32_t bmsr, anlpar, txcfg, rxcfg;
        !          1449:
        !          1450:                        bmsr = CSR_READ_4(sc, NGE_TBI_BMSR);
        !          1451:                        DPRINTFN(2, ("%s: nge_tick: bmsr=%#x\n",
        !          1452:                                     sc->sc_dv.dv_xname, bmsr));
        !          1453:
        !          1454:                        if (!(bmsr & NGE_TBIBMSR_ANEG_DONE)) {
        !          1455:                                CSR_WRITE_4(sc, NGE_TBI_BMCR, 0);
        !          1456:
        !          1457:                                splx(s);
        !          1458:                                return;
        !          1459:                        }
        !          1460:
        !          1461:                        anlpar = CSR_READ_4(sc, NGE_TBI_ANLPAR);
        !          1462:                        txcfg = CSR_READ_4(sc, NGE_TX_CFG);
        !          1463:                        rxcfg = CSR_READ_4(sc, NGE_RX_CFG);
        !          1464:
        !          1465:                        DPRINTFN(2, ("%s: nge_tick: anlpar=%#x, txcfg=%#x, "
        !          1466:                                     "rxcfg=%#x\n", sc->sc_dv.dv_xname, anlpar,
        !          1467:                                     txcfg, rxcfg));
        !          1468:
        !          1469:                        if (anlpar == 0 || anlpar & NGE_TBIANAR_FDX) {
        !          1470:                                txcfg |= (NGE_TXCFG_IGN_HBEAT|
        !          1471:                                          NGE_TXCFG_IGN_CARR);
        !          1472:                                rxcfg |= NGE_RXCFG_RX_FDX;
        !          1473:                        } else {
        !          1474:                                txcfg &= ~(NGE_TXCFG_IGN_HBEAT|
        !          1475:                                           NGE_TXCFG_IGN_CARR);
        !          1476:                                rxcfg &= ~(NGE_RXCFG_RX_FDX);
        !          1477:                        }
        !          1478:                        txcfg |= NGE_TXCFG_AUTOPAD;
        !          1479:                        CSR_WRITE_4(sc, NGE_TX_CFG, txcfg);
        !          1480:                        CSR_WRITE_4(sc, NGE_RX_CFG, rxcfg);
        !          1481:                }
        !          1482:
        !          1483:                DPRINTF(("%s: gigabit link up\n", sc->sc_dv.dv_xname));
        !          1484:                sc->nge_link++;
        !          1485:                if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1486:                        nge_start(ifp);
        !          1487:        } else {
        !          1488:                mii_tick(mii);
        !          1489:                if (mii->mii_media_status & IFM_ACTIVE &&
        !          1490:                    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
        !          1491:                        sc->nge_link++;
        !          1492:                        if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T)
        !          1493:                                DPRINTF(("%s: gigabit link up\n",
        !          1494:                                         sc->sc_dv.dv_xname));
        !          1495:                        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1496:                                nge_start(ifp);
        !          1497:                }
        !          1498:
        !          1499:        }
        !          1500:
        !          1501:        splx(s);
        !          1502: }
        !          1503:
        !          1504: int
        !          1505: nge_intr(arg)
        !          1506:        void                    *arg;
        !          1507: {
        !          1508:        struct nge_softc        *sc;
        !          1509:        struct ifnet            *ifp;
        !          1510:        u_int32_t               status;
        !          1511:        int                     claimed = 0;
        !          1512:
        !          1513:        sc = arg;
        !          1514:        ifp = &sc->arpcom.ac_if;
        !          1515:
        !          1516:        /* Supress unwanted interrupts */
        !          1517:        if (!(ifp->if_flags & IFF_UP)) {
        !          1518:                nge_stop(sc);
        !          1519:                return (0);
        !          1520:        }
        !          1521:
        !          1522:        /* Disable interrupts. */
        !          1523:        CSR_WRITE_4(sc, NGE_IER, 0);
        !          1524:
        !          1525:        /* Data LED on for TBI mode */
        !          1526:        if(sc->nge_tbi)
        !          1527:                 CSR_WRITE_4(sc, NGE_GPIO, CSR_READ_4(sc, NGE_GPIO)
        !          1528:                             | NGE_GPIO_GP3_OUT);
        !          1529:
        !          1530:        for (;;) {
        !          1531:                /* Reading the ISR register clears all interrupts. */
        !          1532:                status = CSR_READ_4(sc, NGE_ISR);
        !          1533:
        !          1534:                if ((status & NGE_INTRS) == 0)
        !          1535:                        break;
        !          1536:
        !          1537:                claimed = 1;
        !          1538:
        !          1539:                if ((status & NGE_ISR_TX_DESC_OK) ||
        !          1540:                    (status & NGE_ISR_TX_ERR) ||
        !          1541:                    (status & NGE_ISR_TX_OK) ||
        !          1542:                    (status & NGE_ISR_TX_IDLE))
        !          1543:                        nge_txeof(sc);
        !          1544:
        !          1545:                if ((status & NGE_ISR_RX_DESC_OK) ||
        !          1546:                    (status & NGE_ISR_RX_ERR) ||
        !          1547:                    (status & NGE_ISR_RX_OFLOW) ||
        !          1548:                    (status & NGE_ISR_RX_FIFO_OFLOW) ||
        !          1549:                    (status & NGE_ISR_RX_IDLE) ||
        !          1550:                    (status & NGE_ISR_RX_OK))
        !          1551:                        nge_rxeof(sc);
        !          1552:
        !          1553:                if ((status & NGE_ISR_RX_IDLE))
        !          1554:                        NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RX_ENABLE);
        !          1555:
        !          1556:                if (status & NGE_ISR_SYSERR) {
        !          1557:                        nge_reset(sc);
        !          1558:                        ifp->if_flags &= ~IFF_RUNNING;
        !          1559:                        nge_init(sc);
        !          1560:                }
        !          1561:
        !          1562: #if 0
        !          1563:                /*
        !          1564:                 * XXX: nge_tick() is not ready to be called this way
        !          1565:                 * it screws up the aneg timeout because mii_tick() is
        !          1566:                 * only to be called once per second.
        !          1567:                 */
        !          1568:                if (status & NGE_IMR_PHY_INTR) {
        !          1569:                        sc->nge_link = 0;
        !          1570:                        nge_tick(sc);
        !          1571:                }
        !          1572: #endif
        !          1573:        }
        !          1574:
        !          1575:        /* Re-enable interrupts. */
        !          1576:        CSR_WRITE_4(sc, NGE_IER, 1);
        !          1577:
        !          1578:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1579:                nge_start(ifp);
        !          1580:
        !          1581:        /* Data LED off for TBI mode */
        !          1582:        if(sc->nge_tbi)
        !          1583:                CSR_WRITE_4(sc, NGE_GPIO, CSR_READ_4(sc, NGE_GPIO)
        !          1584:                            & ~NGE_GPIO_GP3_OUT);
        !          1585:
        !          1586:        return claimed;
        !          1587: }
        !          1588:
        !          1589: /*
        !          1590:  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
        !          1591:  * pointers to the fragment pointers.
        !          1592:  */
        !          1593: int
        !          1594: nge_encap(sc, m_head, txidx)
        !          1595:        struct nge_softc        *sc;
        !          1596:        struct mbuf             *m_head;
        !          1597:        u_int32_t               *txidx;
        !          1598: {
        !          1599:        struct nge_desc         *f = NULL;
        !          1600:        struct mbuf             *m;
        !          1601:        int                     frag, cur, cnt = 0;
        !          1602: #if NVLAN > 0
        !          1603:        struct ifvlan           *ifv = NULL;
        !          1604:
        !          1605:        if ((m_head->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
        !          1606:            m_head->m_pkthdr.rcvif != NULL)
        !          1607:                ifv = m_head->m_pkthdr.rcvif->if_softc;
        !          1608: #endif
        !          1609:
        !          1610:        /*
        !          1611:         * Start packing the mbufs in this chain into
        !          1612:         * the fragment pointers. Stop when we run out
        !          1613:         * of fragments or hit the end of the mbuf chain.
        !          1614:         */
        !          1615:        m = m_head;
        !          1616:        cur = frag = *txidx;
        !          1617:
        !          1618:        for (m = m_head; m != NULL; m = m->m_next) {
        !          1619:                if (m->m_len != 0) {
        !          1620:                        if ((NGE_TX_LIST_CNT -
        !          1621:                            (sc->nge_cdata.nge_tx_cnt + cnt)) < 2)
        !          1622:                                return(ENOBUFS);
        !          1623:                        f = &sc->nge_ldata->nge_tx_list[frag];
        !          1624:                        f->nge_ctl = NGE_CMDSTS_MORE | m->m_len;
        !          1625:                        f->nge_ptr = VTOPHYS(mtod(m, vaddr_t));
        !          1626:                        DPRINTFN(7,("%s: f->nge_ptr=%#x\n",
        !          1627:                                    sc->sc_dv.dv_xname, f->nge_ptr));
        !          1628:                        if (cnt != 0)
        !          1629:                                f->nge_ctl |= NGE_CMDSTS_OWN;
        !          1630:                        cur = frag;
        !          1631:                        NGE_INC(frag, NGE_TX_LIST_CNT);
        !          1632:                        cnt++;
        !          1633:                }
        !          1634:        }
        !          1635:
        !          1636:        if (m != NULL)
        !          1637:                return(ENOBUFS);
        !          1638:
        !          1639:        sc->nge_ldata->nge_tx_list[*txidx].nge_extsts = 0;
        !          1640:
        !          1641: #if NVLAN > 0
        !          1642:        if (ifv != NULL) {
        !          1643:                sc->nge_ldata->nge_tx_list[cur].nge_extsts |=
        !          1644:                        (NGE_TXEXTSTS_VLANPKT|ifv->ifv_tag);
        !          1645:        }
        !          1646: #endif
        !          1647:
        !          1648:        sc->nge_ldata->nge_tx_list[cur].nge_mbuf = m_head;
        !          1649:        sc->nge_ldata->nge_tx_list[cur].nge_ctl &= ~NGE_CMDSTS_MORE;
        !          1650:        sc->nge_ldata->nge_tx_list[*txidx].nge_ctl |= NGE_CMDSTS_OWN;
        !          1651:        sc->nge_cdata.nge_tx_cnt += cnt;
        !          1652:        *txidx = frag;
        !          1653:
        !          1654:        return(0);
        !          1655: }
        !          1656:
        !          1657: /*
        !          1658:  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
        !          1659:  * to the mbuf data regions directly in the transmit lists. We also save a
        !          1660:  * copy of the pointers since the transmit list fragment pointers are
        !          1661:  * physical addresses.
        !          1662:  */
        !          1663:
        !          1664: void
        !          1665: nge_start(ifp)
        !          1666:        struct ifnet            *ifp;
        !          1667: {
        !          1668:        struct nge_softc        *sc;
        !          1669:        struct mbuf             *m_head = NULL;
        !          1670:        u_int32_t               idx;
        !          1671:        int                     pkts = 0;
        !          1672:
        !          1673:        sc = ifp->if_softc;
        !          1674:
        !          1675:        if (!sc->nge_link)
        !          1676:                return;
        !          1677:
        !          1678:        idx = sc->nge_cdata.nge_tx_prod;
        !          1679:
        !          1680:        if (ifp->if_flags & IFF_OACTIVE)
        !          1681:                return;
        !          1682:
        !          1683:        while(sc->nge_ldata->nge_tx_list[idx].nge_mbuf == NULL) {
        !          1684:                IFQ_POLL(&ifp->if_snd, m_head);
        !          1685:                if (m_head == NULL)
        !          1686:                        break;
        !          1687:
        !          1688:                if (nge_encap(sc, m_head, &idx)) {
        !          1689:                        ifp->if_flags |= IFF_OACTIVE;
        !          1690:                        break;
        !          1691:                }
        !          1692:
        !          1693:                /* now we are committed to transmit the packet */
        !          1694:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !          1695:                pkts++;
        !          1696:
        !          1697: #if NBPFILTER > 0
        !          1698:                /*
        !          1699:                 * If there's a BPF listener, bounce a copy of this frame
        !          1700:                 * to him.
        !          1701:                 */
        !          1702:                if (ifp->if_bpf)
        !          1703:                        bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
        !          1704: #endif
        !          1705:        }
        !          1706:        if (pkts == 0)
        !          1707:                return;
        !          1708:
        !          1709:        /* Transmit */
        !          1710:        sc->nge_cdata.nge_tx_prod = idx;
        !          1711:        NGE_SETBIT(sc, NGE_CSR, NGE_CSR_TX_ENABLE);
        !          1712:
        !          1713:        /*
        !          1714:         * Set a timeout in case the chip goes out to lunch.
        !          1715:         */
        !          1716:        ifp->if_timer = 5;
        !          1717: }
        !          1718:
        !          1719: void
        !          1720: nge_init(xsc)
        !          1721:        void                    *xsc;
        !          1722: {
        !          1723:        struct nge_softc        *sc = xsc;
        !          1724:        struct ifnet            *ifp = &sc->arpcom.ac_if;
        !          1725:        struct mii_data         *mii;
        !          1726:        u_int32_t               txcfg, rxcfg;
        !          1727:        int                     s, media;
        !          1728:
        !          1729:        if (ifp->if_flags & IFF_RUNNING)
        !          1730:                return;
        !          1731:
        !          1732:        s = splnet();
        !          1733:
        !          1734:        /*
        !          1735:         * Cancel pending I/O and free all RX/TX buffers.
        !          1736:         */
        !          1737:        nge_stop(sc);
        !          1738:
        !          1739:        mii = sc->nge_tbi ? NULL: &sc->nge_mii;
        !          1740:
        !          1741:        /* Set MAC address */
        !          1742:        CSR_WRITE_4(sc, NGE_RXFILT_CTL, NGE_FILTADDR_PAR0);
        !          1743:        CSR_WRITE_4(sc, NGE_RXFILT_DATA,
        !          1744:            ((u_int16_t *)sc->arpcom.ac_enaddr)[0]);
        !          1745:        CSR_WRITE_4(sc, NGE_RXFILT_CTL, NGE_FILTADDR_PAR1);
        !          1746:        CSR_WRITE_4(sc, NGE_RXFILT_DATA,
        !          1747:            ((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
        !          1748:        CSR_WRITE_4(sc, NGE_RXFILT_CTL, NGE_FILTADDR_PAR2);
        !          1749:        CSR_WRITE_4(sc, NGE_RXFILT_DATA,
        !          1750:            ((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
        !          1751:
        !          1752:        /* Init circular RX list. */
        !          1753:        if (nge_list_rx_init(sc) == ENOBUFS) {
        !          1754:                printf("%s: initialization failed: no "
        !          1755:                        "memory for rx buffers\n", sc->sc_dv.dv_xname);
        !          1756:                nge_stop(sc);
        !          1757:                splx(s);
        !          1758:                return;
        !          1759:        }
        !          1760:
        !          1761:        /*
        !          1762:         * Init tx descriptors.
        !          1763:         */
        !          1764:        nge_list_tx_init(sc);
        !          1765:
        !          1766:        /*
        !          1767:         * For the NatSemi chip, we have to explicitly enable the
        !          1768:         * reception of ARP frames, as well as turn on the 'perfect
        !          1769:         * match' filter where we store the station address, otherwise
        !          1770:         * we won't receive unicasts meant for this host.
        !          1771:         */
        !          1772:        NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_ARP);
        !          1773:        NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_PERFECT);
        !          1774:
        !          1775:         /* If we want promiscuous mode, set the allframes bit. */
        !          1776:        if (ifp->if_flags & IFF_PROMISC)
        !          1777:                NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_ALLPHYS);
        !          1778:        else
        !          1779:                NGE_CLRBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_ALLPHYS);
        !          1780:
        !          1781:        /*
        !          1782:         * Set the capture broadcast bit to capture broadcast frames.
        !          1783:         */
        !          1784:        if (ifp->if_flags & IFF_BROADCAST)
        !          1785:                NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_BROAD);
        !          1786:        else
        !          1787:                NGE_CLRBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_BROAD);
        !          1788:
        !          1789:        /*
        !          1790:         * Load the multicast filter.
        !          1791:         */
        !          1792:        nge_setmulti(sc);
        !          1793:
        !          1794:        /* Turn the receive filter on */
        !          1795:        NGE_SETBIT(sc, NGE_RXFILT_CTL, NGE_RXFILTCTL_ENABLE);
        !          1796:
        !          1797:        /*
        !          1798:         * Load the address of the RX and TX lists.
        !          1799:         */
        !          1800:        CSR_WRITE_4(sc, NGE_RX_LISTPTR,
        !          1801:            VTOPHYS(&sc->nge_ldata->nge_rx_list[0]));
        !          1802:        CSR_WRITE_4(sc, NGE_TX_LISTPTR,
        !          1803:            VTOPHYS(&sc->nge_ldata->nge_tx_list[0]));
        !          1804:
        !          1805:        /* Set RX configuration */
        !          1806:        CSR_WRITE_4(sc, NGE_RX_CFG, NGE_RXCFG);
        !          1807:
        !          1808:        /*
        !          1809:         * Enable hardware checksum validation for all IPv4
        !          1810:         * packets, do not reject packets with bad checksums.
        !          1811:         */
        !          1812:        CSR_WRITE_4(sc, NGE_VLAN_IP_RXCTL, NGE_VIPRXCTL_IPCSUM_ENB);
        !          1813:
        !          1814:        /* Set TX configuration */
        !          1815:        CSR_WRITE_4(sc, NGE_TX_CFG, NGE_TXCFG);
        !          1816:
        !          1817: #if NVLAN > 0
        !          1818:        /*
        !          1819:         * If VLAN support is enabled, tell the chip to insert
        !          1820:         * VLAN tags on a per-packet basis as dictated by the
        !          1821:         * code in the frame encapsulation routine.
        !          1822:         */
        !          1823:        if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
        !          1824:                NGE_SETBIT(sc, NGE_VLAN_IP_TXCTL, NGE_VIPTXCTL_TAG_PER_PKT);
        !          1825: #endif
        !          1826:
        !          1827:        /* Set full/half duplex mode. */
        !          1828:        if (sc->nge_tbi)
        !          1829:                media = sc->nge_ifmedia.ifm_cur->ifm_media;
        !          1830:        else
        !          1831:                media = mii->mii_media_active;
        !          1832:
        !          1833:        txcfg = CSR_READ_4(sc, NGE_TX_CFG);
        !          1834:        rxcfg = CSR_READ_4(sc, NGE_RX_CFG);
        !          1835:
        !          1836:        DPRINTFN(4, ("%s: nge_init txcfg=%#x, rxcfg=%#x\n",
        !          1837:                     sc->sc_dv.dv_xname, txcfg, rxcfg));
        !          1838:
        !          1839:        if ((media & IFM_GMASK) == IFM_FDX) {
        !          1840:                txcfg |= (NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR);
        !          1841:                rxcfg |= (NGE_RXCFG_RX_FDX);
        !          1842:        } else {
        !          1843:                txcfg &= ~(NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR);
        !          1844:                rxcfg &= ~(NGE_RXCFG_RX_FDX);
        !          1845:        }
        !          1846:
        !          1847:        txcfg |= NGE_TXCFG_AUTOPAD;
        !          1848:
        !          1849:        CSR_WRITE_4(sc, NGE_TX_CFG, txcfg);
        !          1850:        CSR_WRITE_4(sc, NGE_RX_CFG, rxcfg);
        !          1851:
        !          1852:        nge_tick(sc);
        !          1853:
        !          1854:        /*
        !          1855:         * Enable the delivery of PHY interrupts based on
        !          1856:         * link/speed/duplex status changes and enable return
        !          1857:         * of extended status information in the DMA descriptors,
        !          1858:         * required for checksum offloading.
        !          1859:         */
        !          1860:        NGE_SETBIT(sc, NGE_CFG, NGE_CFG_PHYINTR_SPD|NGE_CFG_PHYINTR_LNK|
        !          1861:                   NGE_CFG_PHYINTR_DUP|NGE_CFG_EXTSTS_ENB);
        !          1862:
        !          1863:        DPRINTFN(1, ("%s: nge_init: config=%#x\n", sc->sc_dv.dv_xname,
        !          1864:                     CSR_READ_4(sc, NGE_CFG)));
        !          1865:
        !          1866:        /*
        !          1867:         * Configure interrupt holdoff (moderation). We can
        !          1868:         * have the chip delay interrupt delivery for a certain
        !          1869:         * period. Units are in 100us, and the max setting
        !          1870:         * is 25500us (0xFF x 100us). Default is a 100us holdoff.
        !          1871:         */
        !          1872:        CSR_WRITE_4(sc, NGE_IHR, 0x01);
        !          1873:
        !          1874:        /*
        !          1875:         * Enable interrupts.
        !          1876:         */
        !          1877:        CSR_WRITE_4(sc, NGE_IMR, NGE_INTRS);
        !          1878:        CSR_WRITE_4(sc, NGE_IER, 1);
        !          1879:
        !          1880:        /* Enable receiver and transmitter. */
        !          1881:        NGE_CLRBIT(sc, NGE_CSR, NGE_CSR_TX_DISABLE|NGE_CSR_RX_DISABLE);
        !          1882:        NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RX_ENABLE);
        !          1883:
        !          1884:        if (sc->nge_tbi)
        !          1885:            nge_ifmedia_tbi_upd(ifp);
        !          1886:        else
        !          1887:            nge_ifmedia_mii_upd(ifp);
        !          1888:
        !          1889:        ifp->if_flags |= IFF_RUNNING;
        !          1890:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1891:
        !          1892:        splx(s);
        !          1893: }
        !          1894:
        !          1895: /*
        !          1896:  * Set mii media options.
        !          1897:  */
        !          1898: int
        !          1899: nge_ifmedia_mii_upd(ifp)
        !          1900:        struct ifnet            *ifp;
        !          1901: {
        !          1902:        struct nge_softc        *sc = ifp->if_softc;
        !          1903:        struct mii_data         *mii = &sc->nge_mii;
        !          1904:
        !          1905:        DPRINTFN(2, ("%s: nge_ifmedia_mii_upd\n", sc->sc_dv.dv_xname));
        !          1906:
        !          1907:        sc->nge_link = 0;
        !          1908:
        !          1909:        if (mii->mii_instance) {
        !          1910:                struct mii_softc *miisc;
        !          1911:                LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
        !          1912:                        mii_phy_reset(miisc);
        !          1913:        }
        !          1914:        mii_mediachg(mii);
        !          1915:
        !          1916:        return(0);
        !          1917: }
        !          1918:
        !          1919: /*
        !          1920:  * Report current mii media status.
        !          1921:  */
        !          1922: void
        !          1923: nge_ifmedia_mii_sts(ifp, ifmr)
        !          1924:        struct ifnet            *ifp;
        !          1925:        struct ifmediareq       *ifmr;
        !          1926: {
        !          1927:        struct nge_softc        *sc = ifp->if_softc;
        !          1928:        struct mii_data *mii = &sc->nge_mii;
        !          1929:
        !          1930:        DPRINTFN(2, ("%s: nge_ifmedia_mii_sts\n", sc->sc_dv.dv_xname));
        !          1931:
        !          1932:        mii_pollstat(mii);
        !          1933:        ifmr->ifm_active = mii->mii_media_active;
        !          1934:        ifmr->ifm_status = mii->mii_media_status;
        !          1935: }
        !          1936:
        !          1937: /*
        !          1938:  * Set mii media options.
        !          1939:  */
        !          1940: int
        !          1941: nge_ifmedia_tbi_upd(ifp)
        !          1942:        struct ifnet            *ifp;
        !          1943: {
        !          1944:        struct nge_softc        *sc = ifp->if_softc;
        !          1945:
        !          1946:        DPRINTFN(2, ("%s: nge_ifmedia_tbi_upd\n", sc->sc_dv.dv_xname));
        !          1947:
        !          1948:        sc->nge_link = 0;
        !          1949:
        !          1950:        if (IFM_SUBTYPE(sc->nge_ifmedia.ifm_cur->ifm_media)
        !          1951:            == IFM_AUTO) {
        !          1952:                u_int32_t anar, bmcr;
        !          1953:                anar = CSR_READ_4(sc, NGE_TBI_ANAR);
        !          1954:                anar |= (NGE_TBIANAR_HDX | NGE_TBIANAR_FDX);
        !          1955:                CSR_WRITE_4(sc, NGE_TBI_ANAR, anar);
        !          1956:
        !          1957:                bmcr = CSR_READ_4(sc, NGE_TBI_BMCR);
        !          1958:                bmcr |= (NGE_TBIBMCR_ENABLE_ANEG|NGE_TBIBMCR_RESTART_ANEG);
        !          1959:                CSR_WRITE_4(sc, NGE_TBI_BMCR, bmcr);
        !          1960:
        !          1961:                bmcr &= ~(NGE_TBIBMCR_RESTART_ANEG);
        !          1962:                CSR_WRITE_4(sc, NGE_TBI_BMCR, bmcr);
        !          1963:        } else {
        !          1964:                u_int32_t txcfg, rxcfg;
        !          1965:                txcfg = CSR_READ_4(sc, NGE_TX_CFG);
        !          1966:                rxcfg = CSR_READ_4(sc, NGE_RX_CFG);
        !          1967:
        !          1968:                if ((sc->nge_ifmedia.ifm_cur->ifm_media & IFM_GMASK)
        !          1969:                    == IFM_FDX) {
        !          1970:                        txcfg |= NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR;
        !          1971:                        rxcfg |= NGE_RXCFG_RX_FDX;
        !          1972:                } else {
        !          1973:                        txcfg &= ~(NGE_TXCFG_IGN_HBEAT|NGE_TXCFG_IGN_CARR);
        !          1974:                        rxcfg &= ~(NGE_RXCFG_RX_FDX);
        !          1975:                }
        !          1976:
        !          1977:                txcfg |= NGE_TXCFG_AUTOPAD;
        !          1978:                CSR_WRITE_4(sc, NGE_TX_CFG, txcfg);
        !          1979:                CSR_WRITE_4(sc, NGE_RX_CFG, rxcfg);
        !          1980:        }
        !          1981:
        !          1982:        NGE_CLRBIT(sc, NGE_GPIO, NGE_GPIO_GP3_OUT);
        !          1983:
        !          1984:        return(0);
        !          1985: }
        !          1986:
        !          1987: /*
        !          1988:  * Report current tbi media status.
        !          1989:  */
        !          1990: void
        !          1991: nge_ifmedia_tbi_sts(ifp, ifmr)
        !          1992:        struct ifnet            *ifp;
        !          1993:        struct ifmediareq       *ifmr;
        !          1994: {
        !          1995:        struct nge_softc        *sc = ifp->if_softc;
        !          1996:        u_int32_t               bmcr;
        !          1997:
        !          1998:        bmcr = CSR_READ_4(sc, NGE_TBI_BMCR);
        !          1999:
        !          2000:        if (IFM_SUBTYPE(sc->nge_ifmedia.ifm_cur->ifm_media) == IFM_AUTO) {
        !          2001:                u_int32_t bmsr = CSR_READ_4(sc, NGE_TBI_BMSR);
        !          2002:                DPRINTFN(2, ("%s: nge_ifmedia_tbi_sts bmsr=%#x, bmcr=%#x\n",
        !          2003:                             sc->sc_dv.dv_xname, bmsr, bmcr));
        !          2004:
        !          2005:                if (!(bmsr & NGE_TBIBMSR_ANEG_DONE)) {
        !          2006:                        ifmr->ifm_active = IFM_ETHER|IFM_NONE;
        !          2007:                        ifmr->ifm_status = IFM_AVALID;
        !          2008:                        return;
        !          2009:                }
        !          2010:        } else {
        !          2011:                DPRINTFN(2, ("%s: nge_ifmedia_tbi_sts bmcr=%#x\n",
        !          2012:                             sc->sc_dv.dv_xname, bmcr));
        !          2013:        }
        !          2014:
        !          2015:        ifmr->ifm_status = IFM_AVALID|IFM_ACTIVE;
        !          2016:        ifmr->ifm_active = IFM_ETHER|IFM_1000_SX;
        !          2017:
        !          2018:        if (bmcr & NGE_TBIBMCR_LOOPBACK)
        !          2019:                ifmr->ifm_active |= IFM_LOOP;
        !          2020:
        !          2021:        if (IFM_SUBTYPE(sc->nge_ifmedia.ifm_cur->ifm_media) == IFM_AUTO) {
        !          2022:                u_int32_t anlpar = CSR_READ_4(sc, NGE_TBI_ANLPAR);
        !          2023:                DPRINTFN(2, ("%s: nge_ifmedia_tbi_sts anlpar=%#x\n",
        !          2024:                             sc->sc_dv.dv_xname, anlpar));
        !          2025:
        !          2026:                ifmr->ifm_active |= IFM_AUTO;
        !          2027:                if (anlpar & NGE_TBIANLPAR_FDX) {
        !          2028:                        ifmr->ifm_active |= IFM_FDX;
        !          2029:                } else if (anlpar & NGE_TBIANLPAR_HDX) {
        !          2030:                        ifmr->ifm_active |= IFM_HDX;
        !          2031:                } else
        !          2032:                        ifmr->ifm_active |= IFM_FDX;
        !          2033:
        !          2034:        } else if ((sc->nge_ifmedia.ifm_cur->ifm_media & IFM_GMASK) == IFM_FDX)
        !          2035:                ifmr->ifm_active |= IFM_FDX;
        !          2036:        else
        !          2037:                ifmr->ifm_active |= IFM_HDX;
        !          2038:
        !          2039: }
        !          2040:
        !          2041: int
        !          2042: nge_ioctl(ifp, command, data)
        !          2043:        struct ifnet            *ifp;
        !          2044:        u_long                  command;
        !          2045:        caddr_t                 data;
        !          2046: {
        !          2047:        struct nge_softc        *sc = ifp->if_softc;
        !          2048:        struct ifreq            *ifr = (struct ifreq *) data;
        !          2049:        struct ifaddr           *ifa = (struct ifaddr *)data;
        !          2050:        struct mii_data         *mii;
        !          2051:        int                     s, error = 0;
        !          2052:
        !          2053:        s = splnet();
        !          2054:
        !          2055:        if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
        !          2056:                splx(s);
        !          2057:                return (error);
        !          2058:        }
        !          2059:
        !          2060:        switch(command) {
        !          2061:        case SIOCSIFMTU:
        !          2062:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
        !          2063:                        error = EINVAL;
        !          2064:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !          2065:                        ifp->if_mtu = ifr->ifr_mtu;
        !          2066:                break;
        !          2067:        case SIOCSIFADDR:
        !          2068:                ifp->if_flags |= IFF_UP;
        !          2069:                switch (ifa->ifa_addr->sa_family) {
        !          2070: #ifdef INET
        !          2071:                case AF_INET:
        !          2072:                        nge_init(sc);
        !          2073:                        arp_ifinit(&sc->arpcom, ifa);
        !          2074:                        break;
        !          2075: #endif /* INET */
        !          2076:                default:
        !          2077:                        nge_init(sc);
        !          2078:                        break;
        !          2079:                 }
        !          2080:                break;
        !          2081:        case SIOCSIFFLAGS:
        !          2082:                if (ifp->if_flags & IFF_UP) {
        !          2083:                        if (ifp->if_flags & IFF_RUNNING &&
        !          2084:                            ifp->if_flags & IFF_PROMISC &&
        !          2085:                            !(sc->nge_if_flags & IFF_PROMISC)) {
        !          2086:                                NGE_SETBIT(sc, NGE_RXFILT_CTL,
        !          2087:                                    NGE_RXFILTCTL_ALLPHYS|
        !          2088:                                    NGE_RXFILTCTL_ALLMULTI);
        !          2089:                        } else if (ifp->if_flags & IFF_RUNNING &&
        !          2090:                            !(ifp->if_flags & IFF_PROMISC) &&
        !          2091:                            sc->nge_if_flags & IFF_PROMISC) {
        !          2092:                                NGE_CLRBIT(sc, NGE_RXFILT_CTL,
        !          2093:                                    NGE_RXFILTCTL_ALLPHYS);
        !          2094:                                if (!(ifp->if_flags & IFF_ALLMULTI))
        !          2095:                                        NGE_CLRBIT(sc, NGE_RXFILT_CTL,
        !          2096:                                            NGE_RXFILTCTL_ALLMULTI);
        !          2097:                        } else {
        !          2098:                                ifp->if_flags &= ~IFF_RUNNING;
        !          2099:                                nge_init(sc);
        !          2100:                        }
        !          2101:                } else {
        !          2102:                        if (ifp->if_flags & IFF_RUNNING)
        !          2103:                                nge_stop(sc);
        !          2104:                }
        !          2105:                sc->nge_if_flags = ifp->if_flags;
        !          2106:                error = 0;
        !          2107:                break;
        !          2108:        case SIOCADDMULTI:
        !          2109:        case SIOCDELMULTI:
        !          2110:                error = (command == SIOCADDMULTI)
        !          2111:                        ? ether_addmulti(ifr, &sc->arpcom)
        !          2112:                        : ether_delmulti(ifr, &sc->arpcom);
        !          2113:
        !          2114:                if (error == ENETRESET) {
        !          2115:                        if (ifp->if_flags & IFF_RUNNING)
        !          2116:                                nge_setmulti(sc);
        !          2117:                        error = 0;
        !          2118:                }
        !          2119:                break;
        !          2120:        case SIOCGIFMEDIA:
        !          2121:        case SIOCSIFMEDIA:
        !          2122:                if (sc->nge_tbi) {
        !          2123:                        error = ifmedia_ioctl(ifp, ifr, &sc->nge_ifmedia,
        !          2124:                                              command);
        !          2125:                } else {
        !          2126:                        mii = &sc->nge_mii;
        !          2127:                        error = ifmedia_ioctl(ifp, ifr, &mii->mii_media,
        !          2128:                                              command);
        !          2129:                }
        !          2130:                break;
        !          2131:        default:
        !          2132:                error = ENOTTY;
        !          2133:                break;
        !          2134:        }
        !          2135:
        !          2136:        splx(s);
        !          2137:
        !          2138:        return(error);
        !          2139: }
        !          2140:
        !          2141: void
        !          2142: nge_watchdog(ifp)
        !          2143:        struct ifnet            *ifp;
        !          2144: {
        !          2145:        struct nge_softc        *sc;
        !          2146:
        !          2147:        sc = ifp->if_softc;
        !          2148:
        !          2149:        ifp->if_oerrors++;
        !          2150:        printf("%s: watchdog timeout\n", sc->sc_dv.dv_xname);
        !          2151:
        !          2152:        nge_stop(sc);
        !          2153:        nge_reset(sc);
        !          2154:        ifp->if_flags &= ~IFF_RUNNING;
        !          2155:        nge_init(sc);
        !          2156:
        !          2157:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          2158:                nge_start(ifp);
        !          2159: }
        !          2160:
        !          2161: /*
        !          2162:  * Stop the adapter and free any mbufs allocated to the
        !          2163:  * RX and TX lists.
        !          2164:  */
        !          2165: void
        !          2166: nge_stop(sc)
        !          2167:        struct nge_softc        *sc;
        !          2168: {
        !          2169:        int                     i;
        !          2170:        struct ifnet            *ifp;
        !          2171:        struct mii_data         *mii;
        !          2172:
        !          2173:        ifp = &sc->arpcom.ac_if;
        !          2174:        ifp->if_timer = 0;
        !          2175:        if (sc->nge_tbi) {
        !          2176:                mii = NULL;
        !          2177:        } else {
        !          2178:                mii = &sc->nge_mii;
        !          2179:        }
        !          2180:
        !          2181:        timeout_del(&sc->nge_timeout);
        !          2182:
        !          2183:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2184:
        !          2185:        CSR_WRITE_4(sc, NGE_IER, 0);
        !          2186:        CSR_WRITE_4(sc, NGE_IMR, 0);
        !          2187:        NGE_SETBIT(sc, NGE_CSR, NGE_CSR_TX_DISABLE|NGE_CSR_RX_DISABLE);
        !          2188:        DELAY(1000);
        !          2189:        CSR_WRITE_4(sc, NGE_TX_LISTPTR, 0);
        !          2190:        CSR_WRITE_4(sc, NGE_RX_LISTPTR, 0);
        !          2191:
        !          2192:        if (!sc->nge_tbi)
        !          2193:                mii_down(mii);
        !          2194:
        !          2195:        sc->nge_link = 0;
        !          2196:
        !          2197:        /*
        !          2198:         * Free data in the RX lists.
        !          2199:         */
        !          2200:        for (i = 0; i < NGE_RX_LIST_CNT; i++) {
        !          2201:                if (sc->nge_ldata->nge_rx_list[i].nge_mbuf != NULL) {
        !          2202:                        m_freem(sc->nge_ldata->nge_rx_list[i].nge_mbuf);
        !          2203:                        sc->nge_ldata->nge_rx_list[i].nge_mbuf = NULL;
        !          2204:                }
        !          2205:        }
        !          2206:        bzero((char *)&sc->nge_ldata->nge_rx_list,
        !          2207:                sizeof(sc->nge_ldata->nge_rx_list));
        !          2208:
        !          2209:        /*
        !          2210:         * Free the TX list buffers.
        !          2211:         */
        !          2212:        for (i = 0; i < NGE_TX_LIST_CNT; i++) {
        !          2213:                if (sc->nge_ldata->nge_tx_list[i].nge_mbuf != NULL) {
        !          2214:                        m_freem(sc->nge_ldata->nge_tx_list[i].nge_mbuf);
        !          2215:                        sc->nge_ldata->nge_tx_list[i].nge_mbuf = NULL;
        !          2216:                }
        !          2217:        }
        !          2218:
        !          2219:        bzero((char *)&sc->nge_ldata->nge_tx_list,
        !          2220:                sizeof(sc->nge_ldata->nge_tx_list));
        !          2221: }
        !          2222:
        !          2223: /*
        !          2224:  * Stop all chip I/O so that the kernel's probe routines don't
        !          2225:  * get confused by errant DMAs when rebooting.
        !          2226:  */
        !          2227: void
        !          2228: nge_shutdown(xsc)
        !          2229:        void *xsc;
        !          2230: {
        !          2231:        struct nge_softc *sc = (struct nge_softc *)xsc;
        !          2232:
        !          2233:        nge_reset(sc);
        !          2234:        nge_stop(sc);
        !          2235: }
        !          2236:
        !          2237: struct cfattach nge_ca = {
        !          2238:        sizeof(struct nge_softc), nge_probe, nge_attach
        !          2239: };
        !          2240:
        !          2241: struct cfdriver nge_cd = {
        !          2242:        0, "nge", DV_IFNET
        !          2243: };

CVSweb