3C940 / Asus P4P800 gigabit LAN driver

Stuart Walsh stu at ipng.org.uk
Sat Aug 23 08:43:33 PDT 2003


Hi,

I ported the openbsd additions to the sk driver to support the 3c940
gigabit network card which is commonly found in the above asus
motherboard.  Testers/comments/commits welcome, but please don't blame
me if it burns your house down or something :)

Apply the diff in /usr/src/sys.  It will have to be a fairly recent
-current because of the recent pci header reloactions.

Please be aware that I have had reports of panics on kldunloading the sk
module.  I don't posess the hardware myself and this could be present in
the sk driver in general, so more information on this would be greatly
received.

Regards,

Stuart Walsh
-------------- next part --------------
Index: dev/mii/e1000phy.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/e1000phy.c,v
retrieving revision 1.8
diff -u -r1.8 e1000phy.c
--- dev/mii/e1000phy.c	19 Jan 2003 02:59:32 -0000	1.8
+++ dev/mii/e1000phy.c	23 Aug 2003 15:17:42 -0000
@@ -87,7 +86,8 @@
 	ma = device_get_ivars(dev);
 	id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
 
-	if (id != E1000_ID_88E1000 && id != E1000_ID_88E1000S) {
+	if (id != E1000_ID_88E1000 && id != E1000_ID_88E1000S && 
+            id != E1011_ID) {
 		return ENXIO;
 	}
 
@@ -101,6 +101,9 @@
 	struct mii_softc *sc;
 	struct mii_attach_args *ma;
 	struct mii_data *mii;
+#if 0
+    u_int32_t id;
+#endif
 
 	getenv_int("e1000phy_debug", &e1000phy_debug);
 
@@ -117,6 +120,14 @@
 
 	sc->mii_flags |= MIIF_NOISOLATE;
 	mii->mii_instance++;
+
+#if 0
+    id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
+
+    if ((id == E1011_ID) && (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK))
+        sc->mii_flags |= MIIF_HAVEFIBER;
+#endif
+    
 	e1000phy_reset(sc);
 
 	device_printf(dev, " ");
@@ -126,27 +137,37 @@
 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
 	    E1000_CR_ISOLATE);
 */
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
-	    E1000_CR_SPEED_10);
-	printf("10baseT, ");
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
-	    E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
-	printf("10baseT-FDX, ");
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
-	    E1000_CR_SPEED_100);
-	printf("100baseTX, ");
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
-	    E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
-	printf("100baseTX-FDX, ");
-	/*
-	 * 1000BT-simplex not supported; driver must ignore this entry,
-	 * but it must be present in order to manually set full-duplex.
-	 */
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
-	    E1000_CR_SPEED_1000);
-	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
-	    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
-	printf("1000baseTX-FDX, ");
+#if 0
+    if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+#endif
+    	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
+	        E1000_CR_SPEED_10);
+    	printf("10baseT, ");
+    	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
+    	    E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
+    	printf("10baseT-FDX, ");
+    	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
+    	    E1000_CR_SPEED_100);
+    	printf("100baseTX, ");
+    	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
+    	    E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
+    	printf("100baseTX-FDX, ");
+	    /*
+    	 * 1000BT-simplex not supported; driver must ignore this entry,
+    	 * but it must be present in order to manually set full-duplex.
+    	 */
+	    ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
+	        E1000_CR_SPEED_1000);
+    	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
+    	    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
+    	printf("1000baseTX-FDX, ");
+#if 0
+    } else {
+        ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,sc->mii_inst),
+                E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
+    }
+#endif
+        
 	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
 	printf("auto\n");
 #undef ADD
@@ -233,6 +254,13 @@
 			(void)e1000phy_mii_phy_auto(sc);
 			break;
 
+        case IFM_1000_SX:
+            e1000phy_reset(sc);
+                
+            PHY_WRITE(sc, E1000_CR, E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_1000);
+            PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD);
+            break;
+
 		case IFM_1000_T:
 			e1000phy_reset(sc);
 
@@ -351,40 +379,64 @@
 		return;
 	}
 
-	if (ssr & E1000_SSR_1000MBS)
-		mii->mii_media_active |= IFM_1000_T;
-	else if (ssr & E1000_SSR_100MBS)
-		mii->mii_media_active |= IFM_100_TX;
-	else
-		mii->mii_media_active |= IFM_10_T;
+#if 0 
+    if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+#endif
+    	if (ssr & E1000_SSR_1000MBS)
+    		mii->mii_media_active |= IFM_1000_T;
+    	else if (ssr & E1000_SSR_100MBS)
+    		mii->mii_media_active |= IFM_100_TX;
+    	else
+    		mii->mii_media_active |= IFM_10_T;
+#if 0
+    } else {
+        if (ssr & E1000_SSR_1000MBS)
+            mii->mii_media_active |= IFM_1000_SX;
+    }
+#endif
 
 	if (ssr & E1000_SSR_DUPLEX)
 		mii->mii_media_active |= IFM_FDX;
 	else
 		mii->mii_media_active |= IFM_HDX;
 
