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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_sk.c,v 1.142 2007/05/26 16:44:21 reyk Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997, 1998, 1999, 2000
        !             5:  *     Bill Paul <wpaul@ctr.columbia.edu>.  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: /c/ncvs/src/sys/pci/if_sk.c,v 1.20 2000/04/22 02:16:37 wpaul Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * Copyright (c) 2003 Nathan L. Binkert <binkertn@umich.edu>
        !            39:  *
        !            40:  * Permission to use, copy, modify, and distribute this software for any
        !            41:  * purpose with or without fee is hereby granted, provided that the above
        !            42:  * copyright notice and this permission notice appear in all copies.
        !            43:  *
        !            44:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            45:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            46:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            47:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            48:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            49:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            50:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            51:  */
        !            52:
        !            53: /*
        !            54:  * SysKonnect SK-NET gigabit ethernet driver for FreeBSD. Supports
        !            55:  * the SK-984x series adapters, both single port and dual port.
        !            56:  * References:
        !            57:  *     The XaQti XMAC II datasheet,
        !            58:  * http://www.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf
        !            59:  *     The SysKonnect GEnesis manual, http://www.syskonnect.com
        !            60:  *
        !            61:  * Note: XaQti has been acquired by Vitesse, and Vitesse does not have the
        !            62:  * XMAC II datasheet online. I have put my copy at people.freebsd.org as a
        !            63:  * convenience to others until Vitesse corrects this problem:
        !            64:  *
        !            65:  * http://people.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf
        !            66:  *
        !            67:  * Written by Bill Paul <wpaul@ee.columbia.edu>
        !            68:  * Department of Electrical Engineering
        !            69:  * Columbia University, New York City
        !            70:  */
        !            71:
        !            72: /*
        !            73:  * The SysKonnect gigabit ethernet adapters consist of two main
        !            74:  * components: the SysKonnect GEnesis controller chip and the XaQti Corp.
        !            75:  * XMAC II gigabit ethernet MAC. The XMAC provides all of the MAC
        !            76:  * components and a PHY while the GEnesis controller provides a PCI
        !            77:  * interface with DMA support. Each card may have between 512K and
        !            78:  * 2MB of SRAM on board depending on the configuration.
        !            79:  *
        !            80:  * The SysKonnect GEnesis controller can have either one or two XMAC
        !            81:  * chips connected to it, allowing single or dual port NIC configurations.
        !            82:  * SysKonnect has the distinction of being the only vendor on the market
        !            83:  * with a dual port gigabit ethernet NIC. The GEnesis provides dual FIFOs,
        !            84:  * dual DMA queues, packet/MAC/transmit arbiters and direct access to the
        !            85:  * XMAC registers. This driver takes advantage of these features to allow
        !            86:  * both XMACs to operate as independent interfaces.
        !            87:  */
        !            88:
        !            89: #include "bpfilter.h"
        !            90:
        !            91: #include <sys/param.h>
        !            92: #include <sys/systm.h>
        !            93: #include <sys/sockio.h>
        !            94: #include <sys/mbuf.h>
        !            95: #include <sys/malloc.h>
        !            96: #include <sys/kernel.h>
        !            97: #include <sys/socket.h>
        !            98: #include <sys/timeout.h>
        !            99: #include <sys/device.h>
        !           100: #include <sys/queue.h>
        !           101:
        !           102: #include <net/if.h>
        !           103: #include <net/if_dl.h>
        !           104: #include <net/if_types.h>
        !           105:
        !           106: #ifdef INET
        !           107: #include <netinet/in.h>
        !           108: #include <netinet/in_systm.h>
        !           109: #include <netinet/in_var.h>
        !           110: #include <netinet/ip.h>
        !           111: #include <netinet/udp.h>
        !           112: #include <netinet/tcp.h>
        !           113: #include <netinet/if_ether.h>
        !           114: #endif
        !           115:
        !           116: #include <net/if_media.h>
        !           117: #include <net/if_vlan_var.h>
        !           118:
        !           119: #if NBPFILTER > 0
        !           120: #include <net/bpf.h>
        !           121: #endif
        !           122:
        !           123: #include <dev/mii/mii.h>
        !           124: #include <dev/mii/miivar.h>
        !           125: #include <dev/mii/brgphyreg.h>
        !           126:
        !           127: #include <dev/pci/pcireg.h>
        !           128: #include <dev/pci/pcivar.h>
        !           129: #include <dev/pci/pcidevs.h>
        !           130:
        !           131: #include <dev/pci/if_skreg.h>
        !           132: #include <dev/pci/if_skvar.h>
        !           133:
        !           134: int skc_probe(struct device *, void *, void *);
        !           135: void skc_attach(struct device *, struct device *self, void *aux);
        !           136: void skc_shutdown(void *);
        !           137: int sk_probe(struct device *, void *, void *);
        !           138: void sk_attach(struct device *, struct device *self, void *aux);
        !           139: int skcprint(void *, const char *);
        !           140: int sk_intr(void *);
        !           141: void sk_intr_bcom(struct sk_if_softc *);
        !           142: void sk_intr_xmac(struct sk_if_softc *);
        !           143: void sk_intr_yukon(struct sk_if_softc *);
        !           144: static __inline int sk_rxvalid(struct sk_softc *, u_int32_t, u_int32_t);
        !           145: void sk_rxeof(struct sk_if_softc *);
        !           146: void sk_txeof(struct sk_if_softc *);
        !           147: int sk_encap(struct sk_if_softc *, struct mbuf *, u_int32_t *);
        !           148: void sk_start(struct ifnet *);
        !           149: int sk_ioctl(struct ifnet *, u_long, caddr_t);
        !           150: void sk_init(void *);
        !           151: void sk_init_xmac(struct sk_if_softc *);
        !           152: void sk_init_yukon(struct sk_if_softc *);
        !           153: void sk_stop(struct sk_if_softc *);
        !           154: void sk_watchdog(struct ifnet *);
        !           155: int sk_ifmedia_upd(struct ifnet *);
        !           156: void sk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           157: void sk_reset(struct sk_softc *);
        !           158: int sk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t);
        !           159: int sk_alloc_jumbo_mem(struct sk_if_softc *);
        !           160: void *sk_jalloc(struct sk_if_softc *);
        !           161: void sk_jfree(caddr_t, u_int, void *);
        !           162: int sk_init_rx_ring(struct sk_if_softc *);
        !           163: int sk_init_tx_ring(struct sk_if_softc *);
        !           164:
        !           165: int sk_xmac_miibus_readreg(struct device *, int, int);
        !           166: void sk_xmac_miibus_writereg(struct device *, int, int, int);
        !           167: void sk_xmac_miibus_statchg(struct device *);
        !           168:
        !           169: int sk_marv_miibus_readreg(struct device *, int, int);
        !           170: void sk_marv_miibus_writereg(struct device *, int, int, int);
        !           171: void sk_marv_miibus_statchg(struct device *);
        !           172:
        !           173: u_int32_t sk_xmac_hash(caddr_t);
        !           174: u_int32_t sk_yukon_hash(caddr_t);
        !           175: void sk_setfilt(struct sk_if_softc *, caddr_t, int);
        !           176: void sk_setmulti(struct sk_if_softc *);
        !           177: void sk_setpromisc(struct sk_if_softc *);
        !           178: void sk_tick(void *);
        !           179: void sk_yukon_tick(void *);
        !           180: void sk_rxcsum(struct ifnet *, struct mbuf *, const u_int16_t, const u_int16_t);
        !           181:
        !           182: #ifdef SK_DEBUG
        !           183: #define DPRINTF(x)     if (skdebug) printf x
        !           184: #define DPRINTFN(n,x)  if (skdebug >= (n)) printf x
        !           185: int    skdebug = 0;
        !           186:
        !           187: void sk_dump_txdesc(struct sk_tx_desc *, int);
        !           188: void sk_dump_mbuf(struct mbuf *);
        !           189: void sk_dump_bytes(const char *, int);
        !           190: #else
        !           191: #define DPRINTF(x)
        !           192: #define DPRINTFN(n,x)
        !           193: #endif
        !           194:
        !           195: /* supported device vendors */
        !           196: const struct pci_matchid skc_devices[] = {
        !           197:        { PCI_VENDOR_3COM,              PCI_PRODUCT_3COM_3C940 },
        !           198:        { PCI_VENDOR_3COM,              PCI_PRODUCT_3COM_3C940B },
        !           199:        { PCI_VENDOR_CNET,              PCI_PRODUCT_CNET_GIGACARD },
        !           200:        { PCI_VENDOR_DLINK,             PCI_PRODUCT_DLINK_DGE530T_A1 },
        !           201:        { PCI_VENDOR_DLINK,             PCI_PRODUCT_DLINK_DGE530T_B1 },
        !           202:        { PCI_VENDOR_LINKSYS,           PCI_PRODUCT_LINKSYS_EG1064 },
        !           203:        { PCI_VENDOR_MARVELL,           PCI_PRODUCT_MARVELL_YUKON },
        !           204:        { PCI_VENDOR_MARVELL,           PCI_PRODUCT_MARVELL_YUKON_BELKIN },
        !           205:        { PCI_VENDOR_SCHNEIDERKOCH,     PCI_PRODUCT_SCHNEIDERKOCH_SK98XX },
        !           206:        { PCI_VENDOR_SCHNEIDERKOCH,     PCI_PRODUCT_SCHNEIDERKOCH_SK98XX2 },
        !           207: };
        !           208:
        !           209: #define SK_LINKSYS_EG1032_SUBID 0x00151737
        !           210:
        !           211: static inline u_int32_t
        !           212: sk_win_read_4(struct sk_softc *sc, u_int32_t reg)
        !           213: {
        !           214:        return CSR_READ_4(sc, reg);
        !           215: }
        !           216:
        !           217: static inline u_int16_t
        !           218: sk_win_read_2(struct sk_softc *sc, u_int32_t reg)
        !           219: {
        !           220:        return CSR_READ_2(sc, reg);
        !           221: }
        !           222:
        !           223: static inline u_int8_t
        !           224: sk_win_read_1(struct sk_softc *sc, u_int32_t reg)
        !           225: {
        !           226:        return CSR_READ_1(sc, reg);
        !           227: }
        !           228:
        !           229: static inline void
        !           230: sk_win_write_4(struct sk_softc *sc, u_int32_t reg, u_int32_t x)
        !           231: {
        !           232:        CSR_WRITE_4(sc, reg, x);
        !           233: }
        !           234:
        !           235: static inline void
        !           236: sk_win_write_2(struct sk_softc *sc, u_int32_t reg, u_int16_t x)
        !           237: {
        !           238:        CSR_WRITE_2(sc, reg, x);
        !           239: }
        !           240:
        !           241: static inline void
        !           242: sk_win_write_1(struct sk_softc *sc, u_int32_t reg, u_int8_t x)
        !           243: {
        !           244:        CSR_WRITE_1(sc, reg, x);
        !           245: }
        !           246:
        !           247: int
        !           248: sk_xmac_miibus_readreg(struct device *dev, int phy, int reg)
        !           249: {
        !           250:        struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
        !           251:        int i;
        !           252:
        !           253:        DPRINTFN(9, ("sk_xmac_miibus_readreg\n"));
        !           254:
        !           255:        if (sc_if->sk_phytype == SK_PHYTYPE_XMAC && phy != 0)
        !           256:                return (0);
        !           257:
        !           258:        SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8));
        !           259:        SK_XM_READ_2(sc_if, XM_PHY_DATA);
        !           260:        if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) {
        !           261:                for (i = 0; i < SK_TIMEOUT; i++) {
        !           262:                        DELAY(1);
        !           263:                        if (SK_XM_READ_2(sc_if, XM_MMUCMD) &
        !           264:                            XM_MMUCMD_PHYDATARDY)
        !           265:                                break;
        !           266:                }
        !           267:
        !           268:                if (i == SK_TIMEOUT) {
        !           269:                        printf("%s: phy failed to come ready\n",
        !           270:                            sc_if->sk_dev.dv_xname);
        !           271:                        return (0);
        !           272:                }
        !           273:        }
        !           274:        DELAY(1);
        !           275:        return (SK_XM_READ_2(sc_if, XM_PHY_DATA));
        !           276: }
        !           277:
        !           278: void
        !           279: sk_xmac_miibus_writereg(struct device *dev, int phy, int reg, int val)
        !           280: {
        !           281:        struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
        !           282:        int i;
        !           283:
        !           284:        DPRINTFN(9, ("sk_xmac_miibus_writereg\n"));
        !           285:
        !           286:        SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8));
        !           287:        for (i = 0; i < SK_TIMEOUT; i++) {
        !           288:                if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY))
        !           289:                        break;
        !           290:        }
        !           291:
        !           292:        if (i == SK_TIMEOUT) {
        !           293:                printf("%s: phy failed to come ready\n",
        !           294:                    sc_if->sk_dev.dv_xname);
        !           295:                return;
        !           296:        }
        !           297:
        !           298:        SK_XM_WRITE_2(sc_if, XM_PHY_DATA, val);
        !           299:        for (i = 0; i < SK_TIMEOUT; i++) {
        !           300:                DELAY(1);
        !           301:                if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY))
        !           302:                        break;
        !           303:        }
        !           304:
        !           305:        if (i == SK_TIMEOUT)
        !           306:                printf("%s: phy write timed out\n", sc_if->sk_dev.dv_xname);
        !           307: }
        !           308:
        !           309: void
        !           310: sk_xmac_miibus_statchg(struct device *dev)
        !           311: {
        !           312:        struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
        !           313:        struct mii_data *mii = &sc_if->sk_mii;
        !           314:
        !           315:        DPRINTFN(9, ("sk_xmac_miibus_statchg\n"));
        !           316:
        !           317:        /*
        !           318:         * If this is a GMII PHY, manually set the XMAC's
        !           319:         * duplex mode accordingly.
        !           320:         */
        !           321:        if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) {
        !           322:                if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
        !           323:                        SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX);
        !           324:                else
        !           325:                        SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX);
        !           326:        }
        !           327: }
        !           328:
        !           329: int
        !           330: sk_marv_miibus_readreg(struct device *dev, int phy, int reg)
        !           331: {
        !           332:        struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
        !           333:        u_int16_t val;
        !           334:        int i;
        !           335:
        !           336:        if (phy != 0 ||
        !           337:            (sc_if->sk_phytype != SK_PHYTYPE_MARV_COPPER &&
        !           338:             sc_if->sk_phytype != SK_PHYTYPE_MARV_FIBER)) {
        !           339:                DPRINTFN(9, ("sk_marv_miibus_readreg (skip) phy=%d, reg=%#x\n",
        !           340:                             phy, reg));
        !           341:                return (0);
        !           342:        }
        !           343:
        !           344:         SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
        !           345:                      YU_SMICR_REGAD(reg) | YU_SMICR_OP_READ);
        !           346:
        !           347:        for (i = 0; i < SK_TIMEOUT; i++) {
        !           348:                DELAY(1);
        !           349:                val = SK_YU_READ_2(sc_if, YUKON_SMICR);
        !           350:                if (val & YU_SMICR_READ_VALID)
        !           351:                        break;
        !           352:        }
        !           353:
        !           354:        if (i == SK_TIMEOUT) {
        !           355:                printf("%s: phy failed to come ready\n",
        !           356:                       sc_if->sk_dev.dv_xname);
        !           357:                return (0);
        !           358:        }
        !           359:
        !           360:        DPRINTFN(9, ("sk_marv_miibus_readreg: i=%d, timeout=%d\n", i,
        !           361:                     SK_TIMEOUT));
        !           362:
        !           363:         val = SK_YU_READ_2(sc_if, YUKON_SMIDR);
        !           364:
        !           365:        DPRINTFN(9, ("sk_marv_miibus_readreg phy=%d, reg=%#x, val=%#x\n",
        !           366:                     phy, reg, val));
        !           367:
        !           368:        return (val);
        !           369: }
        !           370:
        !           371: void
        !           372: sk_marv_miibus_writereg(struct device *dev, int phy, int reg, int val)
        !           373: {
        !           374:        struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
        !           375:        int i;
        !           376:
        !           377:        DPRINTFN(9, ("sk_marv_miibus_writereg phy=%d reg=%#x val=%#x\n",
        !           378:                     phy, reg, val));
        !           379:
        !           380:        SK_YU_WRITE_2(sc_if, YUKON_SMIDR, val);
        !           381:        SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
        !           382:                      YU_SMICR_REGAD(reg) | YU_SMICR_OP_WRITE);
        !           383:
        !           384:        for (i = 0; i < SK_TIMEOUT; i++) {
        !           385:                DELAY(1);
        !           386:                if (!(SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY))
        !           387:                        break;
        !           388:        }
        !           389:
        !           390:        if (i == SK_TIMEOUT)
        !           391:                printf("%s: phy write timed out\n", sc_if->sk_dev.dv_xname);
        !           392: }
        !           393:
        !           394: void
        !           395: sk_marv_miibus_statchg(struct device *dev)
        !           396: {
        !           397:        DPRINTFN(9, ("sk_marv_miibus_statchg: gpcr=%x\n",
        !           398:                     SK_YU_READ_2(((struct sk_if_softc *)dev), YUKON_GPCR)));
        !           399: }
        !           400:
        !           401: u_int32_t
        !           402: sk_xmac_hash(caddr_t addr)
        !           403: {
        !           404:        u_int32_t crc;
        !           405:
        !           406:        crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
        !           407:        return (~crc & ((1 << SK_HASH_BITS) - 1));
        !           408: }
        !           409:
        !           410: u_int32_t
        !           411: sk_yukon_hash(caddr_t addr)
        !           412: {
        !           413:        u_int32_t crc;
        !           414:
        !           415:        crc = ether_crc32_be(addr, ETHER_ADDR_LEN);
        !           416:        return (crc & ((1 << SK_HASH_BITS) - 1));
        !           417: }
        !           418:
        !           419: void
        !           420: sk_setfilt(struct sk_if_softc *sc_if, caddr_t addr, int slot)
        !           421: {
        !           422:        int base = XM_RXFILT_ENTRY(slot);
        !           423:
        !           424:        SK_XM_WRITE_2(sc_if, base, letoh16(*(u_int16_t *)(&addr[0])));
        !           425:        SK_XM_WRITE_2(sc_if, base + 2, letoh16(*(u_int16_t *)(&addr[2])));
        !           426:        SK_XM_WRITE_2(sc_if, base + 4, letoh16(*(u_int16_t *)(&addr[4])));
        !           427: }
        !           428:
        !           429: void
        !           430: sk_setmulti(struct sk_if_softc *sc_if)
        !           431: {
        !           432:        struct sk_softc *sc = sc_if->sk_softc;
        !           433:        struct ifnet *ifp= &sc_if->arpcom.ac_if;
        !           434:        u_int32_t hashes[2] = { 0, 0 };
        !           435:        int h, i;
        !           436:        struct arpcom *ac = &sc_if->arpcom;
        !           437:        struct ether_multi *enm;
        !           438:        struct ether_multistep step;
        !           439:        u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 };
        !           440:
        !           441:        /* First, zot all the existing filters. */
        !           442:        switch(sc->sk_type) {
        !           443:        case SK_GENESIS:
        !           444:                for (i = 1; i < XM_RXFILT_MAX; i++)
        !           445:                        sk_setfilt(sc_if, (caddr_t)&dummy, i);
        !           446:
        !           447:                SK_XM_WRITE_4(sc_if, XM_MAR0, 0);
        !           448:                SK_XM_WRITE_4(sc_if, XM_MAR2, 0);
        !           449:                break;
        !           450:        case SK_YUKON:
        !           451:        case SK_YUKON_LITE:
        !           452:        case SK_YUKON_LP:
        !           453:                SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
        !           454:                SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
        !           455:                SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
        !           456:                SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
        !           457:                break;
        !           458:        }
        !           459:
        !           460:        /* Now program new ones. */
        !           461: allmulti:
        !           462:        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
        !           463:                hashes[0] = 0xFFFFFFFF;
        !           464:                hashes[1] = 0xFFFFFFFF;
        !           465:        } else {
        !           466:                i = 1;
        !           467:                /* First find the tail of the list. */
        !           468:                ETHER_FIRST_MULTI(step, ac, enm);
        !           469:                while (enm != NULL) {
        !           470:                        if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
        !           471:                                 ETHER_ADDR_LEN)) {
        !           472:                                ifp->if_flags |= IFF_ALLMULTI;
        !           473:                                goto allmulti;
        !           474:                        }
        !           475:                        /*
        !           476:                         * Program the first XM_RXFILT_MAX multicast groups
        !           477:                         * into the perfect filter. For all others,
        !           478:                         * use the hash table.
        !           479:                         */
        !           480:                        if (SK_IS_GENESIS(sc) && i < XM_RXFILT_MAX) {
        !           481:                                sk_setfilt(sc_if, enm->enm_addrlo, i);
        !           482:                                i++;
        !           483:                        }
        !           484:                        else {
        !           485:                                switch(sc->sk_type) {
        !           486:                                case SK_GENESIS:
        !           487:                                        h = sk_xmac_hash(enm->enm_addrlo);
        !           488:                                        break;
        !           489:
        !           490:                                case SK_YUKON:
        !           491:                                case SK_YUKON_LITE:
        !           492:                                case SK_YUKON_LP:
        !           493:                                        h = sk_yukon_hash(enm->enm_addrlo);
        !           494:                                        break;
        !           495:                                }
        !           496:                                if (h < 32)
        !           497:                                        hashes[0] |= (1 << h);
        !           498:                                else
        !           499:                                        hashes[1] |= (1 << (h - 32));
        !           500:                        }
        !           501:
        !           502:                        ETHER_NEXT_MULTI(step, enm);
        !           503:                }
        !           504:        }
        !           505:
        !           506:        switch(sc->sk_type) {
        !           507:        case SK_GENESIS:
        !           508:                SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH|
        !           509:                               XM_MODE_RX_USE_PERFECT);
        !           510:                SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
        !           511:                SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
        !           512:                break;
        !           513:        case SK_YUKON:
        !           514:        case SK_YUKON_LITE:
        !           515:        case SK_YUKON_LP:
        !           516:                SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff);
        !           517:                SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff);
        !           518:                SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff);
        !           519:                SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff);
        !           520:                break;
        !           521:        }
        !           522: }
        !           523:
        !           524: void
        !           525: sk_setpromisc(struct sk_if_softc *sc_if)
        !           526: {
        !           527:        struct sk_softc *sc = sc_if->sk_softc;
        !           528:        struct ifnet *ifp= &sc_if->arpcom.ac_if;
        !           529:
        !           530:        switch(sc->sk_type) {
        !           531:        case SK_GENESIS:
        !           532:                if (ifp->if_flags & IFF_PROMISC)
        !           533:                        SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
        !           534:                else
        !           535:                        SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
        !           536:                break;
        !           537:        case SK_YUKON:
        !           538:        case SK_YUKON_LITE:
        !           539:        case SK_YUKON_LP:
        !           540:                if (ifp->if_flags & IFF_PROMISC) {
        !           541:                        SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
        !           542:                            YU_RCR_UFLEN | YU_RCR_MUFLEN);
        !           543:                } else {
        !           544:                        SK_YU_SETBIT_2(sc_if, YUKON_RCR,
        !           545:                            YU_RCR_UFLEN | YU_RCR_MUFLEN);
        !           546:                }
        !           547:                break;
        !           548:        }
        !           549: }
        !           550:
        !           551: int
        !           552: sk_init_rx_ring(struct sk_if_softc *sc_if)
        !           553: {
        !           554:        struct sk_chain_data    *cd = &sc_if->sk_cdata;
        !           555:        struct sk_ring_data     *rd = sc_if->sk_rdata;
        !           556:        int                     i, nexti;
        !           557:
        !           558:        bzero((char *)rd->sk_rx_ring,
        !           559:            sizeof(struct sk_rx_desc) * SK_RX_RING_CNT);
        !           560:
        !           561:        for (i = 0; i < SK_RX_RING_CNT; i++) {
        !           562:                cd->sk_rx_chain[i].sk_desc = &rd->sk_rx_ring[i];
        !           563:                if (i == (SK_RX_RING_CNT - 1))
        !           564:                        nexti = 0;
        !           565:                else
        !           566:                        nexti = i + 1;
        !           567:                cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[nexti];
        !           568:                rd->sk_rx_ring[i].sk_next = htole32(SK_RX_RING_ADDR(sc_if, nexti));
        !           569:                rd->sk_rx_ring[i].sk_csum1_start = htole16(ETHER_HDR_LEN);
        !           570:                rd->sk_rx_ring[i].sk_csum2_start = htole16(ETHER_HDR_LEN +
        !           571:                    sizeof(struct ip));
        !           572:        }
        !           573:
        !           574:        for (i = 0; i < SK_RX_RING_CNT; i++) {
        !           575:                if (sk_newbuf(sc_if, i, NULL,
        !           576:                    sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) {
        !           577:                        printf("%s: failed alloc of %dth mbuf\n",
        !           578:                            sc_if->sk_dev.dv_xname, i);
        !           579:                        return (ENOBUFS);
        !           580:                }
        !           581:        }
        !           582:
        !           583:        sc_if->sk_cdata.sk_rx_prod = 0;
        !           584:        sc_if->sk_cdata.sk_rx_cons = 0;
        !           585:
        !           586:        return (0);
        !           587: }
        !           588:
        !           589: int
        !           590: sk_init_tx_ring(struct sk_if_softc *sc_if)
        !           591: {
        !           592:        struct sk_softc         *sc = sc_if->sk_softc;
        !           593:        struct sk_chain_data    *cd = &sc_if->sk_cdata;
        !           594:        struct sk_ring_data     *rd = sc_if->sk_rdata;
        !           595:        bus_dmamap_t            dmamap;
        !           596:        struct sk_txmap_entry   *entry;
        !           597:        int                     i, nexti;
        !           598:
        !           599:        bzero((char *)sc_if->sk_rdata->sk_tx_ring,
        !           600:            sizeof(struct sk_tx_desc) * SK_TX_RING_CNT);
        !           601:
        !           602:        SIMPLEQ_INIT(&sc_if->sk_txmap_head);
        !           603:        for (i = 0; i < SK_TX_RING_CNT; i++) {
        !           604:                cd->sk_tx_chain[i].sk_desc = &rd->sk_tx_ring[i];
        !           605:                if (i == (SK_TX_RING_CNT - 1))
        !           606:                        nexti = 0;
        !           607:                else
        !           608:                        nexti = i + 1;
        !           609:                cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[nexti];
        !           610:                rd->sk_tx_ring[i].sk_next = htole32(SK_TX_RING_ADDR(sc_if, nexti));
        !           611:
        !           612:                if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, SK_NTXSEG,
        !           613:                   SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap))
        !           614:                        return (ENOBUFS);
        !           615:
        !           616:                entry = malloc(sizeof(*entry), M_DEVBUF, M_NOWAIT);
        !           617:                if (!entry) {
        !           618:                        bus_dmamap_destroy(sc->sc_dmatag, dmamap);
        !           619:                        return (ENOBUFS);
        !           620:                }
        !           621:                entry->dmamap = dmamap;
        !           622:                SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head, entry, link);
        !           623:        }
        !           624:
        !           625:        sc_if->sk_cdata.sk_tx_prod = 0;
        !           626:        sc_if->sk_cdata.sk_tx_cons = 0;
        !           627:        sc_if->sk_cdata.sk_tx_cnt = 0;
        !           628:
        !           629:        SK_CDTXSYNC(sc_if, 0, SK_TX_RING_CNT,
        !           630:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !           631:
        !           632:        return (0);
        !           633: }
        !           634:
        !           635: int
        !           636: sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m,
        !           637:          bus_dmamap_t dmamap)
        !           638: {
        !           639:        struct mbuf             *m_new = NULL;
        !           640:        struct sk_chain         *c;
        !           641:        struct sk_rx_desc       *r;
        !           642:
        !           643:        if (m == NULL) {
        !           644:                caddr_t buf = NULL;
        !           645:
        !           646:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !           647:                if (m_new == NULL)
        !           648:                        return (ENOBUFS);
        !           649:
        !           650:                /* Allocate the jumbo buffer */
        !           651:                buf = sk_jalloc(sc_if);
        !           652:                if (buf == NULL) {
        !           653:                        m_freem(m_new);
        !           654:                        DPRINTFN(1, ("%s jumbo allocation failed -- packet "
        !           655:                            "dropped!\n", sc_if->arpcom.ac_if.if_xname));
        !           656:                        return (ENOBUFS);
        !           657:                }
        !           658:
        !           659:                /* Attach the buffer to the mbuf */
        !           660:                m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
        !           661:                MEXTADD(m_new, buf, SK_JLEN, 0, sk_jfree, sc_if);
        !           662:        } else {
        !           663:                /*
        !           664:                 * We're re-using a previously allocated mbuf;
        !           665:                 * be sure to re-init pointers and lengths to
        !           666:                 * default values.
        !           667:                 */
        !           668:                m_new = m;
        !           669:                m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
        !           670:                m_new->m_data = m_new->m_ext.ext_buf;
        !           671:        }
        !           672:        m_adj(m_new, ETHER_ALIGN);
        !           673:
        !           674:        c = &sc_if->sk_cdata.sk_rx_chain[i];
        !           675:        r = c->sk_desc;
        !           676:        c->sk_mbuf = m_new;
        !           677:        r->sk_data_lo = htole32(dmamap->dm_segs[0].ds_addr +
        !           678:            (((vaddr_t)m_new->m_data
        !           679:              - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf)));
        !           680:        r->sk_ctl = htole32(SK_JLEN | SK_RXSTAT);
        !           681:
        !           682:        SK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
        !           683:
        !           684:        return (0);
        !           685: }
        !           686:
        !           687: /*
        !           688:  * Memory management for jumbo frames.
        !           689:  */
        !           690:
        !           691: int
        !           692: sk_alloc_jumbo_mem(struct sk_if_softc *sc_if)
        !           693: {
        !           694:        struct sk_softc         *sc = sc_if->sk_softc;
        !           695:        caddr_t                 ptr, kva;
        !           696:        bus_dma_segment_t       seg;
        !           697:        int             i, rseg, state, error;
        !           698:        struct sk_jpool_entry   *entry;
        !           699:
        !           700:        state = error = 0;
        !           701:
        !           702:        /* Grab a big chunk o' storage. */
        !           703:        if (bus_dmamem_alloc(sc->sc_dmatag, SK_JMEM, PAGE_SIZE, 0,
        !           704:                             &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !           705:                printf(": can't alloc rx buffers");
        !           706:                return (ENOBUFS);
        !           707:        }
        !           708:
        !           709:        state = 1;
        !           710:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, SK_JMEM, &kva,
        !           711:                           BUS_DMA_NOWAIT)) {
        !           712:                printf(": can't map dma buffers (%d bytes)", SK_JMEM);
        !           713:                error = ENOBUFS;
        !           714:                goto out;
        !           715:        }
        !           716:
        !           717:        state = 2;
        !           718:        if (bus_dmamap_create(sc->sc_dmatag, SK_JMEM, 1, SK_JMEM, 0,
        !           719:            BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) {
        !           720:                printf(": can't create dma map");
        !           721:                error = ENOBUFS;
        !           722:                goto out;
        !           723:        }
        !           724:
        !           725:        state = 3;
        !           726:        if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map,
        !           727:                            kva, SK_JMEM, NULL, BUS_DMA_NOWAIT)) {
        !           728:                printf(": can't load dma map");
        !           729:                error = ENOBUFS;
        !           730:                goto out;
        !           731:        }
        !           732:
        !           733:        state = 4;
        !           734:        sc_if->sk_cdata.sk_jumbo_buf = (caddr_t)kva;
        !           735:        DPRINTFN(1,("sk_jumbo_buf = 0x%08X\n", sc_if->sk_cdata.sk_jumbo_buf));
        !           736:
        !           737:        LIST_INIT(&sc_if->sk_jfree_listhead);
        !           738:        LIST_INIT(&sc_if->sk_jinuse_listhead);
        !           739:
        !           740:        /*
        !           741:         * Now divide it up into 9K pieces and save the addresses
        !           742:         * in an array.
        !           743:         */
        !           744:        ptr = sc_if->sk_cdata.sk_jumbo_buf;
        !           745:        for (i = 0; i < SK_JSLOTS; i++) {
        !           746:                sc_if->sk_cdata.sk_jslots[i] = ptr;
        !           747:                ptr += SK_JLEN;
        !           748:                entry = malloc(sizeof(struct sk_jpool_entry),
        !           749:                    M_DEVBUF, M_NOWAIT);
        !           750:                if (entry == NULL) {
        !           751:                        sc_if->sk_cdata.sk_jumbo_buf = NULL;
        !           752:                        printf(": no memory for jumbo buffer queue!");
        !           753:                        error = ENOBUFS;
        !           754:                        goto out;
        !           755:                }
        !           756:                entry->slot = i;
        !           757:                LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead,
        !           758:                                 entry, jpool_entries);
        !           759:        }
        !           760: out:
        !           761:        if (error != 0) {
        !           762:                switch (state) {
        !           763:                case 4:
        !           764:                        bus_dmamap_unload(sc->sc_dmatag,
        !           765:                            sc_if->sk_cdata.sk_rx_jumbo_map);
        !           766:                case 3:
        !           767:                        bus_dmamap_destroy(sc->sc_dmatag,
        !           768:                            sc_if->sk_cdata.sk_rx_jumbo_map);
        !           769:                case 2:
        !           770:                        bus_dmamem_unmap(sc->sc_dmatag, kva, SK_JMEM);
        !           771:                case 1:
        !           772:                        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !           773:                        break;
        !           774:                default:
        !           775:                        break;
        !           776:                }
        !           777:        }
        !           778:
        !           779:        return (error);
        !           780: }
        !           781:
        !           782: /*
        !           783:  * Allocate a jumbo buffer.
        !           784:  */
        !           785: void *
        !           786: sk_jalloc(struct sk_if_softc *sc_if)
        !           787: {
        !           788:        struct sk_jpool_entry   *entry;
        !           789:
        !           790:        entry = LIST_FIRST(&sc_if->sk_jfree_listhead);
        !           791:
        !           792:        if (entry == NULL)
        !           793:                return (NULL);
        !           794:
        !           795:        LIST_REMOVE(entry, jpool_entries);
        !           796:        LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
        !           797:        return (sc_if->sk_cdata.sk_jslots[entry->slot]);
        !           798: }
        !           799:
        !           800: /*
        !           801:  * Release a jumbo buffer.
        !           802:  */
        !           803: void
        !           804: sk_jfree(caddr_t buf, u_int size, void *arg)
        !           805: {
        !           806:        struct sk_jpool_entry *entry;
        !           807:        struct sk_if_softc *sc;
        !           808:        int i;
        !           809:
        !           810:        /* Extract the softc struct pointer. */
        !           811:        sc = (struct sk_if_softc *)arg;
        !           812:
        !           813:        if (sc == NULL)
        !           814:                panic("sk_jfree: can't find softc pointer!");
        !           815:
        !           816:        /* calculate the slot this buffer belongs to */
        !           817:        i = ((vaddr_t)buf
        !           818:             - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN;
        !           819:
        !           820:        if ((i < 0) || (i >= SK_JSLOTS))
        !           821:                panic("sk_jfree: asked to free buffer that we don't manage!");
        !           822:
        !           823:        entry = LIST_FIRST(&sc->sk_jinuse_listhead);
        !           824:        if (entry == NULL)
        !           825:                panic("sk_jfree: buffer not in use!");
        !           826:        entry->slot = i;
        !           827:        LIST_REMOVE(entry, jpool_entries);
        !           828:        LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries);
        !           829: }
        !           830:
        !           831: /*
        !           832:  * Set media options.
        !           833:  */
        !           834: int
        !           835: sk_ifmedia_upd(struct ifnet *ifp)
        !           836: {
        !           837:        struct sk_if_softc *sc_if = ifp->if_softc;
        !           838:
        !           839:        mii_mediachg(&sc_if->sk_mii);
        !           840:        return (0);
        !           841: }
        !           842:
        !           843: /*
        !           844:  * Report current media status.
        !           845:  */
        !           846: void
        !           847: sk_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
        !           848: {
        !           849:        struct sk_if_softc *sc_if = ifp->if_softc;
        !           850:
        !           851:        mii_pollstat(&sc_if->sk_mii);
        !           852:        ifmr->ifm_active = sc_if->sk_mii.mii_media_active;
        !           853:        ifmr->ifm_status = sc_if->sk_mii.mii_media_status;
        !           854: }
        !           855:
        !           856: int
        !           857: sk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !           858: {
        !           859:        struct sk_if_softc *sc_if = ifp->if_softc;
        !           860:        struct ifreq *ifr = (struct ifreq *) data;
        !           861:        struct ifaddr *ifa = (struct ifaddr *) data;
        !           862:        struct mii_data *mii;
        !           863:        int s, error = 0;
        !           864:
        !           865:        s = splnet();
        !           866:
        !           867:        if ((error = ether_ioctl(ifp, &sc_if->arpcom, command, data)) > 0) {
        !           868:                splx(s);
        !           869:                return (error);
        !           870:        }
        !           871:
        !           872:        switch(command) {
        !           873:        case SIOCSIFADDR:
        !           874:                ifp->if_flags |= IFF_UP;
        !           875:                if (!(ifp->if_flags & IFF_RUNNING))
        !           876:                        sk_init(sc_if);
        !           877: #ifdef INET
        !           878:                if (ifa->ifa_addr->sa_family == AF_INET)
        !           879:                        arp_ifinit(&sc_if->arpcom, ifa);
        !           880: #endif /* INET */
        !           881:                break;
        !           882:        case SIOCSIFMTU:
        !           883:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
        !           884:                        error = EINVAL;
        !           885:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !           886:                        ifp->if_mtu = ifr->ifr_mtu;
        !           887:                break;
        !           888:        case SIOCSIFFLAGS:
        !           889:                if (ifp->if_flags & IFF_UP) {
        !           890:                        if (ifp->if_flags & IFF_RUNNING &&
        !           891:                            (ifp->if_flags ^ sc_if->sk_if_flags)
        !           892:                             & IFF_PROMISC) {
        !           893:                                sk_setpromisc(sc_if);
        !           894:                                sk_setmulti(sc_if);
        !           895:                        } else {
        !           896:                                if (!(ifp->if_flags & IFF_RUNNING))
        !           897:                                        sk_init(sc_if);
        !           898:                        }
        !           899:                } else {
        !           900:                        if (ifp->if_flags & IFF_RUNNING)
        !           901:                                sk_stop(sc_if);
        !           902:                }
        !           903:                sc_if->sk_if_flags = ifp->if_flags;
        !           904:                break;
        !           905:        case SIOCADDMULTI:
        !           906:        case SIOCDELMULTI:
        !           907:                error = (command == SIOCADDMULTI) ?
        !           908:                    ether_addmulti(ifr, &sc_if->arpcom) :
        !           909:                    ether_delmulti(ifr, &sc_if->arpcom);
        !           910:
        !           911:                if (error == ENETRESET) {
        !           912:                        /*
        !           913:                         * Multicast list has changed; set the hardware
        !           914:                         * filter accordingly.
        !           915:                         */
        !           916:                        if (ifp->if_flags & IFF_RUNNING)
        !           917:                                sk_setmulti(sc_if);
        !           918:                        error = 0;
        !           919:                }
        !           920:                break;
        !           921:        case SIOCGIFMEDIA:
        !           922:        case SIOCSIFMEDIA:
        !           923:                mii = &sc_if->sk_mii;
        !           924:                error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
        !           925:                break;
        !           926:        default:
        !           927:                error = ENOTTY;
        !           928:                break;
        !           929:        }
        !           930:
        !           931:        splx(s);
        !           932:
        !           933:        return (error);
        !           934: }
        !           935:
        !           936: /*
        !           937:  * Probe for a SysKonnect GEnesis chip. Check the PCI vendor and device
        !           938:  * IDs against our list and return a device name if we find a match.
        !           939:  */
        !           940: int
        !           941: skc_probe(struct device *parent, void *match, void *aux)
        !           942: {
        !           943:        struct pci_attach_args *pa = aux;
        !           944:        pci_chipset_tag_t pc = pa->pa_pc;
        !           945:        pcireg_t subid;
        !           946:
        !           947:        subid = pci_conf_read(pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
        !           948:
        !           949:        if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_LINKSYS &&
        !           950:            PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_LINKSYS_EG1032 &&
        !           951:            subid == SK_LINKSYS_EG1032_SUBID)
        !           952:                return (1);
        !           953:
        !           954:        return (pci_matchbyid((struct pci_attach_args *)aux, skc_devices,
        !           955:            sizeof(skc_devices)/sizeof(skc_devices[0])));
        !           956: }
        !           957:
        !           958: /*
        !           959:  * Force the GEnesis into reset, then bring it out of reset.
        !           960:  */
        !           961: void
        !           962: sk_reset(struct sk_softc *sc)
        !           963: {
        !           964:        u_int32_t imtimer_ticks;
        !           965:
        !           966:        DPRINTFN(2, ("sk_reset\n"));
        !           967:
        !           968:        CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_RESET);
        !           969:        CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_RESET);
        !           970:        if (SK_IS_YUKON(sc))
        !           971:                CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_SET);
        !           972:
        !           973:        DELAY(1000);
        !           974:        CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_UNRESET);
        !           975:        DELAY(2);
        !           976:        CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
        !           977:        if (SK_IS_YUKON(sc))
        !           978:                CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR);
        !           979:
        !           980:        DPRINTFN(2, ("sk_reset: sk_csr=%x\n", CSR_READ_2(sc, SK_CSR)));
        !           981:        DPRINTFN(2, ("sk_reset: sk_link_ctrl=%x\n",
        !           982:                     CSR_READ_2(sc, SK_LINK_CTRL)));
        !           983:
        !           984:        if (SK_IS_GENESIS(sc)) {
        !           985:                /* Configure packet arbiter */
        !           986:                sk_win_write_2(sc, SK_PKTARB_CTL, SK_PKTARBCTL_UNRESET);
        !           987:                sk_win_write_2(sc, SK_RXPA1_TINIT, SK_PKTARB_TIMEOUT);
        !           988:                sk_win_write_2(sc, SK_TXPA1_TINIT, SK_PKTARB_TIMEOUT);
        !           989:                sk_win_write_2(sc, SK_RXPA2_TINIT, SK_PKTARB_TIMEOUT);
        !           990:                sk_win_write_2(sc, SK_TXPA2_TINIT, SK_PKTARB_TIMEOUT);
        !           991:        }
        !           992:
        !           993:        /* Enable RAM interface */
        !           994:        sk_win_write_4(sc, SK_RAMCTL, SK_RAMCTL_UNRESET);
        !           995:
        !           996:        /*
        !           997:         * Configure interrupt moderation. The moderation timer
        !           998:         * defers interrupts specified in the interrupt moderation
        !           999:         * timer mask based on the timeout specified in the interrupt
        !          1000:         * moderation timer init register. Each bit in the timer
        !          1001:         * register represents one tick, so to specify a timeout in
        !          1002:         * microseconds, we have to multiply by the correct number of
        !          1003:         * ticks-per-microsecond.
        !          1004:         */
        !          1005:        switch (sc->sk_type) {
        !          1006:        case SK_GENESIS:
        !          1007:                imtimer_ticks = SK_IMTIMER_TICKS_GENESIS;
        !          1008:                break;
        !          1009:        default:
        !          1010:                imtimer_ticks = SK_IMTIMER_TICKS_YUKON;
        !          1011:        }
        !          1012:        sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(100));
        !          1013:        sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF|
        !          1014:            SK_ISR_RX1_EOF|SK_ISR_RX2_EOF);
        !          1015:        sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START);
        !          1016: }
        !          1017:
        !          1018: int
        !          1019: sk_probe(struct device *parent, void *match, void *aux)
        !          1020: {
        !          1021:        struct skc_attach_args *sa = aux;
        !          1022:
        !          1023:        if (sa->skc_port != SK_PORT_A && sa->skc_port != SK_PORT_B)
        !          1024:                return (0);
        !          1025:
        !          1026:        switch (sa->skc_type) {
        !          1027:        case SK_GENESIS:
        !          1028:        case SK_YUKON:
        !          1029:        case SK_YUKON_LITE:
        !          1030:        case SK_YUKON_LP:
        !          1031:                return (1);
        !          1032:        }
        !          1033:
        !          1034:        return (0);
        !          1035: }
        !          1036:
        !          1037: /*
        !          1038:  * Each XMAC chip is attached as a separate logical IP interface.
        !          1039:  * Single port cards will have only one logical interface of course.
        !          1040:  */
        !          1041: void
        !          1042: sk_attach(struct device *parent, struct device *self, void *aux)
        !          1043: {
        !          1044:        struct sk_if_softc *sc_if = (struct sk_if_softc *) self;
        !          1045:        struct sk_softc *sc = (struct sk_softc *)parent;
        !          1046:        struct skc_attach_args *sa = aux;
        !          1047:        struct ifnet *ifp;
        !          1048:        caddr_t kva;
        !          1049:        bus_dma_segment_t seg;
        !          1050:        int i, rseg;
        !          1051:
        !          1052:        sc_if->sk_port = sa->skc_port;
        !          1053:        sc_if->sk_softc = sc;
        !          1054:        sc->sk_if[sa->skc_port] = sc_if;
        !          1055:
        !          1056:        if (sa->skc_port == SK_PORT_A)
        !          1057:                sc_if->sk_tx_bmu = SK_BMU_TXS_CSR0;
        !          1058:        if (sa->skc_port == SK_PORT_B)
        !          1059:                sc_if->sk_tx_bmu = SK_BMU_TXS_CSR1;
        !          1060:
        !          1061:        DPRINTFN(2, ("begin sk_attach: port=%d\n", sc_if->sk_port));
        !          1062:
        !          1063:        /*
        !          1064:         * Get station address for this interface. Note that
        !          1065:         * dual port cards actually come with three station
        !          1066:         * addresses: one for each port, plus an extra. The
        !          1067:         * extra one is used by the SysKonnect driver software
        !          1068:         * as a 'virtual' station address for when both ports
        !          1069:         * are operating in failover mode. Currently we don't
        !          1070:         * use this extra address.
        !          1071:         */
        !          1072:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !          1073:                sc_if->arpcom.ac_enaddr[i] =
        !          1074:                    sk_win_read_1(sc, SK_MAC0_0 + (sa->skc_port * 8) + i);
        !          1075:
        !          1076:        printf(": address %s\n",
        !          1077:            ether_sprintf(sc_if->arpcom.ac_enaddr));
        !          1078:
        !          1079:        /*
        !          1080:         * Set up RAM buffer addresses. The NIC will have a certain
        !          1081:         * amount of SRAM on it, somewhere between 512K and 2MB. We
        !          1082:         * need to divide this up a) between the transmitter and
        !          1083:         * receiver and b) between the two XMACs, if this is a
        !          1084:         * dual port NIC. Our algorithm is to divide up the memory
        !          1085:         * evenly so that everyone gets a fair share.
        !          1086:         */
        !          1087:        if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) {
        !          1088:                u_int32_t               chunk, val;
        !          1089:
        !          1090:                chunk = sc->sk_ramsize / 2;
        !          1091:                val = sc->sk_rboff / sizeof(u_int64_t);
        !          1092:                sc_if->sk_rx_ramstart = val;
        !          1093:                val += (chunk / sizeof(u_int64_t));
        !          1094:                sc_if->sk_rx_ramend = val - 1;
        !          1095:                sc_if->sk_tx_ramstart = val;
        !          1096:                val += (chunk / sizeof(u_int64_t));
        !          1097:                sc_if->sk_tx_ramend = val - 1;
        !          1098:        } else {
        !          1099:                u_int32_t               chunk, val;
        !          1100:
        !          1101:                chunk = sc->sk_ramsize / 4;
        !          1102:                val = (sc->sk_rboff + (chunk * 2 * sc_if->sk_port)) /
        !          1103:                    sizeof(u_int64_t);
        !          1104:                sc_if->sk_rx_ramstart = val;
        !          1105:                val += (chunk / sizeof(u_int64_t));
        !          1106:                sc_if->sk_rx_ramend = val - 1;
        !          1107:                sc_if->sk_tx_ramstart = val;
        !          1108:                val += (chunk / sizeof(u_int64_t));
        !          1109:                sc_if->sk_tx_ramend = val - 1;
        !          1110:        }
        !          1111:
        !          1112:        DPRINTFN(2, ("sk_attach: rx_ramstart=%#x rx_ramend=%#x\n"
        !          1113:                     "           tx_ramstart=%#x tx_ramend=%#x\n",
        !          1114:                     sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend,
        !          1115:                     sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend));
        !          1116:
        !          1117:        /* Read and save PHY type */
        !          1118:        sc_if->sk_phytype = sk_win_read_1(sc, SK_EPROM1) & 0xF;
        !          1119:
        !          1120:        /* Set PHY address */
        !          1121:        if (SK_IS_GENESIS(sc)) {
        !          1122:                switch (sc_if->sk_phytype) {
        !          1123:                        case SK_PHYTYPE_XMAC:
        !          1124:                                sc_if->sk_phyaddr = SK_PHYADDR_XMAC;
        !          1125:                                break;
        !          1126:                        case SK_PHYTYPE_BCOM:
        !          1127:                                sc_if->sk_phyaddr = SK_PHYADDR_BCOM;
        !          1128:                                break;
        !          1129:                        default:
        !          1130:                                printf("%s: unsupported PHY type: %d\n",
        !          1131:                                    sc->sk_dev.dv_xname, sc_if->sk_phytype);
        !          1132:                                return;
        !          1133:                }
        !          1134:        }
        !          1135:
        !          1136:        if (SK_IS_YUKON(sc)) {
        !          1137:                if ((sc_if->sk_phytype < SK_PHYTYPE_MARV_COPPER &&
        !          1138:                    sc->sk_pmd != 'L' && sc->sk_pmd != 'S')) {
        !          1139:                        /* not initialized, punt */
        !          1140:                        sc_if->sk_phytype = SK_PHYTYPE_MARV_COPPER;
        !          1141:
        !          1142:                        sc->sk_coppertype = 1;
        !          1143:                }
        !          1144:
        !          1145:                sc_if->sk_phyaddr = SK_PHYADDR_MARV;
        !          1146:
        !          1147:                if (!(sc->sk_coppertype))
        !          1148:                        sc_if->sk_phytype = SK_PHYTYPE_MARV_FIBER;
        !          1149:        }
        !          1150:
        !          1151:        /* Allocate the descriptor queues. */
        !          1152:        if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct sk_ring_data),
        !          1153:            PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !          1154:                printf(": can't alloc rx buffers\n");
        !          1155:                goto fail;
        !          1156:        }
        !          1157:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
        !          1158:            sizeof(struct sk_ring_data), &kva, BUS_DMA_NOWAIT)) {
        !          1159:                printf(": can't map dma buffers (%lu bytes)\n",
        !          1160:                       (ulong)sizeof(struct sk_ring_data));
        !          1161:                goto fail_1;
        !          1162:        }
        !          1163:        if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct sk_ring_data), 1,
        !          1164:            sizeof(struct sk_ring_data), 0, BUS_DMA_NOWAIT,
        !          1165:             &sc_if->sk_ring_map)) {
        !          1166:                printf(": can't create dma map\n");
        !          1167:                goto fail_2;
        !          1168:        }
        !          1169:        if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_ring_map, kva,
        !          1170:            sizeof(struct sk_ring_data), NULL, BUS_DMA_NOWAIT)) {
        !          1171:                printf(": can't load dma map\n");
        !          1172:                goto fail_3;
        !          1173:        }
        !          1174:         sc_if->sk_rdata = (struct sk_ring_data *)kva;
        !          1175:        bzero(sc_if->sk_rdata, sizeof(struct sk_ring_data));
        !          1176:
        !          1177:        /* Try to allocate memory for jumbo buffers. */
        !          1178:        if (sk_alloc_jumbo_mem(sc_if)) {
        !          1179:                printf(": jumbo buffer allocation failed\n");
        !          1180:                goto fail_3;
        !          1181:        }
        !          1182:
        !          1183:        ifp = &sc_if->arpcom.ac_if;
        !          1184:        ifp->if_softc = sc_if;
        !          1185:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !          1186:        ifp->if_ioctl = sk_ioctl;
        !          1187:        ifp->if_start = sk_start;
        !          1188:        ifp->if_watchdog = sk_watchdog;
        !          1189:        ifp->if_baudrate = 1000000000;
        !          1190:        ifp->if_hardmtu = SK_JUMBO_MTU;
        !          1191:        IFQ_SET_MAXLEN(&ifp->if_snd, SK_TX_RING_CNT - 1);
        !          1192:        IFQ_SET_READY(&ifp->if_snd);
        !          1193:        bcopy(sc_if->sk_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !          1194:
        !          1195:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !          1196:
        !          1197:        /*
        !          1198:         * Do miibus setup.
        !          1199:         */
        !          1200:        switch (sc->sk_type) {
        !          1201:        case SK_GENESIS:
        !          1202:                sk_init_xmac(sc_if);
        !          1203:                break;
        !          1204:        case SK_YUKON:
        !          1205:        case SK_YUKON_LITE:
        !          1206:        case SK_YUKON_LP:
        !          1207:                sk_init_yukon(sc_if);
        !          1208:                break;
        !          1209:        default:
        !          1210:                printf(": unknown device type %d\n", sc->sk_type);
        !          1211:                /* dealloc jumbo on error */
        !          1212:                goto fail_3;
        !          1213:        }
        !          1214:
        !          1215:        DPRINTFN(2, ("sk_attach: 1\n"));
        !          1216:
        !          1217:        sc_if->sk_mii.mii_ifp = ifp;
        !          1218:        if (SK_IS_GENESIS(sc)) {
        !          1219:                sc_if->sk_mii.mii_readreg = sk_xmac_miibus_readreg;
        !          1220:                sc_if->sk_mii.mii_writereg = sk_xmac_miibus_writereg;
        !          1221:                sc_if->sk_mii.mii_statchg = sk_xmac_miibus_statchg;
        !          1222:        } else {
        !          1223:                sc_if->sk_mii.mii_readreg = sk_marv_miibus_readreg;
        !          1224:                sc_if->sk_mii.mii_writereg = sk_marv_miibus_writereg;
        !          1225:                sc_if->sk_mii.mii_statchg = sk_marv_miibus_statchg;
        !          1226:        }
        !          1227:
        !          1228:        ifmedia_init(&sc_if->sk_mii.mii_media, 0,
        !          1229:            sk_ifmedia_upd, sk_ifmedia_sts);
        !          1230:        if (SK_IS_GENESIS(sc)) {
        !          1231:                mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY,
        !          1232:                    MII_OFFSET_ANY, 0);
        !          1233:        } else {
        !          1234:                mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY,
        !          1235:                    MII_OFFSET_ANY, MIIF_DOPAUSE);
        !          1236:        }
        !          1237:        if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) {
        !          1238:                printf("%s: no PHY found!\n", sc_if->sk_dev.dv_xname);
        !          1239:                ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL,
        !          1240:                            0, NULL);
        !          1241:                ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL);
        !          1242:        } else
        !          1243:                ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_AUTO);
        !          1244:
        !          1245:        if (SK_IS_GENESIS(sc)) {
        !          1246:                timeout_set(&sc_if->sk_tick_ch, sk_tick, sc_if);
        !          1247:                timeout_add(&sc_if->sk_tick_ch, hz);
        !          1248:        } else
        !          1249:                timeout_set(&sc_if->sk_tick_ch, sk_yukon_tick, sc_if);
        !          1250:
        !          1251:        /*
        !          1252:         * Call MI attach routines.
        !          1253:         */
        !          1254:        if_attach(ifp);
        !          1255:        ether_ifattach(ifp);
        !          1256:
        !          1257:        shutdownhook_establish(skc_shutdown, sc);
        !          1258:
        !          1259:        DPRINTFN(2, ("sk_attach: end\n"));
        !          1260:        return;
        !          1261:
        !          1262: fail_3:
        !          1263:        bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
        !          1264: fail_2:
        !          1265:        bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct sk_ring_data));
        !          1266: fail_1:
        !          1267:        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !          1268: fail:
        !          1269:        sc->sk_if[sa->skc_port] = NULL;
        !          1270: }
        !          1271:
        !          1272: int
        !          1273: skcprint(void *aux, const char *pnp)
        !          1274: {
        !          1275:        struct skc_attach_args *sa = aux;
        !          1276:
        !          1277:        if (pnp)
        !          1278:                printf("sk port %c at %s",
        !          1279:                    (sa->skc_port == SK_PORT_A) ? 'A' : 'B', pnp);
        !          1280:        else
        !          1281:                printf(" port %c", (sa->skc_port == SK_PORT_A) ? 'A' : 'B');
        !          1282:        return (UNCONF);
        !          1283: }
        !          1284:
        !          1285: /*
        !          1286:  * Attach the interface. Allocate softc structures, do ifmedia
        !          1287:  * setup and ethernet/BPF attach.
        !          1288:  */
        !          1289: void
        !          1290: skc_attach(struct device *parent, struct device *self, void *aux)
        !          1291: {
        !          1292:        struct sk_softc *sc = (struct sk_softc *)self;
        !          1293:        struct pci_attach_args *pa = aux;
        !          1294:        struct skc_attach_args skca;
        !          1295:        pci_chipset_tag_t pc = pa->pa_pc;
        !          1296:        pcireg_t command, memtype;
        !          1297:        pci_intr_handle_t ih;
        !          1298:        const char *intrstr = NULL;
        !          1299:        bus_size_t size;
        !          1300:        u_int8_t skrs;
        !          1301:        char *revstr = NULL;
        !          1302:
        !          1303:        DPRINTFN(2, ("begin skc_attach\n"));
        !          1304:
        !          1305:        /*
        !          1306:         * Handle power management nonsense.
        !          1307:         */
        !          1308:        command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF;
        !          1309:
        !          1310:        if (command == 0x01) {
        !          1311:                command = pci_conf_read(pc, pa->pa_tag, SK_PCI_PWRMGMTCTRL);
        !          1312:                if (command & SK_PSTATE_MASK) {
        !          1313:                        u_int32_t               iobase, membase, irq;
        !          1314:
        !          1315:                        /* Save important PCI config data. */
        !          1316:                        iobase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOIO);
        !          1317:                        membase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOMEM);
        !          1318:                        irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE);
        !          1319:
        !          1320:                        /* Reset the power state. */
        !          1321:                        printf("%s chip is in D%d power mode "
        !          1322:                            "-- setting to D0\n", sc->sk_dev.dv_xname,
        !          1323:                            command & SK_PSTATE_MASK);
        !          1324:                        command &= 0xFFFFFFFC;
        !          1325:                        pci_conf_write(pc, pa->pa_tag,
        !          1326:                            SK_PCI_PWRMGMTCTRL, command);
        !          1327:
        !          1328:                        /* Restore PCI config data. */
        !          1329:                        pci_conf_write(pc, pa->pa_tag, SK_PCI_LOIO, iobase);
        !          1330:                        pci_conf_write(pc, pa->pa_tag, SK_PCI_LOMEM, membase);
        !          1331:                        pci_conf_write(pc, pa->pa_tag, SK_PCI_INTLINE, irq);
        !          1332:                }
        !          1333:        }
        !          1334:
        !          1335:        /*
        !          1336:         * Map control/status registers.
        !          1337:         */
        !          1338:
        !          1339:        memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM);
        !          1340:        switch (memtype) {
        !          1341:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !          1342:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !          1343:                if (pci_mapreg_map(pa, SK_PCI_LOMEM,
        !          1344:                                   memtype, 0, &sc->sk_btag, &sc->sk_bhandle,
        !          1345:                                   NULL, &size, 0) == 0)
        !          1346:                        break;
        !          1347:        default:
        !          1348:                printf(": can't map mem space\n");
        !          1349:                return;
        !          1350:        }
        !          1351:
        !          1352:        sc->sc_dmatag = pa->pa_dmat;
        !          1353:
        !          1354:        sc->sk_type = sk_win_read_1(sc, SK_CHIPVER);
        !          1355:        sc->sk_rev = (sk_win_read_1(sc, SK_CONFIG) >> 4);
        !          1356:
        !          1357:        /* bail out here if chip is not recognized */
        !          1358:        if (! SK_IS_GENESIS(sc) && ! SK_IS_YUKON(sc)) {
        !          1359:                printf(": unknown chip type: %d\n", sc->sk_type);
        !          1360:                goto fail_1;
        !          1361:        }
        !          1362:        DPRINTFN(2, ("skc_attach: allocate interrupt\n"));
        !          1363:
        !          1364:        /* Allocate interrupt */
        !          1365:        if (pci_intr_map(pa, &ih)) {
        !          1366:                printf(": couldn't map interrupt\n");
        !          1367:                goto fail_1;
        !          1368:        }
        !          1369:
        !          1370:        intrstr = pci_intr_string(pc, ih);
        !          1371:        sc->sk_intrhand = pci_intr_establish(pc, ih, IPL_NET, sk_intr, sc,
        !          1372:            self->dv_xname);
        !          1373:        if (sc->sk_intrhand == NULL) {
        !          1374:                printf(": couldn't establish interrupt");
        !          1375:                if (intrstr != NULL)
        !          1376:                        printf(" at %s", intrstr);
        !          1377:                printf("\n");
        !          1378:                goto fail_1;
        !          1379:        }
        !          1380:
        !          1381:        /* Reset the adapter. */
        !          1382:        sk_reset(sc);
        !          1383:
        !          1384:        skrs = sk_win_read_1(sc, SK_EPROM0);
        !          1385:        if (SK_IS_GENESIS(sc)) {
        !          1386:                /* Read and save RAM size and RAMbuffer offset */
        !          1387:                switch(skrs) {
        !          1388:                case SK_RAMSIZE_512K_64:
        !          1389:                        sc->sk_ramsize = 0x80000;
        !          1390:                        sc->sk_rboff = SK_RBOFF_0;
        !          1391:                        break;
        !          1392:                case SK_RAMSIZE_1024K_64:
        !          1393:                        sc->sk_ramsize = 0x100000;
        !          1394:                        sc->sk_rboff = SK_RBOFF_80000;
        !          1395:                        break;
        !          1396:                case SK_RAMSIZE_1024K_128:
        !          1397:                        sc->sk_ramsize = 0x100000;
        !          1398:                        sc->sk_rboff = SK_RBOFF_0;
        !          1399:                        break;
        !          1400:                case SK_RAMSIZE_2048K_128:
        !          1401:                        sc->sk_ramsize = 0x200000;
        !          1402:                        sc->sk_rboff = SK_RBOFF_0;
        !          1403:                        break;
        !          1404:                default:
        !          1405:                        printf(": unknown ram size: %d\n", skrs);
        !          1406:                        goto fail_2;
        !          1407:                        break;
        !          1408:                }
        !          1409:        } else {
        !          1410:                if (skrs == 0x00)
        !          1411:                        sc->sk_ramsize = 0x20000;
        !          1412:                else
        !          1413:                        sc->sk_ramsize = skrs * (1<<12);
        !          1414:                sc->sk_rboff = SK_RBOFF_0;
        !          1415:        }
        !          1416:
        !          1417:        DPRINTFN(2, ("skc_attach: ramsize=%d (%dk), rboff=%d\n",
        !          1418:                     sc->sk_ramsize, sc->sk_ramsize / 1024,
        !          1419:                     sc->sk_rboff));
        !          1420:
        !          1421:        /* Read and save physical media type */
        !          1422:        sc->sk_pmd = sk_win_read_1(sc, SK_PMDTYPE);
        !          1423:
        !          1424:        if (sc->sk_pmd == 'T' || sc->sk_pmd == '1')
        !          1425:                sc->sk_coppertype = 1;
        !          1426:        else
        !          1427:                sc->sk_coppertype = 0;
        !          1428:
        !          1429:        switch (sc->sk_type) {
        !          1430:        case SK_GENESIS:
        !          1431:                sc->sk_name = "GEnesis";
        !          1432:                break;
        !          1433:        case SK_YUKON:
        !          1434:                sc->sk_name = "Yukon";
        !          1435:                break;
        !          1436:        case SK_YUKON_LITE:
        !          1437:                sc->sk_name = "Yukon Lite";
        !          1438:                break;
        !          1439:        case SK_YUKON_LP:
        !          1440:                sc->sk_name = "Yukon LP";
        !          1441:                break;
        !          1442:        default:
        !          1443:                sc->sk_name = "Yukon (Unknown)";
        !          1444:        }
        !          1445:
        !          1446:        /* Yukon Lite Rev A0 needs special test, from sk98lin driver */
        !          1447:        if (sc->sk_type == SK_YUKON || sc->sk_type == SK_YUKON_LP) {
        !          1448:                u_int32_t flashaddr;
        !          1449:                u_int8_t testbyte;
        !          1450:
        !          1451:                flashaddr = sk_win_read_4(sc, SK_EP_ADDR);
        !          1452:
        !          1453:                /* test Flash-Address Register */
        !          1454:                sk_win_write_1(sc, SK_EP_ADDR+3, 0xff);
        !          1455:                testbyte = sk_win_read_1(sc, SK_EP_ADDR+3);
        !          1456:
        !          1457:                if (testbyte != 0) {
        !          1458:                        /* This is a Yukon Lite Rev A0 */
        !          1459:                        sc->sk_type = SK_YUKON_LITE;
        !          1460:                        sc->sk_rev = SK_YUKON_LITE_REV_A0;
        !          1461:                        /* restore Flash-Address Register */
        !          1462:                        sk_win_write_4(sc, SK_EP_ADDR, flashaddr);
        !          1463:                }
        !          1464:        }
        !          1465:
        !          1466:        if (sc->sk_type == SK_YUKON_LITE) {
        !          1467:                switch (sc->sk_rev) {
        !          1468:                case SK_YUKON_LITE_REV_A0:
        !          1469:                        revstr = "A0";
        !          1470:                        break;
        !          1471:                case SK_YUKON_LITE_REV_A1:
        !          1472:                        revstr = "A1";
        !          1473:                        break;
        !          1474:                case SK_YUKON_LITE_REV_A3:
        !          1475:                        revstr = "A3";
        !          1476:                        break;
        !          1477:                default:
        !          1478:                        ;
        !          1479:                }
        !          1480:        }
        !          1481:
        !          1482:        /* Announce the product name. */
        !          1483:        printf(", %s", sc->sk_name);
        !          1484:        if (revstr != NULL)
        !          1485:                printf(" rev. %s", revstr);
        !          1486:        printf(" (0x%x): %s\n", sc->sk_rev, intrstr);
        !          1487:
        !          1488:        sc->sk_macs = 1;
        !          1489:
        !          1490:        if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC))
        !          1491:                sc->sk_macs++;
        !          1492:
        !          1493:        skca.skc_port = SK_PORT_A;
        !          1494:        skca.skc_type = sc->sk_type;
        !          1495:        skca.skc_rev = sc->sk_rev;
        !          1496:        (void)config_found(&sc->sk_dev, &skca, skcprint);
        !          1497:
        !          1498:        if (sc->sk_macs > 1) {
        !          1499:                skca.skc_port = SK_PORT_B;
        !          1500:                skca.skc_type = sc->sk_type;
        !          1501:                skca.skc_rev = sc->sk_rev;
        !          1502:                (void)config_found(&sc->sk_dev, &skca, skcprint);
        !          1503:        }
        !          1504:
        !          1505:        /* Turn on the 'driver is loaded' LED. */
        !          1506:        CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON);
        !          1507:
        !          1508:        return;
        !          1509:
        !          1510: fail_2:
        !          1511:        pci_intr_disestablish(pc, sc->sk_intrhand);
        !          1512: fail_1:
        !          1513:        bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size);
        !          1514: }
        !          1515:
        !          1516: int
        !          1517: sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
        !          1518: {
        !          1519:        struct sk_softc         *sc = sc_if->sk_softc;
        !          1520:        struct sk_tx_desc       *f = NULL;
        !          1521:        u_int32_t               frag, cur, sk_ctl;
        !          1522:        int                     i;
        !          1523:        struct sk_txmap_entry   *entry;
        !          1524:        bus_dmamap_t            txmap;
        !          1525:
        !          1526:        DPRINTFN(2, ("sk_encap\n"));
        !          1527:
        !          1528:        entry = SIMPLEQ_FIRST(&sc_if->sk_txmap_head);
        !          1529:        if (entry == NULL) {
        !          1530:                DPRINTFN(2, ("sk_encap: no txmap available\n"));
        !          1531:                return (ENOBUFS);
        !          1532:        }
        !          1533:        txmap = entry->dmamap;
        !          1534:
        !          1535:        cur = frag = *txidx;
        !          1536:
        !          1537: #ifdef SK_DEBUG
        !          1538:        if (skdebug >= 2)
        !          1539:                sk_dump_mbuf(m_head);
        !          1540: #endif
        !          1541:
        !          1542:        /*
        !          1543:         * Start packing the mbufs in this chain into
        !          1544:         * the fragment pointers. Stop when we run out
        !          1545:         * of fragments or hit the end of the mbuf chain.
        !          1546:         */
        !          1547:        if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head,
        !          1548:            BUS_DMA_NOWAIT)) {
        !          1549:                DPRINTFN(2, ("sk_encap: dmamap failed\n"));
        !          1550:                return (ENOBUFS);
        !          1551:        }
        !          1552:
        !          1553:        if (txmap->dm_nsegs > (SK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) {
        !          1554:                DPRINTFN(2, ("sk_encap: too few descriptors free\n"));
        !          1555:                bus_dmamap_unload(sc->sc_dmatag, txmap);
        !          1556:                return (ENOBUFS);
        !          1557:        }
        !          1558:
        !          1559:        DPRINTFN(2, ("sk_encap: dm_nsegs=%d\n", txmap->dm_nsegs));
        !          1560:
        !          1561:        /* Sync the DMA map. */
        !          1562:        bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize,
        !          1563:            BUS_DMASYNC_PREWRITE);
        !          1564:
        !          1565:        for (i = 0; i < txmap->dm_nsegs; i++) {
        !          1566:                f = &sc_if->sk_rdata->sk_tx_ring[frag];
        !          1567:                f->sk_data_lo = htole32(txmap->dm_segs[i].ds_addr);
        !          1568:                sk_ctl = txmap->dm_segs[i].ds_len | SK_OPCODE_DEFAULT;
        !          1569:                if (i == 0)
        !          1570:                        sk_ctl |= SK_TXCTL_FIRSTFRAG;
        !          1571:                else
        !          1572:                        sk_ctl |= SK_TXCTL_OWN;
        !          1573:                f->sk_ctl = htole32(sk_ctl);
        !          1574:                cur = frag;
        !          1575:                SK_INC(frag, SK_TX_RING_CNT);
        !          1576:        }
        !          1577:
        !          1578:        sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head;
        !          1579:        SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link);
        !          1580:
        !          1581:        sc_if->sk_cdata.sk_tx_map[cur] = entry;
        !          1582:        sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |=
        !          1583:                htole32(SK_TXCTL_LASTFRAG|SK_TXCTL_EOF_INTR);
        !          1584:
        !          1585:        /* Sync descriptors before handing to chip */
        !          1586:        SK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs,
        !          1587:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1588:
        !          1589:        sc_if->sk_rdata->sk_tx_ring[*txidx].sk_ctl |=
        !          1590:                htole32(SK_TXCTL_OWN);
        !          1591:
        !          1592:        /* Sync first descriptor to hand it off */
        !          1593:        SK_CDTXSYNC(sc_if, *txidx, 1, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1594:
        !          1595:        sc_if->sk_cdata.sk_tx_cnt += txmap->dm_nsegs;
        !          1596:
        !          1597: #ifdef SK_DEBUG
        !          1598:        if (skdebug >= 2) {
        !          1599:                struct sk_tx_desc *desc;
        !          1600:                u_int32_t idx;
        !          1601:                for (idx = *txidx; idx != frag; SK_INC(idx, SK_TX_RING_CNT)) {
        !          1602:                        desc = &sc_if->sk_rdata->sk_tx_ring[idx];
        !          1603:                        sk_dump_txdesc(desc, idx);
        !          1604:                }
        !          1605:        }
        !          1606: #endif
        !          1607:
        !          1608:        *txidx = frag;
        !          1609:
        !          1610:        DPRINTFN(2, ("sk_encap: completed successfully\n"));
        !          1611:
        !          1612:        return (0);
        !          1613: }
        !          1614:
        !          1615: void
        !          1616: sk_start(struct ifnet *ifp)
        !          1617: {
        !          1618:         struct sk_if_softc     *sc_if = ifp->if_softc;
        !          1619:         struct sk_softc                *sc = sc_if->sk_softc;
        !          1620:         struct mbuf            *m_head = NULL;
        !          1621:         u_int32_t              idx = sc_if->sk_cdata.sk_tx_prod;
        !          1622:        int                     pkts = 0;
        !          1623:
        !          1624:        DPRINTFN(2, ("sk_start\n"));
        !          1625:
        !          1626:        while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) {
        !          1627:                IFQ_POLL(&ifp->if_snd, m_head);
        !          1628:                if (m_head == NULL)
        !          1629:                        break;
        !          1630:
        !          1631:                /*
        !          1632:                 * Pack the data into the transmit ring. If we
        !          1633:                 * don't have room, set the OACTIVE flag and wait
        !          1634:                 * for the NIC to drain the ring.
        !          1635:                 */
        !          1636:                if (sk_encap(sc_if, m_head, &idx)) {
        !          1637:                        ifp->if_flags |= IFF_OACTIVE;
        !          1638:                        break;
        !          1639:                }
        !          1640:
        !          1641:                /* now we are committed to transmit the packet */
        !          1642:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !          1643:                pkts++;
        !          1644:
        !          1645:                /*
        !          1646:                 * If there's a BPF listener, bounce a copy of this frame
        !          1647:                 * to him.
        !          1648:                 */
        !          1649: #if NBPFILTER > 0
        !          1650:                if (ifp->if_bpf)
        !          1651:                        bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
        !          1652: #endif
        !          1653:        }
        !          1654:        if (pkts == 0)
        !          1655:                return;
        !          1656:
        !          1657:        /* Transmit */
        !          1658:        if (idx != sc_if->sk_cdata.sk_tx_prod) {
        !          1659:                sc_if->sk_cdata.sk_tx_prod = idx;
        !          1660:                CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START);
        !          1661:
        !          1662:                /* Set a timeout in case the chip goes out to lunch. */
        !          1663:                ifp->if_timer = 5;
        !          1664:        }
        !          1665: }
        !          1666:
        !          1667:
        !          1668: void
        !          1669: sk_watchdog(struct ifnet *ifp)
        !          1670: {
        !          1671:        struct sk_if_softc *sc_if = ifp->if_softc;
        !          1672:
        !          1673:        /*
        !          1674:         * Reclaim first as there is a possibility of losing Tx completion
        !          1675:         * interrupts.
        !          1676:         */
        !          1677:        sk_txeof(sc_if);
        !          1678:        if (sc_if->sk_cdata.sk_tx_cnt != 0) {
        !          1679:                printf("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname);
        !          1680:
        !          1681:                ifp->if_oerrors++;
        !          1682:
        !          1683:                sk_init(sc_if);
        !          1684:        }
        !          1685: }
        !          1686:
        !          1687: void
        !          1688: skc_shutdown(void *v)
        !          1689: {
        !          1690:        struct sk_softc         *sc = v;
        !          1691:
        !          1692:        DPRINTFN(2, ("sk_shutdown\n"));
        !          1693:
        !          1694:        /* Turn off the 'driver is loaded' LED. */
        !          1695:        CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF);
        !          1696:
        !          1697:        /*
        !          1698:         * Reset the GEnesis controller. Doing this should also
        !          1699:         * assert the resets on the attached XMAC(s).
        !          1700:         */
        !          1701:        sk_reset(sc);
        !          1702: }
        !          1703:
        !          1704: static __inline int
        !          1705: sk_rxvalid(struct sk_softc *sc, u_int32_t stat, u_int32_t len)
        !          1706: {
        !          1707:        if (sc->sk_type == SK_GENESIS) {
        !          1708:                if ((stat & XM_RXSTAT_ERRFRAME) == XM_RXSTAT_ERRFRAME ||
        !          1709:                    XM_RXSTAT_BYTES(stat) != len)
        !          1710:                        return (0);
        !          1711:        } else {
        !          1712:                if ((stat & (YU_RXSTAT_CRCERR | YU_RXSTAT_LONGERR |
        !          1713:                    YU_RXSTAT_MIIERR | YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC |
        !          1714:                    YU_RXSTAT_JABBER)) != 0 ||
        !          1715:                    (stat & YU_RXSTAT_RXOK) != YU_RXSTAT_RXOK ||
        !          1716:                    YU_RXSTAT_BYTES(stat) != len)
        !          1717:                        return (0);
        !          1718:        }
        !          1719:
        !          1720:        return (1);
        !          1721: }
        !          1722:
        !          1723: void
        !          1724: sk_rxeof(struct sk_if_softc *sc_if)
        !          1725: {
        !          1726:        struct sk_softc         *sc = sc_if->sk_softc;
        !          1727:        struct ifnet            *ifp = &sc_if->arpcom.ac_if;
        !          1728:        struct mbuf             *m;
        !          1729:        struct sk_chain         *cur_rx;
        !          1730:        struct sk_rx_desc       *cur_desc;
        !          1731:        int                     i, cur, total_len = 0;
        !          1732:        u_int32_t               rxstat, sk_ctl;
        !          1733:        bus_dmamap_t            dmamap;
        !          1734:        u_int16_t               csum1, csum2;
        !          1735:
        !          1736:        DPRINTFN(2, ("sk_rxeof\n"));
        !          1737:
        !          1738:        i = sc_if->sk_cdata.sk_rx_prod;
        !          1739:
        !          1740:        for (;;) {
        !          1741:                cur = i;
        !          1742:
        !          1743:                /* Sync the descriptor */
        !          1744:                SK_CDRXSYNC(sc_if, cur,
        !          1745:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1746:
        !          1747:                sk_ctl = letoh32(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl);
        !          1748:                if ((sk_ctl & SK_RXCTL_OWN) != 0) {
        !          1749:                        /* Invalidate the descriptor -- it's not ready yet */
        !          1750:                        SK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_PREREAD);
        !          1751:                        sc_if->sk_cdata.sk_rx_prod = i;
        !          1752:                        break;
        !          1753:                }
        !          1754:
        !          1755:                cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur];
        !          1756:                cur_desc = &sc_if->sk_rdata->sk_rx_ring[cur];
        !          1757:                dmamap = sc_if->sk_cdata.sk_rx_jumbo_map;
        !          1758:
        !          1759:                bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0,
        !          1760:                    dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          1761:
        !          1762:                rxstat = letoh32(cur_desc->sk_xmac_rxstat);
        !          1763:                m = cur_rx->sk_mbuf;
        !          1764:                cur_rx->sk_mbuf = NULL;
        !          1765:                total_len = SK_RXBYTES(letoh32(cur_desc->sk_ctl));
        !          1766:
        !          1767:                csum1 = letoh16(sc_if->sk_rdata->sk_rx_ring[i].sk_csum1);
        !          1768:                csum2 = letoh16(sc_if->sk_rdata->sk_rx_ring[i].sk_csum2);
        !          1769:
        !          1770:                SK_INC(i, SK_RX_RING_CNT);
        !          1771:
        !          1772:                if ((sk_ctl & (SK_RXCTL_STATUS_VALID | SK_RXCTL_FIRSTFRAG |
        !          1773:                    SK_RXCTL_LASTFRAG)) != (SK_RXCTL_STATUS_VALID |
        !          1774:                    SK_RXCTL_FIRSTFRAG | SK_RXCTL_LASTFRAG) ||
        !          1775:                    total_len < SK_MIN_FRAMELEN ||
        !          1776:                    total_len > SK_JUMBO_FRAMELEN ||
        !          1777:                    sk_rxvalid(sc, rxstat, total_len) == 0) {
        !          1778:                        ifp->if_ierrors++;
        !          1779:                        sk_newbuf(sc_if, cur, m, dmamap);
        !          1780:                        continue;
        !          1781:                }
        !          1782:
        !          1783:                /*
        !          1784:                 * Try to allocate a new jumbo buffer. If that
        !          1785:                 * fails, copy the packet to mbufs and put the
        !          1786:                 * jumbo buffer back in the ring so it can be
        !          1787:                 * re-used. If allocating mbufs fails, then we
        !          1788:                 * have to drop the packet.
        !          1789:                 */
        !          1790:                if (sk_newbuf(sc_if, cur, NULL, dmamap) == ENOBUFS) {
        !          1791:                        struct mbuf             *m0;
        !          1792:                        m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
        !          1793:                            total_len + ETHER_ALIGN, 0, ifp, NULL);
        !          1794:                        sk_newbuf(sc_if, cur, m, dmamap);
        !          1795:                        if (m0 == NULL) {
        !          1796:                                ifp->if_ierrors++;
        !          1797:                                continue;
        !          1798:                        }
        !          1799:                        m_adj(m0, ETHER_ALIGN);
        !          1800:                        m = m0;
        !          1801:                } else {
        !          1802:                        m->m_pkthdr.rcvif = ifp;
        !          1803:                        m->m_pkthdr.len = m->m_len = total_len;
        !          1804:                }
        !          1805:
        !          1806:                ifp->if_ipackets++;
        !          1807:
        !          1808:                sk_rxcsum(ifp, m, csum1, csum2);
        !          1809:
        !          1810: #if NBPFILTER > 0
        !          1811:                if (ifp->if_bpf)
        !          1812:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !          1813: #endif
        !          1814:
        !          1815:                /* pass it on. */
        !          1816:                ether_input_mbuf(ifp, m);
        !          1817:        }
        !          1818: }
        !          1819:
        !          1820: void
        !          1821: sk_rxcsum(struct ifnet *ifp, struct mbuf *m, const u_int16_t csum1, const u_int16_t csum2)
        !          1822: {
        !          1823:        struct ether_header *eh;
        !          1824:        struct ip *ip;
        !          1825:        u_int8_t *pp;
        !          1826:        int hlen, len, plen;
        !          1827:        u_int16_t iph_csum, ipo_csum, ipd_csum, csum;
        !          1828:
        !          1829:        pp = mtod(m, u_int8_t *);
        !          1830:        plen = m->m_pkthdr.len;
        !          1831:        if (plen < sizeof(*eh))
        !          1832:                return;
        !          1833:        eh = (struct ether_header *)pp;
        !          1834:        iph_csum = in_cksum_addword(csum1, (~csum2 & 0xffff));
        !          1835:
        !          1836:        if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
        !          1837:                u_int16_t *xp = (u_int16_t *)pp;
        !          1838:
        !          1839:                xp = (u_int16_t *)pp;
        !          1840:                if (xp[1] != htons(ETHERTYPE_IP))
        !          1841:                        return;
        !          1842:                iph_csum = in_cksum_addword(iph_csum, (~xp[0] & 0xffff));
        !          1843:                iph_csum = in_cksum_addword(iph_csum, (~xp[1] & 0xffff));
        !          1844:                xp = (u_int16_t *)(pp + sizeof(struct ip));
        !          1845:                iph_csum = in_cksum_addword(iph_csum, xp[0]);
        !          1846:                iph_csum = in_cksum_addword(iph_csum, xp[1]);
        !          1847:                pp += EVL_ENCAPLEN;
        !          1848:        } else if (eh->ether_type != htons(ETHERTYPE_IP))
        !          1849:                return;
        !          1850:
        !          1851:        pp += sizeof(*eh);
        !          1852:        plen -= sizeof(*eh);
        !          1853:
        !          1854:        ip = (struct ip *)pp;
        !          1855:
        !          1856:        if (ip->ip_v != IPVERSION)
        !          1857:                return;
        !          1858:
        !          1859:        hlen = ip->ip_hl << 2;
        !          1860:        if (hlen < sizeof(struct ip))
        !          1861:                return;
        !          1862:        if (hlen > ntohs(ip->ip_len))
        !          1863:                return;
        !          1864:
        !          1865:        /* Don't deal with truncated or padded packets. */
        !          1866:        if (plen != ntohs(ip->ip_len))
        !          1867:                return;
        !          1868:
        !          1869:        len = hlen - sizeof(struct ip);
        !          1870:        if (len > 0) {
        !          1871:                u_int16_t *p;
        !          1872:
        !          1873:                p = (u_int16_t *)(ip + 1);
        !          1874:                ipo_csum = 0;
        !          1875:                for (ipo_csum = 0; len > 0; len -= sizeof(*p), p++)
        !          1876:                        ipo_csum = in_cksum_addword(ipo_csum, *p);
        !          1877:                iph_csum = in_cksum_addword(iph_csum, ipo_csum);
        !          1878:                ipd_csum = in_cksum_addword(csum2, (~ipo_csum & 0xffff));
        !          1879:        } else
        !          1880:                ipd_csum = csum2;
        !          1881:
        !          1882:        if (iph_csum != 0xffff)
        !          1883:                return;
        !          1884:        m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
        !          1885:
        !          1886:        if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
        !          1887:                return;                 /* ip frag, we're done for now */
        !          1888:
        !          1889:        pp += hlen;
        !          1890:
        !          1891:        /* Only know checksum protocol for udp/tcp */
        !          1892:        if (ip->ip_p == IPPROTO_UDP) {
        !          1893:                struct udphdr *uh = (struct udphdr *)pp;
        !          1894:
        !          1895:                if (uh->uh_sum == 0)    /* udp with no checksum */
        !          1896:                        return;
        !          1897:        } else if (ip->ip_p != IPPROTO_TCP)
        !          1898:                return;
        !          1899:
        !          1900:        csum = in_cksum_phdr(ip->ip_src.s_addr, ip->ip_dst.s_addr,
        !          1901:            htonl(ntohs(ip->ip_len) - hlen + ip->ip_p) + ipd_csum);
        !          1902:        if (csum == 0xffff) {
        !          1903:                m->m_pkthdr.csum_flags |= (ip->ip_p == IPPROTO_TCP) ?
        !          1904:                    M_TCP_CSUM_IN_OK : M_UDP_CSUM_IN_OK;
        !          1905:        }
        !          1906: }
        !          1907:
        !          1908: void
        !          1909: sk_txeof(struct sk_if_softc *sc_if)
        !          1910: {
        !          1911:        struct sk_softc         *sc = sc_if->sk_softc;
        !          1912:        struct sk_tx_desc       *cur_tx;
        !          1913:        struct ifnet            *ifp = &sc_if->arpcom.ac_if;
        !          1914:        u_int32_t               idx, sk_ctl;
        !          1915:        struct sk_txmap_entry   *entry;
        !          1916:
        !          1917:        DPRINTFN(2, ("sk_txeof\n"));
        !          1918:
        !          1919:        /*
        !          1920:         * Go through our tx ring and free mbufs for those
        !          1921:         * frames that have been sent.
        !          1922:         */
        !          1923:        idx = sc_if->sk_cdata.sk_tx_cons;
        !          1924:        while (idx != sc_if->sk_cdata.sk_tx_prod) {
        !          1925:                SK_CDTXSYNC(sc_if, idx, 1,
        !          1926:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !          1927:
        !          1928:                cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx];
        !          1929:                sk_ctl = letoh32(cur_tx->sk_ctl);
        !          1930: #ifdef SK_DEBUG
        !          1931:                if (skdebug >= 2)
        !          1932:                        sk_dump_txdesc(cur_tx, idx);
        !          1933: #endif
        !          1934:                if (sk_ctl & SK_TXCTL_OWN) {
        !          1935:                        SK_CDTXSYNC(sc_if, idx, 1, BUS_DMASYNC_PREREAD);
        !          1936:                        break;
        !          1937:                }
        !          1938:                if (sk_ctl & SK_TXCTL_LASTFRAG)
        !          1939:                        ifp->if_opackets++;
        !          1940:                if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) {
        !          1941:                        entry = sc_if->sk_cdata.sk_tx_map[idx];
        !          1942:
        !          1943:                        m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf);
        !          1944:                        sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL;
        !          1945:
        !          1946:                        bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0,
        !          1947:                            entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1948:
        !          1949:                        bus_dmamap_unload(sc->sc_dmatag, entry->dmamap);
        !          1950:                        SIMPLEQ_INSERT_TAIL(&sc_if->sk_txmap_head, entry,
        !          1951:                                          link);
        !          1952:                        sc_if->sk_cdata.sk_tx_map[idx] = NULL;
        !          1953:                }
        !          1954:                sc_if->sk_cdata.sk_tx_cnt--;
        !          1955:                SK_INC(idx, SK_TX_RING_CNT);
        !          1956:        }
        !          1957:        ifp->if_timer = sc_if->sk_cdata.sk_tx_cnt > 0 ? 5 : 0;
        !          1958:
        !          1959:        if (sc_if->sk_cdata.sk_tx_cnt < SK_TX_RING_CNT - 2)
        !          1960:                ifp->if_flags &= ~IFF_OACTIVE;
        !          1961:
        !          1962:        sc_if->sk_cdata.sk_tx_cons = idx;
        !          1963: }
        !          1964:
        !          1965: void
        !          1966: sk_tick(void *xsc_if)
        !          1967: {
        !          1968:        struct sk_if_softc *sc_if = xsc_if;
        !          1969:        struct mii_data *mii = &sc_if->sk_mii;
        !          1970:        struct ifnet *ifp = &sc_if->arpcom.ac_if;
        !          1971:        int i;
        !          1972:
        !          1973:        DPRINTFN(2, ("sk_tick\n"));
        !          1974:
        !          1975:        if (!(ifp->if_flags & IFF_UP))
        !          1976:                return;
        !          1977:
        !          1978:        if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
        !          1979:                sk_intr_bcom(sc_if);
        !          1980:                return;
        !          1981:        }
        !          1982:
        !          1983:        /*
        !          1984:         * According to SysKonnect, the correct way to verify that
        !          1985:         * the link has come back up is to poll bit 0 of the GPIO
        !          1986:         * register three times. This pin has the signal from the
        !          1987:         * link sync pin connected to it; if we read the same link
        !          1988:         * state 3 times in a row, we know the link is up.
        !          1989:         */
        !          1990:        for (i = 0; i < 3; i++) {
        !          1991:                if (SK_XM_READ_2(sc_if, XM_GPIO) & XM_GPIO_GP0_SET)
        !          1992:                        break;
        !          1993:        }
        !          1994:
        !          1995:        if (i != 3) {
        !          1996:                timeout_add(&sc_if->sk_tick_ch, hz);
        !          1997:                return;
        !          1998:        }
        !          1999:
        !          2000:        /* Turn the GP0 interrupt back on. */
        !          2001:        SK_XM_CLRBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET);
        !          2002:        SK_XM_READ_2(sc_if, XM_ISR);
        !          2003:        mii_tick(mii);
        !          2004:        timeout_del(&sc_if->sk_tick_ch);
        !          2005: }
        !          2006:
        !          2007: void
        !          2008: sk_yukon_tick(void *xsc_if)
        !          2009: {
        !          2010:        struct sk_if_softc *sc_if = xsc_if;
        !          2011:        struct mii_data *mii = &sc_if->sk_mii;
        !          2012:
        !          2013:        mii_tick(mii);
        !          2014:        timeout_add(&sc_if->sk_tick_ch, hz);
        !          2015: }
        !          2016:
        !          2017: void
        !          2018: sk_intr_bcom(struct sk_if_softc *sc_if)
        !          2019: {
        !          2020:        struct mii_data *mii = &sc_if->sk_mii;
        !          2021:        struct ifnet *ifp = &sc_if->arpcom.ac_if;
        !          2022:        int status;
        !          2023:
        !          2024:        DPRINTFN(2, ("sk_intr_bcom\n"));
        !          2025:
        !          2026:        SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
        !          2027:
        !          2028:        /*
        !          2029:         * Read the PHY interrupt register to make sure
        !          2030:         * we clear any pending interrupts.
        !          2031:         */
        !          2032:        status = sk_xmac_miibus_readreg((struct device *)sc_if,
        !          2033:            SK_PHYADDR_BCOM, BRGPHY_MII_ISR);
        !          2034:
        !          2035:        if (!(ifp->if_flags & IFF_RUNNING)) {
        !          2036:                sk_init_xmac(sc_if);
        !          2037:                return;
        !          2038:        }
        !          2039:
        !          2040:        if (status & (BRGPHY_ISR_LNK_CHG|BRGPHY_ISR_AN_PR)) {
        !          2041:                int lstat;
        !          2042:                lstat = sk_xmac_miibus_readreg((struct device *)sc_if,
        !          2043:                    SK_PHYADDR_BCOM, BRGPHY_MII_AUXSTS);
        !          2044:
        !          2045:                if (!(lstat & BRGPHY_AUXSTS_LINK) && sc_if->sk_link) {
        !          2046:                        mii_mediachg(mii);
        !          2047:                        /* Turn off the link LED. */
        !          2048:                        SK_IF_WRITE_1(sc_if, 0,
        !          2049:                            SK_LINKLED1_CTL, SK_LINKLED_OFF);
        !          2050:                        sc_if->sk_link = 0;
        !          2051:                } else if (status & BRGPHY_ISR_LNK_CHG) {
        !          2052:                        sk_xmac_miibus_writereg((struct device *)sc_if,
        !          2053:                            SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFF00);
        !          2054:                        mii_tick(mii);
        !          2055:                        sc_if->sk_link = 1;
        !          2056:                        /* Turn on the link LED. */
        !          2057:                        SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL,
        !          2058:                            SK_LINKLED_ON|SK_LINKLED_LINKSYNC_OFF|
        !          2059:                            SK_LINKLED_BLINK_OFF);
        !          2060:                } else {
        !          2061:                        mii_tick(mii);
        !          2062:                        timeout_add(&sc_if->sk_tick_ch, hz);
        !          2063:                }
        !          2064:        }
        !          2065:
        !          2066:        SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
        !          2067: }
        !          2068:
        !          2069: void
        !          2070: sk_intr_xmac(struct sk_if_softc        *sc_if)
        !          2071: {
        !          2072:        u_int16_t status = SK_XM_READ_2(sc_if, XM_ISR);
        !          2073:
        !          2074:        DPRINTFN(2, ("sk_intr_xmac\n"));
        !          2075:
        !          2076:        if (sc_if->sk_phytype == SK_PHYTYPE_XMAC) {
        !          2077:                if (status & XM_ISR_GP0_SET) {
        !          2078:                        SK_XM_SETBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET);
        !          2079:                        timeout_add(&sc_if->sk_tick_ch, hz);
        !          2080:                }
        !          2081:
        !          2082:                if (status & XM_ISR_AUTONEG_DONE) {
        !          2083:                        timeout_add(&sc_if->sk_tick_ch, hz);
        !          2084:                }
        !          2085:        }
        !          2086:
        !          2087:        if (status & XM_IMR_TX_UNDERRUN)
        !          2088:                SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_TXFIFO);
        !          2089:
        !          2090:        if (status & XM_IMR_RX_OVERRUN)
        !          2091:                SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_RXFIFO);
        !          2092: }
        !          2093:
        !          2094: void
        !          2095: sk_intr_yukon(struct sk_if_softc *sc_if)
        !          2096: {
        !          2097:        u_int8_t status;
        !          2098:
        !          2099:        status = SK_IF_READ_1(sc_if, 0, SK_GMAC_ISR);
        !          2100:        /* RX overrun */
        !          2101:        if ((status & SK_GMAC_INT_RX_OVER) != 0) {
        !          2102:                SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST,
        !          2103:                    SK_RFCTL_RX_FIFO_OVER);
        !          2104:        }
        !          2105:        /* TX underrun */
        !          2106:        if ((status & SK_GMAC_INT_TX_UNDER) != 0) {
        !          2107:                SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST,
        !          2108:                    SK_TFCTL_TX_FIFO_UNDER);
        !          2109:        }
        !          2110:
        !          2111:        DPRINTFN(2, ("sk_intr_yukon status=%#x\n", status));
        !          2112: }
        !          2113:
        !          2114: int
        !          2115: sk_intr(void *xsc)
        !          2116: {
        !          2117:        struct sk_softc         *sc = xsc;
        !          2118:        struct sk_if_softc      *sc_if0 = sc->sk_if[SK_PORT_A];
        !          2119:        struct sk_if_softc      *sc_if1 = sc->sk_if[SK_PORT_B];
        !          2120:        struct ifnet            *ifp0 = NULL, *ifp1 = NULL;
        !          2121:        u_int32_t               status;
        !          2122:        int                     claimed = 0;
        !          2123:
        !          2124:        status = CSR_READ_4(sc, SK_ISSR);
        !          2125:        if (status == 0 || status == 0xffffffff)
        !          2126:                return (0);
        !          2127:
        !          2128:        if (sc_if0 != NULL)
        !          2129:                ifp0 = &sc_if0->arpcom.ac_if;
        !          2130:        if (sc_if1 != NULL)
        !          2131:                ifp1 = &sc_if1->arpcom.ac_if;
        !          2132:
        !          2133:        for (; (status &= sc->sk_intrmask) != 0;) {
        !          2134:                claimed = 1;
        !          2135:
        !          2136:                /* Handle receive interrupts first. */
        !          2137:                if (sc_if0 && (status & SK_ISR_RX1_EOF)) {
        !          2138:                        sk_rxeof(sc_if0);
        !          2139:                        CSR_WRITE_4(sc, SK_BMU_RX_CSR0,
        !          2140:                            SK_RXBMU_CLR_IRQ_EOF|SK_RXBMU_RX_START);
        !          2141:                }
        !          2142:                if (sc_if1 && (status & SK_ISR_RX2_EOF)) {
        !          2143:                        sk_rxeof(sc_if1);
        !          2144:                        CSR_WRITE_4(sc, SK_BMU_RX_CSR1,
        !          2145:                            SK_RXBMU_CLR_IRQ_EOF|SK_RXBMU_RX_START);
        !          2146:                }
        !          2147:
        !          2148:                /* Then transmit interrupts. */
        !          2149:                if (sc_if0 && (status & SK_ISR_TX1_S_EOF)) {
        !          2150:                        sk_txeof(sc_if0);
        !          2151:                        CSR_WRITE_4(sc, SK_BMU_TXS_CSR0,
        !          2152:                            SK_TXBMU_CLR_IRQ_EOF);
        !          2153:                }
        !          2154:                if (sc_if1 && (status & SK_ISR_TX2_S_EOF)) {
        !          2155:                        sk_txeof(sc_if1);
        !          2156:                        CSR_WRITE_4(sc, SK_BMU_TXS_CSR1,
        !          2157:                            SK_TXBMU_CLR_IRQ_EOF);
        !          2158:                }
        !          2159:
        !          2160:                /* Then MAC interrupts. */
        !          2161:                if (sc_if0 && (status & SK_ISR_MAC1) &&
        !          2162:                    (ifp0->if_flags & IFF_RUNNING)) {
        !          2163:                        if (SK_IS_GENESIS(sc))
        !          2164:                                sk_intr_xmac(sc_if0);
        !          2165:                        else
        !          2166:                                sk_intr_yukon(sc_if0);
        !          2167:                }
        !          2168:
        !          2169:                if (sc_if1 && (status & SK_ISR_MAC2) &&
        !          2170:                    (ifp1->if_flags & IFF_RUNNING)) {
        !          2171:                        if (SK_IS_GENESIS(sc))
        !          2172:                                sk_intr_xmac(sc_if1);
        !          2173:                        else
        !          2174:                                sk_intr_yukon(sc_if1);
        !          2175:
        !          2176:                }
        !          2177:
        !          2178:                if (status & SK_ISR_EXTERNAL_REG) {
        !          2179:                        if (sc_if0 != NULL &&
        !          2180:                            sc_if0->sk_phytype == SK_PHYTYPE_BCOM)
        !          2181:                                sk_intr_bcom(sc_if0);
        !          2182:
        !          2183:                        if (sc_if1 != NULL &&
        !          2184:                            sc_if1->sk_phytype == SK_PHYTYPE_BCOM)
        !          2185:                                sk_intr_bcom(sc_if1);
        !          2186:                }
        !          2187:                status = CSR_READ_4(sc, SK_ISSR);
        !          2188:        }
        !          2189:
        !          2190:        CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
        !          2191:
        !          2192:        if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd))
        !          2193:                sk_start(ifp0);
        !          2194:        if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd))
        !          2195:                sk_start(ifp1);
        !          2196:
        !          2197:        return (claimed);
        !          2198: }
        !          2199:
        !          2200: void
        !          2201: sk_init_xmac(struct sk_if_softc        *sc_if)
        !          2202: {
        !          2203:        struct sk_softc         *sc = sc_if->sk_softc;
        !          2204:        struct ifnet            *ifp = &sc_if->arpcom.ac_if;
        !          2205:        struct sk_bcom_hack     bhack[] = {
        !          2206:        { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
        !          2207:        { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
        !          2208:        { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
        !          2209:        { 0, 0 } };
        !          2210:
        !          2211:        DPRINTFN(2, ("sk_init_xmac\n"));
        !          2212:
        !          2213:        /* Unreset the XMAC. */
        !          2214:        SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_UNRESET);
        !          2215:        DELAY(1000);
        !          2216:
        !          2217:        /* Reset the XMAC's internal state. */
        !          2218:        SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
        !          2219:
        !          2220:        /* Save the XMAC II revision */
        !          2221:        sc_if->sk_xmac_rev = XM_XMAC_REV(SK_XM_READ_4(sc_if, XM_DEVID));
        !          2222:
        !          2223:        /*
        !          2224:         * Perform additional initialization for external PHYs,
        !          2225:         * namely for the 1000baseTX cards that use the XMAC's
        !          2226:         * GMII mode.
        !          2227:         */
        !          2228:        if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
        !          2229:                int                     i = 0;
        !          2230:                u_int32_t               val;
        !          2231:
        !          2232:                /* Take PHY out of reset. */
        !          2233:                val = sk_win_read_4(sc, SK_GPIO);
        !          2234:                if (sc_if->sk_port == SK_PORT_A)
        !          2235:                        val |= SK_GPIO_DIR0|SK_GPIO_DAT0;
        !          2236:                else
        !          2237:                        val |= SK_GPIO_DIR2|SK_GPIO_DAT2;
        !          2238:                sk_win_write_4(sc, SK_GPIO, val);
        !          2239:
        !          2240:                /* Enable GMII mode on the XMAC. */
        !          2241:                SK_XM_SETBIT_2(sc_if, XM_HWCFG, XM_HWCFG_GMIIMODE);
        !          2242:
        !          2243:                sk_xmac_miibus_writereg((struct device *)sc_if,
        !          2244:                    SK_PHYADDR_BCOM, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
        !          2245:                DELAY(10000);
        !          2246:                sk_xmac_miibus_writereg((struct device *)sc_if,
        !          2247:                    SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFFF0);
        !          2248:
        !          2249:                /*
        !          2250:                 * Early versions of the BCM5400 apparently have
        !          2251:                 * a bug that requires them to have their reserved
        !          2252:                 * registers initialized to some magic values. I don't
        !          2253:                 * know what the numbers do, I'm just the messenger.
        !          2254:                 */
        !          2255:                if (sk_xmac_miibus_readreg((struct device *)sc_if,
        !          2256:                    SK_PHYADDR_BCOM, 0x03) == 0x6041) {
        !          2257:                        while(bhack[i].reg) {
        !          2258:                                sk_xmac_miibus_writereg((struct device *)sc_if,
        !          2259:                                    SK_PHYADDR_BCOM, bhack[i].reg,
        !          2260:                                    bhack[i].val);
        !          2261:                                i++;
        !          2262:                        }
        !          2263:                }
        !          2264:        }
        !          2265:
        !          2266:        /* Set station address */
        !          2267:        SK_XM_WRITE_2(sc_if, XM_PAR0,
        !          2268:            letoh16(*(u_int16_t *)(&sc_if->arpcom.ac_enaddr[0])));
        !          2269:        SK_XM_WRITE_2(sc_if, XM_PAR1,
        !          2270:            letoh16(*(u_int16_t *)(&sc_if->arpcom.ac_enaddr[2])));
        !          2271:        SK_XM_WRITE_2(sc_if, XM_PAR2,
        !          2272:            letoh16(*(u_int16_t *)(&sc_if->arpcom.ac_enaddr[4])));
        !          2273:        SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_STATION);
        !          2274:
        !          2275:        if (ifp->if_flags & IFF_BROADCAST)
        !          2276:                SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD);
        !          2277:        else
        !          2278:                SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD);
        !          2279:
        !          2280:        /* We don't need the FCS appended to the packet. */
        !          2281:        SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_STRIPFCS);
        !          2282:
        !          2283:        /* We want short frames padded to 60 bytes. */
        !          2284:        SK_XM_SETBIT_2(sc_if, XM_TXCMD, XM_TXCMD_AUTOPAD);
        !          2285:
        !          2286:        /*
        !          2287:         * Enable the reception of all error frames. This is
        !          2288:         * a necessary evil due to the design of the XMAC. The
        !          2289:         * XMAC's receive FIFO is only 8K in size, however jumbo
        !          2290:         * frames can be up to 9000 bytes in length. When bad
        !          2291:         * frame filtering is enabled, the XMAC's RX FIFO operates
        !          2292:         * in 'store and forward' mode. For this to work, the
        !          2293:         * entire frame has to fit into the FIFO, but that means
        !          2294:         * that jumbo frames larger than 8192 bytes will be
        !          2295:         * truncated. Disabling all bad frame filtering causes
        !          2296:         * the RX FIFO to operate in streaming mode, in which
        !          2297:         * case the XMAC will start transfering frames out of the
        !          2298:         * RX FIFO as soon as the FIFO threshold is reached.
        !          2299:         */
        !          2300:        SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_BADFRAMES|
        !          2301:            XM_MODE_RX_GIANTS|XM_MODE_RX_RUNTS|XM_MODE_RX_CRCERRS|
        !          2302:            XM_MODE_RX_INRANGELEN);
        !          2303:
        !          2304:        SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_BIGPKTOK);
        !          2305:
        !          2306:        /*
        !          2307:         * Bump up the transmit threshold. This helps hold off transmit
        !          2308:         * underruns when we're blasting traffic from both ports at once.
        !          2309:         */
        !          2310:        SK_XM_WRITE_2(sc_if, XM_TX_REQTHRESH, SK_XM_TX_FIFOTHRESH);
        !          2311:
        !          2312:        /* Set promiscuous mode */
        !          2313:        sk_setpromisc(sc_if);
        !          2314:
        !          2315:        /* Set multicast filter */
        !          2316:        sk_setmulti(sc_if);
        !          2317:
        !          2318:        /* Clear and enable interrupts */
        !          2319:        SK_XM_READ_2(sc_if, XM_ISR);
        !          2320:        if (sc_if->sk_phytype == SK_PHYTYPE_XMAC)
        !          2321:                SK_XM_WRITE_2(sc_if, XM_IMR, XM_INTRS);
        !          2322:        else
        !          2323:                SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
        !          2324:
        !          2325:        /* Configure MAC arbiter */
        !          2326:        switch(sc_if->sk_xmac_rev) {
        !          2327:        case XM_XMAC_REV_B2:
        !          2328:                sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_B2);
        !          2329:                sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_B2);
        !          2330:                sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_B2);
        !          2331:                sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_B2);
        !          2332:                sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_B2);
        !          2333:                sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_B2);
        !          2334:                sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_B2);
        !          2335:                sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_B2);
        !          2336:                sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2);
        !          2337:                break;
        !          2338:        case XM_XMAC_REV_C1:
        !          2339:                sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_C1);
        !          2340:                sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_C1);
        !          2341:                sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_C1);
        !          2342:                sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_C1);
        !          2343:                sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_C1);
        !          2344:                sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_C1);
        !          2345:                sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_C1);
        !          2346:                sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_C1);
        !          2347:                sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2);
        !          2348:                break;
        !          2349:        default:
        !          2350:                break;
        !          2351:        }
        !          2352:        sk_win_write_2(sc, SK_MACARB_CTL,
        !          2353:            SK_MACARBCTL_UNRESET|SK_MACARBCTL_FASTOE_OFF);
        !          2354:
        !          2355:        sc_if->sk_link = 1;
        !          2356: }
        !          2357:
        !          2358: void sk_init_yukon(struct sk_if_softc *sc_if)
        !          2359: {
        !          2360:        u_int32_t               phy, v;
        !          2361:        u_int16_t               reg;
        !          2362:        struct sk_softc         *sc;
        !          2363:        int                     i;
        !          2364:
        !          2365:        sc = sc_if->sk_softc;
        !          2366:
        !          2367:        DPRINTFN(2, ("sk_init_yukon: start: sk_csr=%#x\n",
        !          2368:                     CSR_READ_4(sc_if->sk_softc, SK_CSR)));
        !          2369:
        !          2370:        if (sc->sk_type == SK_YUKON_LITE &&
        !          2371:            sc->sk_rev >= SK_YUKON_LITE_REV_A3) {
        !          2372:                /*
        !          2373:                 * Workaround code for COMA mode, set PHY reset.
        !          2374:                 * Otherwise it will not correctly take chip out of
        !          2375:                 * powerdown (coma)
        !          2376:                 */
        !          2377:                v = sk_win_read_4(sc, SK_GPIO);
        !          2378:                v |= SK_GPIO_DIR9 | SK_GPIO_DAT9;
        !          2379:                sk_win_write_4(sc, SK_GPIO, v);
        !          2380:        }
        !          2381:
        !          2382:        DPRINTFN(6, ("sk_init_yukon: 1\n"));
        !          2383:
        !          2384:        /* GMAC and GPHY Reset */
        !          2385:        SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET);
        !          2386:        SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET);
        !          2387:        DELAY(1000);
        !          2388:
        !          2389:        DPRINTFN(6, ("sk_init_yukon: 2\n"));
        !          2390:
        !          2391:        if (sc->sk_type == SK_YUKON_LITE &&
        !          2392:            sc->sk_rev >= SK_YUKON_LITE_REV_A3) {
        !          2393:                /*
        !          2394:                 * Workaround code for COMA mode, clear PHY reset
        !          2395:                 */
        !          2396:                v = sk_win_read_4(sc, SK_GPIO);
        !          2397:                v |= SK_GPIO_DIR9;
        !          2398:                v &= ~SK_GPIO_DAT9;
        !          2399:                sk_win_write_4(sc, SK_GPIO, v);
        !          2400:        }
        !          2401:
        !          2402:        phy = SK_GPHY_INT_POL_HI | SK_GPHY_DIS_FC | SK_GPHY_DIS_SLEEP |
        !          2403:                SK_GPHY_ENA_XC | SK_GPHY_ANEG_ALL | SK_GPHY_ENA_PAUSE;
        !          2404:
        !          2405:        if (sc->sk_coppertype)
        !          2406:                phy |= SK_GPHY_COPPER;
        !          2407:        else
        !          2408:                phy |= SK_GPHY_FIBER;
        !          2409:
        !          2410:        DPRINTFN(3, ("sk_init_yukon: phy=%#x\n", phy));
        !          2411:
        !          2412:        SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_SET);
        !          2413:        DELAY(1000);
        !          2414:        SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_CLEAR);
        !          2415:        SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF |
        !          2416:                      SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR);
        !          2417:
        !          2418:        DPRINTFN(3, ("sk_init_yukon: gmac_ctrl=%#x\n",
        !          2419:                     SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL)));
        !          2420:
        !          2421:        DPRINTFN(6, ("sk_init_yukon: 3\n"));
        !          2422:
        !          2423:        /* unused read of the interrupt source register */
        !          2424:        DPRINTFN(6, ("sk_init_yukon: 4\n"));
        !          2425:        SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR);
        !          2426:
        !          2427:        DPRINTFN(6, ("sk_init_yukon: 4a\n"));
        !          2428:        reg = SK_YU_READ_2(sc_if, YUKON_PAR);
        !          2429:        DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg));
        !          2430:
        !          2431:        /* MIB Counter Clear Mode set */
        !          2432:         reg |= YU_PAR_MIB_CLR;
        !          2433:        DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg));
        !          2434:        DPRINTFN(6, ("sk_init_yukon: 4b\n"));
        !          2435:        SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
        !          2436:
        !          2437:        /* MIB Counter Clear Mode clear */
        !          2438:        DPRINTFN(6, ("sk_init_yukon: 5\n"));
        !          2439:         reg &= ~YU_PAR_MIB_CLR;
        !          2440:        SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
        !          2441:
        !          2442:        /* receive control reg */
        !          2443:        DPRINTFN(6, ("sk_init_yukon: 7\n"));
        !          2444:        SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_CRCR);
        !          2445:
        !          2446:        /* transmit parameter register */
        !          2447:        DPRINTFN(6, ("sk_init_yukon: 8\n"));
        !          2448:        SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) |
        !          2449:                      YU_TPR_JAM_IPG(0xb) | YU_TPR_JAM2DATA_IPG(0x1a) );
        !          2450:
        !          2451:        /* serial mode register */
        !          2452:        DPRINTFN(6, ("sk_init_yukon: 9\n"));
        !          2453:        SK_YU_WRITE_2(sc_if, YUKON_SMR, YU_SMR_DATA_BLIND(0x1c) |
        !          2454:                      YU_SMR_MFL_VLAN | YU_SMR_MFL_JUMBO |
        !          2455:                      YU_SMR_IPG_DATA(0x1e));
        !          2456:
        !          2457:        DPRINTFN(6, ("sk_init_yukon: 10\n"));
        !          2458:        /* Setup Yukon's address */
        !          2459:        for (i = 0; i < 3; i++) {
        !          2460:                /* Write Source Address 1 (unicast filter) */
        !          2461:                SK_YU_WRITE_2(sc_if, YUKON_SAL1 + i * 4,
        !          2462:                              sc_if->arpcom.ac_enaddr[i * 2] |
        !          2463:                              sc_if->arpcom.ac_enaddr[i * 2 + 1] << 8);
        !          2464:        }
        !          2465:
        !          2466:        for (i = 0; i < 3; i++) {
        !          2467:                reg = sk_win_read_2(sc_if->sk_softc,
        !          2468:                                    SK_MAC1_0 + i * 2 + sc_if->sk_port * 8);
        !          2469:                SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg);
        !          2470:        }
        !          2471:
        !          2472:        /* Set promiscuous mode */
        !          2473:        sk_setpromisc(sc_if);
        !          2474:
        !          2475:        /* Set multicast filter */
        !          2476:        DPRINTFN(6, ("sk_init_yukon: 11\n"));
        !          2477:        sk_setmulti(sc_if);
        !          2478:
        !          2479:        /* enable interrupt mask for counter overflows */
        !          2480:        DPRINTFN(6, ("sk_init_yukon: 12\n"));
        !          2481:        SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0);
        !          2482:        SK_YU_WRITE_2(sc_if, YUKON_RIMR, 0);
        !          2483:        SK_YU_WRITE_2(sc_if, YUKON_TRIMR, 0);
        !          2484:
        !          2485:        /* Configure RX MAC FIFO Flush Mask */
        !          2486:        v = YU_RXSTAT_FOFL | YU_RXSTAT_CRCERR | YU_RXSTAT_MIIERR |
        !          2487:            YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC | YU_RXSTAT_RUNT |
        !          2488:            YU_RXSTAT_JABBER;
        !          2489:        SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_MASK, v);
        !          2490:
        !          2491:        /* Disable RX MAC FIFO Flush for YUKON-Lite Rev. A0 only */
        !          2492:        if (sc->sk_type == SK_YUKON_LITE && sc->sk_rev == SK_YUKON_LITE_REV_A0)
        !          2493:                v = SK_TFCTL_OPERATION_ON;
        !          2494:        else
        !          2495:                v = SK_TFCTL_OPERATION_ON | SK_RFCTL_FIFO_FLUSH_ON;
        !          2496:        /* Configure RX MAC FIFO */
        !          2497:        SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_CLEAR);
        !          2498:        SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_CTRL_TEST, v);
        !          2499:
        !          2500:        /* Increase flush threshould to 64 bytes */
        !          2501:        SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_THRESHOLD,
        !          2502:            SK_RFCTL_FIFO_THRESHOLD + 1);
        !          2503:
        !          2504:        /* Configure TX MAC FIFO */
        !          2505:        SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_CLEAR);
        !          2506:        SK_IF_WRITE_2(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_OPERATION_ON);
        !          2507:
        !          2508:        DPRINTFN(6, ("sk_init_yukon: end\n"));
        !          2509: }
        !          2510:
        !          2511: /*
        !          2512:  * Note that to properly initialize any part of the GEnesis chip,
        !          2513:  * you first have to take it out of reset mode.
        !          2514:  */
        !          2515: void
        !          2516: sk_init(void *xsc_if)
        !          2517: {
        !          2518:        struct sk_if_softc      *sc_if = xsc_if;
        !          2519:        struct sk_softc         *sc = sc_if->sk_softc;
        !          2520:        struct ifnet            *ifp = &sc_if->arpcom.ac_if;
        !          2521:        struct mii_data         *mii = &sc_if->sk_mii;
        !          2522:        int                     s;
        !          2523:
        !          2524:        DPRINTFN(2, ("sk_init\n"));
        !          2525:
        !          2526:        s = splnet();
        !          2527:
        !          2528:        /* Cancel pending I/O and free all RX/TX buffers. */
        !          2529:        sk_stop(sc_if);
        !          2530:
        !          2531:        if (SK_IS_GENESIS(sc)) {
        !          2532:                /* Configure LINK_SYNC LED */
        !          2533:                SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON);
        !          2534:                SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL,
        !          2535:                              SK_LINKLED_LINKSYNC_ON);
        !          2536:
        !          2537:                /* Configure RX LED */
        !          2538:                SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL,
        !          2539:                              SK_RXLEDCTL_COUNTER_START);
        !          2540:
        !          2541:                /* Configure TX LED */
        !          2542:                SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL,
        !          2543:                              SK_TXLEDCTL_COUNTER_START);
        !          2544:        }
        !          2545:
        !          2546:        /*
        !          2547:         * Configure descriptor poll timer
        !          2548:         *
        !          2549:         * SK-NET GENESIS data sheet says that possibility of losing Start
        !          2550:         * transmit command due to CPU/cache related interim storage problems
        !          2551:         * under certain conditions. The document recommends a polling
        !          2552:         * mechanism to send a Start transmit command to initiate transfer
        !          2553:         * of ready descriptors regulary. To cope with this issue sk(4) now
        !          2554:         * enables descriptor poll timer to initiate descriptor processing
        !          2555:         * periodically as defined by SK_DPT_TIMER_MAX. However sk(4) still
        !          2556:         * issue SK_TXBMU_TX_START to Tx BMU to get fast execution of Tx
        !          2557:         * command instead of waiting for next descriptor polling time.
        !          2558:         * The same rule may apply to Rx side too but it seems that is not
        !          2559:         * needed at the moment.
        !          2560:         * Since sk(4) uses descriptor polling as a last resort there is no
        !          2561:         * need to set smaller polling time than maximum allowable one.
        !          2562:         */
        !          2563:        SK_IF_WRITE_4(sc_if, 0, SK_DPT_INIT, SK_DPT_TIMER_MAX);
        !          2564:
        !          2565:        /* Configure I2C registers */
        !          2566:
        !          2567:        /* Configure XMAC(s) */
        !          2568:        switch (sc->sk_type) {
        !          2569:        case SK_GENESIS:
        !          2570:                sk_init_xmac(sc_if);
        !          2571:                break;
        !          2572:        case SK_YUKON:
        !          2573:        case SK_YUKON_LITE:
        !          2574:        case SK_YUKON_LP:
        !          2575:                sk_init_yukon(sc_if);
        !          2576:                break;
        !          2577:        }
        !          2578:        mii_mediachg(mii);
        !          2579:
        !          2580:        if (SK_IS_GENESIS(sc)) {
        !          2581:                /* Configure MAC FIFOs */
        !          2582:                SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
        !          2583:                SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
        !          2584:                SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
        !          2585:
        !          2586:                SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
        !          2587:                SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
        !          2588:                SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
        !          2589:        }
        !          2590:
        !          2591:        /* Configure transmit arbiter(s) */
        !          2592:        SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL,
        !          2593:            SK_TXARCTL_ON|SK_TXARCTL_FSYNC_ON);
        !          2594:
        !          2595:        /* Configure RAMbuffers */
        !          2596:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_UNRESET);
        !          2597:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_START, sc_if->sk_rx_ramstart);
        !          2598:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_WR_PTR, sc_if->sk_rx_ramstart);
        !          2599:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_RD_PTR, sc_if->sk_rx_ramstart);
        !          2600:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_END, sc_if->sk_rx_ramend);
        !          2601:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_ON);
        !          2602:
        !          2603:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_UNRESET);
        !          2604:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_STORENFWD_ON);
        !          2605:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_START, sc_if->sk_tx_ramstart);
        !          2606:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_WR_PTR, sc_if->sk_tx_ramstart);
        !          2607:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_RD_PTR, sc_if->sk_tx_ramstart);
        !          2608:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_END, sc_if->sk_tx_ramend);
        !          2609:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_ON);
        !          2610:
        !          2611:        /* Configure BMUs */
        !          2612:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_ONLINE);
        !          2613:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_LO,
        !          2614:            SK_RX_RING_ADDR(sc_if, 0));
        !          2615:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_HI, 0);
        !          2616:
        !          2617:        SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_ONLINE);
        !          2618:        SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_LO,
        !          2619:             SK_TX_RING_ADDR(sc_if, 0));
        !          2620:        SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_HI, 0);
        !          2621:
        !          2622:        /* Init descriptors */
        !          2623:        if (sk_init_rx_ring(sc_if) == ENOBUFS) {
        !          2624:                printf("%s: initialization failed: no "
        !          2625:                    "memory for rx buffers\n", sc_if->sk_dev.dv_xname);
        !          2626:                sk_stop(sc_if);
        !          2627:                splx(s);
        !          2628:                return;
        !          2629:        }
        !          2630:
        !          2631:        if (sk_init_tx_ring(sc_if) == ENOBUFS) {
        !          2632:                printf("%s: initialization failed: no "
        !          2633:                    "memory for tx buffers\n", sc_if->sk_dev.dv_xname);
        !          2634:                sk_stop(sc_if);
        !          2635:                splx(s);
        !          2636:                return;
        !          2637:        }
        !          2638:
        !          2639:        /* Configure interrupt handling */
        !          2640:        CSR_READ_4(sc, SK_ISSR);
        !          2641:        if (sc_if->sk_port == SK_PORT_A)
        !          2642:                sc->sk_intrmask |= SK_INTRS1;
        !          2643:        else
        !          2644:                sc->sk_intrmask |= SK_INTRS2;
        !          2645:
        !          2646:        sc->sk_intrmask |= SK_ISR_EXTERNAL_REG;
        !          2647:
        !          2648:        CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
        !          2649:
        !          2650:        /* Start BMUs. */
        !          2651:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_START);
        !          2652:
        !          2653:        if (SK_IS_GENESIS(sc)) {
        !          2654:                /* Enable XMACs TX and RX state machines */
        !          2655:                SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE);
        !          2656:                SK_XM_SETBIT_2(sc_if, XM_MMUCMD,
        !          2657:                               XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
        !          2658:        }
        !          2659:
        !          2660:        if (SK_IS_YUKON(sc)) {
        !          2661:                u_int16_t reg = SK_YU_READ_2(sc_if, YUKON_GPCR);
        !          2662:                reg |= YU_GPCR_TXEN | YU_GPCR_RXEN;
        !          2663:                SK_YU_WRITE_2(sc_if, YUKON_GPCR, reg);
        !          2664:        }
        !          2665:
        !          2666:        /* Activate descriptor polling timer */
        !          2667:        SK_IF_WRITE_4(sc_if, 0, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_START);
        !          2668:        /* start transfer of Tx descriptors */
        !          2669:        CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START);
        !          2670:
        !          2671:        ifp->if_flags |= IFF_RUNNING;
        !          2672:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2673:
        !          2674:        if (SK_IS_YUKON(sc))
        !          2675:                timeout_add(&sc_if->sk_tick_ch, hz);
        !          2676:
        !          2677:        splx(s);
        !          2678: }
        !          2679:
        !          2680: void
        !          2681: sk_stop(struct sk_if_softc *sc_if)
        !          2682: {
        !          2683:        struct sk_softc         *sc = sc_if->sk_softc;
        !          2684:        struct ifnet            *ifp = &sc_if->arpcom.ac_if;
        !          2685:        struct sk_txmap_entry   *dma;
        !          2686:        int                     i;
        !          2687:        u_int32_t               val;
        !          2688:
        !          2689:        DPRINTFN(2, ("sk_stop\n"));
        !          2690:
        !          2691:        timeout_del(&sc_if->sk_tick_ch);
        !          2692:
        !          2693:        ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
        !          2694:
        !          2695:        /* stop Tx descriptor polling timer */
        !          2696:        SK_IF_WRITE_4(sc_if, 0, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_STOP);
        !          2697:        /* stop transfer of Tx descriptors */
        !          2698:        CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_STOP);
        !          2699:        for (i = 0; i < SK_TIMEOUT; i++) {
        !          2700:                val = CSR_READ_4(sc, sc_if->sk_tx_bmu);
        !          2701:                if (!(val & SK_TXBMU_TX_STOP))
        !          2702:                        break;
        !          2703:                DELAY(1);
        !          2704:        }
        !          2705:        if (i == SK_TIMEOUT)
        !          2706:                printf("%s: cannot stop transfer of Tx descriptors\n",
        !          2707:                      sc_if->sk_dev.dv_xname);
        !          2708:        /* stop transfer of Rx descriptors */
        !          2709:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_STOP);
        !          2710:        for (i = 0; i < SK_TIMEOUT; i++) {
        !          2711:                val = SK_IF_READ_4(sc_if, 0, SK_RXQ1_BMU_CSR);
        !          2712:                if (!(val & SK_RXBMU_RX_STOP))
        !          2713:                        break;
        !          2714:                DELAY(1);
        !          2715:        }
        !          2716:        if (i == SK_TIMEOUT)
        !          2717:                printf("%s: cannot stop transfer of Rx descriptors\n",
        !          2718:                      sc_if->sk_dev.dv_xname);
        !          2719:
        !          2720:        if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
        !          2721:                u_int32_t               val;
        !          2722:
        !          2723:                /* Put PHY back into reset. */
        !          2724:                val = sk_win_read_4(sc, SK_GPIO);
        !          2725:                if (sc_if->sk_port == SK_PORT_A) {
        !          2726:                        val |= SK_GPIO_DIR0;
        !          2727:                        val &= ~SK_GPIO_DAT0;
        !          2728:                } else {
        !          2729:                        val |= SK_GPIO_DIR2;
        !          2730:                        val &= ~SK_GPIO_DAT2;
        !          2731:                }
        !          2732:                sk_win_write_4(sc, SK_GPIO, val);
        !          2733:        }
        !          2734:
        !          2735:        /* Turn off various components of this interface. */
        !          2736:        SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
        !          2737:        switch (sc->sk_type) {
        !          2738:        case SK_GENESIS:
        !          2739:                SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL,
        !          2740:                              SK_TXMACCTL_XMAC_RESET);
        !          2741:                SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
        !          2742:                break;
        !          2743:        case SK_YUKON:
        !          2744:        case SK_YUKON_LITE:
        !          2745:        case SK_YUKON_LP:
        !          2746:                SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
        !          2747:                SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
        !          2748:                break;
        !          2749:        }
        !          2750:        SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
        !          2751:        SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
        !          2752:        SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE);
        !          2753:        SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
        !          2754:        SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF);
        !          2755:        SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
        !          2756:        SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
        !          2757:        SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF);
        !          2758:        SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF);
        !          2759:
        !          2760:        /* Disable interrupts */
        !          2761:        if (sc_if->sk_port == SK_PORT_A)
        !          2762:                sc->sk_intrmask &= ~SK_INTRS1;
        !          2763:        else
        !          2764:                sc->sk_intrmask &= ~SK_INTRS2;
        !          2765:        CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
        !          2766:
        !          2767:        SK_XM_READ_2(sc_if, XM_ISR);
        !          2768:        SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
        !          2769:
        !          2770:        /* Free RX and TX mbufs still in the queues. */
        !          2771:        for (i = 0; i < SK_RX_RING_CNT; i++) {
        !          2772:                if (sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf != NULL) {
        !          2773:                        m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf);
        !          2774:                        sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL;
        !          2775:                }
        !          2776:        }
        !          2777:
        !          2778:        for (i = 0; i < SK_TX_RING_CNT; i++) {
        !          2779:                if (sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf != NULL) {
        !          2780:                        m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf);
        !          2781:                        sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL;
        !          2782:                        SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head,
        !          2783:                            sc_if->sk_cdata.sk_tx_map[i], link);
        !          2784:                        sc_if->sk_cdata.sk_tx_map[i] = 0;
        !          2785:                }
        !          2786:        }
        !          2787:
        !          2788:        while ((dma = SIMPLEQ_FIRST(&sc_if->sk_txmap_head))) {
        !          2789:                SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link);
        !          2790:                bus_dmamap_destroy(sc->sc_dmatag, dma->dmamap);
        !          2791:                free(dma, M_DEVBUF);
        !          2792:        }
        !          2793: }
        !          2794:
        !          2795: struct cfattach skc_ca = {
        !          2796:        sizeof(struct sk_softc), skc_probe, skc_attach,
        !          2797: };
        !          2798:
        !          2799: struct cfdriver skc_cd = {
        !          2800:        0, "skc", DV_DULL
        !          2801: };
        !          2802:
        !          2803: struct cfattach sk_ca = {
        !          2804:        sizeof(struct sk_if_softc), sk_probe, sk_attach,
        !          2805: };
        !          2806:
        !          2807: struct cfdriver sk_cd = {
        !          2808:        0, "sk", DV_IFNET
        !          2809: };
        !          2810:
        !          2811: #ifdef SK_DEBUG
        !          2812: void
        !          2813: sk_dump_txdesc(struct sk_tx_desc *desc, int idx)
        !          2814: {
        !          2815: #define DESC_PRINT(X)                                  \
        !          2816:        if (X)                                  \
        !          2817:                printf("txdesc[%d]." #X "=%#x\n",       \
        !          2818:                       idx, X);
        !          2819:
        !          2820:        DESC_PRINT(letoh32(desc->sk_ctl));
        !          2821:        DESC_PRINT(letoh32(desc->sk_next));
        !          2822:        DESC_PRINT(letoh32(desc->sk_data_lo));
        !          2823:        DESC_PRINT(letoh32(desc->sk_data_hi));
        !          2824:        DESC_PRINT(letoh32(desc->sk_xmac_txstat));
        !          2825:        DESC_PRINT(letoh16(desc->sk_rsvd0));
        !          2826:        DESC_PRINT(letoh16(desc->sk_csum_startval));
        !          2827:        DESC_PRINT(letoh16(desc->sk_csum_startpos));
        !          2828:        DESC_PRINT(letoh16(desc->sk_csum_writepos));
        !          2829:        DESC_PRINT(letoh16(desc->sk_rsvd1));
        !          2830: #undef PRINT
        !          2831: }
        !          2832:
        !          2833: void
        !          2834: sk_dump_bytes(const char *data, int len)
        !          2835: {
        !          2836:        int c, i, j;
        !          2837:
        !          2838:        for (i = 0; i < len; i += 16) {
        !          2839:                printf("%08x  ", i);
        !          2840:                c = len - i;
        !          2841:                if (c > 16) c = 16;
        !          2842:
        !          2843:                for (j = 0; j < c; j++) {
        !          2844:                        printf("%02x ", data[i + j] & 0xff);
        !          2845:                        if ((j & 0xf) == 7 && j > 0)
        !          2846:                                printf(" ");
        !          2847:                }
        !          2848:
        !          2849:                for (; j < 16; j++)
        !          2850:                        printf("   ");
        !          2851:                printf("  ");
        !          2852:
        !          2853:                for (j = 0; j < c; j++) {
        !          2854:                        int ch = data[i + j] & 0xff;
        !          2855:                        printf("%c", ' ' <= ch && ch <= '~' ? ch : ' ');
        !          2856:                }
        !          2857:
        !          2858:                printf("\n");
        !          2859:
        !          2860:                if (c < 16)
        !          2861:                        break;
        !          2862:        }
        !          2863: }
        !          2864:
        !          2865: void
        !          2866: sk_dump_mbuf(struct mbuf *m)
        !          2867: {
        !          2868:        int count = m->m_pkthdr.len;
        !          2869:
        !          2870:        printf("m=%#lx, m->m_pkthdr.len=%#d\n", m, m->m_pkthdr.len);
        !          2871:
        !          2872:        while (count > 0 && m) {
        !          2873:                printf("m=%#lx, m->m_data=%#lx, m->m_len=%d\n",
        !          2874:                       m, m->m_data, m->m_len);
        !          2875:                sk_dump_bytes(mtod(m, char *), m->m_len);
        !          2876:
        !          2877:                count -= m->m_len;
        !          2878:                m = m->m_next;
        !          2879:        }
        !          2880: }
        !          2881: #endif

CVSweb