summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_sk.c
diff options
context:
space:
mode:
authorwilko <wilko@FreeBSD.org>2003-09-20 10:53:08 +0000
committerwilko <wilko@FreeBSD.org>2003-09-20 10:53:08 +0000
commit3d954f412f973cdef480c3711423fcadd2760349 (patch)
treecdb2a8a3cec0a4df31f4f70dc242b3e215c2ae39 /sys/pci/if_sk.c
parent6e6824e4bcd845d2681902b69bf6bd16809bbc05 (diff)
downloadFreeBSD-src-3d954f412f973cdef480c3711423fcadd2760349.zip
FreeBSD-src-3d954f412f973cdef480c3711423fcadd2760349.tar.gz
Add support for SK-9521 V2.0 and 3COM 3C940.
Tested at 100Mbit only, using Asus P4P800 onboard 3C940. The -stable version of this patch I have in use for ~2 weeks now, and works just fine for me. Based on: Nathan L. Binkert's patch for OpenBSD Patch submitted by and thanks to: Jung-uk Kim <jkim@niksun.com> MFC after: 2 weeks
Diffstat (limited to 'sys/pci/if_sk.c')
-rw-r--r--sys/pci/if_sk.c708
1 files changed, 559 insertions, 149 deletions
diff --git a/sys/pci/if_sk.c b/sys/pci/if_sk.c
index 6893120..813c94d 100644
--- a/sys/pci/if_sk.c
+++ b/sys/pci/if_sk.c
@@ -1,3 +1,5 @@
+/* $OpenBSD: if_sk.c,v 1.33 2003/08/12 05:23:06 nate Exp $ */
+
/*
* Copyright (c) 1997, 1998, 1999, 2000
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
@@ -31,6 +33,22 @@
*/
/*
+ * Copyright (c) 2003 Nathan L. Binkert <binkertn@umich.edu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
* SysKonnect SK-NET gigabit ethernet driver for FreeBSD. Supports
* the SK-984x series adapters, both single port and dual port.
* References:
@@ -102,10 +120,13 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#if 0
#define SK_USEIOSPACE
+#endif
#include <pci/if_skreg.h>
#include <pci/xmaciireg.h>
+#include <pci/yukonreg.h>
MODULE_DEPEND(sk, pci, 1, 1, 1);
MODULE_DEPEND(sk, ether, 1, 1, 1);
@@ -120,20 +141,36 @@ static const char rcsid[] =
#endif
static struct sk_type sk_devs[] = {
- { SK_VENDORID, SK_DEVICEID_GE, "SysKonnect Gigabit Ethernet" },
+ {
+ VENDORID_SK,
+ DEVICEID_SK_V1,
+ "SysKonnect Gigabit Ethernet (V1.0)"
+ },
+ {
+ VENDORID_SK,
+ DEVICEID_SK_V2,
+ "SysKonnect Gigabit Ethernet (V2.0)"
+ },
+ {
+ VENDORID_3COM,
+ DEVICEID_3COM_3C940,
+ "3Com 3C940 Gigabit Ethernet"
+ },
{ 0, 0, NULL }
};
+static int skc_probe (device_t);
+static int skc_attach (device_t);
+static int skc_detach (device_t);
+static void skc_shutdown (device_t);
+static int sk_detach (device_t);
static int sk_probe (device_t);
static int sk_attach (device_t);
-static int sk_detach (device_t);
-static int sk_detach_xmac (device_t);
-static int sk_probe_xmac (device_t);
-static int sk_attach_xmac (device_t);
static void sk_tick (void *);
static void sk_intr (void *);
static void sk_intr_xmac (struct sk_if_softc *);
static void sk_intr_bcom (struct sk_if_softc *);
+static void sk_intr_yukon (struct sk_if_softc *);
static void sk_rxeof (struct sk_if_softc *);
static void sk_txeof (struct sk_if_softc *);
static int sk_encap (struct sk_if_softc *, struct mbuf *,
@@ -142,9 +179,9 @@ static void sk_start (struct ifnet *);
static int sk_ioctl (struct ifnet *, u_long, caddr_t);
static void sk_init (void *);
static void sk_init_xmac (struct sk_if_softc *);
+static void sk_init_yukon (struct sk_if_softc *);
static void sk_stop (struct sk_if_softc *);
static void sk_watchdog (struct ifnet *);
-static void sk_shutdown (device_t);
static int sk_ifmedia_upd (struct ifnet *);
static void sk_ifmedia_sts (struct ifnet *, struct ifmediareq *);
static void sk_reset (struct sk_softc *);
@@ -169,6 +206,16 @@ static int sk_miibus_readreg (device_t, int, int);
static int sk_miibus_writereg (device_t, int, int, int);
static void sk_miibus_statchg (device_t);
+static int sk_xmac_miibus_readreg (struct sk_if_softc *, int, int);
+static int sk_xmac_miibus_writereg (struct sk_if_softc *, int, int,
+ int);
+static void sk_xmac_miibus_statchg (struct sk_if_softc *);
+
+static int sk_marv_miibus_readreg (struct sk_if_softc *, int, int);
+static int sk_marv_miibus_writereg (struct sk_if_softc *, int, int,
+ int);
+static void sk_marv_miibus_statchg (struct sk_if_softc *);
+
static u_int32_t sk_calchash (caddr_t);
static void sk_setfilt (struct sk_if_softc *, caddr_t, int);
static void sk_setmulti (struct sk_if_softc *);
@@ -191,10 +238,10 @@ static void sk_setmulti (struct sk_if_softc *);
*/
static device_method_t skc_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, sk_probe),
- DEVMETHOD(device_attach, sk_attach),
- DEVMETHOD(device_detach, sk_detach),
- DEVMETHOD(device_shutdown, sk_shutdown),
+ DEVMETHOD(device_probe, skc_probe),
+ DEVMETHOD(device_attach, skc_attach),
+ DEVMETHOD(device_detach, skc_detach),
+ DEVMETHOD(device_shutdown, skc_shutdown),
/* bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
@@ -213,9 +260,9 @@ static devclass_t skc_devclass;
static device_method_t sk_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, sk_probe_xmac),
- DEVMETHOD(device_attach, sk_attach_xmac),
- DEVMETHOD(device_detach, sk_detach_xmac),
+ DEVMETHOD(device_probe, sk_probe),
+ DEVMETHOD(device_attach, sk_attach),
+ DEVMETHOD(device_detach, sk_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
/* bus interface */
@@ -265,8 +312,12 @@ sk_win_read_4(sc, reg)
struct sk_softc *sc;
int reg;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
return(CSR_READ_4(sc, SK_WIN_BASE + SK_REG(reg)));
+#else
+ return(CSR_READ_4(sc, reg));
+#endif
}
static u_int16_t
@@ -274,8 +325,12 @@ sk_win_read_2(sc, reg)
struct sk_softc *sc;
int reg;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
return(CSR_READ_2(sc, SK_WIN_BASE + SK_REG(reg)));
+#else
+ return(CSR_READ_2(sc, reg));
+#endif
}
static u_int8_t
@@ -283,8 +338,12 @@ sk_win_read_1(sc, reg)
struct sk_softc *sc;
int reg;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
return(CSR_READ_1(sc, SK_WIN_BASE + SK_REG(reg)));
+#else
+ return(CSR_READ_1(sc, reg));
+#endif
}
static void
@@ -293,8 +352,12 @@ sk_win_write_4(sc, reg, val)
int reg;
u_int32_t val;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
CSR_WRITE_4(sc, SK_WIN_BASE + SK_REG(reg), val);
+#else
+ CSR_WRITE_4(sc, reg, val);
+#endif
return;
}
@@ -304,8 +367,12 @@ sk_win_write_2(sc, reg, val)
int reg;
u_int32_t val;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
- CSR_WRITE_2(sc, SK_WIN_BASE + SK_REG(reg), (u_int32_t)val);
+ CSR_WRITE_2(sc, SK_WIN_BASE + SK_REG(reg), val);
+#else
+ CSR_WRITE_2(sc, reg, val);
+#endif
return;
}
@@ -315,8 +382,12 @@ sk_win_write_1(sc, reg, val)
int reg;
u_int32_t val;
{
+#ifdef SK_USEIOSPACE
CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
CSR_WRITE_1(sc, SK_WIN_BASE + SK_REG(reg), val);
+#else
+ CSR_WRITE_1(sc, reg, val);
+#endif
return;
}
@@ -329,7 +400,7 @@ sk_win_write_1(sc, reg, val)
* can be used to store asset management information or log messages.
* We read the ID string and read-only into buffers attached to
* the controller softc structure for later use. At the moment,
- * we only use the ID string during sk_attach().
+ * we only use the ID string during skc_attach().
*/
static u_int8_t
sk_vpd_readbyte(sc, addr)
@@ -419,15 +490,69 @@ sk_miibus_readreg(dev, phy, reg)
int phy, reg;
{
struct sk_if_softc *sc_if;
- int i;
sc_if = device_get_softc(dev);
+ switch(sc_if->sk_softc->sk_type) {
+ case SK_GENESIS:
+ return(sk_xmac_miibus_readreg(sc_if, phy, reg));
+ case SK_YUKON:
+ return(sk_marv_miibus_readreg(sc_if, phy, reg));
+ }
+
+ return(0);
+}
+
+static int
+sk_miibus_writereg(dev, phy, reg, val)
+ device_t dev;
+ int phy, reg, val;
+{
+ struct sk_if_softc *sc_if;
+
+ sc_if = device_get_softc(dev);
+
+ switch(sc_if->sk_softc->sk_type) {
+ case SK_GENESIS:
+ return(sk_xmac_miibus_writereg(sc_if, phy, reg, val));
+ case SK_YUKON:
+ return(sk_marv_miibus_writereg(sc_if, phy, reg, val));
+ }
+
+ return(0);
+}
+
+static void
+sk_miibus_statchg(dev)
+ device_t dev;
+{
+ struct sk_if_softc *sc_if;
+
+ sc_if = device_get_softc(dev);
+
+ switch(sc_if->sk_softc->sk_type) {
+ case SK_GENESIS:
+ sk_xmac_miibus_statchg(sc_if);
+ break;
+ case SK_YUKON:
+ sk_marv_miibus_statchg(sc_if);
+ break;
+ }
+
+ return;
+}
+
+static int
+sk_xmac_miibus_readreg(sc_if, phy, reg)
+ struct sk_if_softc *sc_if;
+ int phy, reg;
+{
+ int i;
+
if (sc_if->sk_phytype == SK_PHYTYPE_XMAC && phy != 0)
return(0);
SK_IF_LOCK(sc_if);
-
SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8));
SK_XM_READ_2(sc_if, XM_PHY_DATA);
if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) {
@@ -441,6 +566,7 @@ sk_miibus_readreg(dev, phy, reg)
if (i == SK_TIMEOUT) {
printf("sk%d: phy failed to come ready\n",
sc_if->sk_unit);
+ SK_IF_UNLOCK(sc_if);
return(0);
}
}
@@ -451,16 +577,13 @@ sk_miibus_readreg(dev, phy, reg)
}
static int
-sk_miibus_writereg(dev, phy, reg, val)
- device_t dev;
+sk_xmac_miibus_writereg(sc_if, phy, reg, val)
+ struct sk_if_softc *sc_if;
int phy, reg, val;
{
- struct sk_if_softc *sc_if;
int i;
- sc_if = device_get_softc(dev);
SK_IF_LOCK(sc_if);
-
SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8));
for (i = 0; i < SK_TIMEOUT; i++) {
if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY))
@@ -469,6 +592,7 @@ sk_miibus_writereg(dev, phy, reg, val)
if (i == SK_TIMEOUT) {
printf("sk%d: phy failed to come ready\n", sc_if->sk_unit);
+ SK_IF_UNLOCK(sc_if);
return(ETIMEDOUT);
}
@@ -478,9 +602,7 @@ sk_miibus_writereg(dev, phy, reg, val)
if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY))
break;
}
-
SK_IF_UNLOCK(sc_if);
-
if (i == SK_TIMEOUT)
printf("sk%d: phy write timed out\n", sc_if->sk_unit);
@@ -488,14 +610,13 @@ sk_miibus_writereg(dev, phy, reg, val)
}
static void
-sk_miibus_statchg(dev)
- device_t dev;
-{
+sk_xmac_miibus_statchg(sc_if)
struct sk_if_softc *sc_if;
+{
struct mii_data *mii;
- sc_if = device_get_softc(dev);
mii = device_get_softc(sc_if->sk_miibus);
+
SK_IF_LOCK(sc_if);
/*
* If this is a GMII PHY, manually set the XMAC's
@@ -513,6 +634,73 @@ sk_miibus_statchg(dev)
return;
}
+static int
+sk_marv_miibus_readreg(sc_if, phy, reg)
+ struct sk_if_softc *sc_if;
+ int phy, reg;
+{
+ u_int16_t val;
+ int i;
+
+ if (phy != 0 ||
+ (sc_if->sk_phytype != SK_PHYTYPE_MARV_COPPER &&
+ sc_if->sk_phytype != SK_PHYTYPE_MARV_FIBER)) {
+ return(0);
+ }
+
+ SK_IF_LOCK(sc_if);
+ SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
+ YU_SMICR_REGAD(reg) | YU_SMICR_OP_READ);
+
+ for (i = 0; i < SK_TIMEOUT; i++) {
+ DELAY(1);
+ val = SK_YU_READ_2(sc_if, YUKON_SMICR);
+ if (val & YU_SMICR_READ_VALID)
+ break;
+ }
+
+ if (i == SK_TIMEOUT) {
+ printf("sk%d: phy failed to come ready\n",
+ sc_if->sk_unit);
+ SK_IF_UNLOCK(sc_if);
+ return(0);
+ }
+
+ val = SK_YU_READ_2(sc_if, YUKON_SMIDR);
+ SK_IF_UNLOCK(sc_if);
+
+ return(val);
+}
+
+static int
+sk_marv_miibus_writereg(sc_if, phy, reg, val)
+ struct sk_if_softc *sc_if;
+ int phy, reg, val;
+{
+ int i;
+
+ SK_IF_LOCK(sc_if);
+ SK_YU_WRITE_2(sc_if, YUKON_SMIDR, val);
+ SK_YU_WRITE_2(sc_if, YUKON_SMICR, YU_SMICR_PHYAD(phy) |
+ YU_SMICR_REGAD(reg) | YU_SMICR_OP_WRITE);
+
+ for (i = 0; i < SK_TIMEOUT; i++) {
+ DELAY(1);
+ if (SK_YU_READ_2(sc_if, YUKON_SMICR) & YU_SMICR_BUSY)
+ break;
+ }
+ SK_IF_UNLOCK(sc_if);
+
+ return(0);
+}
+
+static void
+sk_marv_miibus_statchg(sc_if)
+ struct sk_if_softc *sc_if;
+{
+ return;
+}
+
#define SK_POLY 0xEDB88320
#define SK_BITS 6
@@ -554,19 +742,30 @@ static void
sk_setmulti(sc_if)
struct sk_if_softc *sc_if;
{
- struct ifnet *ifp;
+ struct sk_softc *sc = sc_if->sk_softc;
+ struct ifnet *ifp = &sc_if->arpcom.ac_if;
u_int32_t hashes[2] = { 0, 0 };
int h, i;
struct ifmultiaddr *ifma;
u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 };
- ifp = &sc_if->arpcom.ac_if;
/* First, zot all the existing filters. */
- for (i = 1; i < XM_RXFILT_MAX; i++)
- sk_setfilt(sc_if, (caddr_t)&dummy, i);
- SK_XM_WRITE_4(sc_if, XM_MAR0, 0);
- SK_XM_WRITE_4(sc_if, XM_MAR2, 0);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ for (i = 1; i < XM_RXFILT_MAX; i++)
+ sk_setfilt(sc_if, (caddr_t)&dummy, i);
+
+ SK_XM_WRITE_4(sc_if, XM_MAR0, 0);
+ SK_XM_WRITE_4(sc_if, XM_MAR2, 0);
+ break;
+ case SK_YUKON:
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
+ break;
+ }
/* Now program new ones. */
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
@@ -582,7 +781,7 @@ sk_setmulti(sc_if)
* into the perfect filter. For all others,
* use the hash table.
*/
- if (i < XM_RXFILT_MAX) {
+ if (sc->sk_type == SK_GENESIS && i < XM_RXFILT_MAX) {
sk_setfilt(sc_if,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr), i);
i++;
@@ -598,10 +797,20 @@ sk_setmulti(sc_if)
}
}
- SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH|
- XM_MODE_RX_USE_PERFECT);
- SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
- SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH|
+ XM_MODE_RX_USE_PERFECT);
+ SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
+ SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
+ break;
+ case SK_YUKON:
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff);
+ break;
+ }
return;
}
@@ -610,13 +819,10 @@ static int
sk_init_rx_ring(sc_if)
struct sk_if_softc *sc_if;
{
- struct sk_chain_data *cd;
- struct sk_ring_data *rd;
+ struct sk_chain_data *cd = &sc_if->sk_cdata;
+ struct sk_ring_data *rd = sc_if->sk_rdata;
int i;
- cd = &sc_if->sk_cdata;
- rd = sc_if->sk_rdata;
-
bzero((char *)rd->sk_rx_ring,
sizeof(struct sk_rx_desc) * SK_RX_RING_CNT);
@@ -647,13 +853,10 @@ static void
sk_init_tx_ring(sc_if)
struct sk_if_softc *sc_if;
{
- struct sk_chain_data *cd;
- struct sk_ring_data *rd;
+ struct sk_chain_data *cd = &sc_if->sk_cdata;
+ struct sk_ring_data *rd = sc_if->sk_rdata;
int i;
- cd = &sc_if->sk_cdata;
- rd = sc_if->sk_rdata;
-
bzero((char *)sc_if->sk_rdata->sk_tx_ring,
sizeof(struct sk_tx_desc) * SK_TX_RING_CNT);
@@ -856,10 +1059,9 @@ static int
sk_ifmedia_upd(ifp)
struct ifnet *ifp;
{
- struct sk_if_softc *sc_if;
+ struct sk_if_softc *sc_if = ifp->if_softc;
struct mii_data *mii;
- sc_if = ifp->if_softc;
mii = device_get_softc(sc_if->sk_miibus);
sk_init(sc_if);
mii_mediachg(mii);
@@ -895,6 +1097,7 @@ sk_ioctl(ifp, command, data)
caddr_t data;
{
struct sk_if_softc *sc_if = ifp->if_softc;
+ struct sk_softc *sc = sc_if->sk_softc;
struct ifreq *ifr = (struct ifreq *) data;
int error = 0;
struct mii_data *mii;
@@ -915,14 +1118,30 @@ sk_ioctl(ifp, command, data)
if (ifp->if_flags & IFF_RUNNING &&
ifp->if_flags & IFF_PROMISC &&
!(sc_if->sk_if_flags & IFF_PROMISC)) {
- SK_XM_SETBIT_4(sc_if, XM_MODE,
- XM_MODE_RX_PROMISC);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_SETBIT_4(sc_if, XM_MODE,
+ XM_MODE_RX_PROMISC);
+ break;
+ case SK_YUKON:
+ SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
+ YU_RCR_UFLEN | YU_RCR_MUFLEN);
+ break;
+ }
sk_setmulti(sc_if);
} else if (ifp->if_flags & IFF_RUNNING &&
!(ifp->if_flags & IFF_PROMISC) &&
sc_if->sk_if_flags & IFF_PROMISC) {
- SK_XM_CLRBIT_4(sc_if, XM_MODE,
- XM_MODE_RX_PROMISC);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_CLRBIT_4(sc_if, XM_MODE,
+ XM_MODE_RX_PROMISC);
+ break;
+ case SK_YUKON:
+ SK_YU_SETBIT_2(sc_if, YUKON_RCR,
+ YU_RCR_UFLEN | YU_RCR_MUFLEN);
+ break;
+ }
sk_setmulti(sc_if);
} else
sk_init(sc_if);
@@ -958,12 +1177,13 @@ sk_ioctl(ifp, command, data)
* IDs against our list and return a device name if we find a match.
*/
static int
-sk_probe(dev)
+skc_probe(dev)
device_t dev;
{
- struct sk_type *t;
+ struct sk_softc *sc;
+ struct sk_type *t = sk_devs;
- t = sk_devs;
+ sc = device_get_softc(dev);
while(t->sk_name != NULL) {
if ((pci_get_vendor(dev) == t->sk_vid) &&
@@ -984,18 +1204,26 @@ static void
sk_reset(sc)
struct sk_softc *sc;
{
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_SW_RESET);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_MASTER_RESET);
- DELAY(1000);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_SW_UNRESET);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_RESET);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_RESET);
+ if (sc->sk_type == SK_YUKON)
+ CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_SET);
- /* Configure packet arbiter */
- sk_win_write_2(sc, SK_PKTARB_CTL, SK_PKTARBCTL_UNRESET);
- sk_win_write_2(sc, SK_RXPA1_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_TXPA1_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_RXPA2_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_TXPA2_TINIT, SK_PKTARB_TIMEOUT);
+ DELAY(1000);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_UNRESET);
+ DELAY(2);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
+ if (sc->sk_type == SK_YUKON)
+ CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR);
+
+ if (sc->sk_type == SK_GENESIS) {
+ /* Configure packet arbiter */
+ sk_win_write_2(sc, SK_PKTARB_CTL, SK_PKTARBCTL_UNRESET);
+ sk_win_write_2(sc, SK_RXPA1_TINIT, SK_PKTARB_TIMEOUT);
+ sk_win_write_2(sc, SK_TXPA1_TINIT, SK_PKTARB_TIMEOUT);
+ sk_win_write_2(sc, SK_RXPA2_TINIT, SK_PKTARB_TIMEOUT);
+ sk_win_write_2(sc, SK_TXPA2_TINIT, SK_PKTARB_TIMEOUT);
+ }
/* Enable RAM interface */
sk_win_write_4(sc, SK_RAMCTL, SK_RAMCTL_UNRESET);
@@ -1017,16 +1245,27 @@ sk_reset(sc)
}
static int
-sk_probe_xmac(dev)
+sk_probe(dev)
device_t dev;
{
+ struct sk_softc *sc;
+
+ sc = device_get_softc(device_get_parent(dev));
+
/*
* Not much to do here. We always know there will be
* at least one XMAC present, and if there are two,
- * sk_attach() will create a second device instance
+ * skc_attach() will create a second device instance
* for us.
*/
- device_set_desc(dev, "XaQti Corp. XMAC II");
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ device_set_desc(dev, "XaQti Corp. XMAC II");
+ break;
+ case SK_YUKON:
+ device_set_desc(dev, "Marvell Semiconductor, Inc. Yukon");
+ break;
+ }
return(0);
}
@@ -1036,7 +1275,7 @@ sk_probe_xmac(dev)
* Single port cards will have only one logical interface of course.
*/
static int
-sk_attach_xmac(dev)
+sk_attach(dev)
device_t dev;
{
struct sk_softc *sc;
@@ -1064,7 +1303,7 @@ sk_attach_xmac(dev)
sc_if->sk_tx_bmu = SK_BMU_TXS_CSR0;
if (port == SK_PORT_B)
sc_if->sk_tx_bmu = SK_BMU_TXS_CSR1;
-
+
/*
* Get station address for this interface. Note that
* dual port cards actually come with three station
@@ -1123,11 +1362,14 @@ sk_attach_xmac(dev)
case SK_PHYTYPE_BCOM:
sc_if->sk_phyaddr = SK_PHYADDR_BCOM;
break;
+ case SK_PHYTYPE_MARV_COPPER:
+ sc_if->sk_phyaddr = SK_PHYADDR_MARV;
+ break;
default:
printf("skc%d: unsupported PHY type: %d\n",
sc->sk_unit, sc_if->sk_phytype);
error = ENODEV;
- goto fail_xmac;
+ goto fail;
}
/* Allocate the descriptor queues. */
@@ -1137,7 +1379,7 @@ sk_attach_xmac(dev)
if (sc_if->sk_rdata == NULL) {
printf("sk%d: no memory for list buffers!\n", sc_if->sk_unit);
error = ENOMEM;
- goto fail_xmac;
+ goto fail;
}
bzero(sc_if->sk_rdata, sizeof(struct sk_ring_data));
@@ -1147,7 +1389,7 @@ sk_attach_xmac(dev)
printf("sk%d: jumbo buffer allocation failed\n",
sc_if->sk_unit);
error = ENOMEM;
- goto fail_xmac;
+ goto fail;
}
ifp = &sc_if->arpcom.ac_if;
@@ -1174,21 +1416,29 @@ sk_attach_xmac(dev)
/*
* Do miibus setup.
*/
- sk_init_xmac(sc_if);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_init_xmac(sc_if);
+ break;
+ case SK_YUKON:
+ sk_init_yukon(sc_if);
+ break;
+ }
+
if (mii_phy_probe(dev, &sc_if->sk_miibus,
sk_ifmedia_upd, sk_ifmedia_sts)) {
printf("skc%d: no PHY found!\n", sc_if->sk_unit);
ether_ifdetach(ifp);
error = ENXIO;
- goto fail_xmac;
+ goto fail;
}
-fail_xmac:
+fail:
SK_UNLOCK(sc);
if (error) {
/* Access should be ok even though lock has been dropped */
sc->sk_if[port] = NULL;
- sk_detach_xmac(dev);
+ sk_detach(dev);
}
return(error);
@@ -1199,7 +1449,7 @@ fail_xmac:
* setup and ethernet/BPF attach.
*/
static int
-sk_attach(dev)
+skc_attach(dev)
device_t dev;
{
struct sk_softc *sc;
@@ -1263,6 +1513,17 @@ sk_attach(dev)
goto fail;
}
+ /* Set adapter type */
+ switch (pci_get_device(dev)) {
+ case DEVICEID_SK_V1:
+ sc->sk_type = SK_GENESIS;
+ break;
+ case DEVICEID_SK_V2:
+ case DEVICEID_3COM_3C940:
+ sc->sk_type = SK_YUKON;
+ break;
+ }
+
/* Reset the adapter. */
sk_reset(sc);
@@ -1271,29 +1532,34 @@ sk_attach(dev)
/* Read and save vital product data from EEPROM. */
sk_vpd_read(sc);
- /* Read and save RAM size and RAMbuffer offset */
- switch(sk_win_read_1(sc, SK_EPROM0)) {
- case SK_RAMSIZE_512K_64:
- sc->sk_ramsize = 0x80000;
- sc->sk_rboff = SK_RBOFF_0;
- break;
- case SK_RAMSIZE_1024K_64:
- sc->sk_ramsize = 0x100000;
- sc->sk_rboff = SK_RBOFF_80000;
- break;
- case SK_RAMSIZE_1024K_128:
- sc->sk_ramsize = 0x100000;
- sc->sk_rboff = SK_RBOFF_0;
- break;
- case SK_RAMSIZE_2048K_128:
- sc->sk_ramsize = 0x200000;
+ if (sc->sk_type == SK_GENESIS) {
+ /* Read and save RAM size and RAMbuffer offset */
+ switch(sk_win_read_1(sc, SK_EPROM0)) {
+ case SK_RAMSIZE_512K_64:
+ sc->sk_ramsize = 0x80000;
+ sc->sk_rboff = SK_RBOFF_0;
+ break;
+ case SK_RAMSIZE_1024K_64:
+ sc->sk_ramsize = 0x100000;
+ sc->sk_rboff = SK_RBOFF_80000;
+ break;
+ case SK_RAMSIZE_1024K_128:
+ sc->sk_ramsize = 0x100000;
+ sc->sk_rboff = SK_RBOFF_0;
+ break;
+ case SK_RAMSIZE_2048K_128:
+ sc->sk_ramsize = 0x200000;
+ sc->sk_rboff = SK_RBOFF_0;
+ break;
+ default:
+ printf("skc%d: unknown ram size: %d\n",
+ sc->sk_unit, sk_win_read_1(sc, SK_EPROM0));
+ error = ENXIO;
+ goto fail;
+ }
+ } else {
+ sc->sk_ramsize = 0x20000;
sc->sk_rboff = SK_RBOFF_0;
- break;
- default:
- printf("skc%d: unknown ram size: %d\n",
- sc->sk_unit, sk_win_read_1(sc, SK_EPROM0));
- error = ENXIO;
- goto fail;
}
/* Read and save physical media type */
@@ -1347,7 +1613,7 @@ sk_attach(dev)
fail:
if (error)
- sk_detach(dev);
+ skc_detach(dev);
return(error);
}
@@ -1360,7 +1626,7 @@ fail:
* allocated.
*/
static int
-sk_detach_xmac(dev)
+sk_detach(dev)
device_t dev;
{
struct sk_if_softc *sc_if;
@@ -1368,7 +1634,7 @@ sk_detach_xmac(dev)
sc_if = device_get_softc(dev);
KASSERT(mtx_initialized(&sc_if->sk_softc->sk_mtx),
- ("sk mutex not initialized in sk_detach_xmac"));
+ ("sk mutex not initialized in sk_detach"));
SK_IF_LOCK(sc_if);
ifp = &sc_if->arpcom.ac_if;
@@ -1392,7 +1658,7 @@ sk_detach_xmac(dev)
}
static int
-sk_detach(dev)
+skc_detach(dev)
device_t dev;
{
struct sk_softc *sc;
@@ -1538,7 +1804,7 @@ sk_watchdog(ifp)
}
static void
-sk_shutdown(dev)
+skc_shutdown(dev)
device_t dev;
{
struct sk_softc *sc;
@@ -1730,8 +1996,7 @@ sk_intr_bcom(sc_if)
* Read the PHY interrupt register to make sure
* we clear any pending interrupts.
*/
- status = sk_miibus_readreg(sc_if->sk_dev,
- SK_PHYADDR_BCOM, BRGPHY_MII_ISR);
+ status = sk_xmac_miibus_readreg(sc_if, SK_PHYADDR_BCOM, BRGPHY_MII_ISR);
if (!(ifp->if_flags & IFF_RUNNING)) {
sk_init_xmac(sc_if);
@@ -1740,8 +2005,8 @@ sk_intr_bcom(sc_if)
if (status & (BRGPHY_ISR_LNK_CHG|BRGPHY_ISR_AN_PR)) {
int lstat;
- lstat = sk_miibus_readreg(sc_if->sk_dev,
- SK_PHYADDR_BCOM, BRGPHY_MII_AUXSTS);
+ lstat = sk_xmac_miibus_readreg(sc_if, SK_PHYADDR_BCOM,
+ BRGPHY_MII_AUXSTS);
if (!(lstat & BRGPHY_AUXSTS_LINK) && sc_if->sk_link) {
mii_mediachg(mii);
@@ -1750,7 +2015,7 @@ sk_intr_bcom(sc_if)
SK_LINKLED1_CTL, SK_LINKLED_OFF);
sc_if->sk_link = 0;
} else if (status & BRGPHY_ISR_LNK_CHG) {
- sk_miibus_writereg(sc_if->sk_dev, SK_PHYADDR_BCOM,
+ sk_xmac_miibus_writereg(sc_if, SK_PHYADDR_BCOM,
BRGPHY_MII_IMR, 0xFF00);
mii_tick(mii);
sc_if->sk_link = 1;
@@ -1806,6 +2071,17 @@ sk_intr_xmac(sc_if)
}
static void
+sk_intr_yukon(sc_if)
+ struct sk_if_softc *sc_if;
+{
+ int status;
+
+ status = SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR);
+
+ return;
+}
+
+static void
sk_intr(xsc)
void *xsc;
{
@@ -1854,18 +2130,26 @@ sk_intr(xsc)
}
/* Then MAC interrupts. */
- if (status & SK_ISR_MAC1 &&
- ifp0->if_flags & IFF_RUNNING)
- sk_intr_xmac(sc_if0);
+ if (status & SK_ISR_MAC1 && ifp0->if_flags & IFF_RUNNING) {
+ if (sc->sk_type == SK_GENESIS)
+ sk_intr_xmac(sc_if0);
+ else
+ sk_intr_yukon(sc_if0);
+ }
- if (status & SK_ISR_MAC2 &&
- ifp1->if_flags & IFF_RUNNING)
- sk_intr_xmac(sc_if1);
+ if (status & SK_ISR_MAC2 && ifp1->if_flags & IFF_RUNNING) {
+ if (sc->sk_type == SK_GENESIS)
+ sk_intr_xmac(sc_if1);
+ else
+ sk_intr_yukon(sc_if0);
+ }
if (status & SK_ISR_EXTERNAL_REG) {
- if (ifp0 != NULL)
+ if (ifp0 != NULL &&
+ sc_if0->sk_phytype == SK_PHYTYPE_BCOM)
sk_intr_bcom(sc_if0);
- if (ifp1 != NULL)
+ if (ifp1 != NULL &&
+ sc_if1->sk_phytype == SK_PHYTYPE_BCOM)
sk_intr_bcom(sc_if1);
}
}
@@ -1927,10 +2211,10 @@ sk_init_xmac(sc_if)
/* Enable GMII mode on the XMAC. */
SK_XM_SETBIT_2(sc_if, XM_HWCFG, XM_HWCFG_GMIIMODE);
- sk_miibus_writereg(sc_if->sk_dev, SK_PHYADDR_BCOM,
+ sk_xmac_miibus_writereg(sc_if, SK_PHYADDR_BCOM,
BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
DELAY(10000);
- sk_miibus_writereg(sc_if->sk_dev, SK_PHYADDR_BCOM,
+ sk_xmac_miibus_writereg(sc_if, SK_PHYADDR_BCOM,
BRGPHY_MII_IMR, 0xFFF0);
/*
@@ -1939,12 +2223,11 @@ sk_init_xmac(sc_if)
* registers initialized to some magic values. I don't
* know what the numbers do, I'm just the messenger.
*/
- if (sk_miibus_readreg(sc_if->sk_dev,
- SK_PHYADDR_BCOM, 0x03) == 0x6041) {
+ if (sk_xmac_miibus_readreg(sc_if, SK_PHYADDR_BCOM, 0x03)
+ == 0x6041) {
while(bhack[i].reg) {
- sk_miibus_writereg(sc_if->sk_dev,
- SK_PHYADDR_BCOM, bhack[i].reg,
- bhack[i].val);
+ sk_xmac_miibus_writereg(sc_if, SK_PHYADDR_BCOM,
+ bhack[i].reg, bhack[i].val);
i++;
}
}
@@ -2051,6 +2334,101 @@ sk_init_xmac(sc_if)
return;
}
+static void sk_init_yukon(sc_if)
+ struct sk_if_softc *sc_if;
+{
+ u_int32_t phy;
+ u_int16_t reg;
+ int i;
+
+ /* GMAC and GPHY Reset */
+ SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET);
+ SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET);
+ DELAY(1000);
+ SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_CLEAR);
+ SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_RESET_SET);
+ DELAY(1000);
+
+ phy = SK_GPHY_INT_POL_HI | SK_GPHY_DIS_FC | SK_GPHY_DIS_SLEEP |
+ SK_GPHY_ENA_XC | SK_GPHY_ANEG_ALL | SK_GPHY_ENA_PAUSE;
+
+ switch(sc_if->sk_softc->sk_pmd) {
+ case IFM_1000_SX:
+ case IFM_1000_LX:
+ phy |= SK_GPHY_FIBER;
+ break;
+
+ case IFM_1000_CX:
+ case IFM_1000_T:
+ phy |= SK_GPHY_COPPER;
+ break;
+ }
+
+ SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_SET);
+ DELAY(1000);
+ SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, phy | SK_GPHY_RESET_CLEAR);
+ SK_IF_WRITE_4(sc_if, 0, SK_GMAC_CTRL, SK_GMAC_LOOP_OFF |
+ SK_GMAC_PAUSE_ON | SK_GMAC_RESET_CLEAR);
+
+ /* unused read of the interrupt source register */
+ SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR);
+
+ reg = SK_YU_READ_2(sc_if, YUKON_PAR);
+
+ /* MIB Counter Clear Mode set */
+ reg |= YU_PAR_MIB_CLR;
+ SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
+
+ /* MIB Counter Clear Mode clear */
+ reg &= ~YU_PAR_MIB_CLR;
+ SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
+
+ /* receive control reg */
+ SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_UFLEN | YU_RCR_MUFLEN |
+ YU_RCR_CRCR);
+
+ /* transmit parameter register */
+ SK_YU_WRITE_2(sc_if, YUKON_TPR, YU_TPR_JAM_LEN(0x3) |
+ YU_TPR_JAM_IPG(0xb) | YU_TPR_JAM2DATA_IPG(0x1a) );
+
+ /* serial mode register */
+ SK_YU_WRITE_2(sc_if, YUKON_SMR, YU_SMR_DATA_BLIND(0x1c) |
+ YU_SMR_MFL_VLAN | YU_SMR_IPG_DATA(0x1e));
+
+ /* Setup Yukon's address */
+ for (i = 0; i < 3; i++) {
+ /* Write Source Address 1 (unicast filter) */
+ SK_YU_WRITE_2(sc_if, YUKON_SAL1 + i * 4,
+ sc_if->arpcom.ac_enaddr[i * 2] |
+ sc_if->arpcom.ac_enaddr[i * 2 + 1] << 8);
+ }
+
+ for (i = 0; i < 3; i++) {
+ reg = sk_win_read_2(sc_if->sk_softc,
+ SK_MAC1_0 + i * 2 + sc_if->sk_port * 8);
+ SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg);
+ }
+
+ /* clear all Multicast filter hash registers */
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
+
+ /* enable interrupt mask for counter overflows */
+ SK_YU_WRITE_2(sc_if, YUKON_TIMR, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_RIMR, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_TRIMR, 0);
+
+ /* Configure RX MAC FIFO */
+ SK_IF_WRITE_1(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_CLEAR);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXMF1_CTRL_TEST, SK_RFCTL_OPERATION_ON);
+
+ /* Configure TX MAC FIFO */
+ SK_IF_WRITE_1(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_CLEAR);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXMF1_CTRL_TEST, SK_TFCTL_OPERATION_ON);
+}
+
/*
* Note that to properly initialize any part of the GEnesis chip,
* you first have to take it out of reset mode.
@@ -2063,6 +2441,7 @@ sk_init(xsc)
struct sk_softc *sc;
struct ifnet *ifp;
struct mii_data *mii;
+ u_int16_t reg;
SK_IF_LOCK(sc_if);
@@ -2073,30 +2452,44 @@ sk_init(xsc)
/* Cancel pending I/O and free all RX/TX buffers. */
sk_stop(sc_if);
- /* Configure LINK_SYNC LED */
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON);
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_ON);
+ if (sc->sk_type == SK_GENESIS) {
+ /* Configure LINK_SYNC LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON);
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL,
+ SK_LINKLED_LINKSYNC_ON);
- /* Configure RX LED */
- SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_START);
+ /* Configure RX LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL,
+ SK_RXLEDCTL_COUNTER_START);
- /* Configure TX LED */
- SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_START);
+ /* Configure TX LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL,
+ SK_TXLEDCTL_COUNTER_START);
+ }
/* Configure I2C registers */
/* Configure XMAC(s) */
- sk_init_xmac(sc_if);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_init_xmac(sc_if);
+ break;
+ case SK_YUKON:
+ sk_init_yukon(sc_if);
+ break;
+ }
mii_mediachg(mii);
- /* Configure MAC FIFOs */
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
+ if (sc->sk_type == SK_GENESIS) {
+ /* Configure MAC FIFOs */
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
+ }
/* Configure transmit arbiter(s) */
SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL,
@@ -2153,9 +2546,18 @@ sk_init(xsc)
/* Start BMUs. */
SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_START);
- /* Enable XMACs TX and RX state machines */
- SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE);
- SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ /* Enable XMACs TX and RX state machines */
+ SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE);
+ SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+ break;
+ case SK_YUKON:
+ reg = SK_YU_READ_2(sc_if, YUKON_GPCR);
+ reg |= YU_GPCR_TXEN | YU_GPCR_RXEN;
+ reg &= ~(YU_GPCR_SPEED_EN | YU_GPCR_DPLX_EN);
+ SK_YU_WRITE_2(sc_if, YUKON_GPCR, reg);
+ }
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -2196,8 +2598,16 @@ sk_stop(sc_if)
/* Turn off various components of this interface. */
SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
- SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_RESET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_RESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
+ break;
+ case SK_YUKON:
+ SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
+ SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
+ break;
+ }
SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE);
OpenPOWER on IntegriCloud