-	/* FLAG0==rx-flow-control FLAG1==tx-flow-control */
-	if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) {
-		mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
-	} else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
-	    (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
-		mii->mii_media_active |= IFM_FLAG1;
-	} else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
-	    !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
-		mii->mii_media_active |= IFM_FLAG0;
-	}
+#if 0
+	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+        /* FLAG0==rx-flow-control FLAG1==tx-flow-control */
+#endif
+    	if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) {
+    		mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
+    	} else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
+    	    (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
+    		mii->mii_media_active |= IFM_FLAG1;
+    	} else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
+    	    !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
+	    	mii->mii_media_active |= IFM_FLAG0;
+    	}
+#if 0
+    }
+#endif
 }
 
 static int
 e1000phy_mii_phy_auto(struct mii_softc *mii)
 {
-
-	PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
-	    E1000_AR_100TX | E1000_AR_100TX_FD | 
-	    E1000_AR_PAUSE | E1000_AR_ASM_DIR);
-	PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
-	PHY_WRITE(mii, E1000_CR,
-	    E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
+#if 0
+	if ((mii->mii_flags & MIIF_HAVEFIBER) == 0) {
+#endif
+        PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
+	        E1000_AR_100TX | E1000_AR_100TX_FD | 
+    	    E1000_AR_PAUSE | E1000_AR_ASM_DIR);
+    	PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
+#if 0
+    } else {
+        PHY_WRITE(mii, E1000_AR, E1000_FA_1000X_FD |
+                E1000_FA_SYM_PAUSE | E1000_FA_ASYM_PAUSE);
+   }
+#endif
+    
+   PHY_WRITE(mii, E1000_CR, 
+           E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
 
 	return (EJUSTRETURN);
 }
Index: dev/mii/e1000phyreg.h
===================================================================
RCS file: /home/ncvs/src/sys/dev/mii/e1000phyreg.h,v
retrieving revision 1.1
diff -u -r1.1 e1000phyreg.h
--- dev/mii/e1000phyreg.h	9 Apr 2001 21:28:53 -0000	1.1
+++ dev/mii/e1000phyreg.h	23 Aug 2003 15:17:42 -0000
@@ -108,6 +108,7 @@
 #define E1000_ID_88E1000		0x01410C50
 #define E1000_ID_88E1000S		0x01410C40
 #define E1000_ID_MASK			0xFFFFFFF0
+#define E1011_ID                0x01410c20
 
 #define E1000_AR			0x04	/* autonegotiation advertise reg */
 #define E1000_AR_SELECTOR_FIELD		0x0001
@@ -284,3 +285,31 @@
 #define E1000_LCR_PULSE_340_670MS	0x5000
 #define E1000_LCR_PULSE_670_13S		0x6000
 #define E1000_LCR_PULSE_13_26S		0x7000
+
+/* Autonegotiation register bits for fiber cards (Alaska Only!) */
+#define E1000_FA_1000X_FD      0x0020
+#define E1000_FA_1000X         0x0040
+#define E1000_FA_SYM_PAUSE     0x0080
+#define E1000_FA_ASYM_PAUSE        0x0100
+#define E1000_FA_FAULT1            0x1000
+#define E1000_FA_FAULT2            0x2000
+#define E1000_FA_NEXT_PAGE     0x8000
+
+/* autoneg link partner ability register bits for fiber cards (Alaska Only!) */
+#define E1000_FPAR_1000X_FD        0x0020
+#define E1000_FPAR_1000X       0x0040
+#define E1000_FPAR_SYM_PAUSE       0x0080
+#define E1000_FPAR_ASYM_PAUSE      0x0100
+#define E1000_FPAR_FAULT1      0x1000
+#define E1000_FPAR_FAULT2      0x2000
+#define E1000_FPAR_ACK         0x4000
+#define E1000_FPAR_NEXT_PAGE       0x8000
+
+/* The following register is found only on the 88E1011 Alaska PHY */
+#define E1000_ESSR         0x1B    /* Extended PHY specific sts */
+#define E1000_ESSR_FIBER_LINK      0x2000
+#define E1000_ESSR_GMII_COPPER     0x000f
+#define E1000_ESSR_GMII_FIBER      0x0007
+#define E1000_ESSR_TBI_COPPER      0x000d
+#define E1000_ESSR_TBI_FIBER       0x0005
+
Index: pci/if_sk.c
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_sk.c,v
retrieving revision 1.64
diff -u -r1.64 if_sk.c
--- pci/if_sk.c	22 Aug 2003 07:13:21 -0000	1.64
+++ pci/if_sk.c	23 Aug 2003 15:17:42 -0000
@@ -106,6 +106,7 @@
 
 #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);
@@ -121,6 +122,7 @@
 
 static struct sk_type sk_devs[] = {
 	{ SK_VENDORID, SK_DEVICEID_GE, "SysKonnect Gigabit Ethernet" },
+    { SK_VENDOR_3COM, SK_DEVICE_3C940, "3Com 3C940 Gigabit Ethernet" },
 	{ 0, 0, NULL }
 };
 
@@ -134,6 +136,7 @@
 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,6 +145,7 @@
 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);
@@ -165,6 +169,10 @@
 static void sk_vpd_read_res	(struct sk_softc *, struct vpd_res *, int);
 static void sk_vpd_read		(struct sk_softc *);
 
+static int sk_marv_miibus_readreg(device_t, int, int);
+static int sk_marv_miibus_writereg(device_t, int, int, int);
+static void sk_marv_miibus_statchg(device_t);
+
 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);
@@ -414,14 +422,86 @@
 }
 
 static int
