Annotation of sys/dev/pci/if_msk.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_msk.c,v 1.56 2007/06/27 19:15:47 kettenis 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_mskvar.h>
! 133:
! 134: int mskc_probe(struct device *, void *, void *);
! 135: void mskc_attach(struct device *, struct device *self, void *aux);
! 136: void mskc_reset(struct sk_softc *);
! 137: void mskc_shutdown(void *);
! 138: int msk_probe(struct device *, void *, void *);
! 139: void msk_attach(struct device *, struct device *self, void *aux);
! 140: void msk_reset(struct sk_if_softc *);
! 141: int mskcprint(void *, const char *);
! 142: int msk_intr(void *);
! 143: void msk_intr_yukon(struct sk_if_softc *);
! 144: static __inline int msk_rxvalid(struct sk_softc *, u_int32_t, u_int32_t);
! 145: void msk_rxeof(struct sk_if_softc *, u_int16_t, u_int32_t);
! 146: void msk_txeof(struct sk_if_softc *);
! 147: int msk_encap(struct sk_if_softc *, struct mbuf *, u_int32_t *);
! 148: void msk_start(struct ifnet *);
! 149: int msk_ioctl(struct ifnet *, u_long, caddr_t);
! 150: void msk_init(void *);
! 151: void msk_init_yukon(struct sk_if_softc *);
! 152: void msk_stop(struct sk_if_softc *);
! 153: void msk_watchdog(struct ifnet *);
! 154: int msk_ifmedia_upd(struct ifnet *);
! 155: void msk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
! 156: int msk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t);
! 157: int msk_alloc_jumbo_mem(struct sk_if_softc *);
! 158: void *msk_jalloc(struct sk_if_softc *);
! 159: void msk_jfree(caddr_t, u_int, void *);
! 160: int msk_init_rx_ring(struct sk_if_softc *);
! 161: int msk_init_tx_ring(struct sk_if_softc *);
! 162:
! 163: int msk_miibus_readreg(struct device *, int, int);
! 164: void msk_miibus_writereg(struct device *, int, int, int);
! 165: void msk_miibus_statchg(struct device *);
! 166:
! 167: void msk_setfilt(struct sk_if_softc *, caddr_t, int);
! 168: void msk_setmulti(struct sk_if_softc *);
! 169: void msk_setpromisc(struct sk_if_softc *);
! 170: void msk_tick(void *);
! 171:
! 172: #ifdef MSK_DEBUG
! 173: #define DPRINTF(x) if (mskdebug) printf x
! 174: #define DPRINTFN(n,x) if (mskdebug >= (n)) printf x
! 175: int mskdebug = 0;
! 176:
! 177: void msk_dump_txdesc(struct msk_tx_desc *, int);
! 178: void msk_dump_mbuf(struct mbuf *);
! 179: void msk_dump_bytes(const char *, int);
! 180: #else
! 181: #define DPRINTF(x)
! 182: #define DPRINTFN(n,x)
! 183: #endif
! 184:
! 185: /* supported device vendors */
! 186: const struct pci_matchid mskc_devices[] = {
! 187: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE550SX },
! 188: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE550T_B1 },
! 189: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE560SX },
! 190: { PCI_VENDOR_DLINK, PCI_PRODUCT_DLINK_DGE560T },
! 191: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_C032 },
! 192: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_C033 },
! 193: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_C034 },
! 194: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_C036 },
! 195: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_C042 },
! 196: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8021CU },
! 197: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8021X },
! 198: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8022CU },
! 199: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8022X },
! 200: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8035 },
! 201: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8036 },
! 202: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8038 },
! 203: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8039 },
! 204: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8050 },
! 205: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8052 },
! 206: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8053 },
! 207: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8055 },
! 208: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8056 },
! 209: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8058 },
! 210: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8061CU },
! 211: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8061X },
! 212: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8062CU },
! 213: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8062X },
! 214: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8070 },
! 215: { PCI_VENDOR_MARVELL, PCI_PRODUCT_MARVELL_YUKON_8071 },
! 216: { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9Sxx },
! 217: { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9Exx }
! 218: };
! 219:
! 220: static inline u_int32_t
! 221: sk_win_read_4(struct sk_softc *sc, u_int32_t reg)
! 222: {
! 223: return CSR_READ_4(sc, reg);
! 224: }
! 225:
! 226: static inline u_int16_t
! 227: sk_win_read_2(struct sk_softc *sc, u_int32_t reg)
! 228: {
! 229: return CSR_READ_2(sc, reg);
! 230: }
! 231:
! 232: static inline u_int8_t
! 233: sk_win_read_1(struct sk_softc *sc, u_int32_t reg)
! 234: {
! 235: return CSR_READ_1(sc, reg);
! 236: }
! 237:
! 238: static inline void
! 239: sk_win_write_4(struct sk_softc *sc, u_int32_t reg, u_int32_t x)
! 240: {
! 241: CSR_WRITE_4(sc, reg, x);
! 242: }
! 243:
! 244: static inline void
! 245: sk_win_write_2(struct sk_softc *sc, u_int32_t reg, u_int16_t x)
! 246: {
! 247: CSR_WRITE_2(sc, reg, x);
! 248: }
! 249:
! 250: static inline void
! 251: sk_win_write_1(struct sk_softc *sc, u_int32_t reg, u_int8_t x)
! 252: {
! 253: CSR_WRITE_1(sc, reg, x);
! 254: }
! 255:
! 256: int
! 257: msk_miibus_readreg(struct device *dev, int phy, int reg)
! 258: {
! 259: struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
! 260: u_int16_t val;
! 261: int i;
! 262:
! 263: SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
! 264: YU_SMICR_REGAD(reg) | YU_SMICR_OP_READ);
! 265:
! 266: for (i = 0; i < SK_TIMEOUT; i++) {
! 267: DELAY(1);
! 268: val = SK_YU_READ_2(sc_if, YUKON_SMICR);
! 269: if (val & YU_SMICR_READ_VALID)
! 270: break;
! 271: }
! 272:
! 273: if (i == SK_TIMEOUT) {
! 274: printf("%s: phy failed to come ready\n",
! 275: sc_if->sk_dev.dv_xname);
! 276: return (0);
! 277: }
! 278:
! 279: DPRINTFN(9, ("msk_miibus_readreg: i=%d, timeout=%d\n", i,
! 280: SK_TIMEOUT));
! 281:
! 282: val = SK_YU_READ_2(sc_if, YUKON_SMIDR);
! 283:
! 284: DPRINTFN(9, ("msk_miibus_readreg phy=%d, reg=%#x, val=%#x\n",
! 285: phy, reg, val));
! 286:
! 287: return (val);
! 288: }
! 289:
! 290: void
! 291: msk_miibus_writereg(struct device *dev, int phy, int reg, int val)
! 292: {
! 293: struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
! 294: int i;
! 295:
! 296: DPRINTFN(9, ("msk_miibus_writereg phy=%d reg=%#x val=%#x\n",
! 297: phy, reg, val));
! 298:
! 299: SK_YU_WRITE_2(sc_if, YUKON_SMIDR, val);
! 300: SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
! 301: YU_SMICR_REGAD(reg) | YU_SMICR_OP_WRITE);
! 302:
! 303: for (i = 0; i < SK_TIMEOUT; i++) {
! 304: DELAY(1);
! 305: if (!(SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY))
! 306: break;
! 307: }
! 308:
! 309: if (i == SK_TIMEOUT)
! 310: printf("%s: phy write timed out\n", sc_if->sk_dev.dv_xname);
! 311: }
! 312:
! 313: void
! 314: msk_miibus_statchg(struct device *dev)
! 315: {
! 316: struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
! 317: struct mii_data *mii = &sc_if->sk_mii;
! 318: struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
! 319: int gpcr;
! 320:
! 321: gpcr = SK_YU_READ_2(sc_if, YUKON_GPCR);
! 322: gpcr &= (YU_GPCR_TXEN | YU_GPCR_RXEN);
! 323:
! 324: if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
! 325: /* Set speed. */
! 326: gpcr |= YU_GPCR_SPEED_DIS;
! 327: switch (IFM_SUBTYPE(mii->mii_media_active)) {
! 328: case IFM_1000_SX:
! 329: case IFM_1000_LX:
! 330: case IFM_1000_CX:
! 331: case IFM_1000_T:
! 332: gpcr |= (YU_GPCR_GIG | YU_GPCR_SPEED);
! 333: break;
! 334: case IFM_100_TX:
! 335: gpcr |= YU_GPCR_SPEED;
! 336: break;
! 337: }
! 338:
! 339: /* Set duplex. */
! 340: gpcr |= YU_GPCR_DPLX_DIS;
! 341: if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX)
! 342: gpcr |= YU_GPCR_DUPLEX;
! 343:
! 344: /* Disable flow control. */
! 345: gpcr |= YU_GPCR_FCTL_DIS;
! 346: gpcr |= (YU_GPCR_FCTL_TX_DIS | YU_GPCR_FCTL_RX_DIS);
! 347: }
! 348:
! 349: SK_YU_WRITE_2(sc_if, YUKON_GPCR, gpcr);
! 350:
! 351: DPRINTFN(9, ("msk_miibus_statchg: gpcr=%x\n",
! 352: SK_YU_READ_2(((struct sk_if_softc *)dev), YUKON_GPCR)));
! 353: }
! 354:
! 355: void
! 356: msk_setfilt(struct sk_if_softc *sc_if, caddr_t addr, int slot)
! 357: {
! 358: int base = XM_RXFILT_ENTRY(slot);
! 359:
! 360: SK_XM_WRITE_2(sc_if, base, *(u_int16_t *)(&addr[0]));
! 361: SK_XM_WRITE_2(sc_if, base + 2, *(u_int16_t *)(&addr[2]));
! 362: SK_XM_WRITE_2(sc_if, base + 4, *(u_int16_t *)(&addr[4]));
! 363: }
! 364:
! 365: void
! 366: msk_setmulti(struct sk_if_softc *sc_if)
! 367: {
! 368: struct ifnet *ifp= &sc_if->arpcom.ac_if;
! 369: u_int32_t hashes[2] = { 0, 0 };
! 370: int h;
! 371: struct arpcom *ac = &sc_if->arpcom;
! 372: struct ether_multi *enm;
! 373: struct ether_multistep step;
! 374:
! 375: /* First, zot all the existing filters. */
! 376: SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
! 377: SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
! 378: SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
! 379: SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
! 380:
! 381:
! 382: /* Now program new ones. */
! 383: allmulti:
! 384: if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
! 385: hashes[0] = 0xFFFFFFFF;
! 386: hashes[1] = 0xFFFFFFFF;
! 387: } else {
! 388: /* First find the tail of the list. */
! 389: ETHER_FIRST_MULTI(step, ac, enm);
! 390: while (enm != NULL) {
! 391: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
! 392: ETHER_ADDR_LEN)) {
! 393: ifp->if_flags |= IFF_ALLMULTI;
! 394: goto allmulti;
! 395: }
! 396: h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) &
! 397: ((1 << SK_HASH_BITS) - 1);
! 398: if (h < 32)
! 399: hashes[0] |= (1 << h);
! 400: else
! 401: hashes[1] |= (1 << (h - 32));
! 402:
! 403: ETHER_NEXT_MULTI(step, enm);
! 404: }
! 405: }
! 406:
! 407: SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff);
! 408: SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff);
! 409: SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff);
! 410: SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff);
! 411: }
! 412:
! 413: void
! 414: msk_setpromisc(struct sk_if_softc *sc_if)
! 415: {
! 416: struct ifnet *ifp = &sc_if->arpcom.ac_if;
! 417:
! 418: if (ifp->if_flags & IFF_PROMISC)
! 419: SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
! 420: YU_RCR_UFLEN | YU_RCR_MUFLEN);
! 421: else
! 422: SK_YU_SETBIT_2(sc_if, YUKON_RCR,
! 423: YU_RCR_UFLEN | YU_RCR_MUFLEN);
! 424: }
! 425:
! 426: int
! 427: msk_init_rx_ring(struct sk_if_softc *sc_if)
! 428: {
! 429: struct msk_chain_data *cd = &sc_if->sk_cdata;
! 430: struct msk_ring_data *rd = sc_if->sk_rdata;
! 431: int i, nexti;
! 432:
! 433: bzero((char *)rd->sk_rx_ring,
! 434: sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT);
! 435:
! 436: for (i = 0; i < MSK_RX_RING_CNT; i++) {
! 437: cd->sk_rx_chain[i].sk_le = &rd->sk_rx_ring[i];
! 438: if (i == (MSK_RX_RING_CNT - 1))
! 439: nexti = 0;
! 440: else
! 441: nexti = i + 1;
! 442: cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[nexti];
! 443: }
! 444:
! 445: for (i = 0; i < MSK_RX_RING_CNT; i++) {
! 446: if (msk_newbuf(sc_if, i, NULL,
! 447: sc_if->sk_cdata.sk_rx_jumbo_map) == ENOBUFS) {
! 448: printf("%s: failed alloc of %dth mbuf\n",
! 449: sc_if->sk_dev.dv_xname, i);
! 450: return (ENOBUFS);
! 451: }
! 452: }
! 453:
! 454: sc_if->sk_cdata.sk_rx_prod = MSK_RX_RING_CNT - 1;
! 455: sc_if->sk_cdata.sk_rx_cons = 0;
! 456:
! 457: return (0);
! 458: }
! 459:
! 460: int
! 461: msk_init_tx_ring(struct sk_if_softc *sc_if)
! 462: {
! 463: struct sk_softc *sc = sc_if->sk_softc;
! 464: struct msk_chain_data *cd = &sc_if->sk_cdata;
! 465: struct msk_ring_data *rd = sc_if->sk_rdata;
! 466: bus_dmamap_t dmamap;
! 467: struct sk_txmap_entry *entry;
! 468: int i, nexti;
! 469:
! 470: bzero((char *)sc_if->sk_rdata->sk_tx_ring,
! 471: sizeof(struct msk_tx_desc) * MSK_TX_RING_CNT);
! 472:
! 473: SIMPLEQ_INIT(&sc_if->sk_txmap_head);
! 474: for (i = 0; i < MSK_TX_RING_CNT; i++) {
! 475: cd->sk_tx_chain[i].sk_le = &rd->sk_tx_ring[i];
! 476: if (i == (MSK_TX_RING_CNT - 1))
! 477: nexti = 0;
! 478: else
! 479: nexti = i + 1;
! 480: cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[nexti];
! 481:
! 482: if (bus_dmamap_create(sc->sc_dmatag, SK_JLEN, SK_NTXSEG,
! 483: SK_JLEN, 0, BUS_DMA_NOWAIT, &dmamap))
! 484: return (ENOBUFS);
! 485:
! 486: entry = malloc(sizeof(*entry), M_DEVBUF, M_NOWAIT);
! 487: if (!entry) {
! 488: bus_dmamap_destroy(sc->sc_dmatag, dmamap);
! 489: return (ENOBUFS);
! 490: }
! 491: entry->dmamap = dmamap;
! 492: SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head, entry, link);
! 493: }
! 494:
! 495: sc_if->sk_cdata.sk_tx_prod = 0;
! 496: sc_if->sk_cdata.sk_tx_cons = 0;
! 497: sc_if->sk_cdata.sk_tx_cnt = 0;
! 498:
! 499: MSK_CDTXSYNC(sc_if, 0, MSK_TX_RING_CNT,
! 500: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 501:
! 502: return (0);
! 503: }
! 504:
! 505: int
! 506: msk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m,
! 507: bus_dmamap_t dmamap)
! 508: {
! 509: struct mbuf *m_new = NULL;
! 510: struct sk_chain *c;
! 511: struct msk_rx_desc *r;
! 512:
! 513: if (m == NULL) {
! 514: caddr_t buf = NULL;
! 515:
! 516: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
! 517: if (m_new == NULL)
! 518: return (ENOBUFS);
! 519:
! 520: /* Allocate the jumbo buffer */
! 521: buf = msk_jalloc(sc_if);
! 522: if (buf == NULL) {
! 523: m_freem(m_new);
! 524: DPRINTFN(1, ("%s jumbo allocation failed -- packet "
! 525: "dropped!\n", sc_if->arpcom.ac_if.if_xname));
! 526: return (ENOBUFS);
! 527: }
! 528:
! 529: /* Attach the buffer to the mbuf */
! 530: m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
! 531: MEXTADD(m_new, buf, SK_JLEN, 0, msk_jfree, sc_if);
! 532: } else {
! 533: /*
! 534: * We're re-using a previously allocated mbuf;
! 535: * be sure to re-init pointers and lengths to
! 536: * default values.
! 537: */
! 538: m_new = m;
! 539: m_new->m_len = m_new->m_pkthdr.len = SK_JLEN;
! 540: m_new->m_data = m_new->m_ext.ext_buf;
! 541: }
! 542: m_adj(m_new, ETHER_ALIGN);
! 543:
! 544: c = &sc_if->sk_cdata.sk_rx_chain[i];
! 545: r = c->sk_le;
! 546: c->sk_mbuf = m_new;
! 547: r->sk_addr = htole32(dmamap->dm_segs[0].ds_addr +
! 548: (((vaddr_t)m_new->m_data
! 549: - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf)));
! 550: r->sk_len = htole16(SK_JLEN);
! 551: r->sk_ctl = 0;
! 552: r->sk_opcode = SK_Y2_RXOPC_PACKET | SK_Y2_RXOPC_OWN;
! 553:
! 554: MSK_CDRXSYNC(sc_if, i, BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
! 555:
! 556: return (0);
! 557: }
! 558:
! 559: /*
! 560: * Memory management for jumbo frames.
! 561: */
! 562:
! 563: int
! 564: msk_alloc_jumbo_mem(struct sk_if_softc *sc_if)
! 565: {
! 566: struct sk_softc *sc = sc_if->sk_softc;
! 567: caddr_t ptr, kva;
! 568: bus_dma_segment_t seg;
! 569: int i, rseg, state, error;
! 570: struct sk_jpool_entry *entry;
! 571:
! 572: state = error = 0;
! 573:
! 574: /* Grab a big chunk o' storage. */
! 575: if (bus_dmamem_alloc(sc->sc_dmatag, MSK_JMEM, PAGE_SIZE, 0,
! 576: &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 577: printf(": can't alloc rx buffers");
! 578: return (ENOBUFS);
! 579: }
! 580:
! 581: state = 1;
! 582: if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, MSK_JMEM, &kva,
! 583: BUS_DMA_NOWAIT)) {
! 584: printf(": can't map dma buffers (%d bytes)", MSK_JMEM);
! 585: error = ENOBUFS;
! 586: goto out;
! 587: }
! 588:
! 589: state = 2;
! 590: if (bus_dmamap_create(sc->sc_dmatag, MSK_JMEM, 1, MSK_JMEM, 0,
! 591: BUS_DMA_NOWAIT, &sc_if->sk_cdata.sk_rx_jumbo_map)) {
! 592: printf(": can't create dma map");
! 593: error = ENOBUFS;
! 594: goto out;
! 595: }
! 596:
! 597: state = 3;
! 598: if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_cdata.sk_rx_jumbo_map,
! 599: kva, MSK_JMEM, NULL, BUS_DMA_NOWAIT)) {
! 600: printf(": can't load dma map");
! 601: error = ENOBUFS;
! 602: goto out;
! 603: }
! 604:
! 605: state = 4;
! 606: sc_if->sk_cdata.sk_jumbo_buf = (caddr_t)kva;
! 607: DPRINTFN(1,("msk_jumbo_buf = 0x%08X\n", sc_if->sk_cdata.sk_jumbo_buf));
! 608:
! 609: LIST_INIT(&sc_if->sk_jfree_listhead);
! 610: LIST_INIT(&sc_if->sk_jinuse_listhead);
! 611:
! 612: /*
! 613: * Now divide it up into 9K pieces and save the addresses
! 614: * in an array.
! 615: */
! 616: ptr = sc_if->sk_cdata.sk_jumbo_buf;
! 617: for (i = 0; i < MSK_JSLOTS; i++) {
! 618: sc_if->sk_cdata.sk_jslots[i] = ptr;
! 619: ptr += SK_JLEN;
! 620: entry = malloc(sizeof(struct sk_jpool_entry),
! 621: M_DEVBUF, M_NOWAIT);
! 622: if (entry == NULL) {
! 623: sc_if->sk_cdata.sk_jumbo_buf = NULL;
! 624: printf(": no memory for jumbo buffer queue!");
! 625: error = ENOBUFS;
! 626: goto out;
! 627: }
! 628: entry->slot = i;
! 629: LIST_INSERT_HEAD(&sc_if->sk_jfree_listhead,
! 630: entry, jpool_entries);
! 631: }
! 632: out:
! 633: if (error != 0) {
! 634: switch (state) {
! 635: case 4:
! 636: bus_dmamap_unload(sc->sc_dmatag,
! 637: sc_if->sk_cdata.sk_rx_jumbo_map);
! 638: case 3:
! 639: bus_dmamap_destroy(sc->sc_dmatag,
! 640: sc_if->sk_cdata.sk_rx_jumbo_map);
! 641: case 2:
! 642: bus_dmamem_unmap(sc->sc_dmatag, kva, MSK_JMEM);
! 643: case 1:
! 644: bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
! 645: break;
! 646: default:
! 647: break;
! 648: }
! 649: }
! 650:
! 651: return (error);
! 652: }
! 653:
! 654: /*
! 655: * Allocate a jumbo buffer.
! 656: */
! 657: void *
! 658: msk_jalloc(struct sk_if_softc *sc_if)
! 659: {
! 660: struct sk_jpool_entry *entry;
! 661:
! 662: entry = LIST_FIRST(&sc_if->sk_jfree_listhead);
! 663:
! 664: if (entry == NULL)
! 665: return (NULL);
! 666:
! 667: LIST_REMOVE(entry, jpool_entries);
! 668: LIST_INSERT_HEAD(&sc_if->sk_jinuse_listhead, entry, jpool_entries);
! 669: return (sc_if->sk_cdata.sk_jslots[entry->slot]);
! 670: }
! 671:
! 672: /*
! 673: * Release a jumbo buffer.
! 674: */
! 675: void
! 676: msk_jfree(caddr_t buf, u_int size, void *arg)
! 677: {
! 678: struct sk_jpool_entry *entry;
! 679: struct sk_if_softc *sc;
! 680: int i;
! 681:
! 682: /* Extract the softc struct pointer. */
! 683: sc = (struct sk_if_softc *)arg;
! 684:
! 685: if (sc == NULL)
! 686: panic("msk_jfree: can't find softc pointer!");
! 687:
! 688: /* calculate the slot this buffer belongs to */
! 689: i = ((vaddr_t)buf
! 690: - (vaddr_t)sc->sk_cdata.sk_jumbo_buf) / SK_JLEN;
! 691:
! 692: if ((i < 0) || (i >= MSK_JSLOTS))
! 693: panic("msk_jfree: asked to free buffer that we don't manage!");
! 694:
! 695: entry = LIST_FIRST(&sc->sk_jinuse_listhead);
! 696: if (entry == NULL)
! 697: panic("msk_jfree: buffer not in use!");
! 698: entry->slot = i;
! 699: LIST_REMOVE(entry, jpool_entries);
! 700: LIST_INSERT_HEAD(&sc->sk_jfree_listhead, entry, jpool_entries);
! 701: }
! 702:
! 703: /*
! 704: * Set media options.
! 705: */
! 706: int
! 707: msk_ifmedia_upd(struct ifnet *ifp)
! 708: {
! 709: struct sk_if_softc *sc_if = ifp->if_softc;
! 710:
! 711: mii_mediachg(&sc_if->sk_mii);
! 712: return (0);
! 713: }
! 714:
! 715: /*
! 716: * Report current media status.
! 717: */
! 718: void
! 719: msk_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
! 720: {
! 721: struct sk_if_softc *sc_if = ifp->if_softc;
! 722:
! 723: mii_pollstat(&sc_if->sk_mii);
! 724: ifmr->ifm_active = sc_if->sk_mii.mii_media_active;
! 725: ifmr->ifm_status = sc_if->sk_mii.mii_media_status;
! 726: }
! 727:
! 728: int
! 729: msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
! 730: {
! 731: struct sk_if_softc *sc_if = ifp->if_softc;
! 732: struct ifreq *ifr = (struct ifreq *) data;
! 733: struct ifaddr *ifa = (struct ifaddr *) data;
! 734: struct mii_data *mii;
! 735: int s, error = 0;
! 736:
! 737: s = splnet();
! 738:
! 739: if ((error = ether_ioctl(ifp, &sc_if->arpcom, command, data)) > 0) {
! 740: splx(s);
! 741: return (error);
! 742: }
! 743:
! 744: switch(command) {
! 745: case SIOCSIFADDR:
! 746: ifp->if_flags |= IFF_UP;
! 747: if (!(ifp->if_flags & IFF_RUNNING))
! 748: msk_init(sc_if);
! 749: #ifdef INET
! 750: if (ifa->ifa_addr->sa_family == AF_INET)
! 751: arp_ifinit(&sc_if->arpcom, ifa);
! 752: #endif /* INET */
! 753: break;
! 754: case SIOCSIFMTU:
! 755: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
! 756: error = EINVAL;
! 757: else if (ifp->if_mtu != ifr->ifr_mtu)
! 758: ifp->if_mtu = ifr->ifr_mtu;
! 759: break;
! 760: case SIOCSIFFLAGS:
! 761: if (ifp->if_flags & IFF_UP) {
! 762: if (ifp->if_flags & IFF_RUNNING &&
! 763: (sc_if->sk_if_flags ^ ifp->if_flags) &
! 764: IFF_PROMISC) {
! 765: msk_setpromisc(sc_if);
! 766: msk_setmulti(sc_if);
! 767: } else {
! 768: if (!(ifp->if_flags & IFF_RUNNING))
! 769: msk_init(sc_if);
! 770: }
! 771: } else {
! 772: if (ifp->if_flags & IFF_RUNNING)
! 773: msk_stop(sc_if);
! 774: }
! 775: sc_if->sk_if_flags = ifp->if_flags;
! 776: break;
! 777: case SIOCADDMULTI:
! 778: case SIOCDELMULTI:
! 779: error = (command == SIOCADDMULTI) ?
! 780: ether_addmulti(ifr, &sc_if->arpcom) :
! 781: ether_delmulti(ifr, &sc_if->arpcom);
! 782:
! 783: if (error == ENETRESET) {
! 784: /*
! 785: * Multicast list has changed; set the hardware
! 786: * filter accordingly.
! 787: */
! 788: if (ifp->if_flags & IFF_RUNNING)
! 789: msk_setmulti(sc_if);
! 790: error = 0;
! 791: }
! 792: break;
! 793: case SIOCGIFMEDIA:
! 794: case SIOCSIFMEDIA:
! 795: mii = &sc_if->sk_mii;
! 796: error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
! 797: break;
! 798: default:
! 799: error = ENOTTY;
! 800: break;
! 801: }
! 802:
! 803: splx(s);
! 804:
! 805: return (error);
! 806: }
! 807:
! 808: /*
! 809: * Probe for a SysKonnect GEnesis chip. Check the PCI vendor and device
! 810: * IDs against our list and return a device name if we find a match.
! 811: */
! 812: int
! 813: mskc_probe(struct device *parent, void *match, void *aux)
! 814: {
! 815: return (pci_matchbyid((struct pci_attach_args *)aux, mskc_devices,
! 816: sizeof(mskc_devices)/sizeof(mskc_devices[0])));
! 817: }
! 818:
! 819: /*
! 820: * Force the GEnesis into reset, then bring it out of reset.
! 821: */
! 822: void
! 823: mskc_reset(struct sk_softc *sc)
! 824: {
! 825: u_int32_t imtimer_ticks, reg1;
! 826: int reg;
! 827:
! 828: DPRINTFN(2, ("mskc_reset\n"));
! 829:
! 830: CSR_WRITE_1(sc, SK_CSR, SK_CSR_SW_RESET);
! 831: CSR_WRITE_1(sc, SK_CSR, SK_CSR_MASTER_RESET);
! 832:
! 833: DELAY(1000);
! 834: CSR_WRITE_1(sc, SK_CSR, SK_CSR_SW_UNRESET);
! 835: DELAY(2);
! 836: CSR_WRITE_1(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
! 837:
! 838: sk_win_write_1(sc, SK_TESTCTL1, 2);
! 839:
! 840: reg1 = sk_win_read_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG1));
! 841: if (sc->sk_type == SK_YUKON_XL && sc->sk_rev > SK_YUKON_XL_REV_A1)
! 842: reg1 |= (SK_Y2_REG1_PHY1_COMA | SK_Y2_REG1_PHY2_COMA);
! 843: else
! 844: reg1 &= ~(SK_Y2_REG1_PHY1_COMA | SK_Y2_REG1_PHY2_COMA);
! 845: sk_win_write_4(sc, SK_Y2_PCI_REG(SK_PCI_OURREG1), reg1);
! 846:
! 847: if (sc->sk_type == SK_YUKON_XL && sc->sk_rev > SK_YUKON_XL_REV_A1)
! 848: sk_win_write_1(sc, SK_Y2_CLKGATE,
! 849: SK_Y2_CLKGATE_LINK1_GATE_DIS |
! 850: SK_Y2_CLKGATE_LINK2_GATE_DIS |
! 851: SK_Y2_CLKGATE_LINK1_CORE_DIS |
! 852: SK_Y2_CLKGATE_LINK2_CORE_DIS |
! 853: SK_Y2_CLKGATE_LINK1_PCI_DIS | SK_Y2_CLKGATE_LINK2_PCI_DIS);
! 854: else
! 855: sk_win_write_1(sc, SK_Y2_CLKGATE, 0);
! 856:
! 857: CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_SET);
! 858: CSR_WRITE_2(sc, SK_LINK_CTRL + SK_WIN_LEN, SK_LINK_RESET_SET);
! 859: DELAY(1000);
! 860: CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR);
! 861: CSR_WRITE_2(sc, SK_LINK_CTRL + SK_WIN_LEN, SK_LINK_RESET_CLEAR);
! 862:
! 863: sk_win_write_1(sc, SK_TESTCTL1, 1);
! 864:
! 865: DPRINTFN(2, ("mskc_reset: sk_csr=%x\n", CSR_READ_1(sc, SK_CSR)));
! 866: DPRINTFN(2, ("mskc_reset: sk_link_ctrl=%x\n",
! 867: CSR_READ_2(sc, SK_LINK_CTRL)));
! 868:
! 869: /* Disable ASF */
! 870: CSR_WRITE_1(sc, SK_Y2_ASF_CSR, SK_Y2_ASF_RESET);
! 871: CSR_WRITE_2(sc, SK_CSR, SK_CSR_ASF_OFF);
! 872:
! 873: /* Clear I2C IRQ noise */
! 874: CSR_WRITE_4(sc, SK_I2CHWIRQ, 1);
! 875:
! 876: /* Disable hardware timer */
! 877: CSR_WRITE_1(sc, SK_TIMERCTL, SK_IMCTL_STOP);
! 878: CSR_WRITE_1(sc, SK_TIMERCTL, SK_IMCTL_IRQ_CLEAR);
! 879:
! 880: /* Disable descriptor polling */
! 881: CSR_WRITE_4(sc, SK_DPT_TIMER_CTRL, SK_DPT_TCTL_STOP);
! 882:
! 883: /* Disable time stamps */
! 884: CSR_WRITE_1(sc, SK_TSTAMP_CTL, SK_TSTAMP_STOP);
! 885: CSR_WRITE_1(sc, SK_TSTAMP_CTL, SK_TSTAMP_IRQ_CLEAR);
! 886:
! 887: /* Enable RAM interface */
! 888: sk_win_write_1(sc, SK_RAMCTL, SK_RAMCTL_UNRESET);
! 889: for (reg = SK_TO0;reg <= SK_TO11; reg++)
! 890: sk_win_write_1(sc, reg, 36);
! 891: sk_win_write_1(sc, SK_RAMCTL + (SK_WIN_LEN / 2), SK_RAMCTL_UNRESET);
! 892: for (reg = SK_TO0;reg <= SK_TO11; reg++)
! 893: sk_win_write_1(sc, reg + (SK_WIN_LEN / 2), 36);
! 894:
! 895: /*
! 896: * Configure interrupt moderation. The moderation timer
! 897: * defers interrupts specified in the interrupt moderation
! 898: * timer mask based on the timeout specified in the interrupt
! 899: * moderation timer init register. Each bit in the timer
! 900: * register represents one tick, so to specify a timeout in
! 901: * microseconds, we have to multiply by the correct number of
! 902: * ticks-per-microsecond.
! 903: */
! 904: switch (sc->sk_type) {
! 905: case SK_YUKON_EC:
! 906: case SK_YUKON_XL:
! 907: case SK_YUKON_FE:
! 908: imtimer_ticks = SK_IMTIMER_TICKS_YUKON_EC;
! 909: break;
! 910: default:
! 911: imtimer_ticks = SK_IMTIMER_TICKS_YUKON;
! 912: }
! 913:
! 914: /* Reset status ring. */
! 915: bzero((char *)sc->sk_status_ring,
! 916: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc));
! 917: sc->sk_status_idx = 0;
! 918:
! 919: sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_RESET);
! 920: sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_UNRESET);
! 921:
! 922: sk_win_write_2(sc, SK_STAT_BMU_LIDX, MSK_STATUS_RING_CNT - 1);
! 923: sk_win_write_4(sc, SK_STAT_BMU_ADDRLO,
! 924: sc->sk_status_map->dm_segs[0].ds_addr);
! 925: sk_win_write_4(sc, SK_STAT_BMU_ADDRHI,
! 926: (u_int64_t)sc->sk_status_map->dm_segs[0].ds_addr >> 32);
! 927: sk_win_write_2(sc, SK_STAT_BMU_TX_THRESH, 10);
! 928: sk_win_write_1(sc, SK_STAT_BMU_FIFOWM, 16);
! 929: sk_win_write_1(sc, SK_STAT_BMU_FIFOIWM, 16);
! 930:
! 931: #if 0
! 932: sk_win_write_4(sc, SK_Y2_LEV_TIMERINIT, SK_IM_USECS(100));
! 933: sk_win_write_4(sc, 0x0ec0, SK_IM_USECS(1000));
! 934:
! 935: sk_win_write_4(sc, 0x0ed0, SK_IM_USECS(20));
! 936: #else
! 937: sk_win_write_4(sc, SK_Y2_ISR_ITIMERINIT, SK_IM_USECS(4));
! 938: #endif
! 939:
! 940: sk_win_write_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_ON);
! 941:
! 942: sk_win_write_1(sc, SK_Y2_LEV_ITIMERCTL, SK_IMCTL_START);
! 943: sk_win_write_1(sc, SK_Y2_TX_ITIMERCTL, SK_IMCTL_START);
! 944: sk_win_write_1(sc, SK_Y2_ISR_ITIMERCTL, SK_IMCTL_START);
! 945: }
! 946:
! 947: int
! 948: msk_probe(struct device *parent, void *match, void *aux)
! 949: {
! 950: struct skc_attach_args *sa = aux;
! 951:
! 952: if (sa->skc_port != SK_PORT_A && sa->skc_port != SK_PORT_B)
! 953: return (0);
! 954:
! 955: switch (sa->skc_type) {
! 956: case SK_YUKON_XL:
! 957: case SK_YUKON_EC_U:
! 958: case SK_YUKON_EX:
! 959: case SK_YUKON_EC:
! 960: case SK_YUKON_FE:
! 961: return (1);
! 962: }
! 963:
! 964: return (0);
! 965: }
! 966:
! 967: void
! 968: msk_reset(struct sk_if_softc *sc_if)
! 969: {
! 970: /* GMAC and GPHY Reset */
! 971: SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET);
! 972: SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET);
! 973: DELAY(1000);
! 974: SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_CLEAR);
! 975: SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF |
! 976: SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR);
! 977: }
! 978:
! 979: /*
! 980: * Each XMAC chip is attached as a separate logical IP interface.
! 981: * Single port cards will have only one logical interface of course.
! 982: */
! 983: void
! 984: msk_attach(struct device *parent, struct device *self, void *aux)
! 985: {
! 986: struct sk_if_softc *sc_if = (struct sk_if_softc *) self;
! 987: struct sk_softc *sc = (struct sk_softc *)parent;
! 988: struct skc_attach_args *sa = aux;
! 989: struct ifnet *ifp;
! 990: caddr_t kva;
! 991: bus_dma_segment_t seg;
! 992: int i, rseg;
! 993: u_int32_t chunk;
! 994: int mii_flags;
! 995:
! 996: sc_if->sk_port = sa->skc_port;
! 997: sc_if->sk_softc = sc;
! 998: sc->sk_if[sa->skc_port] = sc_if;
! 999:
! 1000: DPRINTFN(2, ("begin msk_attach: port=%d\n", sc_if->sk_port));
! 1001:
! 1002: /*
! 1003: * Get station address for this interface. Note that
! 1004: * dual port cards actually come with three station
! 1005: * addresses: one for each port, plus an extra. The
! 1006: * extra one is used by the SysKonnect driver software
! 1007: * as a 'virtual' station address for when both ports
! 1008: * are operating in failover mode. Currently we don't
! 1009: * use this extra address.
! 1010: */
! 1011: for (i = 0; i < ETHER_ADDR_LEN; i++)
! 1012: sc_if->arpcom.ac_enaddr[i] =
! 1013: sk_win_read_1(sc, SK_MAC0_0 + (sa->skc_port * 8) + i);
! 1014:
! 1015: printf(": address %s\n",
! 1016: ether_sprintf(sc_if->arpcom.ac_enaddr));
! 1017:
! 1018: /*
! 1019: * Set up RAM buffer addresses. The Yukon2 has a small amount
! 1020: * of SRAM on it, somewhere between 4K and 48K. We need to
! 1021: * divide this up between the transmitter and receiver. We
! 1022: * give the receiver 2/3 of the memory (rounded down), and the
! 1023: * transmitter whatever remains.
! 1024: */
! 1025: chunk = (2 * (sc->sk_ramsize / sizeof(u_int64_t)) / 3) & ~0xff;
! 1026: sc_if->sk_rx_ramstart = 0;
! 1027: sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1;
! 1028: chunk = (sc->sk_ramsize / sizeof(u_int64_t)) - chunk;
! 1029: sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1;
! 1030: sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1;
! 1031:
! 1032: DPRINTFN(2, ("msk_attach: rx_ramstart=%#x rx_ramend=%#x\n"
! 1033: " tx_ramstart=%#x tx_ramend=%#x\n",
! 1034: sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend,
! 1035: sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend));
! 1036:
! 1037: /* Allocate the descriptor queues. */
! 1038: if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct msk_ring_data),
! 1039: PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 1040: printf(": can't alloc rx buffers\n");
! 1041: goto fail;
! 1042: }
! 1043: if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
! 1044: sizeof(struct msk_ring_data), &kva, BUS_DMA_NOWAIT)) {
! 1045: printf(": can't map dma buffers (%lu bytes)\n",
! 1046: (ulong)sizeof(struct msk_ring_data));
! 1047: goto fail_1;
! 1048: }
! 1049: if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct msk_ring_data), 1,
! 1050: sizeof(struct msk_ring_data), 0, BUS_DMA_NOWAIT,
! 1051: &sc_if->sk_ring_map)) {
! 1052: printf(": can't create dma map\n");
! 1053: goto fail_2;
! 1054: }
! 1055: if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_ring_map, kva,
! 1056: sizeof(struct msk_ring_data), NULL, BUS_DMA_NOWAIT)) {
! 1057: printf(": can't load dma map\n");
! 1058: goto fail_3;
! 1059: }
! 1060: sc_if->sk_rdata = (struct msk_ring_data *)kva;
! 1061: bzero(sc_if->sk_rdata, sizeof(struct msk_ring_data));
! 1062:
! 1063: /* Try to allocate memory for jumbo buffers. */
! 1064: if (msk_alloc_jumbo_mem(sc_if)) {
! 1065: printf(": jumbo buffer allocation failed\n");
! 1066: goto fail_3;
! 1067: }
! 1068:
! 1069: ifp = &sc_if->arpcom.ac_if;
! 1070: ifp->if_softc = sc_if;
! 1071: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 1072: ifp->if_ioctl = msk_ioctl;
! 1073: ifp->if_start = msk_start;
! 1074: ifp->if_watchdog = msk_watchdog;
! 1075: ifp->if_baudrate = 1000000000;
! 1076: if (sc->sk_type != SK_YUKON_FE)
! 1077: ifp->if_hardmtu = SK_JUMBO_MTU;
! 1078: IFQ_SET_MAXLEN(&ifp->if_snd, MSK_TX_RING_CNT - 1);
! 1079: IFQ_SET_READY(&ifp->if_snd);
! 1080: bcopy(sc_if->sk_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 1081:
! 1082: ifp->if_capabilities = IFCAP_VLAN_MTU;
! 1083:
! 1084: msk_reset(sc_if);
! 1085:
! 1086: /*
! 1087: * Do miibus setup.
! 1088: */
! 1089: msk_init_yukon(sc_if);
! 1090:
! 1091: DPRINTFN(2, ("msk_attach: 1\n"));
! 1092:
! 1093: sc_if->sk_mii.mii_ifp = ifp;
! 1094: sc_if->sk_mii.mii_readreg = msk_miibus_readreg;
! 1095: sc_if->sk_mii.mii_writereg = msk_miibus_writereg;
! 1096: sc_if->sk_mii.mii_statchg = msk_miibus_statchg;
! 1097:
! 1098: ifmedia_init(&sc_if->sk_mii.mii_media, 0,
! 1099: msk_ifmedia_upd, msk_ifmedia_sts);
! 1100: mii_flags = MIIF_DOPAUSE;
! 1101: if (sc->sk_fibertype)
! 1102: mii_flags |= MIIF_HAVEFIBER;
! 1103: mii_attach(self, &sc_if->sk_mii, 0xffffffff, 0,
! 1104: MII_OFFSET_ANY, mii_flags);
! 1105: if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) {
! 1106: printf("%s: no PHY found!\n", sc_if->sk_dev.dv_xname);
! 1107: ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL,
! 1108: 0, NULL);
! 1109: ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL);
! 1110: } else
! 1111: ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_AUTO);
! 1112:
! 1113: timeout_set(&sc_if->sk_tick_ch, msk_tick, sc_if);
! 1114:
! 1115: /*
! 1116: * Call MI attach routines.
! 1117: */
! 1118: if_attach(ifp);
! 1119: ether_ifattach(ifp);
! 1120:
! 1121: shutdownhook_establish(mskc_shutdown, sc);
! 1122:
! 1123: DPRINTFN(2, ("msk_attach: end\n"));
! 1124: return;
! 1125:
! 1126: fail_3:
! 1127: bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
! 1128: fail_2:
! 1129: bus_dmamem_unmap(sc->sc_dmatag, kva, sizeof(struct msk_ring_data));
! 1130: fail_1:
! 1131: bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
! 1132: fail:
! 1133: sc->sk_if[sa->skc_port] = NULL;
! 1134: }
! 1135:
! 1136: int
! 1137: mskcprint(void *aux, const char *pnp)
! 1138: {
! 1139: struct skc_attach_args *sa = aux;
! 1140:
! 1141: if (pnp)
! 1142: printf("sk port %c at %s",
! 1143: (sa->skc_port == SK_PORT_A) ? 'A' : 'B', pnp);
! 1144: else
! 1145: printf(" port %c", (sa->skc_port == SK_PORT_A) ? 'A' : 'B');
! 1146: return (UNCONF);
! 1147: }
! 1148:
! 1149: /*
! 1150: * Attach the interface. Allocate softc structures, do ifmedia
! 1151: * setup and ethernet/BPF attach.
! 1152: */
! 1153: void
! 1154: mskc_attach(struct device *parent, struct device *self, void *aux)
! 1155: {
! 1156: struct sk_softc *sc = (struct sk_softc *)self;
! 1157: struct pci_attach_args *pa = aux;
! 1158: struct skc_attach_args skca;
! 1159: pci_chipset_tag_t pc = pa->pa_pc;
! 1160: pcireg_t command, memtype;
! 1161: pci_intr_handle_t ih;
! 1162: const char *intrstr = NULL;
! 1163: bus_size_t size;
! 1164: u_int8_t hw, pmd;
! 1165: char *revstr = NULL;
! 1166: caddr_t kva;
! 1167: bus_dma_segment_t seg;
! 1168: int rseg;
! 1169:
! 1170: DPRINTFN(2, ("begin mskc_attach\n"));
! 1171:
! 1172: /*
! 1173: * Handle power management nonsense.
! 1174: */
! 1175: command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF;
! 1176:
! 1177: if (command == 0x01) {
! 1178: command = pci_conf_read(pc, pa->pa_tag, SK_PCI_PWRMGMTCTRL);
! 1179: if (command & SK_PSTATE_MASK) {
! 1180: u_int32_t iobase, membase, irq;
! 1181:
! 1182: /* Save important PCI config data. */
! 1183: iobase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOIO);
! 1184: membase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOMEM);
! 1185: irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE);
! 1186:
! 1187: /* Reset the power state. */
! 1188: printf("%s chip is in D%d power mode "
! 1189: "-- setting to D0\n", sc->sk_dev.dv_xname,
! 1190: command & SK_PSTATE_MASK);
! 1191: command &= 0xFFFFFFFC;
! 1192: pci_conf_write(pc, pa->pa_tag,
! 1193: SK_PCI_PWRMGMTCTRL, command);
! 1194:
! 1195: /* Restore PCI config data. */
! 1196: pci_conf_write(pc, pa->pa_tag, SK_PCI_LOIO, iobase);
! 1197: pci_conf_write(pc, pa->pa_tag, SK_PCI_LOMEM, membase);
! 1198: pci_conf_write(pc, pa->pa_tag, SK_PCI_INTLINE, irq);
! 1199: }
! 1200: }
! 1201:
! 1202: /*
! 1203: * Map control/status registers.
! 1204: */
! 1205:
! 1206: memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM);
! 1207: switch (memtype) {
! 1208: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
! 1209: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
! 1210: if (pci_mapreg_map(pa, SK_PCI_LOMEM,
! 1211: memtype, 0, &sc->sk_btag, &sc->sk_bhandle,
! 1212: NULL, &size, 0) == 0)
! 1213: break;
! 1214: default:
! 1215: printf(": can't map mem space\n");
! 1216: return;
! 1217: }
! 1218:
! 1219: sc->sc_dmatag = pa->pa_dmat;
! 1220:
! 1221: sc->sk_type = sk_win_read_1(sc, SK_CHIPVER);
! 1222: sc->sk_rev = (sk_win_read_1(sc, SK_CONFIG) >> 4);
! 1223:
! 1224: /* bail out here if chip is not recognized */
! 1225: if (!(SK_IS_YUKON2(sc))) {
! 1226: printf(": unknown chip type: %d\n", sc->sk_type);
! 1227: goto fail_1;
! 1228: }
! 1229: DPRINTFN(2, ("mskc_attach: allocate interrupt\n"));
! 1230:
! 1231: /* Allocate interrupt */
! 1232: if (pci_intr_map(pa, &ih)) {
! 1233: printf(": couldn't map interrupt\n");
! 1234: goto fail_1;
! 1235: }
! 1236:
! 1237: intrstr = pci_intr_string(pc, ih);
! 1238: sc->sk_intrhand = pci_intr_establish(pc, ih, IPL_NET, msk_intr, sc,
! 1239: self->dv_xname);
! 1240: if (sc->sk_intrhand == NULL) {
! 1241: printf(": couldn't establish interrupt");
! 1242: if (intrstr != NULL)
! 1243: printf(" at %s", intrstr);
! 1244: printf("\n");
! 1245: goto fail_1;
! 1246: }
! 1247:
! 1248: if (bus_dmamem_alloc(sc->sc_dmatag,
! 1249: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc),
! 1250: PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
! 1251: printf(": can't alloc status buffers\n");
! 1252: goto fail_2;
! 1253: }
! 1254:
! 1255: if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
! 1256: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc),
! 1257: &kva, BUS_DMA_NOWAIT)) {
! 1258: printf(": can't map dma buffers (%lu bytes)\n",
! 1259: (ulong)(MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc)));
! 1260: goto fail_3;
! 1261: }
! 1262: if (bus_dmamap_create(sc->sc_dmatag,
! 1263: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 1,
! 1264: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc), 0,
! 1265: BUS_DMA_NOWAIT, &sc->sk_status_map)) {
! 1266: printf(": can't create dma map\n");
! 1267: goto fail_4;
! 1268: }
! 1269: if (bus_dmamap_load(sc->sc_dmatag, sc->sk_status_map, kva,
! 1270: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc),
! 1271: NULL, BUS_DMA_NOWAIT)) {
! 1272: printf(": can't load dma map\n");
! 1273: goto fail_5;
! 1274: }
! 1275: sc->sk_status_ring = (struct msk_status_desc *)kva;
! 1276: bzero(sc->sk_status_ring,
! 1277: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc));
! 1278:
! 1279: /* Reset the adapter. */
! 1280: mskc_reset(sc);
! 1281:
! 1282: sc->sk_ramsize = sk_win_read_1(sc, SK_EPROM0) * 4096;
! 1283: DPRINTFN(2, ("mskc_attach: ramsize=%dK\n", sc->sk_ramsize / 1024));
! 1284:
! 1285: pmd = sk_win_read_1(sc, SK_PMDTYPE);
! 1286: if (pmd == 'L' || pmd == 'S' || pmd == 'P')
! 1287: sc->sk_fibertype = 1;
! 1288:
! 1289: switch (sc->sk_type) {
! 1290: case SK_YUKON_XL:
! 1291: sc->sk_name = "Yukon-2 XL";
! 1292: break;
! 1293: case SK_YUKON_EC_U:
! 1294: sc->sk_name = "Yukon-2 EC Ultra";
! 1295: break;
! 1296: case SK_YUKON_EX:
! 1297: sc->sk_name = "Yukon-2 Extreme";
! 1298: break;
! 1299: case SK_YUKON_EC:
! 1300: sc->sk_name = "Yukon-2 EC";
! 1301: break;
! 1302: case SK_YUKON_FE:
! 1303: sc->sk_name = "Yukon-2 FE";
! 1304: break;
! 1305: default:
! 1306: sc->sk_name = "Yukon (Unknown)";
! 1307: }
! 1308:
! 1309: if (sc->sk_type == SK_YUKON_XL) {
! 1310: switch (sc->sk_rev) {
! 1311: case SK_YUKON_XL_REV_A0:
! 1312: revstr = "A0";
! 1313: break;
! 1314: case SK_YUKON_XL_REV_A1:
! 1315: revstr = "A1";
! 1316: break;
! 1317: case SK_YUKON_XL_REV_A2:
! 1318: revstr = "A2";
! 1319: break;
! 1320: case SK_YUKON_XL_REV_A3:
! 1321: revstr = "A3";
! 1322: break;
! 1323: default:
! 1324: ;
! 1325: }
! 1326: }
! 1327:
! 1328: if (sc->sk_type == SK_YUKON_EC) {
! 1329: switch (sc->sk_rev) {
! 1330: case SK_YUKON_EC_REV_A1:
! 1331: revstr = "A1";
! 1332: break;
! 1333: case SK_YUKON_EC_REV_A2:
! 1334: revstr = "A2";
! 1335: break;
! 1336: case SK_YUKON_EC_REV_A3:
! 1337: revstr = "A3";
! 1338: break;
! 1339: default:
! 1340: ;
! 1341: }
! 1342: }
! 1343:
! 1344: if (sc->sk_type == SK_YUKON_EC_U) {
! 1345: switch (sc->sk_rev) {
! 1346: case SK_YUKON_EC_U_REV_A0:
! 1347: revstr = "A0";
! 1348: break;
! 1349: case SK_YUKON_EC_U_REV_A1:
! 1350: revstr = "A1";
! 1351: break;
! 1352: default:
! 1353: ;
! 1354: }
! 1355: }
! 1356:
! 1357: /* Announce the product name. */
! 1358: printf(", %s", sc->sk_name);
! 1359: if (revstr != NULL)
! 1360: printf(" rev. %s", revstr);
! 1361: printf(" (0x%x): %s\n", sc->sk_rev, intrstr);
! 1362:
! 1363: sc->sk_macs = 1;
! 1364:
! 1365: hw = sk_win_read_1(sc, SK_Y2_HWRES);
! 1366: if ((hw & SK_Y2_HWRES_LINK_MASK) == SK_Y2_HWRES_LINK_DUAL) {
! 1367: if ((sk_win_read_1(sc, SK_Y2_CLKGATE) &
! 1368: SK_Y2_CLKGATE_LINK2_INACTIVE) == 0)
! 1369: sc->sk_macs++;
! 1370: }
! 1371:
! 1372: skca.skc_port = SK_PORT_A;
! 1373: skca.skc_type = sc->sk_type;
! 1374: skca.skc_rev = sc->sk_rev;
! 1375: (void)config_found(&sc->sk_dev, &skca, mskcprint);
! 1376:
! 1377: if (sc->sk_macs > 1) {
! 1378: skca.skc_port = SK_PORT_B;
! 1379: skca.skc_type = sc->sk_type;
! 1380: skca.skc_rev = sc->sk_rev;
! 1381: (void)config_found(&sc->sk_dev, &skca, mskcprint);
! 1382: }
! 1383:
! 1384: /* Turn on the 'driver is loaded' LED. */
! 1385: CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON);
! 1386:
! 1387: return;
! 1388:
! 1389: fail_5:
! 1390: bus_dmamap_destroy(sc->sc_dmatag, sc->sk_status_map);
! 1391: fail_4:
! 1392: bus_dmamem_unmap(sc->sc_dmatag, kva,
! 1393: MSK_STATUS_RING_CNT * sizeof(struct msk_status_desc));
! 1394: fail_3:
! 1395: bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
! 1396: fail_2:
! 1397: pci_intr_disestablish(pc, sc->sk_intrhand);
! 1398: fail_1:
! 1399: bus_space_unmap(sc->sk_btag, sc->sk_bhandle, size);
! 1400: }
! 1401:
! 1402: int
! 1403: msk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
! 1404: {
! 1405: struct sk_softc *sc = sc_if->sk_softc;
! 1406: struct msk_tx_desc *f = NULL;
! 1407: u_int32_t frag, cur;
! 1408: int i;
! 1409: struct sk_txmap_entry *entry;
! 1410: bus_dmamap_t txmap;
! 1411:
! 1412: DPRINTFN(2, ("msk_encap\n"));
! 1413:
! 1414: entry = SIMPLEQ_FIRST(&sc_if->sk_txmap_head);
! 1415: if (entry == NULL) {
! 1416: DPRINTFN(2, ("msk_encap: no txmap available\n"));
! 1417: return (ENOBUFS);
! 1418: }
! 1419: txmap = entry->dmamap;
! 1420:
! 1421: cur = frag = *txidx;
! 1422:
! 1423: #ifdef MSK_DEBUG
! 1424: if (mskdebug >= 2)
! 1425: msk_dump_mbuf(m_head);
! 1426: #endif
! 1427:
! 1428: /*
! 1429: * Start packing the mbufs in this chain into
! 1430: * the fragment pointers. Stop when we run out
! 1431: * of fragments or hit the end of the mbuf chain.
! 1432: */
! 1433: if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head,
! 1434: BUS_DMA_NOWAIT)) {
! 1435: DPRINTFN(2, ("msk_encap: dmamap failed\n"));
! 1436: return (ENOBUFS);
! 1437: }
! 1438:
! 1439: if (txmap->dm_nsegs > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) {
! 1440: DPRINTFN(2, ("msk_encap: too few descriptors free\n"));
! 1441: bus_dmamap_unload(sc->sc_dmatag, txmap);
! 1442: return (ENOBUFS);
! 1443: }
! 1444:
! 1445: DPRINTFN(2, ("msk_encap: dm_nsegs=%d\n", txmap->dm_nsegs));
! 1446:
! 1447: /* Sync the DMA map. */
! 1448: bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize,
! 1449: BUS_DMASYNC_PREWRITE);
! 1450:
! 1451: for (i = 0; i < txmap->dm_nsegs; i++) {
! 1452: f = &sc_if->sk_rdata->sk_tx_ring[frag];
! 1453: f->sk_addr = htole32(txmap->dm_segs[i].ds_addr);
! 1454: f->sk_len = htole16(txmap->dm_segs[i].ds_len);
! 1455: f->sk_ctl = 0;
! 1456: if (i == 0)
! 1457: f->sk_opcode = SK_Y2_TXOPC_PACKET;
! 1458: else
! 1459: f->sk_opcode = SK_Y2_TXOPC_BUFFER | SK_Y2_TXOPC_OWN;
! 1460: cur = frag;
! 1461: SK_INC(frag, MSK_TX_RING_CNT);
! 1462: }
! 1463:
! 1464: sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head;
! 1465: SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link);
! 1466:
! 1467: sc_if->sk_cdata.sk_tx_map[cur] = entry;
! 1468: sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= SK_Y2_TXCTL_LASTFRAG;
! 1469:
! 1470: /* Sync descriptors before handing to chip */
! 1471: MSK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs,
! 1472: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1473:
! 1474: sc_if->sk_rdata->sk_tx_ring[*txidx].sk_opcode |= SK_Y2_TXOPC_OWN;
! 1475:
! 1476: /* Sync first descriptor to hand it off */
! 1477: MSK_CDTXSYNC(sc_if, *txidx, 1,
! 1478: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 1479:
! 1480: sc_if->sk_cdata.sk_tx_cnt += txmap->dm_nsegs;
! 1481:
! 1482: #ifdef MSK_DEBUG
! 1483: if (mskdebug >= 2) {
! 1484: struct msk_tx_desc *le;
! 1485: u_int32_t idx;
! 1486: for (idx = *txidx; idx != frag; SK_INC(idx, MSK_TX_RING_CNT)) {
! 1487: le = &sc_if->sk_rdata->sk_tx_ring[idx];
! 1488: msk_dump_txdesc(le, idx);
! 1489: }
! 1490: }
! 1491: #endif
! 1492:
! 1493: *txidx = frag;
! 1494:
! 1495: DPRINTFN(2, ("msk_encap: completed successfully\n"));
! 1496:
! 1497: return (0);
! 1498: }
! 1499:
! 1500: void
! 1501: msk_start(struct ifnet *ifp)
! 1502: {
! 1503: struct sk_if_softc *sc_if = ifp->if_softc;
! 1504: struct mbuf *m_head = NULL;
! 1505: u_int32_t idx = sc_if->sk_cdata.sk_tx_prod;
! 1506: int pkts = 0;
! 1507:
! 1508: DPRINTFN(2, ("msk_start\n"));
! 1509:
! 1510: while (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) {
! 1511: IFQ_POLL(&ifp->if_snd, m_head);
! 1512: if (m_head == NULL)
! 1513: break;
! 1514:
! 1515: /*
! 1516: * Pack the data into the transmit ring. If we
! 1517: * don't have room, set the OACTIVE flag and wait
! 1518: * for the NIC to drain the ring.
! 1519: */
! 1520: if (msk_encap(sc_if, m_head, &idx)) {
! 1521: ifp->if_flags |= IFF_OACTIVE;
! 1522: break;
! 1523: }
! 1524:
! 1525: /* now we are committed to transmit the packet */
! 1526: IFQ_DEQUEUE(&ifp->if_snd, m_head);
! 1527: pkts++;
! 1528:
! 1529: /*
! 1530: * If there's a BPF listener, bounce a copy of this frame
! 1531: * to him.
! 1532: */
! 1533: #if NBPFILTER > 0
! 1534: if (ifp->if_bpf)
! 1535: bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
! 1536: #endif
! 1537: }
! 1538: if (pkts == 0)
! 1539: return;
! 1540:
! 1541: /* Transmit */
! 1542: if (idx != sc_if->sk_cdata.sk_tx_prod) {
! 1543: sc_if->sk_cdata.sk_tx_prod = idx;
! 1544: SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_PUTIDX, idx);
! 1545:
! 1546: /* Set a timeout in case the chip goes out to lunch. */
! 1547: ifp->if_timer = 5;
! 1548: }
! 1549: }
! 1550:
! 1551: void
! 1552: msk_watchdog(struct ifnet *ifp)
! 1553: {
! 1554: struct sk_if_softc *sc_if = ifp->if_softc;
! 1555:
! 1556: /*
! 1557: * Reclaim first as there is a possibility of losing Tx completion
! 1558: * interrupts.
! 1559: */
! 1560: msk_txeof(sc_if);
! 1561: if (sc_if->sk_cdata.sk_tx_cnt != 0) {
! 1562: printf("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname);
! 1563:
! 1564: ifp->if_oerrors++;
! 1565:
! 1566: /* XXX Resets both ports; we shouldn't do that. */
! 1567: mskc_reset(sc_if->sk_softc);
! 1568: msk_reset(sc_if);
! 1569: msk_init(sc_if);
! 1570: }
! 1571: }
! 1572:
! 1573: void
! 1574: mskc_shutdown(void *v)
! 1575: {
! 1576: struct sk_softc *sc = v;
! 1577:
! 1578: DPRINTFN(2, ("msk_shutdown\n"));
! 1579:
! 1580: /* Turn off the 'driver is loaded' LED. */
! 1581: CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF);
! 1582:
! 1583: /*
! 1584: * Reset the GEnesis controller. Doing this should also
! 1585: * assert the resets on the attached XMAC(s).
! 1586: */
! 1587: mskc_reset(sc);
! 1588: }
! 1589:
! 1590: static __inline int
! 1591: msk_rxvalid(struct sk_softc *sc, u_int32_t stat, u_int32_t len)
! 1592: {
! 1593: if ((stat & (YU_RXSTAT_CRCERR | YU_RXSTAT_LONGERR |
! 1594: YU_RXSTAT_MIIERR | YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC |
! 1595: YU_RXSTAT_JABBER)) != 0 ||
! 1596: (stat & YU_RXSTAT_RXOK) != YU_RXSTAT_RXOK ||
! 1597: YU_RXSTAT_BYTES(stat) != len)
! 1598: return (0);
! 1599:
! 1600: return (1);
! 1601: }
! 1602:
! 1603: void
! 1604: msk_rxeof(struct sk_if_softc *sc_if, u_int16_t len, u_int32_t rxstat)
! 1605: {
! 1606: struct sk_softc *sc = sc_if->sk_softc;
! 1607: struct ifnet *ifp = &sc_if->arpcom.ac_if;
! 1608: struct mbuf *m;
! 1609: struct sk_chain *cur_rx;
! 1610: int cur, total_len = len;
! 1611: bus_dmamap_t dmamap;
! 1612:
! 1613: DPRINTFN(2, ("msk_rxeof\n"));
! 1614:
! 1615: cur = sc_if->sk_cdata.sk_rx_cons;
! 1616: SK_INC(sc_if->sk_cdata.sk_rx_cons, MSK_RX_RING_CNT);
! 1617: SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT);
! 1618:
! 1619: /* Sync the descriptor */
! 1620: MSK_CDRXSYNC(sc_if, cur, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1621:
! 1622: cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur];
! 1623: dmamap = sc_if->sk_cdata.sk_rx_jumbo_map;
! 1624:
! 1625: bus_dmamap_sync(sc_if->sk_softc->sc_dmatag, dmamap, 0,
! 1626: dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
! 1627:
! 1628: m = cur_rx->sk_mbuf;
! 1629: cur_rx->sk_mbuf = NULL;
! 1630:
! 1631: if (total_len < SK_MIN_FRAMELEN ||
! 1632: total_len > SK_JUMBO_FRAMELEN ||
! 1633: msk_rxvalid(sc, rxstat, total_len) == 0) {
! 1634: ifp->if_ierrors++;
! 1635: msk_newbuf(sc_if, cur, m, dmamap);
! 1636: return;
! 1637: }
! 1638:
! 1639: /*
! 1640: * Try to allocate a new jumbo buffer. If that fails, copy the
! 1641: * packet to mbufs and put the jumbo buffer back in the ring
! 1642: * so it can be re-used. If allocating mbufs fails, then we
! 1643: * have to drop the packet.
! 1644: */
! 1645: if (msk_newbuf(sc_if, cur, NULL, dmamap) == ENOBUFS) {
! 1646: struct mbuf *m0;
! 1647: m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
! 1648: total_len + ETHER_ALIGN, 0, ifp, NULL);
! 1649: msk_newbuf(sc_if, cur, m, dmamap);
! 1650: if (m0 == NULL) {
! 1651: ifp->if_ierrors++;
! 1652: return;
! 1653: }
! 1654: m_adj(m0, ETHER_ALIGN);
! 1655: m = m0;
! 1656: } else {
! 1657: m->m_pkthdr.rcvif = ifp;
! 1658: m->m_pkthdr.len = m->m_len = total_len;
! 1659: }
! 1660:
! 1661: ifp->if_ipackets++;
! 1662:
! 1663: #if NBPFILTER > 0
! 1664: if (ifp->if_bpf)
! 1665: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 1666: #endif
! 1667:
! 1668: /* pass it on. */
! 1669: ether_input_mbuf(ifp, m);
! 1670: }
! 1671:
! 1672: void
! 1673: msk_txeof(struct sk_if_softc *sc_if)
! 1674: {
! 1675: struct sk_softc *sc = sc_if->sk_softc;
! 1676: struct msk_tx_desc *cur_tx;
! 1677: struct ifnet *ifp = &sc_if->arpcom.ac_if;
! 1678: u_int32_t idx, reg, sk_ctl;
! 1679: struct sk_txmap_entry *entry;
! 1680:
! 1681: DPRINTFN(2, ("msk_txeof\n"));
! 1682:
! 1683: if (sc_if->sk_port == SK_PORT_A)
! 1684: reg = SK_STAT_BMU_TXA1_RIDX;
! 1685: else
! 1686: reg = SK_STAT_BMU_TXA2_RIDX;
! 1687:
! 1688: /*
! 1689: * Go through our tx ring and free mbufs for those
! 1690: * frames that have been sent.
! 1691: */
! 1692: idx = sc_if->sk_cdata.sk_tx_cons;
! 1693: while (idx != sk_win_read_2(sc, reg)) {
! 1694: MSK_CDTXSYNC(sc_if, idx, 1,
! 1695: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1696:
! 1697: cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx];
! 1698: sk_ctl = cur_tx->sk_ctl;
! 1699: #ifdef MSK_DEBUG
! 1700: if (mskdebug >= 2)
! 1701: msk_dump_txdesc(cur_tx, idx);
! 1702: #endif
! 1703: if (sk_ctl & SK_Y2_TXCTL_LASTFRAG)
! 1704: ifp->if_opackets++;
! 1705: if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) {
! 1706: entry = sc_if->sk_cdata.sk_tx_map[idx];
! 1707:
! 1708: m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf);
! 1709: sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL;
! 1710:
! 1711: bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0,
! 1712: entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 1713:
! 1714: bus_dmamap_unload(sc->sc_dmatag, entry->dmamap);
! 1715: SIMPLEQ_INSERT_TAIL(&sc_if->sk_txmap_head, entry,
! 1716: link);
! 1717: sc_if->sk_cdata.sk_tx_map[idx] = NULL;
! 1718: }
! 1719: sc_if->sk_cdata.sk_tx_cnt--;
! 1720: SK_INC(idx, MSK_TX_RING_CNT);
! 1721: }
! 1722: ifp->if_timer = sc_if->sk_cdata.sk_tx_cnt > 0 ? 5 : 0;
! 1723:
! 1724: if (sc_if->sk_cdata.sk_tx_cnt < MSK_TX_RING_CNT - 2)
! 1725: ifp->if_flags &= ~IFF_OACTIVE;
! 1726:
! 1727: sc_if->sk_cdata.sk_tx_cons = idx;
! 1728: }
! 1729:
! 1730: void
! 1731: msk_tick(void *xsc_if)
! 1732: {
! 1733: struct sk_if_softc *sc_if = xsc_if;
! 1734: struct mii_data *mii = &sc_if->sk_mii;
! 1735: int s;
! 1736:
! 1737: s = splnet();
! 1738: mii_tick(mii);
! 1739: splx(s);
! 1740: timeout_add(&sc_if->sk_tick_ch, hz);
! 1741: }
! 1742:
! 1743: void
! 1744: msk_intr_yukon(struct sk_if_softc *sc_if)
! 1745: {
! 1746: u_int8_t status;
! 1747:
! 1748: status = SK_IF_READ_1(sc_if, 0, SK_GMAC_ISR);
! 1749: /* RX overrun */
! 1750: if ((status & SK_GMAC_INT_RX_OVER) != 0) {
! 1751: SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST,
! 1752: SK_RFCTL_RX_FIFO_OVER);
! 1753: }
! 1754: /* TX underrun */
! 1755: if ((status & SK_GMAC_INT_TX_UNDER) != 0) {
! 1756: SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST,
! 1757: SK_TFCTL_TX_FIFO_UNDER);
! 1758: }
! 1759:
! 1760: DPRINTFN(2, ("msk_intr_yukon status=%#x\n", status));
! 1761: }
! 1762:
! 1763: int
! 1764: msk_intr(void *xsc)
! 1765: {
! 1766: struct sk_softc *sc = xsc;
! 1767: struct sk_if_softc *sc_if0 = sc->sk_if[SK_PORT_A];
! 1768: struct sk_if_softc *sc_if1 = sc->sk_if[SK_PORT_B];
! 1769: struct ifnet *ifp0 = NULL, *ifp1 = NULL;
! 1770: int claimed = 0;
! 1771: u_int32_t status;
! 1772: struct msk_status_desc *cur_st;
! 1773:
! 1774: status = CSR_READ_4(sc, SK_Y2_ISSR2);
! 1775: if (status == 0) {
! 1776: CSR_WRITE_4(sc, SK_Y2_ICR, 2);
! 1777: return (0);
! 1778: }
! 1779:
! 1780: status = CSR_READ_4(sc, SK_ISR);
! 1781:
! 1782: if (sc_if0 != NULL)
! 1783: ifp0 = &sc_if0->arpcom.ac_if;
! 1784: if (sc_if1 != NULL)
! 1785: ifp1 = &sc_if1->arpcom.ac_if;
! 1786:
! 1787: if (sc_if0 && (status & SK_Y2_IMR_MAC1) &&
! 1788: (ifp0->if_flags & IFF_RUNNING)) {
! 1789: msk_intr_yukon(sc_if0);
! 1790: }
! 1791:
! 1792: if (sc_if1 && (status & SK_Y2_IMR_MAC2) &&
! 1793: (ifp1->if_flags & IFF_RUNNING)) {
! 1794: msk_intr_yukon(sc_if1);
! 1795: }
! 1796:
! 1797: MSK_CDSTSYNC(sc, sc->sk_status_idx,
! 1798: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1799: cur_st = &sc->sk_status_ring[sc->sk_status_idx];
! 1800:
! 1801: while (cur_st->sk_opcode & SK_Y2_STOPC_OWN) {
! 1802: cur_st->sk_opcode &= ~SK_Y2_STOPC_OWN;
! 1803: switch (cur_st->sk_opcode) {
! 1804: case SK_Y2_STOPC_RXSTAT:
! 1805: msk_rxeof(sc->sk_if[cur_st->sk_link],
! 1806: letoh16(cur_st->sk_len),
! 1807: letoh32(cur_st->sk_status));
! 1808: SK_IF_WRITE_2(sc->sk_if[cur_st->sk_link], 0,
! 1809: SK_RXQ1_Y2_PREF_PUTIDX,
! 1810: sc->sk_if[cur_st->sk_link]->sk_cdata.sk_rx_prod);
! 1811: break;
! 1812: case SK_Y2_STOPC_TXSTAT:
! 1813: if (sc_if0)
! 1814: msk_txeof(sc_if0);
! 1815: if (sc_if1)
! 1816: msk_txeof(sc_if1);
! 1817: break;
! 1818: default:
! 1819: printf("opcode=0x%x\n", cur_st->sk_opcode);
! 1820: break;
! 1821: }
! 1822: SK_INC(sc->sk_status_idx, MSK_STATUS_RING_CNT);
! 1823:
! 1824: MSK_CDSTSYNC(sc, sc->sk_status_idx,
! 1825: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 1826: cur_st = &sc->sk_status_ring[sc->sk_status_idx];
! 1827: }
! 1828:
! 1829: if (status & SK_Y2_IMR_BMU) {
! 1830: CSR_WRITE_4(sc, SK_STAT_BMU_CSR, SK_STAT_BMU_IRQ_CLEAR);
! 1831: claimed = 1;
! 1832: }
! 1833:
! 1834: CSR_WRITE_4(sc, SK_Y2_ICR, 2);
! 1835:
! 1836: if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd))
! 1837: msk_start(ifp0);
! 1838: if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd))
! 1839: msk_start(ifp1);
! 1840:
! 1841: return (claimed);
! 1842: }
! 1843:
! 1844: void
! 1845: msk_init_yukon(struct sk_if_softc *sc_if)
! 1846: {
! 1847: u_int32_t v;
! 1848: u_int16_t reg;
! 1849: struct sk_softc *sc;
! 1850: int i;
! 1851:
! 1852: sc = sc_if->sk_softc;
! 1853:
! 1854: DPRINTFN(2, ("msk_init_yukon: start: sk_csr=%#x\n",
! 1855: CSR_READ_4(sc_if->sk_softc, SK_CSR)));
! 1856:
! 1857: DPRINTFN(6, ("msk_init_yukon: 1\n"));
! 1858:
! 1859: DPRINTFN(3, ("msk_init_yukon: gmac_ctrl=%#x\n",
! 1860: SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL)));
! 1861:
! 1862: DPRINTFN(6, ("msk_init_yukon: 3\n"));
! 1863:
! 1864: /* unused read of the interrupt source register */
! 1865: DPRINTFN(6, ("msk_init_yukon: 4\n"));
! 1866: SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR);
! 1867:
! 1868: DPRINTFN(6, ("msk_init_yukon: 4a\n"));
! 1869: reg = SK_YU_READ_2(sc_if, YUKON_PAR);
! 1870: DPRINTFN(6, ("msk_init_yukon: YUKON_PAR=%#x\n", reg));
! 1871:
! 1872: /* MIB Counter Clear Mode set */
! 1873: reg |= YU_PAR_MIB_CLR;
! 1874: DPRINTFN(6, ("msk_init_yukon: YUKON_PAR=%#x\n", reg));
! 1875: DPRINTFN(6, ("msk_init_yukon: 4b\n"));
! 1876: SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
! 1877:
! 1878: /* MIB Counter Clear Mode clear */
! 1879: DPRINTFN(6, ("msk_init_yukon: 5\n"));
! 1880: reg &= ~YU_PAR_MIB_CLR;
! 1881: SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
! 1882:
! 1883: /* receive control reg */
! 1884: DPRINTFN(6, ("msk_init_yukon: 7\n"));
! 1885: SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_CRCR);
! 1886:
! 1887: /* transmit parameter register */
! 1888: DPRINTFN(6, ("msk_init_yukon: 8\n"));
! 1889: SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) |
! 1890: YU_TPR_JAM_IPG(0xb) | YU_TPR_JAM2DATA_IPG(0x1a) );
! 1891:
! 1892: /* serial mode register */
! 1893: DPRINTFN(6, ("msk_init_yukon: 9\n"));
! 1894: reg = YU_SMR_DATA_BLIND(0x1c) |
! 1895: YU_SMR_MFL_VLAN |
! 1896: YU_SMR_IPG_DATA(0x1e);
! 1897:
! 1898: if (sc->sk_type != SK_YUKON_FE)
! 1899: reg |= YU_SMR_MFL_JUMBO;
! 1900:
! 1901: SK_YU_WRITE_2(sc_if, YUKON_SMR, reg);
! 1902:
! 1903: DPRINTFN(6, ("msk_init_yukon: 10\n"));
! 1904: /* Setup Yukon's address */
! 1905: for (i = 0; i < 3; i++) {
! 1906: /* Write Source Address 1 (unicast filter) */
! 1907: SK_YU_WRITE_2(sc_if, YUKON_SAL1 + i * 4,
! 1908: sc_if->arpcom.ac_enaddr[i * 2] |
! 1909: sc_if->arpcom.ac_enaddr[i * 2 + 1] << 8);
! 1910: }
! 1911:
! 1912: for (i = 0; i < 3; i++) {
! 1913: reg = sk_win_read_2(sc_if->sk_softc,
! 1914: SK_MAC1_0 + i * 2 + sc_if->sk_port * 8);
! 1915: SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg);
! 1916: }
! 1917:
! 1918: /* Set promiscuous mode */
! 1919: msk_setpromisc(sc_if);
! 1920:
! 1921: /* Set multicast filter */
! 1922: DPRINTFN(6, ("msk_init_yukon: 11\n"));
! 1923: msk_setmulti(sc_if);
! 1924:
! 1925: /* enable interrupt mask for counter overflows */
! 1926: DPRINTFN(6, ("msk_init_yukon: 12\n"));
! 1927: SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0);
! 1928: SK_YU_WRITE_2(sc_if, YUKON_RIMR, 0);
! 1929: SK_YU_WRITE_2(sc_if, YUKON_TRIMR, 0);
! 1930:
! 1931: /* Configure RX MAC FIFO Flush Mask */
! 1932: v = YU_RXSTAT_FOFL | YU_RXSTAT_CRCERR | YU_RXSTAT_MIIERR |
! 1933: YU_RXSTAT_BADFC | YU_RXSTAT_GOODFC | YU_RXSTAT_RUNT |
! 1934: YU_RXSTAT_JABBER;
! 1935: SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_MASK, v);
! 1936:
! 1937: /* Configure RX MAC FIFO */
! 1938: SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_CLEAR);
! 1939: SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_OPERATION_ON |
! 1940: SK_RFCTL_FIFO_FLUSH_ON);
! 1941:
! 1942: /* Increase flush threshould to 64 bytes */
! 1943: SK_IF_WRITE_2(sc_if, 0, SK_RXMF1_FLUSH_THRESHOLD,
! 1944: SK_RFCTL_FIFO_THRESHOLD + 1);
! 1945:
! 1946: /* Configure TX MAC FIFO */
! 1947: SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_CLEAR);
! 1948: SK_IF_WRITE_2(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_OPERATION_ON);
! 1949:
! 1950: #if 1
! 1951: SK_YU_WRITE_2(sc_if, YUKON_GPCR, YU_GPCR_TXEN | YU_GPCR_RXEN);
! 1952: #endif
! 1953: DPRINTFN(6, ("msk_init_yukon: end\n"));
! 1954: }
! 1955:
! 1956: /*
! 1957: * Note that to properly initialize any part of the GEnesis chip,
! 1958: * you first have to take it out of reset mode.
! 1959: */
! 1960: void
! 1961: msk_init(void *xsc_if)
! 1962: {
! 1963: struct sk_if_softc *sc_if = xsc_if;
! 1964: struct sk_softc *sc = sc_if->sk_softc;
! 1965: struct ifnet *ifp = &sc_if->arpcom.ac_if;
! 1966: struct mii_data *mii = &sc_if->sk_mii;
! 1967: int s;
! 1968:
! 1969: DPRINTFN(2, ("msk_init\n"));
! 1970:
! 1971: s = splnet();
! 1972:
! 1973: /* Cancel pending I/O and free all RX/TX buffers. */
! 1974: msk_stop(sc_if);
! 1975:
! 1976: /* Configure I2C registers */
! 1977:
! 1978: /* Configure XMAC(s) */
! 1979: msk_init_yukon(sc_if);
! 1980: mii_mediachg(mii);
! 1981:
! 1982: /* Configure transmit arbiter(s) */
! 1983: SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_ON);
! 1984: #if 0
! 1985: SK_TXARCTL_ON|SK_TXARCTL_FSYNC_ON);
! 1986: #endif
! 1987:
! 1988: /* Configure RAMbuffers */
! 1989: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_UNRESET);
! 1990: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_START, sc_if->sk_rx_ramstart);
! 1991: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_WR_PTR, sc_if->sk_rx_ramstart);
! 1992: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_RD_PTR, sc_if->sk_rx_ramstart);
! 1993: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_END, sc_if->sk_rx_ramend);
! 1994: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_ON);
! 1995:
! 1996: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_UNRESET);
! 1997: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_STORENFWD_ON);
! 1998: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_START, sc_if->sk_tx_ramstart);
! 1999: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_WR_PTR, sc_if->sk_tx_ramstart);
! 2000: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_RD_PTR, sc_if->sk_tx_ramstart);
! 2001: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_END, sc_if->sk_tx_ramend);
! 2002: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_ON);
! 2003:
! 2004: /* Configure BMUs */
! 2005: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000016);
! 2006: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000d28);
! 2007: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, 0x00000080);
! 2008: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_WATERMARK, 0x00000600);
! 2009:
! 2010: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000016);
! 2011: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000d28);
! 2012: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, 0x00000080);
! 2013: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_WATERMARK, 0x00000600);
! 2014:
! 2015: /* Make sure the sync transmit queue is disabled. */
! 2016: SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_RESET);
! 2017:
! 2018: /* Init descriptors */
! 2019: if (msk_init_rx_ring(sc_if) == ENOBUFS) {
! 2020: printf("%s: initialization failed: no "
! 2021: "memory for rx buffers\n", sc_if->sk_dev.dv_xname);
! 2022: msk_stop(sc_if);
! 2023: splx(s);
! 2024: return;
! 2025: }
! 2026:
! 2027: if (msk_init_tx_ring(sc_if) == ENOBUFS) {
! 2028: printf("%s: initialization failed: no "
! 2029: "memory for tx buffers\n", sc_if->sk_dev.dv_xname);
! 2030: msk_stop(sc_if);
! 2031: splx(s);
! 2032: return;
! 2033: }
! 2034:
! 2035: /* Initialize prefetch engine. */
! 2036: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001);
! 2037: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000002);
! 2038: SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_LIDX, MSK_RX_RING_CNT - 1);
! 2039: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_ADDRLO,
! 2040: MSK_RX_RING_ADDR(sc_if, 0));
! 2041: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_ADDRHI,
! 2042: (u_int64_t)MSK_RX_RING_ADDR(sc_if, 0) >> 32);
! 2043: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000008);
! 2044: SK_IF_READ_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR);
! 2045:
! 2046: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001);
! 2047: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000002);
! 2048: SK_IF_WRITE_2(sc_if, 1, SK_TXQA1_Y2_PREF_LIDX, MSK_TX_RING_CNT - 1);
! 2049: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_ADDRLO,
! 2050: MSK_TX_RING_ADDR(sc_if, 0));
! 2051: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_ADDRHI,
! 2052: (u_int64_t)MSK_TX_RING_ADDR(sc_if, 0) >> 32);
! 2053: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000008);
! 2054: SK_IF_READ_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR);
! 2055:
! 2056: SK_IF_WRITE_2(sc_if, 0, SK_RXQ1_Y2_PREF_PUTIDX,
! 2057: sc_if->sk_cdata.sk_rx_prod);
! 2058:
! 2059: /* Configure interrupt handling */
! 2060: if (sc_if->sk_port == SK_PORT_A)
! 2061: sc->sk_intrmask |= SK_Y2_INTRS1;
! 2062: else
! 2063: sc->sk_intrmask |= SK_Y2_INTRS2;
! 2064: sc->sk_intrmask |= SK_Y2_IMR_BMU;
! 2065: CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
! 2066:
! 2067: ifp->if_flags |= IFF_RUNNING;
! 2068: ifp->if_flags &= ~IFF_OACTIVE;
! 2069:
! 2070: timeout_add(&sc_if->sk_tick_ch, hz);
! 2071:
! 2072: splx(s);
! 2073: }
! 2074:
! 2075: void
! 2076: msk_stop(struct sk_if_softc *sc_if)
! 2077: {
! 2078: struct sk_softc *sc = sc_if->sk_softc;
! 2079: struct ifnet *ifp = &sc_if->arpcom.ac_if;
! 2080: struct sk_txmap_entry *dma;
! 2081: int i;
! 2082:
! 2083: DPRINTFN(2, ("msk_stop\n"));
! 2084:
! 2085: timeout_del(&sc_if->sk_tick_ch);
! 2086:
! 2087: ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
! 2088:
! 2089: /* Stop transfer of Tx descriptors */
! 2090:
! 2091: /* Stop transfer of Rx descriptors */
! 2092:
! 2093: /* Turn off various components of this interface. */
! 2094: SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
! 2095: SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
! 2096: SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
! 2097: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
! 2098: SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
! 2099: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_BMU_CSR, SK_TXBMU_OFFLINE);
! 2100: SK_IF_WRITE_4(sc_if, 1, SK_TXRBA1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
! 2101: SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF);
! 2102: SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
! 2103: SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_STOP);
! 2104: SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF);
! 2105: SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF);
! 2106:
! 2107: SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_Y2_PREF_CSR, 0x00000001);
! 2108: SK_IF_WRITE_4(sc_if, 1, SK_TXQA1_Y2_PREF_CSR, 0x00000001);
! 2109:
! 2110: /* Disable interrupts */
! 2111: if (sc_if->sk_port == SK_PORT_A)
! 2112: sc->sk_intrmask &= ~SK_Y2_INTRS1;
! 2113: else
! 2114: sc->sk_intrmask &= ~SK_Y2_INTRS2;
! 2115: CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
! 2116:
! 2117: SK_XM_READ_2(sc_if, XM_ISR);
! 2118: SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
! 2119:
! 2120: /* Free RX and TX mbufs still in the queues. */
! 2121: for (i = 0; i < MSK_RX_RING_CNT; i++) {
! 2122: if (sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf != NULL) {
! 2123: m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf);
! 2124: sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL;
! 2125: }
! 2126: }
! 2127:
! 2128: for (i = 0; i < MSK_TX_RING_CNT; i++) {
! 2129: if (sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf != NULL) {
! 2130: m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf);
! 2131: sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL;
! 2132: SIMPLEQ_INSERT_HEAD(&sc_if->sk_txmap_head,
! 2133: sc_if->sk_cdata.sk_tx_map[i], link);
! 2134: sc_if->sk_cdata.sk_tx_map[i] = 0;
! 2135: }
! 2136: }
! 2137:
! 2138: while ((dma = SIMPLEQ_FIRST(&sc_if->sk_txmap_head))) {
! 2139: SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link);
! 2140: bus_dmamap_destroy(sc->sc_dmatag, dma->dmamap);
! 2141: free(dma, M_DEVBUF);
! 2142: }
! 2143: }
! 2144:
! 2145: struct cfattach mskc_ca = {
! 2146: sizeof(struct sk_softc), mskc_probe, mskc_attach,
! 2147: };
! 2148:
! 2149: struct cfdriver mskc_cd = {
! 2150: 0, "mskc", DV_DULL
! 2151: };
! 2152:
! 2153: struct cfattach msk_ca = {
! 2154: sizeof(struct sk_if_softc), msk_probe, msk_attach,
! 2155: };
! 2156:
! 2157: struct cfdriver msk_cd = {
! 2158: 0, "msk", DV_IFNET
! 2159: };
! 2160:
! 2161: #ifdef MSK_DEBUG
! 2162: void
! 2163: msk_dump_txdesc(struct msk_tx_desc *le, int idx)
! 2164: {
! 2165: #define DESC_PRINT(X) \
! 2166: if (X) \
! 2167: printf("txdesc[%d]." #X "=%#x\n", \
! 2168: idx, X);
! 2169:
! 2170: DESC_PRINT(letoh32(le->sk_addr));
! 2171: DESC_PRINT(letoh16(le->sk_len));
! 2172: DESC_PRINT(le->sk_ctl);
! 2173: DESC_PRINT(le->sk_opcode);
! 2174: #undef DESC_PRINT
! 2175: }
! 2176:
! 2177: void
! 2178: msk_dump_bytes(const char *data, int len)
! 2179: {
! 2180: int c, i, j;
! 2181:
! 2182: for (i = 0; i < len; i += 16) {
! 2183: printf("%08x ", i);
! 2184: c = len - i;
! 2185: if (c > 16) c = 16;
! 2186:
! 2187: for (j = 0; j < c; j++) {
! 2188: printf("%02x ", data[i + j] & 0xff);
! 2189: if ((j & 0xf) == 7 && j > 0)
! 2190: printf(" ");
! 2191: }
! 2192:
! 2193: for (; j < 16; j++)
! 2194: printf(" ");
! 2195: printf(" ");
! 2196:
! 2197: for (j = 0; j < c; j++) {
! 2198: int ch = data[i + j] & 0xff;
! 2199: printf("%c", ' ' <= ch && ch <= '~' ? ch : ' ');
! 2200: }
! 2201:
! 2202: printf("\n");
! 2203:
! 2204: if (c < 16)
! 2205: break;
! 2206: }
! 2207: }
! 2208:
! 2209: void
! 2210: msk_dump_mbuf(struct mbuf *m)
! 2211: {
! 2212: int count = m->m_pkthdr.len;
! 2213:
! 2214: printf("m=%#lx, m->m_pkthdr.len=%#d\n", m, m->m_pkthdr.len);
! 2215:
! 2216: while (count > 0 && m) {
! 2217: printf("m=%#lx, m->m_data=%#lx, m->m_len=%d\n",
! 2218: m, m->m_data, m->m_len);
! 2219: msk_dump_bytes(mtod(m, char *), m->m_len);
! 2220:
! 2221: count -= m->m_len;
! 2222: m = m->m_next;
! 2223: }
! 2224: }
! 2225: #endif
CVSweb