+sk_marv_miibus_readreg(dev, phy, reg)
+   struct device *dev;
+   int phy, reg;
+{
+    struct sk_if_softc *sc_if;
+    u_int16_t val;
+    int i;
+
+    sc_if = device_get_softc(dev);
+
+    if (phy != 0)
+        return(0);
+
+    if (sc_if->sk_phytype != SK_PHYTYPE_MARV_COPPER &&
+         sc_if->sk_phytype != SK_PHYTYPE_MARV_FIBER)
+       return(0);
+
+    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);
+        return 0;
+    }
+
+    val = SK_YU_READ_2(sc_if, YUKON_SMIDR);
+
+    return val;
+}
+
+static int
+sk_marv_miibus_writereg(dev, phy, reg, val)
+   struct device *dev;
+   int phy, reg, val;
+{
+    struct sk_if_softc *sc_if;
+    int i;
+
+    sc_if = device_get_softc(dev);
+
+    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;
+    }
+    return(0);
+}
+
+static void
+sk_marv_miibus_statchg(dev)
+   struct device *dev;
+{
+}
+
+static int
 sk_miibus_readreg(dev, phy, reg)
 	device_t		dev;
 	int			phy, reg;
 {
 	struct sk_if_softc	*sc_if;
+    struct sk_softc     *sc;
 	int			i;
 
 	sc_if = device_get_softc(dev);
+    sc = sc_if->sk_softc;
+
+    if (sc->sk_type == SK_YUKON)
+        return(sk_marv_miibus_readreg(dev, phy, reg));
 
 	if (sc_if->sk_phytype == SK_PHYTYPE_XMAC && phy != 0)
 		return(0);
@@ -456,9 +536,15 @@
 	int			phy, reg, val;
 {
 	struct sk_if_softc	*sc_if;
+    struct sk_softc     *sc;
 	int			i;
 
 	sc_if = device_get_softc(dev);
+    sc = sc_if->sk_softc;
+
+    if (sc->sk_type == SK_YUKON)
+        return(sk_marv_miibus_writereg(dev, phy, reg, val));
+
 	SK_IF_LOCK(sc_if);
 
 	SK_XM_WRITE_2(sc_if, XM_PHY_ADDR, reg|(phy << 8));
@@ -492,9 +578,15 @@
 	device_t		dev;
 {
 	struct sk_if_softc	*sc_if;
+    struct sk_softc     *sc;
 	struct mii_data		*mii;
 
 	sc_if = device_get_softc(dev);
+
+    sc = sc_if->sk_softc;
+    if (sc->sk_type == SK_YUKON)
+        return(sk_marv_miibus_statchg(dev));
+
 	mii = device_get_softc(sc_if->sk_miibus);
 	SK_IF_LOCK(sc_if);
 	/*
@@ -554,7 +646,8 @@
 sk_setmulti(sc_if)
 	struct sk_if_softc	*sc_if;
 {
-	struct ifnet		*ifp;
+	struct sk_softc *sc = sc_if->sk_softc;
+    struct ifnet		*ifp;
 	u_int32_t		hashes[2] = { 0, 0 };
 	int			h, i;
 	struct ifmultiaddr	*ifma;
@@ -563,10 +656,21 @@
 	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 +686,7 @@
 			 * 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,11 +702,21 @@
 		}
 	}
 
-	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;
 }
 
@@ -895,6 +1009,7 @@
 	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 +1030,28 @@
 			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);
@@ -984,18 +1113,26 @@
 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);
-
-	/* 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);
+    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);
+ 
+    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);
@@ -1123,6 +1260,9 @@
 	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);
@@ -1174,8 +1314,19 @@
 	/*
 	 * Do miibus setup.
 	 */
-	sk_init_xmac(sc_if);
-	if (mii_phy_probe(dev, &sc_if->sk_miibus,
+    switch(sc->sk_type) {
+    case SK_GENESIS: 
+	    sk_init_xmac(sc_if);
+        break;
+    case SK_YUKON:
+        sk_init_yukon(sc_if);
+        break;
+    default:
+        panic("skc%d: unknown device type %d", sc_if->sk_unit, sc->sk_type);
+
+    }
+	
+    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);
@@ -1210,6 +1361,7 @@
 
 	mtx_init(&sc->sk_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
 	    MTX_DEF | MTX_RECURSE);
+
 #ifndef BURN_BRIDGES
 	/*
 	 * Handle power management nonsense.
@@ -1271,30 +1423,48 @@
 	/* Read and save vital product data from EEPROM. */
 	sk_vpd_read(sc);
 
+    /* Decide which chip we have */
+    switch(pci_get_device(dev)) {
+    case SK_DEVICEID_GE:
+        sc->sk_type = SK_GENESIS;
+        break;
+    case SK_DEVICE_3C940:
+        sc->sk_type = SK_YUKON;
+        break;
+    default:
+        printf(": unknown device!\n");
+        goto fail;
+    }
+
 	/* 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;
-	}
+	if(sc->sk_type == SK_GENESIS) {
+        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;
+    }
 
 	/* Read and save physical media type */
 	switch(sk_win_read_1(sc, SK_PMDTYPE)) {
@@ -1805,6 +1975,15 @@
 	return;
 }
 
+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);
+}
+
 static void
 sk_intr(xsc)
 	void			*xsc;
@@ -1854,18 +2033,26 @@
 		}
 
 		/* Then MAC interrupts. */
-		if (status & SK_ISR_MAC1 &&
-		    ifp0->if_flags & IFF_RUNNING)
-			sk_intr_xmac(sc_if0);
-
-		if (status & SK_ISR_MAC2 &&
-		    ifp1->if_flags & IFF_RUNNING)
-			sk_intr_xmac(sc_if1);
+		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) {
+			if (sc->sk_type == SK_GENESIS)
+                sk_intr_xmac(sc_if1);
+            else
+                sk_intr_yukon(sc_if1);
+        }
 
 		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);
 		}
 	}
@@ -2051,6 +2238,103 @@
 	return;
 }
 
+void sk_init_yukon(sc_if)
+    struct sk_if_softc  *sc_if;
+{
+    u_int32_t       /*mac, */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_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.
@@ -2073,30 +2357,41 @@
 	/* 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);
-
-	/* 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);
+    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 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);
-
-	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);
+	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);
+    }
 
 	/* Configure transmit arbiter(s) */
 	SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL,
@@ -2153,9 +2448,18 @@
 	/* 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);
+	if(sc->sk_type == 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);
+    }
+
+    if(sc->sk_type == SK_YUKON) {
+        u_int16_t 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 +2500,17 @@
 
 	/* 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);
Index: pci/if_skreg.h
===================================================================
RCS file: /home/ncvs/src/sys/pci/if_skreg.h,v
retrieving revision 1.15
diff -u -r1.15 if_skreg.h
--- pci/if_skreg.h	9 Feb 2001 06:11:20 -0000	1.15
+++ pci/if_skreg.h	23 Aug 2003 15:17:42 -0000
@@ -36,11 +36,18 @@
  * SysKonnect PCI vendor ID
  */
 #define SK_VENDORID		0x1148
+#define SK_VENDOR_3COM   0x10b7
 
 /*
  * SK-NET gigabit ethernet device ID
  */
 #define SK_DEVICEID_GE		0x4300
+#define SK_DEVICE_3C940   0x1700
+
+/* Values to keep the different chip revisions apart */
+#define SK_GENESIS 0
+#define SK_YUKON 1
+
 
 /*
  * GEnesis registers. The GEnesis chip has a 256-byte I/O window
@@ -328,6 +335,9 @@
 #define SK_PHYTYPE_BCOM		1	/* Broadcom BCM5400 */
 #define SK_PHYTYPE_LONE		2	/* Level One LXT1000 */
 #define SK_PHYTYPE_NAT		3	/* National DP83891 */
+#define SK_PHYTYPE_MARV_COPPER 4       /* Marvell 88E1011S */
+#define SK_PHYTYPE_MARV_FIBER  5       /* Marvell 88E1011S (fiber) */
+    
 
 /*
  * PHY addresses.
@@ -336,6 +346,8 @@
 #define SK_PHYADDR_BCOM		0x1
 #define SK_PHYADDR_LONE		0x3
 #define SK_PHYADDR_NAT		0x0
+#define SK_PHYADDR_MARV     0x0
+
 
 #define SK_CONFIG_SINGLEMAC	0x01
 #define SK_CONFIG_DIS_DSL_CLK	0x02
@@ -805,6 +817,29 @@
 
 #define SK_FIFO_END		0x3F
 
+/* Receive MAC FIFO 1 (Yukon Only) */
+#define SK_RXMF1_END       0x0C40
+#define SK_RXMF1_THRESHOLD 0x0C44
+#define SK_RXMF1_CTRL_TEST 0x0C48
+#define SK_RXMF1_WRITE_PTR 0x0C60
+#define SK_RXMF1_WRITE_LEVEL   0x0C68
+#define SK_RXMF1_READ_PTR  0x0C70
+#define SK_RXMF1_READ_LEVEL    0x0C78
+
+#define SK_RFCTL_WR_PTR_TST_ON 0x00004000  /* Write pointer test on*/
+#define SK_RFCTL_WR_PTR_TST_OFF    0x00002000  /* Write pointer test off */
+#define SK_RFCTL_WR_PTR_STEP   0x00001000  /* Write pointer increment */
+#define SK_RFCTL_RD_PTR_TST_ON 0x00000400  /* Read pointer test on */
+#define SK_RFCTL_RD_PTR_TST_OFF    0x00000200  /* Read pointer test off */
+#define SK_RFCTL_RD_PTR_STEP   0x00000100  /* Read pointer increment */
+#define SK_RFCTL_RX_FIFO_OVER  0x00000040  /* Clear IRQ RX FIFO Overrun */
+#define SK_RFCTL_FRAME_RX_DONE 0x00000010  /* Clear IRQ Frame RX Done */
+#define SK_RFCTL_OPERATION_ON  0x00000008  /* Operational mode on */
+#define SK_RFCTL_OPERATION_OFF 0x00000004  /* Operational mode off */
+#define SK_RFCTL_RESET_CLEAR   0x00000002  /* MAC FIFO Reset Clear */
+#define SK_RFCTL_RESET_SET 0x00000001  /* MAC FIFO Reset Set */
+
+
 /* Block 25 -- RX MAC FIFO 2 regisrers and LINK_SYNC counter */
 #define SK_RXF2_END		0x0C80
 #define SK_RXF2_WPTR		0x0C84
@@ -864,6 +899,31 @@
 #define SK_TXLED1_CTL		0x0D28
 #define SK_TXLED1_TST		0x0D29
 
+/* Receive MAC FIFO 1 (Yukon Only) */
+#define SK_TXMF1_END       0x0D40
+#define SK_TXMF1_THRESHOLD 0x0D44
+#define SK_TXMF1_CTRL_TEST 0x0D48
+#define SK_TXMF1_WRITE_PTR 0x0D60
+#define SK_TXMF1_WRITE_SHADOW  0x0D64
+#define SK_TXMF1_WRITE_LEVEL   0x0D68
+#define SK_TXMF1_READ_PTR  0x0D70
+#define SK_TXMF1_RESTART_PTR   0x0D74
+#define SK_TXMF1_READ_LEVEL    0x0D78
+
+#define SK_TFCTL_WR_PTR_TST_ON 0x00004000  /* Write pointer test on*/
+#define SK_TFCTL_WR_PTR_TST_OFF    0x00002000  /* Write pointer test off */
+#define SK_TFCTL_WR_PTR_STEP   0x00001000  /* Write pointer increment */
+#define SK_TFCTL_RD_PTR_TST_ON 0x00000400  /* Read pointer test on */
+#define SK_TFCTL_RD_PTR_TST_OFF    0x00000200  /* Read pointer test off */
+#define SK_TFCTL_RD_PTR_STEP   0x00000100  /* Read pointer increment */
+#define SK_TFCTL_TX_FIFO_UNDER 0x00000040  /* Clear IRQ TX FIFO Under */
+#define SK_TFCTL_FRAME_TX_DONE 0x00000020  /* Clear IRQ Frame TX Done */
+#define SK_TFCTL_IRQ_PARITY_ER 0x00000010  /* Clear IRQ Parity Error */
+#define SK_TFCTL_OPERATION_ON  0x00000008  /* Operational mode on */
+#define SK_TFCTL_OPERATION_OFF 0x00000004  /* Operational mode off */
+#define SK_TFCTL_RESET_CLEAR   0x00000002  /* MAC FIFO Reset Clear */
+#define SK_TFCTL_RESET_SET 0x00000001  /* MAC FIFO Reset Set */
+
 /* Block 27 -- TX MAC FIFO 2 regisrers  */
 #define SK_TXF2_END		0x0D80
 #define SK_TXF2_WPTR		0x0D84
@@ -903,6 +963,114 @@
 #define SK_FIFO_OFF		0x00000004
 #define SK_FIFO_ON		0x00000008
 
+/* Block 28 -- Descriptor Poll Timer */
+#define SK_DPT_INIT        0x0e00  /* Initial value 24 bits */
+#define SK_DPT_TIMER       0x0e04  /* Mul of 78.12MHz clk (24b) */
+
+#define SK_DPT_TIMER_CTRL  0x0e08  /* Timer Control 16 bits */
+#define SK_DPT_TCTL_STOP   0x0001  /* Stop Timer */
+#define SK_DPT_TCTL_START  0x0002  /* Start Timer */
+
+#define SK_DPT_TIMER_TEST  0x0e0a  /* Timer Test 16 bits */
+#define SK_DPT_TTEST_STEP  0x0001  /* Timer Decrement */
+#define SK_DPT_TTEST_OFF   0x0002  /* Test Mode Off */
+#define SK_DPT_TTEST_ON        0x0004  /* Test Mode On */
+
+/* Block 29 -- reserved */
+
+/* Block 30 -- GMAC/GPHY Control Registers (Yukon Only)*/
+#define SK_GMAC_CTRL       0x0f00  /* GMAC Control Register */
+#define SK_GPHY_CTRL       0x0f04  /* GPHY Control Register */
+#define SK_GMAC_ISR        0x0f08  /* GMAC Interrupt Source Register */
+#define SK_GMAC_IMR        0x0f08  /* GMAC Interrupt Mask Register */
+#define SK_LINK_CTRL       0x0f10  /* Link Control Register (LCR) */
+#define SK_WOL_CTRL        0x0f20  /* Wake on LAN Control Register */
+#define SK_MAC_ADDR_LOW        0x0f24  /* Mack Address Registers LOW */
+#define SK_MAC_ADDR_HIGH   0x0f28  /* Mack Address Registers HIGH */
+#define SK_PAT_READ_PTR        0x0f2c  /* Pattern Read Pointer Register */
+#define SK_PAT_LEN_REG0        0x0f30  /* Pattern Length Register 0 */
+#define SK_PAT_LEN0        0x0f30  /* Pattern Length 0 */
+#define SK_PAT_LEN1        0x0f31  /* Pattern Length 1 */
+#define SK_PAT_LEN2        0x0f32  /* Pattern Length 2 */
+#define SK_PAT_LEN3        0x0f33  /* Pattern Length 3 */
+#define SK_PAT_LEN_REG1        0x0f34  /* Pattern Length Register 1 */
+#define SK_PAT_LEN4        0x0f34  /* Pattern Length 4 */
+#define SK_PAT_LEN5        0x0f35  /* Pattern Length 5 */
+#define SK_PAT_LEN6        0x0f36  /* Pattern Length 6 */
+#define SK_PAT_LEN7        0x0f37  /* Pattern Length 7 */
+#define SK_PAT_CTR_REG0        0x0f38  /* Pattern Counter Register 0 */
+#define SK_PAT_CTR0        0x0f38  /* Pattern Counter 0 */
+#define SK_PAT_CTR1        0x0f39  /* Pattern Counter 1 */
+#define SK_PAT_CTR2        0x0f3a  /* Pattern Counter 2 */
+#define SK_PAT_CTR3        0x0f3b  /* Pattern Counter 3 */
+#define SK_PAT_CTR_REG1        0x0f3c  /* Pattern Counter Register 1 */
+#define SK_PAT_CTR4        0x0f3c  /* Pattern Counter 4 */
+#define SK_PAT_CTR5        0x0f3d  /* Pattern Counter 5 */
+#define SK_PAT_CTR6        0x0f3e  /* Pattern Counter 6 */
+#define SK_PAT_CTR7        0x0f3f  /* Pattern Counter 7 */
+
+#define SK_GMAC_LOOP_ON        0x00000020  /* Loopback mode for testing */
+#define SK_GMAC_LOOP_OFF   0x00000010  /* purposes */
+#define SK_GMAC_PAUSE_ON   0x00000008  /* enable forward of pause */
+#define SK_GMAC_PAUSE_OFF  0x00000004  /* signal to GMAC */
+#define SK_GMAC_RESET_CLEAR    0x00000002  /* Clear GMAC Reset */
+#define SK_GMAC_RESET_SET  0x00000001  /* Set GMAC Reset */
+
+#define SK_GPHY_SEL_BDT        0x10000000  /* Select Bidirectional xfer */
+#define SK_GPHY_INT_POL_HI 0x08000000  /* IRQ Polarity Active */
+#define SK_GPHY_75_OHM     0x04000000  /* Use 75 Ohm Termination */
+#define SK_GPHY_DIS_FC     0x02000000  /* Disable Auto Fiber/Copper */
+#define SK_GPHY_DIS_SLEEP  0x01000000  /* Disable Energy Detect */
+#define SK_GPHY_HWCFG_M_3  0x00800000  /* HWCFG_MODE[3] */
+#define SK_GPHY_HWCFG_M_2  0x00400000  /* HWCFG_MODE[2] */
+#define SK_GPHY_HWCFG_M_1  0x00200000  /* HWCFG_MODE[1] */
+#define SK_GPHY_HWCFG_M_0  0x00100000  /* HWCFG_MODE[0] */
+#define SK_GPHY_ANEG_0     0x00080000  /* ANEG[0] */
+#define SK_GPHY_ENA_XC     0x00040000  /* Enable MDI Crossover */
+#define SK_GPHY_DIS_125        0x00020000  /* Disable 125MHz Clock */
+#define SK_GPHY_ANEG_3     0x00010000  /* ANEG[3] */
+#define SK_GPHY_ANEG_2     0x00008000  /* ANEG[2] */
+#define SK_GPHY_ANEG_1     0x00004000  /* ANEG[1] */
+#define SK_GPHY_ENA_PAUSE  0x00002000  /* Enable Pause */
+#define SK_GPHY_PHYADDR_4  0x00001000  /* Bit 4 of Phy Addr */
+#define SK_GPHY_PHYADDR_3  0x00000800  /* Bit 3 of Phy Addr */
+#define SK_GPHY_PHYADDR_2  0x00000400  /* Bit 2 of Phy Addr */
+#define SK_GPHY_PHYADDR_1  0x00000200  /* Bit 1 of Phy Addr */
+#define SK_GPHY_PHYADDR_0  0x00000100  /* Bit 0 of Phy Addr */
+#define SK_GPHY_RESET_CLEAR    0x00000002  /* Clear GPHY Reset */
+#define SK_GPHY_RESET_SET  0x00000001  /* Set GPHY Reset */
+
+#define SK_GPHY_COPPER     (SK_GPHY_HWCFG_M_0 | SK_GPHY_HWCFG_M_1 | \
+       SK_GPHY_HWCFG_M_2 | SK_GPHY_HWCFG_M_3 )
+#define SK_GPHY_FIBER      (SK_GPHY_HWCFG_M_0 | SK_GPHY_HWCFG_M_1 | \
+       SK_GPHY_HWCFG_M_2 )
+#define SK_GPHY_ANEG_ALL   (SK_GPHY_ANEG_0 | SK_GPHY_ANEG_1 | \
+       SK_GPHY_ANEG_2 | SK_GPHY_ANEG_3 )
+
+#define SK_GMAC_INT_TX_OFLOW   0x20    /* Transmit Counter Overflow */
+#define SK_GMAC_INT_RX_OFLOW   0x10    /* Receiver Overflow */
+#define SK_GMAC_INT_TX_UNDER   0x08    /* Transmit FIFO Underrun */
+#define SK_GMAC_INT_TX_DONE    0x04    /* Transmit Complete */
+#define SK_GMAC_INT_RX_OVER    0x02    /* Receive FIFO Overrun */
+#define SK_GMAC_INT_RX_DONE    0x01    /* Receive Complete */
+
+#define SK_LINK_RESET_CLEAR    0x0002  /* Link Reset Clear */
+#define SK_LINK_RESET_SET  0x0001  /* Link Reset Set */
+
+/* Block 31 -- reserved */
+
+/* Block 32-33 -- Pattern Ram */
+#define SK_WOL_PRAM        0x1000
+
+/* Block 0x22 - 0x3f -- reserved */
+
+/* Block 0x50 to 0x5F -- MARV 1 registers */
+#define SK_MARV1_BASE  0x2800
+
+/* Block 0x70 to 0x7F -- MARV 2 registers */
+#define SK_MARV2_BASE  0x3800
+
+
 /* Block 0x40 to 0x4F -- XMAC 1 registers */
 #define SK_XMAC1_BASE	0x2000
 #define SK_XMAC1_END	0x23FF
@@ -910,6 +1078,35 @@
 /* Block 0x60 to 0x6F -- XMAC 2 registers */
 #define SK_XMAC2_BASE	0x3000
 #define SK_XMAC2_END	0x33FF
+
+/* Compute relative offset of an MARV register in the MARV window(s). */
+#define SK_YU_REG(sc, reg) \
+   ((reg) + SK_MARV1_BASE + \
+   (((sc)->sk_port) * (SK_MARV2_BASE - SK_MARV1_BASE)))
+
+#define SK_YU_READ_4(sc, reg)      \
+   sk_win_read_4((sc)->sk_softc, SK_YU_REG((sc), (reg)))
+
+#define SK_YU_READ_2(sc, reg)      \
+   sk_win_read_2((sc)->sk_softc, SK_YU_REG((sc), (reg)))
+
+#define SK_YU_WRITE_4(sc, reg, val)    \
+   sk_win_write_4((sc)->sk_softc, SK_YU_REG((sc), (reg)), (val))
+
+#define SK_YU_WRITE_2(sc, reg, val)    \
+   sk_win_write_2((sc)->sk_softc, SK_YU_REG((sc), (reg)), (val))
+
+#define SK_YU_SETBIT_4(sc, reg, x) \
+   SK_YU_WRITE_4(sc, reg, (SK_YU_READ_4(sc, reg)) | (x))
+
+#define SK_YU_CLRBIT_4(sc, reg, x) \
+   SK_YU_WRITE_4(sc, reg, (SK_YU_READ_4(sc, reg)) & ~(x))
+
+#define SK_YU_SETBIT_2(sc, reg, x) \
+   SK_YU_WRITE_2(sc, reg, (SK_YU_READ_2(sc, reg)) | (x))
+
+#define SK_YU_CLRBIT_2(sc, reg, x) \
+   SK_YU_WRITE_2(sc, reg, (SK_YU_READ_2(sc, reg)) & ~(x))
 
 /* Compute relative offset of an XMAC register in the XMAC window(s). */
 #define SK_XMAC_REG(reg, mac)	(((reg) * 2) + SK_XMAC1_BASE + \
Index: pci/yukonreg.h
===================================================================
RCS file: pci/yukonreg.h
diff -N pci/yukonreg.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ pci/yukonreg.h	23 Aug 2003 15:17:42 -0000
@@ -0,0 +1,169 @@
+/*	$OpenBSD: yukonreg.h,v 1.2 2003/08/12 05:23:06 nate Exp $ */
+/*
+ * Copyright (c) 2003 Nathan L. Binkert <binkertn at 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.
+ */
+
+/* General Purpose Status Register (GPSR) */
+#define YUKON_GPSR		0x0000
+
+#define YU_GPSR_SPEED		0x8000	/* speed 0 - 10Mbps, 1 - 100Mbps */
+#define YU_GPSR_DUPLEX		0x4000	/* 0 - half duplex, 1 - full duplex */
+#define YU_GPSR_FCTL_TX		0x2000	/* flow control */
+#define YU_GPSR_LINK		0x1000	/* link status (down/up) */
+#define YU_GPSR_PAUSE		0x0800	/* flow control enable/disable */
+#define YU_GPSR_TX_IN_PROG	0x0400	/* transmit in progress */
+#define YU_GPSR_EXCESS_COL	0x0200	/* excessive collisions occurred */
+#define YU_GPSR_LATE_COL	0x0100	/* late collision occurred */
+#define YU_GPSR_MII_PHY_STC	0x0020	/* MII PHY status change */
+#define YU_GPSR_GIG_SPEED	0x0010	/* Gigabit Speed (0 - use speed bit) */
+#define YU_GPSR_PARTITION	0x0008	/* partition mode */
+#define YU_GPSR_FCTL_RX		0x0004	/* flow control enable/disable */
+#define YU_GPSR_PROMS_EN	0x0002	/* promiscuous mode enable/disable */
+
+/* General Purpose Control Register (GPCR) */
+#define YUKON_GPCR		0x0004
+
+#define YU_GPCR_FCTL_TX		0x2000	/* Transmit flow control 802.3x */
+#define YU_GPCR_TXEN		0x1000	/* Transmit Enable */
+#define YU_GPCR_RXEN		0x0800	/* Receive Enable */
+#define YU_GPCR_LPBK		0x0200	/* Loopback Enable */
+#define YU_GPCR_PAR		0x0100	/* Partition Enable */
+#define YU_GPCR_GIG		0x0080	/* Gigabit Speed */
+#define YU_GPCR_FLP		0x0040	/* Force Link Pass */
+#define YU_GPCR_DUPLEX		0x0020	/* Duplex Enable */
+#define YU_GPCR_FCTL_RX		0x0010	/* Receive flow control 802.3x */
+#define YU_GPCR_SPEED		0x0008	/* Port Speed */
+#define YU_GPCR_DPLX_EN		0x0004	/* Enable Auto-Update for duplex */
+#define YU_GPCR_FCTL_EN		0x0002	/* Enabel Auto-Update for 802.3x */
+#define YU_GPCR_SPEED_EN	0x0001	/* Enable Auto-Update for speed */
+
+/* Transmit Control Register (TCR) */
+#define YUKON_TCR		0x0008
+
+#define YU_TCR_FJ		0x8000	/* force jam / flow control */
+#define YU_TCR_CRCD		0x4000	/* insert CRC (0 - enable) */
+#define YU_TCR_PADD		0x2000	/* pad packets to 64b (0 - enable) */
+#define YU_TCR_COLTH		0x1c00	/* collision threshold */
+
+/* Receive Control Register (RCR) */
+#define YUKON_RCR		0x000c
+
+#define YU_RCR_UFLEN		0x8000	/* unicast filter enable */
+#define YU_RCR_MUFLEN		0x4000	/* multicast filter enable */
+#define YU_RCR_CRCR		0x2000	/* remove CRC */
+#define YU_RCR_PASSFC		0x1000	/* pass flow control packets */
+
+/* Transmit Flow Control Register (TFCR) */
+#define YUKON_TFCR		0x0010	/* Pause Time */
+
+/* Transmit Parameter Register (TPR) */
+#define YUKON_TPR		0x0014
+
+#define YU_TPR_JAM_LEN(x)	(((x) & 0x3) << 14)
+#define YU_TPR_JAM_IPG(x)	(((x) & 0x1f) << 9)
+#define YU_TPR_JAM2DATA_IPG(x)	(((x) & 0x1f) << 4)
+
+/* Serial Mode Register (SMR) */
+#define YUKON_SMR		0x0018
+
+#define YU_SMR_DATA_BLIND(x)	(((x) & 0x1f) << 11)
+#define YU_SMR_LIMIT4		0x0400	/* reset after 16 / 4 collisions */
+#define YU_SMR_MFL_JUMBO	0x0100	/* max frame length for jumbo frames */
+#define YU_SMR_MFL_VLAN		0x0200	/* max frame length + vlan tag */
+#define YU_SMR_IPG_DATA(x)	((x) & 0x1f)
+
+/* Source Address Low #1 (SAL1) */
+#define YUKON_SAL1		0x001c	/* SA1[15:0] */
+
+/* Source Address Middle #1 (SAM1) */
+#define YUKON_SAM1		0x0020	/* SA1[31:16] */
+
+/* Source Address High #1 (SAH1) */
+#define YUKON_SAH1		0x0024	/* SA1[47:32] */
+
+/* Source Address Low #2 (SAL2) */
+#define YUKON_SAL2		0x0028	/* SA2[15:0] */
+
+/* Source Address Middle #2 (SAM2) */
+#define YUKON_SAM2		0x002c	/* SA2[31:16] */
+
+/* Source Address High #2 (SAH2) */
+#define YUKON_SAH2		0x0030	/* SA2[47:32] */
+
+/* Multicatst Address Hash Register 1 (MCAH1) */
+#define YUKON_MCAH1		0x0034
+
+/* Multicatst Address Hash Register 2 (MCAH2) */
+#define YUKON_MCAH2		0x0038
+
+/* Multicatst Address Hash Register 3 (MCAH3) */
+#define YUKON_MCAH3		0x003c
+
+/* Multicatst Address Hash Register 4 (MCAH4) */
+#define YUKON_MCAH4		0x0040
+
+/* Transmit Interrupt Register (TIR) */
+#define YUKON_TIR		0x0044
+
+#define YU_TIR_OUT_UNICAST	0x0001	/* Num Unicast Packets Transmitted */
+#define YU_TIR_OUT_BROADCAST	0x0002	/* Num Broadcast Packets Transmitted */
+#define YU_TIR_OUT_PAUSE	0x0004	/* Num Pause Packets Transmitted */
+#define YU_TIR_OUT_MULTICAST	0x0008	/* Num Multicast Packets Transmitted */
+#define YU_TIR_OUT_OCTETS	0x0030	/* Num Bytes Transmitted */
+#define YU_TIR_OUT_64_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_127_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_255_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_511_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_1023_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_1518_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_MAX_OCTETS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_SPARE	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_COLLISIONS	0x0000	/* Num Packets Transmitted */
+#define YU_TIR_OUT_LATE		0x0000	/* Num Packets Transmitted */
+
+/* Receive Interrupt Register (RIR) */
+#define YUKON_RIR		0x0048
+
+/* Transmit and Receive Interrupt Register (TRIR) */
+#define YUKON_TRIR		0x004c
+
+/* Transmit Interrupt Mask Register (TIMR) */
+#define YUKON_TIMR		0x0050
+
+/* Receive Interrupt Mask Register (RIMR) */
+#define YUKON_RIMR		0x0054
+
+/* Transmit and Receive Interrupt Mask Register (TRIMR) */
+#define YUKON_TRIMR		0x0058
+
+/* SMI Control Register (SMICR) */
+#define YUKON_SMICR		0x0080
+
+#define YU_SMICR_PHYAD(x)	(((x) & 0x1f) << 11)
+#define YU_SMICR_REGAD(x)	(((x) & 0x1f) << 6)
+#define YU_SMICR_OPCODE		0x0020	/* opcode (0 - write, 1 - read) */
+#define YU_SMICR_OP_READ	0x0020	/* opcode read */
+#define YU_SMICR_OP_WRITE	0x0000	/* opcode write */
+#define YU_SMICR_READ_VALID	0x0010	/* read valid */
+#define YU_SMICR_BUSY		0x0008	/* busy (writing) */
+
+/* SMI Data Register (SMIDR) */
+#define YUKON_SMIDR		0x0084
+
+/* PHY Addres Register (PAR) */
+#define YUKON_PAR		0x0088
+
+#define YU_PAR_MIB_CLR		0x0020	/* MIB Counters Clear Mode */
+#define YU_PAR_LOAD_TSTCNT	0x0010	/* Load count 0xfffffff0 into cntr */


More information about the freebsd-current mailing list