Subject: kern/22511: port of OpenBSD sk driver
To: None <gnats-bugs@gnats.netbsd.org>
From: None <stephen@degler.net>
List: netbsd-bugs
Date: 08/17/2003 03:31:26
>Number:         22511
>Category:       kern
>Synopsis:       port of OpenBSD sk driver
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Aug 17 07:32:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Stephen Degler
>Release:        NetBSD 1.6W
>Organization:
	
>Environment:
	
	
System: NetBSD kashmir.degler.net 1.6W NetBSD 1.6W (KASHMIR) #41: Sun Aug 17 01:29:39 EDT 2003 sdegler@kashmir.degler.net:/vol1/NetBSD/kernels/KASHMIR i386
Architecture: i386
Machine: i386
>Description:
	This driver adds support for the SK98XX and 3Com 3C940 gigabit
	ethernet cards.
>How-To-Repeat:
	Plug in card/motherboard with devices noted above.  Observe the
	-current kernel fail to recognize the aforementioned devices.
>Fix:
	Apply patch below.  Regen a kernel.  See bits fly.

	Note I've only tested so far on i386 at 100baseTX full-duplex.
	Even at this speed performance looks as if further tuning will
	be needed.  Also, sk_stop is somewhat dubious.  On a dual channel
	controller, this may shut down both channels.

Index: sys/arch/i386/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.567
diff -u -r1.567 GENERIC
--- sys/arch/i386/conf/GENERIC	2003/08/07 12:06:15	1.567
+++ sys/arch/i386/conf/GENERIC	2003/08/17 07:03:57
@@ -688,6 +688,8 @@
 rtk*	at pci? dev ? function ?	# Realtek 8129/8139
 sf*	at pci? dev ? function ?	# Adaptec AIC-6915 Ethernet
 sip*	at pci? dev ? function ?	# SiS 900/DP83815 Ethernet
+skc*	at pci? dev ? funtcion ?	# SysKonnect SK9821 Gigabit Ethernet
+sk*	at skc?				# SysKonnect SK9821 Gigabit Ethernet
 ste*	at pci? dev ? function ?	# Sundance ST-201 Ethernet
 stge*	at pci? dev ? function ?	# Sundance/Tamarack TC9021 Gigabit
 ti*	at pci? dev ? function ?	# Alteon ACEnic gigabit Ethernet
Index: sys/dev/pci/files.pci
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/files.pci,v
retrieving revision 1.190
diff -u -r1.190 files.pci
--- sys/dev/pci/files.pci	2003/08/08 20:46:09	1.190
+++ sys/dev/pci/files.pci	2003/08/17 07:03:57
@@ -605,3 +605,11 @@
 device	txp: ether, ifnet, arp
 attach	txp at pci
 file	dev/pci/if_txp.c		txp
+
+# Syskonnect
+device skc { }
+attach skc at pci
+device  sk: ether, ifnet, arp, mii
+attach  sk at skc
+file dev/pci/if_sk.c			skc | sk
+
Index: sys/dev/pci/if_sk.c
===================================================================
RCS file: if_sk.c
diff -N if_sk.c
--- /dev/null	Thu Jul 11 11:18:53 2002
+++ sys/dev/pci/if_sk.c	Sun Aug 17 07:03:58 2003
@@ -0,0 +1,2575 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*	$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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: /c/ncvs/src/sys/pci/if_sk.c,v 1.20 2000/04/22 02:16:37 wpaul Exp $
+ */
+
+/*
+ * 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:
+ * 	The XaQti XMAC II datasheet,
+ * http://www.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf
+ *	The SysKonnect GEnesis manual, http://www.syskonnect.com
+ *
+ * Note: XaQti has been acquired by Vitesse, and Vitesse does not have the
+ * XMAC II datasheet online. I have put my copy at people.freebsd.org as a
+ * convenience to others until Vitesse corrects this problem:
+ *
+ * http://people.freebsd.org/~wpaul/SysKonnect/xmacii_datasheet_rev_c_9-29.pdf
+ *
+ * Written by Bill Paul <wpaul@ee.columbia.edu>
+ * Department of Electrical Engineering
+ * Columbia University, New York City
+ */
+
+/*
+ * The SysKonnect gigabit ethernet adapters consist of two main
+ * components: the SysKonnect GEnesis controller chip and the XaQti Corp.
+ * XMAC II gigabit ethernet MAC. The XMAC provides all of the MAC
+ * components and a PHY while the GEnesis controller provides a PCI
+ * interface with DMA support. Each card may have between 512K and
+ * 2MB of SRAM on board depending on the configuration.
+ *
+ * The SysKonnect GEnesis controller can have either one or two XMAC
+ * chips connected to it, allowing single or dual port NIC configurations.
+ * SysKonnect has the distinction of being the only vendor on the market
+ * with a dual port gigabit ethernet NIC. The GEnesis provides dual FIFOs,
+ * dual DMA queues, packet/MAC/transmit arbiters and direct access to the
+ * XMAC registers. This driver takes advantage of these features to allow
+ * both XMACs to operate as independent interfaces.
+ */
+ 
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/queue.h>
+#include <sys/callout.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <net/if_media.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/brgphyreg.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#define	SK_VERBOSE
+/* #define SK_USEIOSPACE */
+
+#include <dev/pci/if_skreg.h>
+#include <dev/pci/xmaciireg.h>
+#include <dev/pci/yukonreg.h>
+#include <dev/pci/if_skvar.h>
+
+int skc_probe(struct device *, struct cfdata *, void *);
+void skc_attach(struct device *, struct device *self, void *aux);
+int sk_probe(struct device *, struct cfdata *, void *);
+void sk_attach(struct device *, struct device *self, void *aux);
+int skcprint(void *, const char *);
+int sk_intr(void *);
+void sk_intr_bcom(struct sk_if_softc *);
+void sk_intr_xmac(struct sk_if_softc *);
+void sk_intr_yukon(struct sk_if_softc *);
+void sk_rxeof(struct sk_if_softc *);
+void sk_txeof(struct sk_if_softc *);
+int sk_encap(struct sk_if_softc *, struct mbuf *, u_int32_t *);
+void sk_start(struct ifnet *);
+int sk_ioctl(struct ifnet *, u_long, caddr_t);
+int sk_init(struct ifnet *);
+void sk_init_xmac(struct sk_if_softc *);
+void sk_init_yukon(struct sk_if_softc *);
+void sk_stop(struct ifnet *, int);
+void sk_watchdog(struct ifnet *);
+void sk_shutdown(void *);
+int sk_ifmedia_upd(struct ifnet *);
+void sk_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+void sk_reset(struct sk_softc *);
+int sk_newbuf(struct sk_if_softc *, int, struct mbuf *, bus_dmamap_t);
+int sk_init_rx_ring(struct sk_if_softc *);
+int sk_init_tx_ring(struct sk_if_softc *);
+u_int8_t sk_vpd_readbyte(struct sk_softc *, int);
+void sk_vpd_read_res(struct sk_softc *,
+					struct vpd_res *, int);
+void sk_vpd_read(struct sk_softc *);
+
+int sk_xmac_miibus_readreg(struct device *, int, int);
+void sk_xmac_miibus_writereg(struct device *, int, int, int);
+void sk_xmac_miibus_statchg(struct device *);
+
+int sk_marv_miibus_readreg(struct device *, int, int);
+void sk_marv_miibus_writereg(struct device *, int, int, int);
+void sk_marv_miibus_statchg(struct device *);
+
+u_int32_t sk_calchash(caddr_t);
+void sk_setfilt(struct sk_if_softc *, caddr_t, int);
+void sk_setmulti(struct sk_if_softc *);
+void sk_tick(void *);
+
+/* #define SK_DEBUG 2 */
+#ifdef SK_DEBUG
+#define DPRINTF(x)	if (skdebug) printf x
+#define DPRINTFN(n,x)	if (skdebug >= (n)) printf x
+int	skdebug = SK_DEBUG;
+
+void sk_dump_txdesc(struct sk_tx_desc *, int);
+void sk_dump_mbuf(struct mbuf *);
+void sk_dump_bytes(const char *, int);
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+#define SK_SETBIT(sc, reg, x)		\
+	CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | x)
+
+#define SK_CLRBIT(sc, reg, x)		\
+	CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~x)
+
+#define SK_WIN_SETBIT_4(sc, reg, x)	\
+	sk_win_write_4(sc, reg, sk_win_read_4(sc, reg) | x)
+
+#define SK_WIN_CLRBIT_4(sc, reg, x)	\
+	sk_win_write_4(sc, reg, sk_win_read_4(sc, reg) & ~x)
+
+#define SK_WIN_SETBIT_2(sc, reg, x)	\
+	sk_win_write_2(sc, reg, sk_win_read_2(sc, reg) | x)
+
+#define SK_WIN_CLRBIT_2(sc, reg, x)	\
+	sk_win_write_2(sc, reg, sk_win_read_2(sc, reg) & ~x)
+
+/* supported device vendors */
+const struct sk_product { 
+	pci_vendor_id_t		sk_vendor;
+	pci_product_id_t	sk_product; } sk_products[] = {
+		{ PCI_VENDOR_3COM,
+		  PCI_PRODUCT_3COM_3C940,
+		},
+		{ PCI_VENDOR_SCHNEIDERKOCH,
+		  PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE,
+		},
+		{ PCI_VENDOR_SCHNEIDERKOCH,
+		  PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2,
+		},
+		{ 0,
+		  0,
+		  0
+		}
+	};
+
+static inline u_int32_t
+sk_win_read_4(struct sk_softc *sc, u_int32_t 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 inline u_int16_t
+sk_win_read_2(struct sk_softc *sc, u_int32_t 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 inline u_int8_t
+sk_win_read_1(struct sk_softc *sc, u_int32_t 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 inline void
+sk_win_write_4(struct sk_softc *sc, u_int32_t reg, u_int32_t x)
+{
+#ifdef SK_USEIOSPACE
+	CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
+	CSR_WRITE_4(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+	CSR_WRITE_4(sc, reg, x);
+#endif
+}
+
+static inline void
+sk_win_write_2(struct sk_softc *sc, u_int32_t reg, u_int16_t x)
+{
+#ifdef SK_USEIOSPACE
+	CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
+	CSR_WRITE_2(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+	CSR_WRITE_2(sc, reg, x);
+#endif
+}
+
+static inline void
+sk_win_write_1(struct sk_softc *sc, u_int32_t reg, u_int8_t x)
+{
+#ifdef SK_USEIOSPACE
+	CSR_WRITE_4(sc, SK_RAP, SK_WIN(reg));
+	CSR_WRITE_1(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+	CSR_WRITE_1(sc, reg, x);
+#endif
+}
+
+/*
+ * The VPD EEPROM contains Vital Product Data, as suggested in
+ * the PCI 2.1 specification. The VPD data is separared into areas
+ * denoted by resource IDs. The SysKonnect VPD contains an ID string
+ * resource (the name of the adapter), a read-only area resource
+ * containing various key/data fields and a read/write area which
+ * 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().
+ */
+u_int8_t
+sk_vpd_readbyte(struct sk_softc *sc, int addr)
+{
+	int			i;
+
+	sk_win_write_2(sc, SK_PCI_REG(SK_PCI_VPD_ADDR), addr);
+	for (i = 0; i < SK_TIMEOUT; i++) {
+		DELAY(1);
+		if (sk_win_read_2(sc,
+		    SK_PCI_REG(SK_PCI_VPD_ADDR)) & SK_VPD_FLAG)
+			break;
+	}
+
+	if (i == SK_TIMEOUT)
+		return(0);
+
+	return(sk_win_read_1(sc, SK_PCI_REG(SK_PCI_VPD_DATA)));
+}
+
+void
+sk_vpd_read_res(struct sk_softc *sc, struct vpd_res *res, int addr)
+{
+	int			i;
+	u_int8_t		*ptr;
+
+	ptr = (u_int8_t *)res;
+	for (i = 0; i < sizeof(struct vpd_res); i++)
+		ptr[i] = sk_vpd_readbyte(sc, i + addr);
+}
+
+void
+sk_vpd_read(struct sk_softc *sc)
+{
+	int			pos = 0, i;
+	struct vpd_res		res;
+
+	if (sc->sk_vpd_prodname != NULL)
+		free(sc->sk_vpd_prodname, M_DEVBUF);
+	if (sc->sk_vpd_readonly != NULL)
+		free(sc->sk_vpd_readonly, M_DEVBUF);
+	sc->sk_vpd_prodname = NULL;
+	sc->sk_vpd_readonly = NULL;
+
+	sk_vpd_read_res(sc, &res, pos);
+
+	if (res.vr_id != VPD_RES_ID) {
+		printf("%s: bad VPD resource id: expected %x got %x\n",
+		    sc->sk_dev.dv_xname, VPD_RES_ID, res.vr_id);
+		return;
+	}
+
+	pos += sizeof(res);
+	sc->sk_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_NOWAIT);
+	if (sc->sk_vpd_prodname == NULL)
+		panic("sk_vpd_read");
+	for (i = 0; i < res.vr_len; i++)
+		sc->sk_vpd_prodname[i] = sk_vpd_readbyte(sc, i + pos);
+	sc->sk_vpd_prodname[i] = '\0';
+	pos += i;
+
+	sk_vpd_read_res(sc, &res, pos);
+
+	if (res.vr_id != VPD_RES_READ) {
+		printf("%s: bad VPD resource id: expected %x got %x\n",
+		    sc->sk_dev.dv_xname, VPD_RES_READ, res.vr_id);
+		return;
+	}
+
+	pos += sizeof(res);
+	sc->sk_vpd_readonly = malloc(res.vr_len, M_DEVBUF, M_NOWAIT);
+	if (sc->sk_vpd_readonly == NULL)
+		panic("sk_vpd_read");
+	for (i = 0; i < res.vr_len + 1; i++)
+		sc->sk_vpd_readonly[i] = sk_vpd_readbyte(sc, i + pos);
+}
+
+int
+sk_xmac_miibus_readreg(struct device *dev, int phy, int reg)
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
+	int i;
+
+	DPRINTFN(9, ("sk_xmac_miibus_readreg\n"));
+
+	if (sc_if->sk_phytype == SK_PHYTYPE_XMAC && phy != 0)
+		return(0);
+
+	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) {
+		for (i = 0; i < SK_TIMEOUT; i++) {
+			DELAY(1);
+			if (SK_XM_READ_2(sc_if, XM_MMUCMD) &
+			    XM_MMUCMD_PHYDATARDY)
+				break;
+		}
+
+		if (i == SK_TIMEOUT) {
+			printf("%s: phy failed to come ready\n",
+			    sc_if->sk_dev.dv_xname);
+			return(0);
+		}
+	}
+	DELAY(1);
+	return(SK_XM_READ_2(sc_if, XM_PHY_DATA));
+}
+
+void
+sk_xmac_miibus_writereg(struct device *dev, int phy, int reg, int val)
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
+	int i;
+
+	DPRINTFN(9, ("sk_xmac_miibus_writereg\n"));
+
+	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))
+			break;
+	}
+
+	if (i == SK_TIMEOUT) {
+		printf("%s: phy failed to come ready\n",
+		    sc_if->sk_dev.dv_xname);
+		return;
+	}
+
+	SK_XM_WRITE_2(sc_if, XM_PHY_DATA, val);
+	for (i = 0; i < SK_TIMEOUT; i++) {
+		DELAY(1);
+		if (!(SK_XM_READ_2(sc_if, XM_MMUCMD) & XM_MMUCMD_PHYBUSY))
+			break;
+	}
+
+	if (i == SK_TIMEOUT)
+		printf("%s: phy write timed out\n", sc_if->sk_dev.dv_xname);
+}
+
+void
+sk_xmac_miibus_statchg(struct device *dev)
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
+	struct mii_data *mii = &sc_if->sk_mii;
+
+	DPRINTFN(9, ("sk_xmac_miibus_statchg\n"));
+
+	/*
+	 * If this is a GMII PHY, manually set the XMAC's
+	 * duplex mode accordingly.
+	 */
+	if (sc_if->sk_phytype != SK_PHYTYPE_XMAC) {
+		if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
+			SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX);
+		} else {
+			SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_GMIIFDX);
+		}
+	}
+}
+
+int
+sk_marv_miibus_readreg(dev, phy, reg)
+	struct device *dev;
+	int phy, reg;
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
+	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)) {
+		DPRINTFN(9, ("sk_marv_miibus_readreg (skip) phy=%d, reg=%#x\n",
+			     phy, reg));
+		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("%s: phy failed to come ready\n",
+		       sc_if->sk_dev.dv_xname);
+		return 0;
+	}
+        
+ 	DPRINTFN(9, ("sk_marv_miibus_readreg: i=%d, timeout=%d\n", i,
+		     SK_TIMEOUT));
+
+        val = SK_YU_READ_2(sc_if, YUKON_SMIDR);
+
+	DPRINTFN(9, ("sk_marv_miibus_readreg phy=%d, reg=%#x, val=%#x\n",
+		     phy, reg, val));
+
+	return val;
+}
+
+void
+sk_marv_miibus_writereg(dev, phy, reg, val)
+	struct device *dev;
+	int phy, reg, val;
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *)dev;
+	int i;
+
+	DPRINTFN(9, ("sk_marv_miibus_writereg phy=%d reg=%#x val=%#x\n",
+		     phy, reg, val));
+
+	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;
+	}
+}
+
+void
+sk_marv_miibus_statchg(dev)
+	struct device *dev;
+{
+	DPRINTFN(9, ("sk_marv_miibus_statchg: gpcr=%x\n",
+		     SK_YU_READ_2(((struct sk_if_softc *)dev), YUKON_GPCR)));
+}
+
+#define SK_BITS		6
+#define SK_POLY	0xEDB88320
+
+u_int32_t
+sk_calchash(caddr_t addr)
+{
+	u_int32_t		crc;
+
+	crc = ether_crc32_be(addr,ETHER_ADDR_LEN);
+        crc = ~crc & ((1<< SK_BITS) - 1);	
+	DPRINTFN(2,("multicast hash for %s is %x\n",ether_sprintf(addr),crc));
+        return (crc);
+}
+
+void
+sk_setfilt(struct sk_if_softc *sc_if, caddr_t addr, int slot)
+{
+	int base = XM_RXFILT_ENTRY(slot);
+
+	SK_XM_WRITE_2(sc_if, base, *(u_int16_t *)(&addr[0]));
+	SK_XM_WRITE_2(sc_if, base + 2, *(u_int16_t *)(&addr[2]));
+	SK_XM_WRITE_2(sc_if, base + 4, *(u_int16_t *)(&addr[4]));
+}
+
+void
+sk_setmulti(struct sk_if_softc *sc_if)
+{
+	struct sk_softc *sc = sc_if->sk_softc;
+	struct ifnet *ifp= &sc_if->sk_ethercom.ec_if;
+	u_int32_t hashes[2] = { 0, 0 };
+	int h, i;
+	struct ethercom *ec = &sc_if->sk_ethercom;
+	struct ether_multi *enm;
+	struct ether_multistep step;
+	u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 };
+
+	/* First, zot all the existing filters. */
+	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. */
+allmulti:
+	if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+		hashes[0] = 0xFFFFFFFF;
+		hashes[1] = 0xFFFFFFFF;
+	} else {
+		i = 1;
+		/* First find the tail of the list. */
+		ETHER_FIRST_MULTI(step, ec, enm);
+		while (enm != NULL) {
+			if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
+				 ETHER_ADDR_LEN)) {
+				ifp->if_flags |= IFF_ALLMULTI;
+				goto allmulti;
+			}
+			DPRINTFN(2,("multicast address %s\n",
+	    			ether_sprintf(enm->enm_addrlo)));
+			/*
+			 * Program the first XM_RXFILT_MAX multicast groups
+			 * into the perfect filter. For all others,
+			 * use the hash table.
+			 */
+			if (sc->sk_type == SK_GENESIS && i < XM_RXFILT_MAX) {
+				sk_setfilt(sc_if, enm->enm_addrlo, i);
+				i++;
+			}
+			else {
+				h = sk_calchash(enm->enm_addrlo);
+				if (h < 32)
+					hashes[0] |= (1 << h);
+				else
+					hashes[1] |= (1 << (h - 32));
+			}
+
+			ETHER_NEXT_MULTI(step, enm);
+		}
+	}
+
+	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;
+	}
+}
+
+int
+sk_init_rx_ring(struct sk_if_softc *sc_if)
+{
+	struct sk_chain_data	*cd = &sc_if->sk_cdata;
+	struct sk_ring_data	*rd = sc_if->sk_rdata;
+	int			i;
+
+	bzero((char *)rd->sk_rx_ring,
+	    sizeof(struct sk_rx_desc) * SK_RX_RING_CNT);
+
+	for (i = 0; i < SK_RX_RING_CNT; i++) {
+		cd->sk_rx_chain[i].sk_desc = &rd->sk_rx_ring[i];
+		if (i == (SK_RX_RING_CNT - 1)) {
+			cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[0];
+			rd->sk_rx_ring[i].sk_next = SK_RX_RING_ADDR(sc_if, 0);
+		} else {
+			cd->sk_rx_chain[i].sk_next = &cd->sk_rx_chain[i + 1];
+			rd->sk_rx_ring[i].sk_next = SK_RX_RING_ADDR(sc_if,i+1);
+		}
+	}
+
+	for (i = 0; i < SK_RX_RING_CNT; i++) {
+		if (sk_newbuf(sc_if, i, NULL, NULL) == ENOBUFS) {
+			printf("%s: failed alloc of %dth mbuf\n",
+			    sc_if->sk_dev.dv_xname, i);
+			return(ENOBUFS);
+		}
+	}
+	sc_if->sk_cdata.sk_rx_prod = 0;
+	sc_if->sk_cdata.sk_rx_cons = 0;
+
+	return(0);
+}
+
+int
+sk_init_tx_ring(struct sk_if_softc *sc_if)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct sk_chain_data	*cd = &sc_if->sk_cdata;
+	struct sk_ring_data	*rd = sc_if->sk_rdata;
+	bus_dmamap_t		dmamap;
+	struct sk_txmap_entry	*entry;
+	int			i;
+
+	bzero((char *)sc_if->sk_rdata->sk_tx_ring,
+	    sizeof(struct sk_tx_desc) * SK_TX_RING_CNT);
+
+	SLIST_INIT(&sc_if->sk_txmap_listhead);
+	for (i = 0; i < SK_TX_RING_CNT; i++) {
+		cd->sk_tx_chain[i].sk_desc = &rd->sk_tx_ring[i];
+		if (i == (SK_TX_RING_CNT - 1)) {
+			cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[0];
+			rd->sk_tx_ring[i].sk_next = SK_TX_RING_ADDR(sc_if, 0);
+		} else {
+			cd->sk_tx_chain[i].sk_next = &cd->sk_tx_chain[i + 1];
+			rd->sk_tx_ring[i].sk_next = SK_TX_RING_ADDR(sc_if,i+1);
+		}
+
+		if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, SK_NTXSEG,
+		    MCLBYTES, 0, BUS_DMA_NOWAIT, &dmamap))
+			return (ENOBUFS);
+
+		entry = malloc(sizeof(*entry), M_DEVBUF, M_NOWAIT);
+		if (!entry) {
+			bus_dmamap_destroy(sc->sc_dmatag, dmamap);
+			return (ENOBUFS);
+		}
+		entry->dmamap = dmamap;
+		SLIST_INSERT_HEAD(&sc_if->sk_txmap_listhead, entry, link);
+	}
+
+	sc_if->sk_cdata.sk_tx_prod = 0;
+	sc_if->sk_cdata.sk_tx_cons = 0;
+	sc_if->sk_cdata.sk_tx_cnt = 0;
+
+	return (0);
+}
+
+int
+sk_newbuf(struct sk_if_softc *sc_if, int i, struct mbuf *m,
+	  bus_dmamap_t dmamap)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct mbuf		*m_new = NULL;
+	struct sk_chain		*c;
+	struct sk_rx_desc	*r;
+
+	if (dmamap == NULL) {
+		/* if (m) panic() */
+
+		if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1, MCLBYTES,
+				      0, BUS_DMA_NOWAIT, &dmamap)) {
+			printf("%s: can't create recv map\n",
+			       sc_if->sk_dev.dv_xname);
+			return(ENOMEM);
+		}
+	} else if (m == NULL)
+		bus_dmamap_unload(sc->sc_dmatag, dmamap);
+
+	sc_if->sk_cdata.sk_rx_map[i] = dmamap;
+
+	if (m == NULL) {
+		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
+		if (m_new == NULL) {
+			printf("%s: no memory for rx list -- "
+			    "packet dropped!\n", sc_if->sk_dev.dv_xname);
+			return(ENOBUFS);
+		}
+
+		/* Allocate the jumbo buffer */
+		MCLGET(m_new, M_DONTWAIT);
+		if (!(m_new->m_flags & M_EXT)) {
+			m_freem(m_new);
+			return (ENOBUFS);
+		}
+
+		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+
+		m_adj(m_new, ETHER_ALIGN);
+
+		if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m_new,
+					 BUS_DMA_NOWAIT))
+			return(ENOBUFS);
+	} else {
+		/*
+	 	 * We're re-using a previously allocated mbuf;
+		 * be sure to re-init pointers and lengths to
+		 * default values.
+		 */
+		m_new = m;
+		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+		m_adj(m_new, ETHER_ALIGN);
+		m_new->m_data = m_new->m_ext.ext_buf;
+	}
+
+	c = &sc_if->sk_cdata.sk_rx_chain[i];
+	r = c->sk_desc;
+	c->sk_mbuf = m_new;
+	r->sk_data_lo = dmamap->dm_segs[0].ds_addr;
+	r->sk_ctl = dmamap->dm_segs[0].ds_len | SK_RXSTAT;
+
+	return(0);
+}
+
+/*
+ * Set media options.
+ */
+int
+sk_ifmedia_upd(struct ifnet *ifp)
+{
+	struct sk_if_softc *sc_if = ifp->if_softc;
+
+	(void) sk_init(ifp);
+	mii_mediachg(&sc_if->sk_mii);
+	return(0);
+}
+
+/*
+ * Report current media status.
+ */
+void
+sk_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+	struct sk_if_softc *sc_if = ifp->if_softc;
+
+	mii_pollstat(&sc_if->sk_mii);
+	ifmr->ifm_active = sc_if->sk_mii.mii_media_active;
+	ifmr->ifm_status = sc_if->sk_mii.mii_media_status;
+}
+
+int
+sk_ioctl(struct ifnet *ifp, u_long command, 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;
+	/* struct ifaddr *ifa = (struct ifaddr *) data; */
+	struct mii_data *mii;
+	int s, error = 0;
+
+	/* DPRINTFN(2, ("sk_ioctl\n")); */
+
+	s = splnet();
+
+	switch(command) {
+
+	case SIOCSIFFLAGS:
+	        DPRINTFN(2, ("sk_ioctl IFFLAGS\n"));
+		if (ifp->if_flags & IFF_UP) {
+			if (ifp->if_flags & IFF_RUNNING &&
+			    ifp->if_flags & IFF_PROMISC &&
+			    !(sc_if->sk_if_flags & IFF_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) {
+				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
+				(void) sk_init(ifp);
+		} else {
+			if (ifp->if_flags & IFF_RUNNING)
+				sk_stop(ifp,0);
+		}
+		sc_if->sk_if_flags = ifp->if_flags;
+		error = 0;
+		break;
+
+	case SIOCGIFMEDIA:
+	case SIOCSIFMEDIA:
+	        DPRINTFN(2, ("sk_ioctl MEDIA\n"));
+		mii = &sc_if->sk_mii;
+		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
+		break;
+	default:
+	        DPRINTFN(2, ("sk_ioctl ETHER\n"));
+		error = ether_ioctl(ifp, command, data);
+
+		if ( error == ENETRESET) {
+			sk_setmulti(sc_if);
+			DPRINTFN(2, ("sk_ioctl setmulti called\n"));
+			error = 0;
+		} else if ( error ) {
+			splx(s);
+			return error;
+		}
+		break;
+	}
+
+	splx(s);
+	return(error);
+}
+
+/*
+ * Lookup: Check the PCI vendor and device, and return a pointer to
+ * The structure if the IDs match against our list.
+ */
+
+static const struct sk_product *sk_lookup(const struct pci_attach_args *pa)
+{
+	const struct sk_product *psk;
+	
+	for ( psk = &sk_products[0]; psk->sk_vendor != NULL; psk++ ) {
+		if (PCI_VENDOR(pa->pa_id) == psk->sk_vendor &&
+		    PCI_PRODUCT(pa->pa_id) == psk->sk_product)
+			return (psk);
+	}
+	return (NULL);
+}
+
+/*
+ * Probe for a SysKonnect GEnesis chip.
+ */
+
+int
+skc_probe(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
+	const struct sk_product *psk;
+	
+	if ((psk = sk_lookup(pa))) {
+		return(1);
+	}
+	return(0);
+}
+
+/*
+ * Force the GEnesis into reset, then bring it out of reset.
+ */
+void sk_reset(struct sk_softc *sc)
+{
+	DPRINTFN(2, ("sk_reset\n"));
+
+	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);
+
+	DPRINTFN(2, ("sk_reset: sk_csr=%x\n", CSR_READ_2(sc, SK_CSR)));
+	DPRINTFN(2, ("sk_reset: sk_link_ctrl=%x\n",
+		     CSR_READ_2(sc, SK_LINK_CTRL)));
+
+	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);
+
+	/*
+         * Configure interrupt moderation. The moderation timer
+	 * defers interrupts specified in the interrupt moderation
+	 * timer mask based on the timeout specified in the interrupt
+	 * moderation timer init register. Each bit in the timer
+	 * register represents 18.825ns, so to specify a timeout in
+	 * microseconds, we have to multiply by 54.
+	 */
+        sk_win_write_4(sc, SK_IMTIMERINIT, SK_IM_USECS(200));
+        sk_win_write_4(sc, SK_IMMR, SK_ISR_TX1_S_EOF|SK_ISR_TX2_S_EOF|
+	    SK_ISR_RX1_EOF|SK_ISR_RX2_EOF);
+        sk_win_write_1(sc, SK_IMTIMERCTL, SK_IMCTL_START);
+}
+
+int
+sk_probe(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct skc_attach_args *sa = aux;
+
+	if (sa->skc_port != SK_PORT_A && sa->skc_port != SK_PORT_B)
+		return(0);
+
+	return (1);
+}
+
+/*
+ * Each XMAC chip is attached as a separate logical IP interface.
+ * Single port cards will have only one logical interface of course.
+ */
+void
+sk_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct sk_if_softc *sc_if = (struct sk_if_softc *) self;
+	struct sk_softc *sc = (struct sk_softc *)parent;
+	struct skc_attach_args *sa = aux;
+	struct ifnet *ifp;
+	caddr_t kva;
+	bus_dma_segment_t seg;
+	int i, rseg;
+
+	sc_if->sk_port = sa->skc_port;
+	sc_if->sk_softc = sc;
+	sc->sk_if[sa->skc_port] = sc_if;
+
+	if (sa->skc_port == SK_PORT_A)
+		sc_if->sk_tx_bmu = SK_BMU_TXS_CSR0;
+	if (sa->skc_port == SK_PORT_B)
+		sc_if->sk_tx_bmu = SK_BMU_TXS_CSR1;
+
+	DPRINTFN(2, ("begin sk_attach: port=%d\n", sc_if->sk_port));
+
+	/*
+	 * Get station address for this interface. Note that
+	 * dual port cards actually come with three station
+	 * addresses: one for each port, plus an extra. The
+	 * extra one is used by the SysKonnect driver software
+	 * as a 'virtual' station address for when both ports
+	 * are operating in failover mode. Currently we don't
+	 * use this extra address.
+	 */
+	for (i = 0; i < ETHER_ADDR_LEN; i++)
+		sc_if->sk_enaddr[i] =
+			sk_win_read_1(sc, SK_MAC0_0 + (sa->skc_port * 8) + i);
+
+
+	printf(": address %s\n",
+	    ether_sprintf(sc_if->sk_enaddr));
+
+	/*
+	 * Set up RAM buffer addresses. The NIC will have a certain
+	 * amount of SRAM on it, somewhere between 512K and 2MB. We
+	 * need to divide this up a) between the transmitter and
+ 	 * receiver and b) between the two XMACs, if this is a
+	 * dual port NIC. Our algotithm is to divide up the memory
+	 * evenly so that everyone gets a fair share.
+	 */
+	if (sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC) {
+		u_int32_t		chunk, val;
+
+		chunk = sc->sk_ramsize / 2;
+		val = sc->sk_rboff / sizeof(u_int64_t);
+		sc_if->sk_rx_ramstart = val;
+		val += (chunk / sizeof(u_int64_t));
+		sc_if->sk_rx_ramend = val - 1;
+		sc_if->sk_tx_ramstart = val;
+		val += (chunk / sizeof(u_int64_t));
+		sc_if->sk_tx_ramend = val - 1;
+	} else {
+		u_int32_t		chunk, val;
+
+		chunk = sc->sk_ramsize / 4;
+		val = (sc->sk_rboff + (chunk * 2 * sc_if->sk_port)) /
+		    sizeof(u_int64_t);
+		sc_if->sk_rx_ramstart = val;
+		val += (chunk / sizeof(u_int64_t));
+		sc_if->sk_rx_ramend = val - 1;
+		sc_if->sk_tx_ramstart = val;
+		val += (chunk / sizeof(u_int64_t));
+		sc_if->sk_tx_ramend = val - 1;
+	}
+
+	DPRINTFN(2, ("sk_attach: rx_ramstart=%#x rx_ramend=%#x\n"
+		     "           tx_ramstart=%#x tx_ramend=%#x\n",
+		     sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend,
+		     sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend));
+
+	/* Read and save PHY type and set PHY address */
+	sc_if->sk_phytype = sk_win_read_1(sc, SK_EPROM1) & 0xF;
+	switch (sc_if->sk_phytype) {
+	case SK_PHYTYPE_XMAC:
+		sc_if->sk_phyaddr = SK_PHYADDR_XMAC;
+		break;
+	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("%s: unsupported PHY type: %d\n",
+		    sc->sk_dev.dv_xname, sc_if->sk_phytype);
+		return;
+	}
+
+	/* Allocate the descriptor queues. */
+	if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct sk_ring_data),
+	    PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
+		printf("%s: can't alloc rx buffers\n", sc->sk_dev.dv_xname);
+		goto fail;
+	}
+	if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
+	    sizeof(struct sk_ring_data), &kva, BUS_DMA_NOWAIT)) {
+		printf("%s: can't map dma buffers (%d bytes)\n",
+		       sc_if->sk_dev.dv_xname, sizeof(struct sk_ring_data));
+		bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
+		goto fail;
+	}
+	if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct sk_ring_data), 1,
+	    sizeof(struct sk_ring_data), 0, BUS_DMA_NOWAIT,
+            &sc_if->sk_ring_map)) {
+		printf("%s: can't create dma map\n", sc_if->sk_dev.dv_xname);
+		bus_dmamem_unmap(sc->sc_dmatag, kva,
+		    sizeof(struct sk_ring_data));
+		bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
+		goto fail;
+	}
+	if (bus_dmamap_load(sc->sc_dmatag, sc_if->sk_ring_map, kva,
+	    sizeof(struct sk_ring_data), NULL, BUS_DMA_NOWAIT)) {
+		printf("%s: can't load dma map\n", sc_if->sk_dev.dv_xname);
+		bus_dmamap_destroy(sc->sc_dmatag, sc_if->sk_ring_map);
+		bus_dmamem_unmap(sc->sc_dmatag, kva,
+		    sizeof(struct sk_ring_data));
+		bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
+		goto fail;
+	}
+        sc_if->sk_rdata = (struct sk_ring_data *)kva;
+	bzero(sc_if->sk_rdata, sizeof(struct sk_ring_data));
+
+	ifp = &sc_if->sk_ethercom.ec_if;
+	ifp->if_softc = sc_if;
+	ifp->if_mtu = ETHERMTU;
+	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_ioctl = sk_ioctl;
+	ifp->if_start = sk_start;
+	ifp->if_stop = sk_stop;
+	ifp->if_init = sk_init;
+	ifp->if_watchdog = sk_watchdog;
+	ifp->if_baudrate = 1000000000;
+	ifp->if_capabilities |= ETHERCAP_VLAN_MTU;
+	IFQ_SET_MAXLEN(&ifp->if_snd, SK_TX_RING_CNT - 1);
+	IFQ_SET_READY(&ifp->if_snd);
+	bcopy(sc_if->sk_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+
+	/*
+	 * Do miibus setup.
+	 */
+	switch (sc->sk_type) {
+	case SK_GENESIS:
+		sk_init_xmac(sc_if);
+		break;
+	case SK_YUKON:
+		sk_init_yukon(sc_if);
+		break;
+	default:
+		panic("%s: unknown device type %d", sc->sk_dev.dv_xname,
+		      sc->sk_type);
+	}
+
+ 	DPRINTFN(2, ("sk_attach: 1\n"));
+
+	sc_if->sk_mii.mii_ifp = ifp;
+	switch (sc->sk_type) {
+	case SK_GENESIS:
+		sc_if->sk_mii.mii_readreg = sk_xmac_miibus_readreg;
+		sc_if->sk_mii.mii_writereg = sk_xmac_miibus_writereg;
+		sc_if->sk_mii.mii_statchg = sk_xmac_miibus_statchg;
+		break;
+	case SK_YUKON:
+		sc_if->sk_mii.mii_readreg = sk_marv_miibus_readreg;
+		sc_if->sk_mii.mii_writereg = sk_marv_miibus_writereg;
+		sc_if->sk_mii.mii_statchg = sk_marv_miibus_statchg;
+		break;
+	}
+
+	ifmedia_init(&sc_if->sk_mii.mii_media, 0,
+	    sk_ifmedia_upd, sk_ifmedia_sts);
+	mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY,
+	    MII_OFFSET_ANY, 0);
+	if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) {
+		printf("%s: no PHY found!\n", sc_if->sk_dev.dv_xname);
+		ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL,
+			    0, NULL);
+		ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL);
+	}
+	else
+		ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_AUTO);
+
+	callout_init(&sc_if->sk_tick_ch);
+	callout_reset(&sc_if->sk_tick_ch,hz,sk_tick,sc_if);
+
+	DPRINTFN(2, ("sk_attach: 1\n"));
+
+	/*
+	 * Call MI attach routines.
+	 */
+	if_attach(ifp);
+
+	ether_ifattach(ifp, sc_if->sk_enaddr);
+
+#if NRND > 0
+        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
+            RND_TYPE_NET, 0);
+#endif
+
+	DPRINTFN(2, ("sk_attach: end\n"));
+
+	return;
+
+fail:
+	sc->sk_if[sa->skc_port] = NULL;
+}
+
+int
+skcprint(void *aux, const char *pnp)
+{
+	struct skc_attach_args *sa = aux;
+
+	if (pnp)
+		printf("sk port %c at %s",
+		    (sa->skc_port == SK_PORT_A) ? 'A' : 'B', pnp);
+	else
+		printf(" port %c", (sa->skc_port == SK_PORT_A) ? 'A' : 'B');
+	return (UNCONF);
+}
+
+/*
+ * Attach the interface. Allocate softc structures, do ifmedia
+ * setup and ethernet/BPF attach.
+ */
+void
+skc_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct sk_softc *sc = (struct sk_softc *)self;
+	struct pci_attach_args *pa = aux;
+	struct skc_attach_args skca;
+	pci_chipset_tag_t pc = pa->pa_pc;
+	pcireg_t memtype;
+	pci_intr_handle_t ih;
+	const char *intrstr = NULL;
+	bus_addr_t iobase;
+	bus_size_t iosize;
+	int s;
+	u_int32_t command;
+
+	DPRINTFN(2, ("begin skc_attach\n"));
+
+	s = splnet();
+
+	/*
+	 * Handle power management nonsense.
+	 */
+	command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF;
+
+	if (command == 0x01) {
+		command = pci_conf_read(pc, pa->pa_tag, SK_PCI_PWRMGMTCTRL);
+		if (command & SK_PSTATE_MASK) {
+			u_int32_t		iobase, membase, irq;
+
+			/* Save important PCI config data. */
+			iobase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOIO);
+			membase = pci_conf_read(pc, pa->pa_tag, SK_PCI_LOMEM);
+			irq = pci_conf_read(pc, pa->pa_tag, SK_PCI_INTLINE);
+
+			/* Reset the power state. */
+			printf("%s chip is in D%d power mode "
+			    "-- setting to D0\n", sc->sk_dev.dv_xname,
+			    command & SK_PSTATE_MASK);
+			command &= 0xFFFFFFFC;
+			pci_conf_write(pc, pa->pa_tag,
+			    SK_PCI_PWRMGMTCTRL, command);
+
+			/* Restore PCI config data. */
+			pci_conf_write(pc, pa->pa_tag, SK_PCI_LOIO, iobase);
+			pci_conf_write(pc, pa->pa_tag, SK_PCI_LOMEM, membase);
+			pci_conf_write(pc, pa->pa_tag, SK_PCI_INTLINE, irq);
+		}
+	}
+
+	/*
+	 * Map control/status registers.
+	 */
+	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+	command |= PCI_COMMAND_IO_ENABLE |
+	    PCI_COMMAND_MEM_ENABLE |
+	    PCI_COMMAND_MASTER_ENABLE;
+	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
+	command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+
+	switch (PCI_PRODUCT(pa->pa_id)) {
+	case PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE:
+		sc->sk_type = SK_GENESIS;
+		break;
+	case PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2:
+	case PCI_PRODUCT_3COM_3C940:
+		sc->sk_type = SK_YUKON;
+		break;
+	default:
+		printf(": unknown device!\n");
+		goto fail;
+	}
+
+#ifdef SK_USEIOSPACE
+	if (!(command & PCI_COMMAND_IO_ENABLE)) {
+		printf(": failed to enable I/O ports!\n");
+		goto fail;
+	}
+	/*
+	 * Map control/status registers.
+	 */
+	if (pci_mapreg_map(pa, SK_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
+			   &iobase, &iosize)) {
+		printf(": can't find i/o space\n");
+		goto fail;
+	}
+#else
+	if (!(command & PCI_COMMAND_MEM_ENABLE)) {
+		printf(": failed to enable memory mapping!\n");
+		goto fail;
+	}
+	memtype = pci_mapreg_type(pc, pa->pa_tag, SK_PCI_LOMEM);
+	switch (memtype) {
+        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
+        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
+                if (pci_mapreg_map(pa, SK_PCI_LOMEM,
+				   memtype, 0, &sc->sk_btag, &sc->sk_bhandle,
+				   &iobase, &iosize) == 0)
+                        break;
+        default:
+                printf("%s: can't find mem space\n",
+		       sc->sk_dev.dv_xname);
+                return;
+	}
+
+	DPRINTFN(2, ("skc_attach: iobase=%lx, iosize=%lx\n", iobase, iosize));
+#endif
+	sc->sc_dmatag = pa->pa_dmat;
+
+	DPRINTFN(2, ("skc_attach: allocate interrupt\n"));
+
+	/* Allocate interrupt */
+	if (pci_intr_map(pa, &ih)) {
+		printf(": couldn't map interrupt\n");
+		goto fail;
+	}
+
+	intrstr = pci_intr_string(pc, ih);
+	sc->sk_intrhand = pci_intr_establish(pc, ih, IPL_NET, sk_intr, sc);
+	if (sc->sk_intrhand == NULL) {
+		printf(": couldn't establish interrupt");
+		if (intrstr != NULL)
+			printf(" at %s", intrstr);
+		goto fail;
+	}
+	printf(": %s\n", intrstr);
+
+	/* Reset the adapter. */
+	sk_reset(sc);
+
+	/* Read and save vital product data from EEPROM. */
+	sk_vpd_read(sc);
+
+	if (sc->sk_type == SK_GENESIS) {
+		u_int8_t val = sk_win_read_1(sc, SK_EPROM0);
+		/* Read and save RAM size and RAMbuffer offset */
+		switch(val) {
+		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("%s: unknown ram size: %d\n",
+			       sc->sk_dev.dv_xname, val);
+			goto fail;
+			break;
+		}
+
+		DPRINTFN(2, ("skc_attach: ramsize=%d(%dk), rboff=%d\n",
+			     sc->sk_ramsize, sc->sk_ramsize / 1024,
+			     sc->sk_rboff));
+	} else {
+		sc->sk_ramsize = 0x20000;
+		sc->sk_rboff = SK_RBOFF_0;
+
+		DPRINTFN(2, ("skc_attach: ramsize=%dk (%d), rboff=%d\n",
+			     sc->sk_ramsize / 1024, sc->sk_ramsize,
+			     sc->sk_rboff));
+	}
+
+	/* Read and save physical media type */
+	switch(sk_win_read_1(sc, SK_PMDTYPE)) {
+	case SK_PMD_1000BASESX:
+		sc->sk_pmd = IFM_1000_SX;
+		break;
+	case SK_PMD_1000BASELX:
+		sc->sk_pmd = IFM_1000_LX;
+		break;
+	case SK_PMD_1000BASECX:
+		sc->sk_pmd = IFM_1000_CX;
+		break;
+	case SK_PMD_1000BASETX:
+		sc->sk_pmd = IFM_1000_T;
+		break;
+	default:
+		printf("%s: unknown media type: 0x%x\n",
+		    sc->sk_dev.dv_xname, sk_win_read_1(sc, SK_PMDTYPE));
+		goto fail;
+	}
+
+	/* Announce the product name. */
+	printf("%s: %s\n", sc->sk_dev.dv_xname, sc->sk_vpd_prodname);
+
+	skca.skc_port = SK_PORT_A;
+	(void)config_found(&sc->sk_dev, &skca, skcprint);
+
+	if (!(sk_win_read_1(sc, SK_CONFIG) & SK_CONFIG_SINGLEMAC)) {
+		skca.skc_port = SK_PORT_B;
+		(void)config_found(&sc->sk_dev, &skca, skcprint);
+	}
+
+	/* Turn on the 'driver is loaded' LED. */
+	CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_ON);
+
+fail:
+	splx(s);
+}
+
+int
+sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct sk_tx_desc	*f = NULL;
+	u_int32_t		frag, cur, cnt = 0;
+	int			i;
+	struct sk_txmap_entry	*entry;
+	bus_dmamap_t		txmap;
+
+	DPRINTFN(3, ("sk_encap\n"));
+
+	entry = SLIST_FIRST(&sc_if->sk_txmap_listhead);
+	if (entry == NULL) {
+		DPRINTFN(3, ("sk_encap: no txmap available\n"));
+		return ENOBUFS;
+	}
+	txmap = entry->dmamap;
+
+	cur = frag = *txidx;
+
+#ifdef SK_DEBUG
+	if (skdebug >= 3)
+		sk_dump_mbuf(m_head);
+#endif
+
+	/*
+	 * Start packing the mbufs in this chain into
+	 * the fragment pointers. Stop when we run out
+	 * of fragments or hit the end of the mbuf chain.
+	 */
+	if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head,
+	    BUS_DMA_NOWAIT)) {
+		DPRINTFN(1, ("sk_encap: dmamap failed\n"));
+		return(ENOBUFS);
+	}
+
+	DPRINTFN(3, ("sk_encap: dm_nsegs=%d\n", txmap->dm_nsegs));
+
+	for (i = 0; i < txmap->dm_nsegs; i++) {
+		if ((SK_TX_RING_CNT - (sc_if->sk_cdata.sk_tx_cnt + cnt)) < 2) {
+			DPRINTFN(1, ("sk_encap: too few descriptors free\n"));
+			return(ENOBUFS);
+		}
+		f = &sc_if->sk_rdata->sk_tx_ring[frag];
+		f->sk_data_lo = txmap->dm_segs[i].ds_addr;
+		f->sk_ctl = txmap->dm_segs[i].ds_len | SK_OPCODE_DEFAULT;
+		if (cnt == 0)
+			f->sk_ctl |= SK_TXCTL_FIRSTFRAG;
+		else
+			f->sk_ctl |= SK_TXCTL_OWN;
+
+		cur = frag;
+		SK_INC(frag, SK_TX_RING_CNT);
+		cnt++;
+	}
+
+	sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head;
+	SLIST_REMOVE_HEAD(&sc_if->sk_txmap_listhead, link);
+	sc_if->sk_cdata.sk_tx_map[cur] = entry;
+	sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |=
+		SK_TXCTL_LASTFRAG|SK_TXCTL_EOF_INTR;
+	sc_if->sk_rdata->sk_tx_ring[*txidx].sk_ctl |= SK_TXCTL_OWN;
+	sc_if->sk_cdata.sk_tx_cnt += cnt;
+
+#ifdef SK_DEBUG
+	if (skdebug >= 3) {
+		struct sk_tx_desc *desc;
+		u_int32_t idx;
+		for (idx = *txidx; idx != frag; SK_INC(idx, SK_TX_RING_CNT)) {
+			desc = &sc_if->sk_rdata->sk_tx_ring[idx];
+			sk_dump_txdesc(desc, idx);
+		}
+	}
+#endif
+
+	*txidx = frag;
+
+	DPRINTFN(3, ("sk_encap: completed successfully\n"));
+
+	return(0);
+}
+
+void
+sk_start(struct ifnet *ifp)
+{
+        struct sk_if_softc	*sc_if = ifp->if_softc;
+        struct sk_softc		*sc = sc_if->sk_softc;
+        struct mbuf		*m_head = NULL;
+        u_int32_t		idx = sc_if->sk_cdata.sk_tx_prod;
+	int			pkts = 0;
+
+	DPRINTFN(3, ("sk_start\n"));
+
+	while(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf == NULL) {
+		IFQ_POLL(&ifp->if_snd, m_head);
+		if (m_head == NULL)
+			break;
+
+		/*
+		 * Pack the data into the transmit ring. If we
+		 * don't have room, set the OACTIVE flag and wait
+		 * for the NIC to drain the ring.
+		 */
+		if (sk_encap(sc_if, m_head, &idx)) {
+			ifp->if_flags |= IFF_OACTIVE;
+			break;
+		}
+
+		/* now we are committed to transmit the packet */
+		IFQ_DEQUEUE(&ifp->if_snd, m_head);
+		pkts++;
+
+		/*
+		 * If there's a BPF listener, bounce a copy of this frame
+		 * to him.
+		 */
+#if NBPFILTER > 0
+		if (ifp->if_bpf)
+			bpf_mtap(ifp->if_bpf, m_head);
+#endif
+	}
+	if (pkts == 0)
+		return;
+
+	/* Transmit */
+	sc_if->sk_cdata.sk_tx_prod = idx;
+	CSR_WRITE_4(sc, sc_if->sk_tx_bmu, SK_TXBMU_TX_START);
+
+	/* Set a timeout in case the chip goes out to lunch. */
+	ifp->if_timer = 5;
+}
+
+
+void
+sk_watchdog(struct ifnet *ifp)
+{
+	struct sk_if_softc *sc_if = ifp->if_softc;
+
+	printf("%s: watchdog timeout\n", sc_if->sk_dev.dv_xname);
+	(void) sk_init(ifp);
+}
+
+void
+sk_shutdown(void * v)
+{
+	struct sk_if_softc	*sc_if = (struct sk_if_softc *)v;
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct ifnet 		*ifp = &sc_if->sk_ethercom.ec_if;
+
+	DPRINTFN(2, ("sk_shutdown\n"));
+	sk_stop(ifp,1);
+
+	/* Turn off the 'driver is loaded' LED. */
+	CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF);
+
+	/*
+	 * Reset the GEnesis controller. Doing this should also
+	 * assert the resets on the attached XMAC(s).
+	 */
+	sk_reset(sc);
+}
+
+void
+sk_rxeof(struct sk_if_softc *sc_if)
+{
+	struct ifnet		*ifp = &sc_if->sk_ethercom.ec_if;
+	struct mbuf		*m;
+	struct sk_chain		*cur_rx;
+	struct sk_rx_desc	*cur_desc;
+	int			i, cur, total_len = 0;
+	u_int32_t		rxstat;
+	bus_dmamap_t		dmamap;
+
+	DPRINTFN(3, ("sk_rxeof\n"));
+
+	i = sc_if->sk_cdata.sk_rx_prod;
+
+	while(!(sc_if->sk_rdata->sk_rx_ring[i].sk_ctl & SK_RXCTL_OWN)) {
+		cur = i;
+		cur_rx = &sc_if->sk_cdata.sk_rx_chain[cur];
+		cur_desc = &sc_if->sk_rdata->sk_rx_ring[cur];
+
+		rxstat = cur_desc->sk_xmac_rxstat;
+		m = cur_rx->sk_mbuf;
+		cur_rx->sk_mbuf = NULL;
+		total_len = SK_RXBYTES(cur_desc->sk_ctl);
+
+		dmamap = sc_if->sk_cdata.sk_rx_map[cur];
+		sc_if->sk_cdata.sk_rx_map[cur] = 0;
+
+		SK_INC(i, SK_RX_RING_CNT);
+
+		if (rxstat & XM_RXSTAT_ERRFRAME) {
+			ifp->if_ierrors++;
+			sk_newbuf(sc_if, cur, m, dmamap);
+			continue;
+		}
+
+		/*
+		 * Try to allocate a new jumbo buffer. If that
+		 * fails, copy the packet to mbufs and put the
+		 * jumbo buffer back in the ring so it can be
+		 * re-used. If allocating mbufs fails, then we
+		 * have to drop the packet.
+		 */
+		if (sk_newbuf(sc_if, cur, NULL, dmamap) == ENOBUFS) {
+			struct mbuf		*m0;
+			m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
+			    total_len + ETHER_ALIGN, 0, ifp, NULL);
+			sk_newbuf(sc_if, cur, m, dmamap);
+			if (m0 == NULL) {
+				printf("%s: no receive buffers "
+				    "available -- packet dropped!\n",
+				    sc_if->sk_dev.dv_xname);
+				ifp->if_ierrors++;
+				continue;
+			}
+			m_adj(m0, ETHER_ALIGN);
+			m = m0;
+		} else {
+			m->m_pkthdr.rcvif = ifp;
+			m->m_pkthdr.len = m->m_len = total_len;
+		}
+
+		ifp->if_ipackets++;
+
+#if NBPFILTER > 0
+		if (ifp->if_bpf)
+			bpf_mtap(ifp->if_bpf, m);
+#endif
+		/* pass it on. */
+		(*ifp->if_input)(ifp, m);
+	}
+
+	sc_if->sk_cdata.sk_rx_prod = i;
+}
+
+void
+sk_txeof(struct sk_if_softc *sc_if)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct sk_tx_desc	*cur_tx = NULL;
+	struct ifnet		*ifp = &sc_if->sk_ethercom.ec_if;
+	u_int32_t		idx;
+	struct sk_txmap_entry	*entry;
+
+	DPRINTFN(3, ("sk_txeof\n"));
+
+	/*
+	 * Go through our tx ring and free mbufs for those
+	 * frames that have been sent.
+	 */
+	idx = sc_if->sk_cdata.sk_tx_cons;
+	while(idx != sc_if->sk_cdata.sk_tx_prod) {
+		cur_tx = &sc_if->sk_rdata->sk_tx_ring[idx];
+#ifdef SK_DEBUG
+		if (skdebug >= 3)
+			sk_dump_txdesc(cur_tx, idx);
+#endif
+		if (cur_tx->sk_ctl & SK_TXCTL_OWN)
+			break;
+		if (cur_tx->sk_ctl & SK_TXCTL_LASTFRAG)
+			ifp->if_opackets++;
+		if (sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf != NULL) {
+			m_freem(sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf);
+			sc_if->sk_cdata.sk_tx_chain[idx].sk_mbuf = NULL;
+
+			entry = sc_if->sk_cdata.sk_tx_map[idx];
+			bus_dmamap_sync(sc->sc_dmatag, entry->dmamap, 0,
+			    entry->dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
+
+			bus_dmamap_unload(sc->sc_dmatag, entry->dmamap);
+			SLIST_INSERT_HEAD(&sc_if->sk_txmap_listhead, entry,
+					  link);
+			sc_if->sk_cdata.sk_tx_map[idx] = NULL;
+		}
+		sc_if->sk_cdata.sk_tx_cnt--;
+		SK_INC(idx, SK_TX_RING_CNT);
+		ifp->if_timer = 0;
+	}
+
+	sc_if->sk_cdata.sk_tx_cons = idx;
+
+	if (cur_tx != NULL)
+		ifp->if_flags &= ~IFF_OACTIVE;
+}
+
+void
+sk_tick(void *xsc_if)
+{
+	struct sk_if_softc *sc_if = xsc_if;
+	struct mii_data *mii = &sc_if->sk_mii;
+	struct ifnet *ifp = &sc_if->sk_ethercom.ec_if;
+	int i;
+
+	DPRINTFN(3, ("sk_tick\n"));
+
+	if (!(ifp->if_flags & IFF_UP))
+		return;
+
+	if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
+		sk_intr_bcom(sc_if);
+		return;
+	}
+
+	/*
+	 * According to SysKonnect, the correct way to verify that
+	 * the link has come back up is to poll bit 0 of the GPIO
+	 * register three times. This pin has the signal from the
+	 * link sync pin connected to it; if we read the same link
+	 * state 3 times in a row, we know the link is up.
+	 */
+	for (i = 0; i < 3; i++) {
+		if (SK_XM_READ_2(sc_if, XM_GPIO) & XM_GPIO_GP0_SET)
+			break;
+	}
+
+	if (i != 3) {
+		callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if);
+		return;
+	}
+
+	/* Turn the GP0 interrupt back on. */
+	SK_XM_CLRBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET);
+	SK_XM_READ_2(sc_if, XM_ISR);
+	mii_tick(mii);
+	mii_pollstat(mii);
+	callout_stop(&sc_if->sk_tick_ch);
+}
+
+void
+sk_intr_bcom(struct sk_if_softc *sc_if)
+{
+	struct mii_data *mii = &sc_if->sk_mii;
+	struct ifnet *ifp = &sc_if->sk_ethercom.ec_if;
+	int status;
+
+
+	DPRINTFN(3, ("sk_intr_bcom\n"));
+
+	SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+
+	/*
+	 * Read the PHY interrupt register to make sure
+	 * we clear any pending interrupts.
+	 */
+	status = sk_xmac_miibus_readreg((struct device *)sc_if,
+	    SK_PHYADDR_BCOM, BRGPHY_MII_ISR);
+
+	if (!(ifp->if_flags & IFF_RUNNING)) {
+		sk_init_xmac(sc_if);
+		return;
+	}
+
+	if (status & (BRGPHY_ISR_LNK_CHG|BRGPHY_ISR_AN_PR)) {
+		int lstat;
+		lstat = sk_xmac_miibus_readreg((struct device *)sc_if,
+		    SK_PHYADDR_BCOM, BRGPHY_MII_AUXSTS);
+
+		if (!(lstat & BRGPHY_AUXSTS_LINK) && sc_if->sk_link) {
+			mii_mediachg(mii);
+			/* Turn off the link LED. */
+			SK_IF_WRITE_1(sc_if, 0,
+			    SK_LINKLED1_CTL, SK_LINKLED_OFF);
+			sc_if->sk_link = 0;
+		} else if (status & BRGPHY_ISR_LNK_CHG) {
+			sk_xmac_miibus_writereg((struct device *)sc_if,
+			    SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFF00);
+			mii_tick(mii);
+			sc_if->sk_link = 1;
+			/* Turn on the link LED. */
+			SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL,
+			    SK_LINKLED_ON|SK_LINKLED_LINKSYNC_OFF|
+			    SK_LINKLED_BLINK_OFF);
+			mii_pollstat(mii);
+		} else {
+			mii_tick(mii);
+			callout_reset(&sc_if->sk_tick_ch, hz, sk_tick,sc_if);
+		}
+	}
+
+	SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+}
+
+void
+sk_intr_xmac(struct sk_if_softc	*sc_if)
+{
+	u_int16_t status = SK_XM_READ_2(sc_if, XM_ISR);
+
+	DPRINTFN(3, ("sk_intr_xmac\n"));
+
+	if (sc_if->sk_phytype == SK_PHYTYPE_XMAC) {
+		if (status & XM_ISR_GP0_SET) {
+			SK_XM_SETBIT_2(sc_if, XM_IMR, XM_IMR_GP0_SET);
+			callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if);
+		}
+
+		if (status & XM_ISR_AUTONEG_DONE) {
+			callout_reset(&sc_if->sk_tick_ch, hz, sk_tick, sc_if);
+		}
+	}
+
+	if (status & XM_IMR_TX_UNDERRUN)
+		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_TXFIFO);
+
+	if (status & XM_IMR_RX_OVERRUN)
+		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_FLUSH_RXFIFO);
+}
+
+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);
+
+	DPRINTFN(3, ("sk_intr_yukon status=%#x\n", status));
+}
+
+int
+sk_intr(void *xsc)
+{
+	struct sk_softc		*sc = xsc;
+	struct sk_if_softc	*sc_if0 = sc->sk_if[SK_PORT_A];
+	struct sk_if_softc	*sc_if1 = sc->sk_if[SK_PORT_B];
+	struct ifnet		*ifp0 = NULL, *ifp1 = NULL;
+	u_int32_t		status;
+	int			claimed = 0;
+
+	if (sc_if0 != NULL)
+		ifp0 = &sc_if0->sk_ethercom.ec_if;
+	if (sc_if1 != NULL)
+		ifp1 = &sc_if1->sk_ethercom.ec_if;
+
+	for (;;) {
+		status = CSR_READ_4(sc, SK_ISSR);
+		DPRINTFN(3, ("sk_intr: status=%#x\n", status));
+
+		if (!(status & sc->sk_intrmask))
+			break;
+
+		claimed = 1;
+
+		/* Handle receive interrupts first. */
+		if (status & SK_ISR_RX1_EOF) {
+			sk_rxeof(sc_if0);
+			CSR_WRITE_4(sc, SK_BMU_RX_CSR0,
+			    SK_RXBMU_CLR_IRQ_EOF|SK_RXBMU_RX_START);
+		}
+		if (status & SK_ISR_RX2_EOF) {
+			sk_rxeof(sc_if1);
+			CSR_WRITE_4(sc, SK_BMU_RX_CSR1,
+			    SK_RXBMU_CLR_IRQ_EOF|SK_RXBMU_RX_START);
+		}
+
+		/* Then transmit interrupts. */
+		if (status & SK_ISR_TX1_S_EOF) {
+			sk_txeof(sc_if0);
+			CSR_WRITE_4(sc, SK_BMU_TXS_CSR0,
+			    SK_TXBMU_CLR_IRQ_EOF);
+		}
+		if (status & SK_ISR_TX2_S_EOF) {
+			sk_txeof(sc_if1);
+			CSR_WRITE_4(sc, SK_BMU_TXS_CSR1,
+			    SK_TXBMU_CLR_IRQ_EOF);
+		}
+
+		/* Then MAC interrupts. */
+		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 &&
+			    sc_if0->sk_phytype == SK_PHYTYPE_BCOM)
+				sk_intr_bcom(sc_if0);
+
+			if (ifp1 != NULL &&
+			    sc_if1->sk_phytype == SK_PHYTYPE_BCOM)
+				sk_intr_bcom(sc_if1);
+		}
+	}
+
+	CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
+
+	if (ifp0 != NULL && !IFQ_IS_EMPTY(&ifp0->if_snd))
+		sk_start(ifp0);
+	if (ifp1 != NULL && !IFQ_IS_EMPTY(&ifp1->if_snd))
+		sk_start(ifp1);
+
+	return (claimed);
+}
+
+void
+sk_init_xmac(struct sk_if_softc	*sc_if)
+{
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct ifnet		*ifp = &sc_if->sk_ethercom.ec_if;
+	struct sk_bcom_hack     bhack[] = {
+	{ 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
+	{ 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
+	{ 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+	{ 0, 0 } };
+
+	DPRINTFN(1, ("sk_init_xmac\n"));
+
+	/* Unreset the XMAC. */
+	SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_UNRESET);
+	DELAY(1000);
+
+	/* Reset the XMAC's internal state. */
+	SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
+
+	/* Save the XMAC II revision */
+	sc_if->sk_xmac_rev = XM_XMAC_REV(SK_XM_READ_4(sc_if, XM_DEVID));
+
+	/*
+	 * Perform additional initialization for external PHYs,
+	 * namely for the 1000baseTX cards that use the XMAC's
+	 * GMII mode.
+	 */
+	if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
+		int			i = 0;
+		u_int32_t		val;
+
+		/* Take PHY out of reset. */
+		val = sk_win_read_4(sc, SK_GPIO);
+		if (sc_if->sk_port == SK_PORT_A)
+			val |= SK_GPIO_DIR0|SK_GPIO_DAT0;
+		else
+			val |= SK_GPIO_DIR2|SK_GPIO_DAT2;
+		sk_win_write_4(sc, SK_GPIO, val);
+
+		/* Enable GMII mode on the XMAC. */
+		SK_XM_SETBIT_2(sc_if, XM_HWCFG, XM_HWCFG_GMIIMODE);
+
+		sk_xmac_miibus_writereg((struct device *)sc_if,
+		    SK_PHYADDR_BCOM, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
+		DELAY(10000);
+		sk_xmac_miibus_writereg((struct device *)sc_if,
+		    SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFFF0);
+
+		/*
+		 * Early versions of the BCM5400 apparently have
+		 * a bug that requires them to have their reserved
+		 * registers initialized to some magic values. I don't
+		 * know what the numbers do, I'm just the messenger.
+		 */
+		if (sk_xmac_miibus_readreg((struct device *)sc_if,
+		    SK_PHYADDR_BCOM, 0x03) == 0x6041) {
+			while(bhack[i].reg) {
+				sk_xmac_miibus_writereg((struct device *)sc_if,
+				    SK_PHYADDR_BCOM, bhack[i].reg,
+				    bhack[i].val);
+				i++;
+			}
+		}
+	}
+
+	/* Set station address */
+	SK_XM_WRITE_2(sc_if, XM_PAR0,
+		      *(u_int16_t *)(&sc_if->sk_enaddr[0]));
+	SK_XM_WRITE_2(sc_if, XM_PAR1,
+		      *(u_int16_t *)(&sc_if->sk_enaddr[2]));
+	SK_XM_WRITE_2(sc_if, XM_PAR2,
+		      *(u_int16_t *)(&sc_if->sk_enaddr[4]));
+	SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_STATION);
+
+	if (ifp->if_flags & IFF_PROMISC) {
+		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
+	} else {
+		SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_PROMISC);
+	}
+
+	if (ifp->if_flags & IFF_BROADCAST) {
+		SK_XM_CLRBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD);
+	} else {
+		SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_NOBROAD);
+	}
+
+	/* We don't need the FCS appended to the packet. */
+	SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_STRIPFCS);
+
+	/* We want short frames padded to 60 bytes. */
+	SK_XM_SETBIT_2(sc_if, XM_TXCMD, XM_TXCMD_AUTOPAD);
+
+	/*
+	 * Enable the reception of all error frames. This is is
+	 * a necessary evil due to the design of the XMAC. The
+	 * XMAC's receive FIFO is only 8K in size, however jumbo
+	 * frames can be up to 9000 bytes in length. When bad
+	 * frame filtering is enabled, the XMAC's RX FIFO operates
+	 * in 'store and forward' mode. For this to work, the
+	 * entire frame has to fit into the FIFO, but that means
+	 * that jumbo frames larger than 8192 bytes will be
+	 * truncated. Disabling all bad frame filtering causes
+	 * the RX FIFO to operate in streaming mode, in which
+	 * case the XMAC will start transfering frames out of the
+	 * RX FIFO as soon as the FIFO threshold is reached.
+	 */
+	SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_BADFRAMES|
+	    XM_MODE_RX_GIANTS|XM_MODE_RX_RUNTS|XM_MODE_RX_CRCERRS|
+	    XM_MODE_RX_INRANGELEN);
+
+	if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN))
+		SK_XM_SETBIT_2(sc_if, XM_RXCMD, XM_RXCMD_BIGPKTOK);
+	else
+		SK_XM_CLRBIT_2(sc_if, XM_RXCMD, XM_RXCMD_BIGPKTOK);
+
+	/*
+	 * Bump up the transmit threshold. This helps hold off transmit
+	 * underruns when we're blasting traffic from both ports at once.
+	 */
+	SK_XM_WRITE_2(sc_if, XM_TX_REQTHRESH, SK_XM_TX_FIFOTHRESH);
+
+	/* Set multicast filter */
+	sk_setmulti(sc_if);
+
+	/* Clear and enable interrupts */
+	SK_XM_READ_2(sc_if, XM_ISR);
+	if (sc_if->sk_phytype == SK_PHYTYPE_XMAC)
+		SK_XM_WRITE_2(sc_if, XM_IMR, XM_INTRS);
+	else
+		SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
+
+	/* Configure MAC arbiter */
+	switch(sc_if->sk_xmac_rev) {
+	case XM_XMAC_REV_B2:
+		sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_B2);
+		sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2);
+		break;
+	case XM_XMAC_REV_C1:
+		sk_win_write_1(sc, SK_RCINIT_RX1, SK_RCINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_RCINIT_TX1, SK_RCINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_RCINIT_RX2, SK_RCINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_RCINIT_TX2, SK_RCINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_MINIT_RX1, SK_MINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_MINIT_TX1, SK_MINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_MINIT_RX2, SK_MINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_MINIT_TX2, SK_MINIT_XMAC_C1);
+		sk_win_write_1(sc, SK_RECOVERY_CTL, SK_RECOVERY_XMAC_B2);
+		break;
+	default:
+		break;
+	}
+	sk_win_write_2(sc, SK_MACARB_CTL,
+	    SK_MACARBCTL_UNRESET|SK_MACARBCTL_FASTOE_OFF);
+
+	sc_if->sk_link = 1;
+}
+
+void sk_init_yukon(sc_if)
+	struct sk_if_softc	*sc_if;
+{
+	u_int32_t		/*mac, */phy;
+	u_int16_t		reg;
+	int			i;
+
+	DPRINTFN(1, ("sk_init_yukon: start: sk_csr=%#x\n",
+		     CSR_READ_4(sc_if->sk_softc, SK_CSR)));
+
+	/* GMAC and GPHY Reset */
+	SK_IF_WRITE_4(sc_if, 0, SK_GPHY_CTRL, SK_GPHY_RESET_SET);
+
+	DPRINTFN(6, ("sk_init_yukon: 1\n"));
+
+	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);
+
+
+	DPRINTFN(6, ("sk_init_yukon: 2\n"));
+
+	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;
+	}
+
+	DPRINTFN(3, ("sk_init_yukon: phy=%#x\n", phy));
+
+	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);
+
+	DPRINTFN(3, ("sk_init_yukon: gmac_ctrl=%#x\n",
+		     SK_IF_READ_4(sc_if, 0, SK_GMAC_CTRL)));
+
+	DPRINTFN(6, ("sk_init_yukon: 3\n"));
+
+	/* unused read of the interrupt source register */
+	DPRINTFN(6, ("sk_init_yukon: 4\n"));
+	SK_IF_READ_2(sc_if, 0, SK_GMAC_ISR);
+
+	DPRINTFN(6, ("sk_init_yukon: 4a\n"));
+	reg = SK_YU_READ_2(sc_if, YUKON_PAR);
+	DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg));
+
+	/* MIB Counter Clear Mode set */
+        reg |= YU_PAR_MIB_CLR;
+	DPRINTFN(6, ("sk_init_yukon: YUKON_PAR=%#x\n", reg));
+	DPRINTFN(6, ("sk_init_yukon: 4b\n"));
+	SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
+        
+	/* MIB Counter Clear Mode clear */
+	DPRINTFN(6, ("sk_init_yukon: 5\n"));
+        reg &= ~YU_PAR_MIB_CLR;
+	SK_YU_WRITE_2(sc_if, YUKON_PAR, reg);
+
+	/* receive control reg */
+	DPRINTFN(6, ("sk_init_yukon: 7\n"));
+	SK_YU_WRITE_2(sc_if, YUKON_RCR, YU_RCR_UFLEN | YU_RCR_MUFLEN |
+		      YU_RCR_CRCR);
+
+	/* transmit parameter register */
+	DPRINTFN(6, ("sk_init_yukon: 8\n"));
+	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 */
+	DPRINTFN(6, ("sk_init_yukon: 9\n"));
+	SK_YU_WRITE_2(sc_if, YUKON_SMR, YU_SMR_DATA_BLIND(0x1c) |
+		      YU_SMR_MFL_VLAN | YU_SMR_IPG_DATA(0x1e));
+
+	DPRINTFN(6, ("sk_init_yukon: 10\n"));
+	/* 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->sk_enaddr[i * 2] |
+			      sc_if->sk_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 */
+	DPRINTFN(6, ("sk_init_yukon: 11\n"));
+	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 */
+	DPRINTFN(6, ("sk_init_yukon: 12\n"));
+	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);
+		
+	DPRINTFN(6, ("sk_init_yukon: end\n"));
+}
+
+/*
+ * Note that to properly initialize any part of the GEnesis chip,
+ * you first have to take it out of reset mode.
+ */
+int
+sk_init(struct ifnet *ifp)
+{
+	struct sk_if_softc	*sc_if = ifp->if_softc;
+	struct sk_softc		*sc = sc_if->sk_softc;
+	struct mii_data		*mii = &sc_if->sk_mii;
+	int			s;
+
+	DPRINTFN(1, ("sk_init\n"));
+
+	s = splnet();
+
+	/* Cancel pending I/O and free all RX/TX buffers. */
+	sk_stop(ifp,0);
+
+	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) */
+	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);
+
+	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,
+	    SK_TXARCTL_ON|SK_TXARCTL_FSYNC_ON);
+
+	/* Configure RAMbuffers */
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_UNRESET);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_START, sc_if->sk_rx_ramstart);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_WR_PTR, sc_if->sk_rx_ramstart);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_RD_PTR, sc_if->sk_rx_ramstart);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_END, sc_if->sk_rx_ramend);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_ON);
+
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_UNRESET);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_STORENFWD_ON);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_START, sc_if->sk_tx_ramstart);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_WR_PTR, sc_if->sk_tx_ramstart);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_RD_PTR, sc_if->sk_tx_ramstart);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_END, sc_if->sk_tx_ramend);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_ON);
+
+	/* Configure BMUs */
+	SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_ONLINE);
+	SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_LO,
+	    SK_RX_RING_ADDR(sc_if, 0));
+	SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_CURADDR_HI, 0);
+
+	SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_ONLINE);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_LO,
+            SK_TX_RING_ADDR(sc_if, 0));
+	SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_CURADDR_HI, 0);
+
+	/* Init descriptors */
+	if (sk_init_rx_ring(sc_if) == ENOBUFS) {
+		printf("%s: initialization failed: no "
+		    "memory for rx buffers\n", sc_if->sk_dev.dv_xname);
+		sk_stop(ifp,0);
+		splx(s);
+		return(ENOBUFS);
+	}
+
+	if (sk_init_tx_ring(sc_if) == ENOBUFS) {
+		printf("%s: initialization failed: no "
+		    "memory for tx buffers\n", sc_if->sk_dev.dv_xname);
+		sk_stop(ifp,0);
+		splx(s);
+		return(ENOBUFS);
+	}
+
+	/* Configure interrupt handling */
+	CSR_READ_4(sc, SK_ISSR);
+	if (sc_if->sk_port == SK_PORT_A)
+		sc->sk_intrmask |= SK_INTRS1;
+	else
+		sc->sk_intrmask |= SK_INTRS2;
+
+	sc->sk_intrmask |= SK_ISR_EXTERNAL_REG;
+
+	CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
+
+	/* Start BMUs. */
+	SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_START);
+
+	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;
+
+	splx(s);
+	return(0);
+}
+
+void
+sk_stop(struct ifnet *ifp, int disable)
+{
+        struct sk_if_softc	*sc_if = ifp->if_softc;
+	struct sk_softc		*sc = sc_if->sk_softc;
+	int			i;
+
+	DPRINTFN(1, ("sk_stop\n"));
+
+	callout_stop(&sc_if->sk_tick_ch);
+
+	if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
+		u_int32_t		val;
+
+		/* Put PHY back into reset. */
+		val = sk_win_read_4(sc, SK_GPIO);
+		if (sc_if->sk_port == SK_PORT_A) {
+			val |= SK_GPIO_DIR0;
+			val &= ~SK_GPIO_DAT0;
+		} else {
+			val |= SK_GPIO_DIR2;
+			val &= ~SK_GPIO_DAT2;
+		}
+		sk_win_write_4(sc, SK_GPIO, val);
+	}
+
+	/* Turn off various components of this interface. */
+	SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
+	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);
+	SK_IF_WRITE_4(sc_if, 1, SK_TXRBS1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
+	SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL, SK_TXARCTL_OFF);
+	SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
+	SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_RXLEDCTL_COUNTER_STOP);
+	SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_OFF);
+	SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_OFF);
+
+	/* Disable interrupts */
+	if (sc_if->sk_port == SK_PORT_A)
+		sc->sk_intrmask &= ~SK_INTRS1;
+	else
+		sc->sk_intrmask &= ~SK_INTRS2;
+	CSR_WRITE_4(sc, SK_IMR, sc->sk_intrmask);
+
+	SK_XM_READ_2(sc_if, XM_ISR);
+	SK_XM_WRITE_2(sc_if, XM_IMR, 0xFFFF);
+
+	/* Free RX and TX mbufs still in the queues. */
+	if ( disable ) {
+	for (i = 0; i < SK_RX_RING_CNT; i++) {
+		if (sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf != NULL) {
+			m_freem(sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf);
+			sc_if->sk_cdata.sk_rx_chain[i].sk_mbuf = NULL;
+		}
+	}
+
+	for (i = 0; i < SK_TX_RING_CNT; i++) {
+		if (sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf != NULL) {
+			m_freem(sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf);
+			sc_if->sk_cdata.sk_tx_chain[i].sk_mbuf = NULL;
+		}
+	}
+	}
+
+	ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
+}
+
+CFATTACH_DECL(skc,sizeof(struct sk_softc), skc_probe, skc_attach, NULL, NULL);
+
+/*
+struct cfdriver skc_cd = {
+	0, "skc", DV_DULL
+};
+*/
+
+CFATTACH_DECL(sk,sizeof(struct sk_if_softc), sk_probe, sk_attach, NULL, NULL);
+
+/*
+struct cfdriver sk_cd = {
+	0, "sk", DV_IFNET
+};
+*/
+
+#ifdef SK_DEBUG
+void
+sk_dump_txdesc(struct sk_tx_desc *desc, int idx)
+{
+#define DESC_PRINT(X)					\
+	if (desc->X)					\
+		printf("txdesc[%d]." #X "=%#x\n",	\
+		       idx, desc->X);
+
+	DESC_PRINT(sk_ctl);
+	DESC_PRINT(sk_next);
+	DESC_PRINT(sk_data_lo);
+	DESC_PRINT(sk_data_hi);
+	DESC_PRINT(sk_xmac_txstat);
+	DESC_PRINT(sk_rsvd0);
+	DESC_PRINT(sk_csum_startval);
+	DESC_PRINT(sk_csum_startpos);
+	DESC_PRINT(sk_csum_writepos);
+	DESC_PRINT(sk_rsvd1);
+#undef PRINT
+}
+
+void
+sk_dump_bytes(const char *data, int len)
+{
+	int c, i, j;
+
+	for (i = 0; i < len; i += 16) {
+		printf("%08x  ", i);
+		c = len - i;
+		if (c > 16) c = 16;
+
+		for (j = 0; j < c; j++) {
+			printf("%02x ", data[i + j] & 0xff);
+			if ((j & 0xf) == 7 && j > 0)
+				printf(" ");
+		}
+		
+		for (; j < 16; j++)
+			printf("   ");
+		printf("  ");
+
+		for (j = 0; j < c; j++) {
+			int ch = data[i + j] & 0xff;
+			printf("%c", ' ' <= ch && ch <= '~' ? ch : ' ');
+		}
+		
+		printf("\n");
+		
+		if (c < 16)
+			break;
+	}
+}
+
+void
+sk_dump_mbuf(struct mbuf *m)
+{
+	int count = m->m_pkthdr.len;
+
+	printf("m=%p, m->m_pkthdr.len=%d\n", m, m->m_pkthdr.len);
+
+	while (count > 0 && m) {
+		printf("m=%p, m->m_data=%p, m->m_len=%d\n",
+		       m, m->m_data, m->m_len);
+		sk_dump_bytes(mtod(m, char *), m->m_len);
+
+		count -= m->m_len;
+		m = m->m_next;
+	}
+}
+#endif
Index: sys/dev/pci/if_skreg.h
===================================================================
RCS file: if_skreg.h
diff -N if_skreg.h
--- /dev/null	Thu Jul 11 11:18:53 2002
+++ sys/dev/pci/if_skreg.h	Sun Aug 17 07:04:00 2003
@@ -0,0 +1,1374 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*	$OpenBSD: if_skreg.h,v 1.10 2003/08/12 05:23:06 nate Exp $	*/
+
+/*
+ * Copyright (c) 1997, 1998, 1999, 2000
+ *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: /c/ncvs/src/sys/pci/if_skreg.h,v 1.9 2000/04/22 02:16:37 wpaul Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _DEV_PCI_IF_SKREG_H_
+#define _DEV_PCI_IF_SKREG_H_
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+/* 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
+ * but internally it has a 16K register space. This 16K space is
+ * divided into 128-byte blocks. The first 128 bytes of the I/O
+ * window represent the first block, which is permanently mapped
+ * at the start of the window. The other 127 blocks can be mapped
+ * to the second 128 bytes of the I/O window by setting the desired
+ * block value in the RAP register in block 0. Not all of the 127
+ * blocks are actually used. Most registers are 32 bits wide, but
+ * there are a few 16-bit and 8-bit ones as well.
+ */
+
+
+/* Start of remappable register window. */
+#define SK_WIN_BASE		0x0080
+
+/* Size of a window */
+#define SK_WIN_LEN		0x80
+
+#define SK_WIN_MASK		0x3F80
+#define SK_REG_MASK		0x7F
+
+/* Compute the window of a given register (for the RAP register) */
+#define SK_WIN(reg)		(((reg) & SK_WIN_MASK) / SK_WIN_LEN)
+
+/* Compute the relative offset of a register within the window */
+#define SK_REG(reg)		((reg) & SK_REG_MASK)
+
+#define SK_PORT_A	0
+#define SK_PORT_B	1
+
+/*
+ * Compute offset of port-specific register. Since there are two
+ * ports, there are two of some GEnesis modules (e.g. two sets of
+ * DMA queues, two sets of FIFO control registers, etc...). Normally,
+ * the block for port 0 is at offset 0x0 and the block for port 1 is
+ * at offset 0x80 (i.e. the next page over). However for the transmit
+ * BMUs and RAMbuffers, there are two blocks for each port: one for
+ * the sync transmit queue and one for the async queue (which we don't
+ * use). However instead of ordering them like this:
+ * TX sync 1 / TX sync 2 / TX async 1 / TX async 2
+ * SysKonnect has instead ordered them like this:
+ * TX sync 1 / TX async 1 / TX sync 2 / TX async 2
+ * This means that when referencing the TX BMU and RAMbuffer registers,
+ * we have to double the block offset (0x80 * 2) in order to reach the
+ * second queue. This prevents us from using the same formula
+ * (sk_port * 0x80) to compute the offsets for all of the port-specific
+ * blocks: we need an extra offset for the BMU and RAMbuffer registers.
+ * The simplest thing is to provide an extra argument to these macros:
+ * the 'skip' parameter. The 'skip' value is the number of extra pages
+ * for skip when computing the port0/port1 offsets. For most registers,
+ * the skip value is 0; for the BMU and RAMbuffer registers, it's 1.
+ */
+#define SK_IF_READ_4(sc_if, skip, reg)		\
+	sk_win_read_4(sc_if->sk_softc, reg +	\
+	((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN))
+#define SK_IF_READ_2(sc_if, skip, reg)		\
+	sk_win_read_2(sc_if->sk_softc, reg + 	\
+	((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN))
+#define SK_IF_READ_1(sc_if, skip, reg)		\
+	sk_win_read_1(sc_if->sk_softc, reg +	\
+	((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN))
+
+#define SK_IF_WRITE_4(sc_if, skip, reg, val)	\
+	sk_win_write_4(sc_if->sk_softc,		\
+	reg + ((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN), val)
+#define SK_IF_WRITE_2(sc_if, skip, reg, val)	\
+	sk_win_write_2(sc_if->sk_softc,		\
+	reg + ((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN), val)
+#define SK_IF_WRITE_1(sc_if, skip, reg, val)	\
+	sk_win_write_1(sc_if->sk_softc,		\
+	reg + ((sc_if->sk_port * (skip + 1)) * SK_WIN_LEN), val)
+
+/* Block 0 registers, permanently mapped at iobase. */
+#define SK_RAP		0x0000
+#define SK_CSR		0x0004
+#define SK_LED		0x0006
+#define SK_ISR		0x0008	/* interrupt source */
+#define SK_IMR		0x000C	/* interrupt mask */
+#define SK_IESR		0x0010	/* interrupt hardware error source */
+#define SK_IEMR		0x0014  /* interrupt hardware error mask */
+#define SK_ISSR		0x0018	/* special interrupt source */
+#define SK_XM_IMR0	0x0020
+#define SK_XM_ISR0	0x0028
+#define SK_XM_PHYADDR0	0x0030
+#define SK_XM_PHYDATA0	0x0034
+#define SK_XM_IMR1	0x0040
+#define SK_XM_ISR1	0x0048
+#define SK_XM_PHYADDR1	0x0050
+#define SK_XM_PHYDATA1	0x0054
+#define SK_BMU_RX_CSR0	0x0060
+#define SK_BMU_RX_CSR1	0x0064
+#define SK_BMU_TXS_CSR0	0x0068
+#define SK_BMU_TXA_CSR0	0x006C
+#define SK_BMU_TXS_CSR1	0x0070
+#define SK_BMU_TXA_CSR1	0x0074
+
+/* SK_CSR register */
+#define SK_CSR_SW_RESET			0x0001
+#define SK_CSR_SW_UNRESET		0x0002
+#define SK_CSR_MASTER_RESET		0x0004
+#define SK_CSR_MASTER_UNRESET		0x0008
+#define SK_CSR_MASTER_STOP		0x0010
+#define SK_CSR_MASTER_DONE		0x0020
+#define SK_CSR_SW_IRQ_CLEAR		0x0040
+#define SK_CSR_SW_IRQ_SET		0x0080
+#define SK_CSR_SLOTSIZE			0x0100 /* 1 == 64 bits, 0 == 32 */
+#define SK_CSR_BUSCLOCK			0x0200 /* 1 == 33/66 MHz, = 33 */
+
+/* SK_LED register */
+#define SK_LED_GREEN_OFF		0x01
+#define SK_LED_GREEN_ON			0x02
+
+/* SK_ISR register */
+#define SK_ISR_TX2_AS_CHECK		0x00000001
+#define SK_ISR_TX2_AS_EOF		0x00000002
+#define SK_ISR_TX2_AS_EOB		0x00000004
+#define SK_ISR_TX2_S_CHECK		0x00000008
+#define SK_ISR_TX2_S_EOF		0x00000010
+#define SK_ISR_TX2_S_EOB		0x00000020
+#define SK_ISR_TX1_AS_CHECK		0x00000040
+#define SK_ISR_TX1_AS_EOF		0x00000080
+#define SK_ISR_TX1_AS_EOB		0x00000100
+#define SK_ISR_TX1_S_CHECK		0x00000200
+#define SK_ISR_TX1_S_EOF		0x00000400
+#define SK_ISR_TX1_S_EOB		0x00000800
+#define SK_ISR_RX2_CHECK		0x00001000
+#define SK_ISR_RX2_EOF			0x00002000
+#define SK_ISR_RX2_EOB			0x00004000
+#define SK_ISR_RX1_CHECK		0x00008000
+#define SK_ISR_RX1_EOF			0x00010000
+#define SK_ISR_RX1_EOB			0x00020000
+#define SK_ISR_LINK2_OFLOW		0x00040000
+#define SK_ISR_MAC2			0x00080000
+#define SK_ISR_LINK1_OFLOW		0x00100000
+#define SK_ISR_MAC1			0x00200000
+#define SK_ISR_TIMER			0x00400000
+#define SK_ISR_EXTERNAL_REG		0x00800000
+#define SK_ISR_SW			0x01000000
+#define SK_ISR_I2C_RDY			0x02000000
+#define SK_ISR_TX2_TIMEO		0x04000000
+#define SK_ISR_TX1_TIMEO		0x08000000
+#define SK_ISR_RX2_TIMEO		0x10000000
+#define SK_ISR_RX1_TIMEO		0x20000000
+#define SK_ISR_RSVD			0x40000000
+#define SK_ISR_HWERR			0x80000000
+
+/* SK_IMR register */
+#define SK_IMR_TX2_AS_CHECK		0x00000001
+#define SK_IMR_TX2_AS_EOF		0x00000002
+#define SK_IMR_TX2_AS_EOB		0x00000004
+#define SK_IMR_TX2_S_CHECK		0x00000008
+#define SK_IMR_TX2_S_EOF		0x00000010
+#define SK_IMR_TX2_S_EOB		0x00000020
+#define SK_IMR_TX1_AS_CHECK		0x00000040
+#define SK_IMR_TX1_AS_EOF		0x00000080
+#define SK_IMR_TX1_AS_EOB		0x00000100
+#define SK_IMR_TX1_S_CHECK		0x00000200
+#define SK_IMR_TX1_S_EOF		0x00000400
+#define SK_IMR_TX1_S_EOB		0x00000800
+#define SK_IMR_RX2_CHECK		0x00001000
+#define SK_IMR_RX2_EOF			0x00002000
+#define SK_IMR_RX2_EOB			0x00004000
+#define SK_IMR_RX1_CHECK		0x00008000
+#define SK_IMR_RX1_EOF			0x00010000
+#define SK_IMR_RX1_EOB			0x00020000
+#define SK_IMR_LINK2_OFLOW		0x00040000
+#define SK_IMR_MAC2			0x00080000
+#define SK_IMR_LINK1_OFLOW		0x00100000
+#define SK_IMR_MAC1			0x00200000
+#define SK_IMR_TIMER			0x00400000
+#define SK_IMR_EXTERNAL_REG		0x00800000
+#define SK_IMR_SW			0x01000000
+#define SK_IMR_I2C_RDY			0x02000000
+#define SK_IMR_TX2_TIMEO		0x04000000
+#define SK_IMR_TX1_TIMEO		0x08000000
+#define SK_IMR_RX2_TIMEO		0x10000000
+#define SK_IMR_RX1_TIMEO		0x20000000
+#define SK_IMR_RSVD			0x40000000
+#define SK_IMR_HWERR			0x80000000
+
+#define SK_INTRS1	\
+	(SK_IMR_RX1_EOF|SK_IMR_TX1_S_EOF|SK_IMR_MAC1)
+
+#define SK_INTRS2	\
+	(SK_IMR_RX2_EOF|SK_IMR_TX2_S_EOF|SK_IMR_MAC2)
+
+/* SK_IESR register */
+#define SK_IESR_PAR_RX2			0x00000001
+#define SK_IESR_PAR_RX1			0x00000002
+#define SK_IESR_PAR_MAC2		0x00000004
+#define SK_IESR_PAR_MAC1		0x00000008
+#define SK_IESR_PAR_WR_RAM		0x00000010
+#define SK_IESR_PAR_RD_RAM		0x00000020
+#define SK_IESR_NO_TSTAMP_MAC2		0x00000040
+#define SK_IESR_NO_TSTAMO_MAC1		0x00000080
+#define SK_IESR_NO_STS_MAC2		0x00000100
+#define SK_IESR_NO_STS_MAC1		0x00000200
+#define SK_IESR_IRQ_STS			0x00000400
+#define SK_IESR_MASTERERR		0x00000800
+
+/* SK_IEMR register */
+#define SK_IEMR_PAR_RX2			0x00000001
+#define SK_IEMR_PAR_RX1			0x00000002
+#define SK_IEMR_PAR_MAC2		0x00000004
+#define SK_IEMR_PAR_MAC1		0x00000008
+#define SK_IEMR_PAR_WR_RAM		0x00000010
+#define SK_IEMR_PAR_RD_RAM		0x00000020
+#define SK_IEMR_NO_TSTAMP_MAC2		0x00000040
+#define SK_IEMR_NO_TSTAMO_MAC1		0x00000080
+#define SK_IEMR_NO_STS_MAC2		0x00000100
+#define SK_IEMR_NO_STS_MAC1		0x00000200
+#define SK_IEMR_IRQ_STS			0x00000400
+#define SK_IEMR_MASTERERR		0x00000800
+
+/* Block 2 */
+#define SK_MAC0_0	0x0100
+#define SK_MAC0_1	0x0104
+#define SK_MAC1_0	0x0108
+#define SK_MAC1_1	0x010C
+#define SK_MAC2_0	0x0110
+#define SK_MAC2_1	0x0114
+#define SK_CONNTYPE	0x0118
+#define SK_PMDTYPE	0x0119
+#define SK_CONFIG	0x011A
+#define SK_CHIPVER	0x011B
+#define SK_EPROM0	0x011C
+#define SK_EPROM1	0x011D
+#define SK_EPROM2	0x011E
+#define SK_EPROM3	0x011F
+#define SK_EP_ADDR	0x0120
+#define SK_EP_DATA	0x0124
+#define SK_EP_LOADCTL	0x0128
+#define SK_EP_LOADTST	0x0129
+#define SK_TIMERINIT	0x0130
+#define SK_TIMER	0x0134
+#define SK_TIMERCTL	0x0138
+#define SK_TIMERTST	0x0139
+#define SK_IMTIMERINIT	0x0140
+#define SK_IMTIMER	0x0144
+#define SK_IMTIMERCTL	0x0148
+#define SK_IMTIMERTST	0x0149
+#define SK_IMMR		0x014C
+#define SK_IHWEMR	0x0150
+#define SK_TESTCTL1	0x0158
+#define SK_TESTCTL2	0x0159
+#define SK_GPIO		0x015C
+#define SK_I2CHWCTL	0x0160
+#define SK_I2CHWDATA	0x0164
+#define SK_I2CHWIRQ	0x0168
+#define SK_I2CSW	0x016C
+#define SK_BLNKINIT	0x0170
+#define SK_BLNKCOUNT	0x0174
+#define SK_BLNKCTL	0x0178
+#define SK_BLNKSTS	0x0179
+#define SK_BLNKTST	0x017A
+
+#define SK_IMCTL_STOP	0x02
+#define SK_IMCTL_START	0x04
+
+#define SK_IMTIMER_TICKS	54
+#define SK_IM_USECS(x)		((x) * SK_IMTIMER_TICKS)
+
+/*
+ * The SK_EPROM0 register contains a byte that describes the
+ * amount of SRAM mounted on the NIC. The value also tells if
+ * the chips are 64K or 128K. This affects the RAMbuffer address
+ * offset that we need to use.
+ */
+#define SK_RAMSIZE_512K_64	0x1
+#define SK_RAMSIZE_1024K_128	0x2
+#define SK_RAMSIZE_1024K_64	0x3
+#define SK_RAMSIZE_2048K_128	0x4
+
+#define SK_RBOFF_0		0x0
+#define SK_RBOFF_80000		0x80000
+
+/*
+ * SK_EEPROM1 contains the PHY type, which may be XMAC for
+ * fiber-based cards or BCOM for 1000baseT cards with a Broadcom
+ * PHY.
+ */
+#define SK_PHYTYPE_XMAC		0       /* integeated XMAC II PHY */
+#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.
+ */
+#define SK_PHYADDR_XMAC		0x0
+#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
+
+#define SK_PMD_1000BASELX	0x4C
+#define SK_PMD_1000BASESX	0x53
+#define SK_PMD_1000BASECX	0x43
+#define SK_PMD_1000BASETX	0x54
+
+/* GPIO bits */
+#define SK_GPIO_DAT0		0x00000001
+#define SK_GPIO_DAT1		0x00000002
+#define SK_GPIO_DAT2		0x00000004
+#define SK_GPIO_DAT3		0x00000008
+#define SK_GPIO_DAT4		0x00000010
+#define SK_GPIO_DAT5		0x00000020
+#define SK_GPIO_DAT6		0x00000040
+#define SK_GPIO_DAT7		0x00000080
+#define SK_GPIO_DAT8		0x00000100
+#define SK_GPIO_DAT9		0x00000200
+#define SK_GPIO_DIR0		0x00010000
+#define SK_GPIO_DIR1		0x00020000
+#define SK_GPIO_DIR2		0x00040000
+#define SK_GPIO_DIR3		0x00080000
+#define SK_GPIO_DIR4		0x00100000
+#define SK_GPIO_DIR5		0x00200000
+#define SK_GPIO_DIR6		0x00400000
+#define SK_GPIO_DIR7		0x00800000
+#define SK_GPIO_DIR8		0x01000000
+#define SK_GPIO_DIR9           0x02000000
+
+/* Block 3 Ram interface and MAC arbiter registers */
+#define SK_RAMADDR	0x0180
+#define SK_RAMDATA0	0x0184
+#define SK_RAMDATA1	0x0188
+#define SK_TO0		0x0190
+#define SK_TO1		0x0191
+#define SK_TO2		0x0192
+#define SK_TO3		0x0193
+#define SK_TO4		0x0194
+#define SK_TO5		0x0195
+#define SK_TO6		0x0196
+#define SK_TO7		0x0197
+#define SK_TO8		0x0198
+#define SK_TO9		0x0199
+#define SK_TO10		0x019A
+#define SK_TO11		0x019B
+#define SK_RITIMEO_TMR	0x019C
+#define SK_RAMCTL	0x01A0
+#define SK_RITIMER_TST	0x01A2
+
+#define SK_RAMCTL_RESET		0x0001
+#define SK_RAMCTL_UNRESET	0x0002
+#define SK_RAMCTL_CLR_IRQ_WPAR	0x0100
+#define SK_RAMCTL_CLR_IRQ_RPAR	0x0200
+
+/* Mac arbiter registers */
+#define SK_MINIT_RX1	0x01B0
+#define SK_MINIT_RX2	0x01B1
+#define SK_MINIT_TX1	0x01B2
+#define SK_MINIT_TX2	0x01B3
+#define SK_MTIMEO_RX1	0x01B4
+#define SK_MTIMEO_RX2	0x01B5
+#define SK_MTIMEO_TX1	0x01B6
+#define SK_MTIEMO_TX2	0x01B7
+#define SK_MACARB_CTL	0x01B8
+#define SK_MTIMER_TST	0x01BA
+#define SK_RCINIT_RX1	0x01C0
+#define SK_RCINIT_RX2	0x01C1
+#define SK_RCINIT_TX1	0x01C2
+#define SK_RCINIT_TX2	0x01C3
+#define SK_RCTIMEO_RX1	0x01C4
+#define SK_RCTIMEO_RX2	0x01C5
+#define SK_RCTIMEO_TX1	0x01C6
+#define SK_RCTIMEO_TX2	0x01C7
+#define SK_RECOVERY_CTL	0x01C8
+#define SK_RCTIMER_TST	0x01CA
+
+/* Packet arbiter registers */
+#define SK_RXPA1_TINIT	0x01D0
+#define SK_RXPA2_TINIT	0x01D4
+#define SK_TXPA1_TINIT	0x01D8
+#define SK_TXPA2_TINIT	0x01DC
+#define SK_RXPA1_TIMEO	0x01E0
+#define SK_RXPA2_TIMEO	0x01E4
+#define SK_TXPA1_TIMEO	0x01E8
+#define SK_TXPA2_TIMEO	0x01EC
+#define SK_PKTARB_CTL	0x01F0
+#define SK_PKTATB_TST	0x01F2
+
+#define SK_PKTARB_TIMEOUT	0x2000
+
+#define SK_PKTARBCTL_RESET		0x0001
+#define SK_PKTARBCTL_UNRESET		0x0002
+#define SK_PKTARBCTL_RXTO1_OFF		0x0004
+#define SK_PKTARBCTL_RXTO1_ON		0x0008
+#define SK_PKTARBCTL_RXTO2_OFF		0x0010
+#define SK_PKTARBCTL_RXTO2_ON		0x0020
+#define SK_PKTARBCTL_TXTO1_OFF		0x0040
+#define SK_PKTARBCTL_TXTO1_ON		0x0080
+#define SK_PKTARBCTL_TXTO2_OFF		0x0100
+#define SK_PKTARBCTL_TXTO2_ON		0x0200
+#define SK_PKTARBCTL_CLR_IRQ_RXTO1	0x0400
+#define SK_PKTARBCTL_CLR_IRQ_RXTO2	0x0800
+#define SK_PKTARBCTL_CLR_IRQ_TXTO1	0x1000
+#define SK_PKTARBCTL_CLR_IRQ_TXTO2	0x2000
+
+#define SK_MINIT_XMAC_B2	54
+#define SK_MINIT_XMAC_C1	63
+
+#define SK_MACARBCTL_RESET	0x0001
+#define SK_MACARBCTL_UNRESET	0x0002
+#define SK_MACARBCTL_FASTOE_OFF	0x0004
+#define SK_MACARBCRL_FASTOE_ON	0x0008
+
+#define SK_RCINIT_XMAC_B2	54
+#define SK_RCINIT_XMAC_C1	0
+
+#define SK_RECOVERYCTL_RX1_OFF	0x0001
+#define SK_RECOVERYCTL_RX1_ON	0x0002
+#define SK_RECOVERYCTL_RX2_OFF	0x0004
+#define SK_RECOVERYCTL_RX2_ON	0x0008
+#define SK_RECOVERYCTL_TX1_OFF	0x0010
+#define SK_RECOVERYCTL_TX1_ON	0x0020
+#define SK_RECOVERYCTL_TX2_OFF	0x0040
+#define SK_RECOVERYCTL_TX2_ON	0x0080
+
+#define SK_RECOVERY_XMAC_B2				\
+	(SK_RECOVERYCTL_RX1_ON|SK_RECOVERYCTL_RX2_ON|	\
+	SK_RECOVERYCTL_TX1_ON|SK_RECOVERYCTL_TX2_ON)
+
+#define SK_RECOVERY_XMAC_C1				\
+	(SK_RECOVERYCTL_RX1_OFF|SK_RECOVERYCTL_RX2_OFF|	\
+	SK_RECOVERYCTL_TX1_OFF|SK_RECOVERYCTL_TX2_OFF)
+
+/* Block 4 -- TX Arbiter MAC 1 */
+#define SK_TXAR1_TIMERINIT	0x0200
+#define SK_TXAR1_TIMERVAL	0x0204
+#define SK_TXAR1_LIMITINIT	0x0208
+#define SK_TXAR1_LIMITCNT	0x020C
+#define SK_TXAR1_COUNTERCTL	0x0210
+#define SK_TXAR1_COUNTERTST	0x0212
+#define SK_TXAR1_COUNTERSTS	0x0212
+
+/* Block 5 -- TX Arbiter MAC 2 */
+#define SK_TXAR2_TIMERINIT	0x0280
+#define SK_TXAR2_TIMERVAL	0x0284
+#define SK_TXAR2_LIMITINIT	0x0288
+#define SK_TXAR2_LIMITCNT	0x028C
+#define SK_TXAR2_COUNTERCTL	0x0290
+#define SK_TXAR2_COUNTERTST	0x0291
+#define SK_TXAR2_COUNTERSTS	0x0292
+
+#define SK_TXARCTL_OFF		0x01
+#define SK_TXARCTL_ON		0x02
+#define SK_TXARCTL_RATECTL_OFF	0x04
+#define SK_TXARCTL_RATECTL_ON	0x08
+#define SK_TXARCTL_ALLOC_OFF	0x10
+#define SK_TXARCTL_ALLOC_ON	0x20
+#define SK_TXARCTL_FSYNC_OFF	0x40
+#define SK_TXARCTL_FSYNC_ON	0x80
+
+/* Block 6 -- External registers */
+#define SK_EXTREG_BASE	0x300
+#define SK_EXTREG_END	0x37C
+
+/* Block 7 -- PCI config registers */
+#define SK_PCI_BASE	0x0380
+#define SK_PCI_END	0x03FC
+
+/* Compute offset of mirrored PCI register */
+#define SK_PCI_REG(reg)		((reg) + SK_PCI_BASE)
+
+/* Block 8 -- RX queue 1 */
+#define SK_RXQ1_BUFCNT		0x0400
+#define SK_RXQ1_BUFCTL		0x0402
+#define SK_RXQ1_NEXTDESC	0x0404
+#define SK_RXQ1_RXBUF_LO	0x0408
+#define SK_RXQ1_RXBUF_HI	0x040C
+#define SK_RXQ1_RXSTAT		0x0410
+#define SK_RXQ1_TIMESTAMP	0x0414
+#define SK_RXQ1_CSUM1		0x0418
+#define SK_RXQ1_CSUM2		0x041A
+#define SK_RXQ1_CSUM1_START	0x041C
+#define SK_RXQ1_CSUM2_START	0x041E
+#define SK_RXQ1_CURADDR_LO	0x0420
+#define SK_RXQ1_CURADDR_HI	0x0424
+#define SK_RXQ1_CURCNT_LO	0x0428
+#define SK_RXQ1_CURCNT_HI	0x042C
+#define SK_RXQ1_CURBYTES	0x0430
+#define SK_RXQ1_BMU_CSR		0x0434
+#define SK_RXQ1_WATERMARK	0x0438
+#define SK_RXQ1_FLAG		0x043A
+#define SK_RXQ1_TEST1		0x043C
+#define SK_RXQ1_TEST2		0x0440
+#define SK_RXQ1_TEST3		0x0444
+
+/* Block 9 -- RX queue 2 */
+#define SK_RXQ2_BUFCNT		0x0480
+#define SK_RXQ2_BUFCTL		0x0482
+#define SK_RXQ2_NEXTDESC	0x0484
+#define SK_RXQ2_RXBUF_LO	0x0488
+#define SK_RXQ2_RXBUF_HI	0x048C
+#define SK_RXQ2_RXSTAT		0x0490
+#define SK_RXQ2_TIMESTAMP	0x0494
+#define SK_RXQ2_CSUM1		0x0498
+#define SK_RXQ2_CSUM2		0x049A
+#define SK_RXQ2_CSUM1_START	0x049C
+#define SK_RXQ2_CSUM2_START	0x049E
+#define SK_RXQ2_CURADDR_LO	0x04A0
+#define SK_RXQ2_CURADDR_HI	0x04A4
+#define SK_RXQ2_CURCNT_LO	0x04A8
+#define SK_RXQ2_CURCNT_HI	0x04AC
+#define SK_RXQ2_CURBYTES	0x04B0
+#define SK_RXQ2_BMU_CSR		0x04B4
+#define SK_RXQ2_WATERMARK	0x04B8
+#define SK_RXQ2_FLAG		0x04BA
+#define SK_RXQ2_TEST1		0x04BC
+#define SK_RXQ2_TEST2		0x04C0
+#define SK_RXQ2_TEST3		0x04C4
+
+#define SK_RXBMU_CLR_IRQ_ERR		0x00000001
+#define SK_RXBMU_CLR_IRQ_EOF		0x00000002
+#define SK_RXBMU_CLR_IRQ_EOB		0x00000004
+#define SK_RXBMU_CLR_IRQ_PAR		0x00000008
+#define SK_RXBMU_RX_START		0x00000010
+#define SK_RXBMU_RX_STOP		0x00000020
+#define SK_RXBMU_POLL_OFF		0x00000040
+#define SK_RXBMU_POLL_ON		0x00000080
+#define SK_RXBMU_TRANSFER_SM_RESET	0x00000100
+#define SK_RXBMU_TRANSFER_SM_UNRESET	0x00000200
+#define SK_RXBMU_DESCWR_SM_RESET	0x00000400
+#define SK_RXBMU_DESCWR_SM_UNRESET	0x00000800
+#define SK_RXBMU_DESCRD_SM_RESET	0x00001000
+#define SK_RXBMU_DESCRD_SM_UNRESET	0x00002000
+#define SK_RXBMU_SUPERVISOR_SM_RESET	0x00004000
+#define SK_RXBMU_SUPERVISOR_SM_UNRESET	0x00008000
+#define SK_RXBMU_PFI_SM_RESET		0x00010000
+#define SK_RXBMU_PFI_SM_UNRESET		0x00020000
+#define SK_RXBMU_FIFO_RESET		0x00040000
+#define SK_RXBMU_FIFO_UNRESET		0x00080000
+#define SK_RXBMU_DESC_RESET		0x00100000
+#define SK_RXBMU_DESC_UNRESET		0x00200000
+#define SK_RXBMU_SUPERVISOR_IDLE	0x01000000
+
+#define SK_RXBMU_ONLINE		\
+	(SK_RXBMU_TRANSFER_SM_UNRESET|SK_RXBMU_DESCWR_SM_UNRESET|	\
+	SK_RXBMU_DESCRD_SM_UNRESET|SK_RXBMU_SUPERVISOR_SM_UNRESET|	\
+	SK_RXBMU_PFI_SM_UNRESET|SK_RXBMU_FIFO_UNRESET|			\
+	SK_RXBMU_DESC_UNRESET)
+
+#define SK_RXBMU_OFFLINE		\
+	(SK_RXBMU_TRANSFER_SM_RESET|SK_RXBMU_DESCWR_SM_RESET|	\
+	SK_RXBMU_DESCRD_SM_RESET|SK_RXBMU_SUPERVISOR_SM_RESET|	\
+	SK_RXBMU_PFI_SM_RESET|SK_RXBMU_FIFO_RESET|		\
+	SK_RXBMU_DESC_RESET)
+
+/* Block 12 -- TX sync queue 1 */
+#define SK_TXQS1_BUFCNT		0x0600
+#define SK_TXQS1_BUFCTL		0x0602
+#define SK_TXQS1_NEXTDESC	0x0604
+#define SK_TXQS1_RXBUF_LO	0x0608
+#define SK_TXQS1_RXBUF_HI	0x060C
+#define SK_TXQS1_RXSTAT		0x0610
+#define SK_TXQS1_CSUM_STARTVAL	0x0614
+#define SK_TXQS1_CSUM_STARTPOS	0x0618
+#define SK_TXQS1_CSUM_WRITEPOS	0x061A
+#define SK_TXQS1_CURADDR_LO	0x0620
+#define SK_TXQS1_CURADDR_HI	0x0624
+#define SK_TXQS1_CURCNT_LO	0x0628
+#define SK_TXQS1_CURCNT_HI	0x062C
+#define SK_TXQS1_CURBYTES	0x0630
+#define SK_TXQS1_BMU_CSR	0x0634
+#define SK_TXQS1_WATERMARK	0x0638
+#define SK_TXQS1_FLAG		0x063A
+#define SK_TXQS1_TEST1		0x063C
+#define SK_TXQS1_TEST2		0x0640
+#define SK_TXQS1_TEST3		0x0644
+
+/* Block 13 -- TX async queue 1 */
+#define SK_TXQA1_BUFCNT		0x0680
+#define SK_TXQA1_BUFCTL		0x0682
+#define SK_TXQA1_NEXTDESC	0x0684
+#define SK_TXQA1_RXBUF_LO	0x0688
+#define SK_TXQA1_RXBUF_HI	0x068C
+#define SK_TXQA1_RXSTAT		0x0690
+#define SK_TXQA1_CSUM_STARTVAL	0x0694
+#define SK_TXQA1_CSUM_STARTPOS	0x0698
+#define SK_TXQA1_CSUM_WRITEPOS	0x069A
+#define SK_TXQA1_CURADDR_LO	0x06A0
+#define SK_TXQA1_CURADDR_HI	0x06A4
+#define SK_TXQA1_CURCNT_LO	0x06A8
+#define SK_TXQA1_CURCNT_HI	0x06AC
+#define SK_TXQA1_CURBYTES	0x06B0
+#define SK_TXQA1_BMU_CSR	0x06B4
+#define SK_TXQA1_WATERMARK	0x06B8
+#define SK_TXQA1_FLAG		0x06BA
+#define SK_TXQA1_TEST1		0x06BC
+#define SK_TXQA1_TEST2		0x06C0
+#define SK_TXQA1_TEST3		0x06C4
+
+/* Block 14 -- TX sync queue 2 */
+#define SK_TXQS2_BUFCNT		0x0700
+#define SK_TXQS2_BUFCTL		0x0702
+#define SK_TXQS2_NEXTDESC	0x0704
+#define SK_TXQS2_RXBUF_LO	0x0708
+#define SK_TXQS2_RXBUF_HI	0x070C
+#define SK_TXQS2_RXSTAT		0x0710
+#define SK_TXQS2_CSUM_STARTVAL	0x0714
+#define SK_TXQS2_CSUM_STARTPOS	0x0718
+#define SK_TXQS2_CSUM_WRITEPOS	0x071A
+#define SK_TXQS2_CURADDR_LO	0x0720
+#define SK_TXQS2_CURADDR_HI	0x0724
+#define SK_TXQS2_CURCNT_LO	0x0728
+#define SK_TXQS2_CURCNT_HI	0x072C
+#define SK_TXQS2_CURBYTES	0x0730
+#define SK_TXQS2_BMU_CSR	0x0734
+#define SK_TXQS2_WATERMARK	0x0738
+#define SK_TXQS2_FLAG		0x073A
+#define SK_TXQS2_TEST1		0x073C
+#define SK_TXQS2_TEST2		0x0740
+#define SK_TXQS2_TEST3		0x0744
+
+/* Block 15 -- TX async queue 2 */
+#define SK_TXQA2_BUFCNT		0x0780
+#define SK_TXQA2_BUFCTL		0x0782
+#define SK_TXQA2_NEXTDESC	0x0784
+#define SK_TXQA2_RXBUF_LO	0x0788
+#define SK_TXQA2_RXBUF_HI	0x078C
+#define SK_TXQA2_RXSTAT		0x0790
+#define SK_TXQA2_CSUM_STARTVAL	0x0794
+#define SK_TXQA2_CSUM_STARTPOS	0x0798
+#define SK_TXQA2_CSUM_WRITEPOS	0x079A
+#define SK_TXQA2_CURADDR_LO	0x07A0
+#define SK_TXQA2_CURADDR_HI	0x07A4
+#define SK_TXQA2_CURCNT_LO	0x07A8
+#define SK_TXQA2_CURCNT_HI	0x07AC
+#define SK_TXQA2_CURBYTES	0x07B0
+#define SK_TXQA2_BMU_CSR	0x07B4
+#define SK_TXQA2_WATERMARK	0x07B8
+#define SK_TXQA2_FLAG		0x07BA
+#define SK_TXQA2_TEST1		0x07BC
+#define SK_TXQA2_TEST2		0x07C0
+#define SK_TXQA2_TEST3		0x07C4
+
+#define SK_TXBMU_CLR_IRQ_ERR		0x00000001
+#define SK_TXBMU_CLR_IRQ_EOF		0x00000002
+#define SK_TXBMU_CLR_IRQ_EOB		0x00000004
+#define SK_TXBMU_TX_START		0x00000010
+#define SK_TXBMU_TX_STOP		0x00000020
+#define SK_TXBMU_POLL_OFF		0x00000040
+#define SK_TXBMU_POLL_ON		0x00000080
+#define SK_TXBMU_TRANSFER_SM_RESET	0x00000100
+#define SK_TXBMU_TRANSFER_SM_UNRESET	0x00000200
+#define SK_TXBMU_DESCWR_SM_RESET	0x00000400
+#define SK_TXBMU_DESCWR_SM_UNRESET	0x00000800
+#define SK_TXBMU_DESCRD_SM_RESET	0x00001000
+#define SK_TXBMU_DESCRD_SM_UNRESET	0x00002000
+#define SK_TXBMU_SUPERVISOR_SM_RESET	0x00004000
+#define SK_TXBMU_SUPERVISOR_SM_UNRESET	0x00008000
+#define SK_TXBMU_PFI_SM_RESET		0x00010000
+#define SK_TXBMU_PFI_SM_UNRESET		0x00020000
+#define SK_TXBMU_FIFO_RESET		0x00040000
+#define SK_TXBMU_FIFO_UNRESET		0x00080000
+#define SK_TXBMU_DESC_RESET		0x00100000
+#define SK_TXBMU_DESC_UNRESET		0x00200000
+#define SK_TXBMU_SUPERVISOR_IDLE	0x01000000
+
+#define SK_TXBMU_ONLINE		\
+	(SK_TXBMU_TRANSFER_SM_UNRESET|SK_TXBMU_DESCWR_SM_UNRESET|	\
+	SK_TXBMU_DESCRD_SM_UNRESET|SK_TXBMU_SUPERVISOR_SM_UNRESET|	\
+	SK_TXBMU_PFI_SM_UNRESET|SK_TXBMU_FIFO_UNRESET|			\
+	SK_TXBMU_DESC_UNRESET)
+
+#define SK_TXBMU_OFFLINE		\
+	(SK_TXBMU_TRANSFER_SM_RESET|SK_TXBMU_DESCWR_SM_RESET|	\
+	SK_TXBMU_DESCRD_SM_RESET|SK_TXBMU_SUPERVISOR_SM_RESET|	\
+	SK_TXBMU_PFI_SM_RESET|SK_TXBMU_FIFO_RESET|		\
+	SK_TXBMU_DESC_RESET)
+
+/* Block 16 -- Receive RAMbuffer 1 */
+#define SK_RXRB1_START		0x0800
+#define SK_RXRB1_END		0x0804
+#define SK_RXRB1_WR_PTR		0x0808
+#define SK_RXRB1_RD_PTR		0x080C
+#define SK_RXRB1_UTHR_PAUSE	0x0810
+#define SK_RXRB1_LTHR_PAUSE	0x0814
+#define SK_RXRB1_UTHR_HIPRIO	0x0818
+#define SK_RXRB1_UTHR_LOPRIO	0x081C
+#define SK_RXRB1_PKTCNT		0x0820
+#define SK_RXRB1_LVL		0x0824
+#define SK_RXRB1_CTLTST		0x0828
+
+/* Block 17 -- Receive RAMbuffer 2 */
+#define SK_RXRB2_START		0x0880
+#define SK_RXRB2_END		0x0884
+#define SK_RXRB2_WR_PTR		0x0888
+#define SK_RXRB2_RD_PTR		0x088C
+#define SK_RXRB2_UTHR_PAUSE	0x0890
+#define SK_RXRB2_LTHR_PAUSE	0x0894
+#define SK_RXRB2_UTHR_HIPRIO	0x0898
+#define SK_RXRB2_UTHR_LOPRIO	0x089C
+#define SK_RXRB2_PKTCNT		0x08A0
+#define SK_RXRB2_LVL		0x08A4
+#define SK_RXRB2_CTLTST		0x08A8
+
+/* Block 20 -- Sync. Transmit RAMbuffer 1 */
+#define SK_TXRBS1_START		0x0A00
+#define SK_TXRBS1_END		0x0A04
+#define SK_TXRBS1_WR_PTR	0x0A08
+#define SK_TXRBS1_RD_PTR	0x0A0C
+#define SK_TXRBS1_PKTCNT	0x0A20
+#define SK_TXRBS1_LVL		0x0A24
+#define SK_TXRBS1_CTLTST	0x0A28
+
+/* Block 21 -- Async. Transmit RAMbuffer 1 */
+#define SK_TXRBA1_START		0x0A80
+#define SK_TXRBA1_END		0x0A84
+#define SK_TXRBA1_WR_PTR	0x0A88
+#define SK_TXRBA1_RD_PTR	0x0A8C
+#define SK_TXRBA1_PKTCNT	0x0AA0
+#define SK_TXRBA1_LVL		0x0AA4
+#define SK_TXRBA1_CTLTST	0x0AA8
+
+/* Block 22 -- Sync. Transmit RAMbuffer 2 */
+#define SK_TXRBS2_START		0x0B00
+#define SK_TXRBS2_END		0x0B04
+#define SK_TXRBS2_WR_PTR	0x0B08
+#define SK_TXRBS2_RD_PTR	0x0B0C
+#define SK_TXRBS2_PKTCNT	0x0B20
+#define SK_TXRBS2_LVL		0x0B24
+#define SK_TXRBS2_CTLTST	0x0B28
+
+/* Block 23 -- Async. Transmit RAMbuffer 2 */
+#define SK_TXRBA2_START		0x0B80
+#define SK_TXRBA2_END		0x0B84
+#define SK_TXRBA2_WR_PTR	0x0B88
+#define SK_TXRBA2_RD_PTR	0x0B8C
+#define SK_TXRBA2_PKTCNT	0x0BA0
+#define SK_TXRBA2_LVL		0x0BA4
+#define SK_TXRBA2_CTLTST	0x0BA8
+
+#define SK_RBCTL_RESET		0x00000001
+#define SK_RBCTL_UNRESET	0x00000002
+#define SK_RBCTL_OFF		0x00000004
+#define SK_RBCTL_ON		0x00000008
+#define SK_RBCTL_STORENFWD_OFF	0x00000010
+#define SK_RBCTL_STORENFWD_ON	0x00000020
+
+/* Block 24 -- RX MAC FIFO 1 regisrers and LINK_SYNC counter */
+#define SK_RXF1_END		0x0C00
+#define SK_RXF1_WPTR		0x0C04
+#define SK_RXF1_RPTR		0x0C0C
+#define SK_RXF1_PKTCNT		0x0C10
+#define SK_RXF1_LVL		0x0C14
+#define SK_RXF1_MACCTL		0x0C18
+#define SK_RXF1_CTL		0x0C1C
+#define SK_RXLED1_CNTINIT	0x0C20
+#define SK_RXLED1_COUNTER	0x0C24
+#define SK_RXLED1_CTL		0x0C28
+#define SK_RXLED1_TST		0x0C29
+#define SK_LINK_SYNC1_CINIT	0x0C30
+#define SK_LINK_SYNC1_COUNTER	0x0C34
+#define SK_LINK_SYNC1_CTL	0x0C38
+#define SK_LINK_SYNC1_TST	0x0C39
+#define SK_LINKLED1_CTL		0x0C3C
+
+#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
+#define SK_RXF2_RPTR		0x0C8C
+#define SK_RXF2_PKTCNT		0x0C90
+#define SK_RXF2_LVL		0x0C94
+#define SK_RXF2_MACCTL		0x0C98
+#define SK_RXF2_CTL		0x0C9C
+#define SK_RXLED2_CNTINIT	0x0CA0
+#define SK_RXLED2_COUNTER	0x0CA4
+#define SK_RXLED2_CTL		0x0CA8
+#define SK_RXLED2_TST		0x0CA9
+#define SK_LINK_SYNC2_CINIT	0x0CB0
+#define SK_LINK_SYNC2_COUNTER	0x0CB4
+#define SK_LINK_SYNC2_CTL	0x0CB8
+#define SK_LINK_SYNC2_TST	0x0CB9
+#define SK_LINKLED2_CTL		0x0CBC
+
+#define SK_RXMACCTL_CLR_IRQ_NOSTS	0x00000001
+#define SK_RXMACCTL_CLR_IRQ_NOTSTAMP	0x00000002
+#define SK_RXMACCTL_TSTAMP_OFF		0x00000004
+#define SK_RXMACCTL_RSTAMP_ON		0x00000008
+#define SK_RXMACCTL_FLUSH_OFF		0x00000010
+#define SK_RXMACCTL_FLUSH_ON		0x00000020
+#define SK_RXMACCTL_PAUSE_OFF		0x00000040
+#define SK_RXMACCTL_PAUSE_ON		0x00000080
+#define SK_RXMACCTL_AFULL_OFF		0x00000100
+#define SK_RXMACCTL_AFULL_ON		0x00000200
+#define SK_RXMACCTL_VALIDTIME_PATCH_OFF	0x00000400
+#define SK_RXMACCTL_VALIDTIME_PATCH_ON	0x00000800
+#define SK_RXMACCTL_RXRDY_PATCH_OFF	0x00001000
+#define SK_RXMACCTL_RXRDY_PATCH_ON	0x00002000
+#define SK_RXMACCTL_STS_TIMEO		0x00FF0000
+#define SK_RXMACCTL_TSTAMP_TIMEO	0xFF000000
+
+#define SK_RXLEDCTL_ENABLE		0x0001
+#define SK_RXLEDCTL_COUNTER_STOP	0x0002
+#define SK_RXLEDCTL_COUNTER_START	0x0004
+
+#define SK_LINKLED_OFF			0x0001
+#define SK_LINKLED_ON			0x0002
+#define SK_LINKLED_LINKSYNC_OFF		0x0004
+#define SK_LINKLED_LINKSYNC_ON		0x0008
+#define SK_LINKLED_BLINK_OFF		0x0010
+#define SK_LINKLED_BLINK_ON		0x0020
+
+/* Block 26 -- TX MAC FIFO 1 regisrers  */
+#define SK_TXF1_END		0x0D00
+#define SK_TXF1_WPTR		0x0D04
+#define SK_TXF1_RPTR		0x0D0C
+#define SK_TXF1_PKTCNT		0x0D10
+#define SK_TXF1_LVL		0x0D14
+#define SK_TXF1_MACCTL		0x0D18
+#define SK_TXF1_CTL		0x0D1C
+#define SK_TXLED1_CNTINIT	0x0D20
+#define SK_TXLED1_COUNTER	0x0D24
+#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
+#define SK_TXF2_RPTR		0x0D8C
+#define SK_TXF2_PKTCNT		0x0D90
+#define SK_TXF2_LVL		0x0D94
+#define SK_TXF2_MACCTL		0x0D98
+#define SK_TXF2_CTL		0x0D9C
+#define SK_TXLED2_CNTINIT	0x0DA0
+#define SK_TXLED2_COUNTER	0x0DA4
+#define SK_TXLED2_CTL		0x0DA8
+#define SK_TXLED2_TST		0x0DA9
+
+#define SK_TXMACCTL_XMAC_RESET		0x00000001
+#define SK_TXMACCTL_XMAC_UNRESET	0x00000002
+#define SK_TXMACCTL_LOOP_OFF		0x00000004
+#define SK_TXMACCTL_LOOP_ON		0x00000008
+#define SK_TXMACCTL_FLUSH_OFF		0x00000010
+#define SK_TXMACCTL_FLUSH_ON		0x00000020
+#define SK_TXMACCTL_WAITEMPTY_OFF	0x00000040
+#define SK_TXMACCTL_WAITEMPTY_ON	0x00000080
+#define SK_TXMACCTL_AFULL_OFF		0x00000100
+#define SK_TXMACCTL_AFULL_ON		0x00000200
+#define SK_TXMACCTL_TXRDY_PATCH_OFF	0x00000400
+#define SK_TXMACCTL_RXRDY_PATCH_ON	0x00000800
+#define SK_TXMACCTL_PKT_RECOVERY_OFF	0x00001000
+#define SK_TXMACCTL_PKT_RECOVERY_ON	0x00002000
+#define SK_TXMACCTL_CLR_IRQ_PERR	0x00008000
+#define SK_TXMACCTL_WAITAFTERFLUSH	0x00010000
+
+#define SK_TXLEDCTL_ENABLE		0x0001
+#define SK_TXLEDCTL_COUNTER_STOP	0x0002
+#define SK_TXLEDCTL_COUNTER_START	0x0004
+
+#define SK_FIFO_RESET		0x00000001
+#define SK_FIFO_UNRESET		0x00000002
+#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 0x40 to 0x4F -- XMAC 1 registers */
+#define SK_XMAC1_BASE	0x2000
+
+/* Block 0x50 to 0x5F -- MARV 1 registers */
+#define SK_MARV1_BASE	0x2800
+
+/* Block 0x60 to 0x6F -- XMAC 2 registers */
+#define SK_XMAC2_BASE	0x3000
+
+/* Block 0x70 to 0x7F -- MARV 2 registers */
+#define SK_MARV2_BASE	0x3800
+
+/* Compute relative offset of an XMAC register in the XMAC window(s). */
+#define SK_XMAC_REG(sc, reg)	(((reg) * 2) + SK_XMAC1_BASE + \
+	(((sc)->sk_port) * (SK_XMAC2_BASE - SK_XMAC1_BASE)))
+
+#if 0
+#define SK_XM_READ_4(sc, reg)						\
+	((sk_win_read_2(sc->sk_softc,					\
+	      SK_XMAC_REG(sc, reg)) & 0xFFFF) |		\
+	 ((sk_win_read_2(sc->sk_softc,					\
+	      SK_XMAC_REG(sc, reg + 2)) & 0xFFFF) << 16))
+
+#define SK_XM_WRITE_4(sc, reg, val)					\
+	sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg),		\
+		       ((val) & 0xFFFF));				\
+	sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg + 2),		\
+		       ((val) >> 16) & 0xFFFF)
+#else
+#define SK_XM_READ_4(sc, reg)		\
+	sk_win_read_4(sc->sk_softc, SK_XMAC_REG(sc, reg))
+
+#define SK_XM_WRITE_4(sc, reg, val)	\
+	sk_win_write_4(sc->sk_softc, SK_XMAC_REG(sc, reg), (val))
+#endif
+
+#define SK_XM_READ_2(sc, reg)		\
+	sk_win_read_2(sc->sk_softc, SK_XMAC_REG(sc, reg))
+
+#define SK_XM_WRITE_2(sc, reg, val)	\
+	sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg), val)
+
+#define SK_XM_SETBIT_4(sc, reg, x)	\
+	SK_XM_WRITE_4(sc, reg, (SK_XM_READ_4(sc, reg)) | (x))
+
+#define SK_XM_CLRBIT_4(sc, reg, x)	\
+	SK_XM_WRITE_4(sc, reg, (SK_XM_READ_4(sc, reg)) & ~(x))
+
+#define SK_XM_SETBIT_2(sc, reg, x)	\
+	SK_XM_WRITE_2(sc, reg, (SK_XM_READ_2(sc, reg)) | (x))
+
+#define SK_XM_CLRBIT_2(sc, reg, x)	\
+	SK_XM_WRITE_2(sc, reg, (SK_XM_READ_2(sc, reg)) & ~(x))
+
+/* 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))
+
+/*
+ * The default FIFO threshold on the XMAC II is 4 bytes. On
+ * dual port NICs, this often leads to transmit underruns, so we
+ * bump the threshold a little.
+ */
+#define SK_XM_TX_FIFOTHRESH	512
+
+#define SK_PCI_VENDOR_ID	0x0000
+#define SK_PCI_DEVICE_ID	0x0002
+#define SK_PCI_COMMAND		0x0004
+#define SK_PCI_STATUS		0x0006
+#define SK_PCI_REVID		0x0008
+#define SK_PCI_CLASSCODE	0x0009
+#define SK_PCI_CACHELEN		0x000C
+#define SK_PCI_LATENCY_TIMER	0x000D
+#define SK_PCI_HEADER_TYPE	0x000E
+#define SK_PCI_LOMEM		0x0010
+#define SK_PCI_LOIO		0x0014
+#define SK_PCI_SUBVEN_ID	0x002C
+#define SK_PCI_SYBSYS_ID	0x002E
+#define SK_PCI_BIOSROM		0x0030
+#define SK_PCI_INTLINE		0x003C
+#define SK_PCI_INTPIN		0x003D
+#define SK_PCI_MINGNT		0x003E
+#define SK_PCI_MINLAT		0x003F
+
+/* device specific PCI registers */
+#define SK_PCI_OURREG1		0x0040
+#define SK_PCI_OURREG2		0x0044
+#define SK_PCI_CAPID		0x0048 /* 8 bits */
+#define SK_PCI_NEXTPTR		0x0049 /* 8 bits */
+#define SK_PCI_PWRMGMTCAP	0x004A /* 16 bits */
+#define SK_PCI_PWRMGMTCTRL	0x004C /* 16 bits */
+#define SK_PCI_PME_EVENT	0x004F
+#define SK_PCI_VPD_CAPID	0x0050
+#define SK_PCI_VPD_NEXTPTR	0x0051
+#define SK_PCI_VPD_ADDR		0x0052
+#define SK_PCI_VPD_DATA		0x0054
+
+#define SK_PSTATE_MASK		0x0003
+#define SK_PSTATE_D0		0x0000
+#define SK_PSTATE_D1		0x0001
+#define SK_PSTATE_D2		0x0002
+#define SK_PSTATE_D3		0x0003
+#define SK_PME_EN		0x0010
+#define SK_PME_STATUS		0x8000
+
+/*
+ * VPD flag bit. Set to 0 to initiate a read, will become 1 when
+ * read is complete. Set to 1 to initiate a write, will become 0
+ * when write is finished.
+ */
+#define SK_VPD_FLAG		0x8000
+
+/* VPD structures */
+struct vpd_res {
+	u_int8_t		vr_id;
+	u_int8_t		vr_len;
+	u_int8_t		vr_pad;
+};
+
+struct vpd_key {
+	char			vk_key[2];
+	u_int8_t		vk_len;
+};
+
+#define VPD_RES_ID	0x82	/* ID string */
+#define VPD_RES_READ	0x90	/* start of read only area */
+#define VPD_RES_WRITE	0x81	/* start of read/write area */
+#define VPD_RES_END	0x78	/* end tag */
+
+#define CSR_WRITE_4(sc, reg, val) \
+	bus_space_write_4((sc)->sk_btag, (sc)->sk_bhandle, (reg), (val))
+#define CSR_WRITE_2(sc, reg, val) \
+	bus_space_write_2((sc)->sk_btag, (sc)->sk_bhandle, (reg), (val))
+#define CSR_WRITE_1(sc, reg, val) \
+	bus_space_write_1((sc)->sk_btag, (sc)->sk_bhandle, (reg), (val))
+
+#define CSR_READ_4(sc, reg) \
+	bus_space_read_4((sc)->sk_btag, (sc)->sk_bhandle, (reg))
+#define CSR_READ_2(sc, reg) \
+	bus_space_read_2((sc)->sk_btag, (sc)->sk_bhandle, (reg))
+#define CSR_READ_1(sc, reg) \
+	bus_space_read_1((sc)->sk_btag, (sc)->sk_bhandle, (reg))
+
+struct sk_type {
+	u_int16_t		sk_vid;
+	u_int16_t		sk_did;
+	char			*sk_name;
+};
+
+/* RX queue descriptor data structure */
+struct sk_rx_desc {
+	u_int32_t		sk_ctl;
+	u_int32_t		sk_next;
+	u_int32_t		sk_data_lo;
+	u_int32_t		sk_data_hi;
+	u_int32_t		sk_xmac_rxstat;
+	u_int32_t		sk_timestamp;
+	u_int16_t		sk_csum2;
+	u_int16_t		sk_csum1;
+	u_int16_t		sk_csum2_start;
+	u_int16_t		sk_csum1_start;
+};
+
+#define SK_OPCODE_DEFAULT	0x00550000
+#define SK_OPCODE_CSUM		0x00560000
+
+#define SK_RXCTL_LEN		0x0000FFFF
+#define SK_RXCTL_OPCODE		0x00FF0000
+#define SK_RXCTL_TSTAMP_VALID	0x01000000
+#define SK_RXCTL_STATUS_VALID	0x02000000
+#define SK_RXCTL_DEV0		0x04000000
+#define SK_RXCTL_EOF_INTR	0x08000000
+#define SK_RXCTL_EOB_INTR	0x10000000
+#define SK_RXCTL_LASTFRAG	0x20000000
+#define SK_RXCTL_FIRSTFRAG	0x40000000
+#define SK_RXCTL_OWN		0x80000000
+
+#define SK_RXSTAT	\
+	(SK_OPCODE_DEFAULT|SK_RXCTL_EOF_INTR|SK_RXCTL_LASTFRAG| \
+	 SK_RXCTL_FIRSTFRAG|SK_RXCTL_OWN)
+
+struct sk_tx_desc {
+	u_int32_t		sk_ctl;
+	u_int32_t		sk_next;
+	u_int32_t		sk_data_lo;
+	u_int32_t		sk_data_hi;
+	u_int32_t		sk_xmac_txstat;
+	u_int16_t		sk_rsvd0;
+	u_int16_t		sk_csum_startval;
+	u_int16_t		sk_csum_startpos;
+	u_int16_t		sk_csum_writepos;
+	u_int32_t		sk_rsvd1;
+};
+
+#define SK_TXCTL_LEN		0x0000FFFF
+#define SK_TXCTL_OPCODE		0x00FF0000
+#define SK_TXCTL_SW		0x01000000
+#define SK_TXCTL_NOCRC		0x02000000
+#define SK_TXCTL_STORENFWD	0x04000000
+#define SK_TXCTL_EOF_INTR	0x08000000
+#define SK_TXCTL_EOB_INTR	0x10000000
+#define SK_TXCTL_LASTFRAG	0x20000000
+#define SK_TXCTL_FIRSTFRAG	0x40000000
+#define SK_TXCTL_OWN		0x80000000
+
+#define SK_TXSTAT	\
+	(SK_OPCODE_DEFAULT|SK_TXCTL_EOF_INTR|SK_TXCTL_LASTFRAG|SK_TXCTL_OWN)
+
+#define SK_RXBYTES(x)		(x) & 0x0000FFFF;
+#define SK_TXBYTES		SK_RXBYTES
+
+#define SK_TX_RING_CNT		512
+#define SK_RX_RING_CNT		256
+
+/*
+ * Jumbo buffer stuff. Note that we must allocate more jumbo
+ * buffers than there are descriptors in the receive ring. This
+ * is because we don't know how long it will take for a packet
+ * to be released after we hand it off to the upper protocol
+ * layers. To be safe, we allocate 1.5 times the number of
+ * receive descriptors.
+ */
+#define SK_JUMBO_FRAMELEN	9018
+#define SK_JUMBO_MTU		(SK_JUMBO_FRAMELEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+#define SK_JSLOTS		384
+
+#define SK_JRAWLEN	(SK_JUMBO_FRAMELEN + ETHER_ALIGN)
+#define SK_JLEN		SK_JRAWLEN
+#define SK_MCLBYTES	SK_JLEN
+#define SK_JPAGESZ	PAGE_SIZE
+#define SK_RESID	(SK_JPAGESZ - (SK_JLEN * SK_JSLOTS) % SK_JPAGESZ)
+#define SK_JMEM		((SK_JLEN * SK_JSLOTS) + SK_RESID)
+
+#define SK_MAXUNIT	256
+#define SK_TIMEOUT	1000
+#define ETHER_ALIGN	2
+
+
+#endif /* _DEV_PCI_IF_SKREG_H_ */
+
Index: sys/dev/pci/if_skvar.h
===================================================================
RCS file: if_skvar.h
diff -N if_skvar.h
--- /dev/null	Thu Jul 11 11:18:53 2002
+++ sys/dev/pci/if_skvar.h	Sun Aug 17 07:04:00 2003
@@ -0,0 +1,215 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*	$OpenBSD: if_skreg.h,v 1.10 2003/08/12 05:23:06 nate Exp $	*/
+
+/*
+ * Copyright (c) 1997, 1998, 1999, 2000
+ *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: /c/ncvs/src/sys/pci/if_skreg.h,v 1.9 2000/04/22 02:16:37 wpaul Exp $
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _DEV_PCI_IF_SKVAR_H_
+#define _DEV_PCI_IF_SKVAR_H_
+
+#include <dev/pci/if_skreg.h>
+#include <dev/pci/xmaciireg.h>
+#include <dev/pci/yukonreg.h>
+
+struct sk_jslot {
+	caddr_t			sk_buf;
+	int			sk_inuse;
+};
+
+struct sk_jpool_entry {
+	int                             slot;
+	LIST_ENTRY(sk_jpool_entry)	jpool_entries;
+};
+
+struct sk_chain {
+	void			*sk_desc;
+	struct mbuf		*sk_mbuf;
+	struct sk_chain		*sk_next;
+};
+
+/*
+ * Number of DMA segments in a TxCB. Note that this is carefully
+ * chosen to make the total struct size an even power of two. It's
+ * critical that no TxCB be split across a page boundry since
+ * no attempt is made to allocate physically contiguous memory.
+ * 
+ */
+#define SK_NTXSEG      30
+
+struct sk_txmap_entry {
+	bus_dmamap_t			dmamap;
+	SLIST_ENTRY(sk_txmap_entry)	link;
+};
+
+struct sk_chain_data {
+	struct sk_chain		sk_tx_chain[SK_TX_RING_CNT];
+	struct sk_chain		sk_rx_chain[SK_RX_RING_CNT];
+	struct sk_txmap_entry	*sk_tx_map[SK_TX_RING_CNT];
+	bus_dmamap_t		sk_rx_map[SK_RX_RING_CNT];
+	int			sk_tx_prod;
+	int			sk_tx_cons;
+	int			sk_tx_cnt;
+	int			sk_rx_prod;
+	int			sk_rx_cons;
+	int			sk_rx_cnt;
+	/* Stick the jumbo mem management stuff here too. */
+	struct sk_jslot		sk_jslots[SK_JSLOTS];
+	void			*sk_jumbo_buf;
+
+};
+
+struct sk_ring_data {
+	struct sk_tx_desc	sk_tx_ring[SK_TX_RING_CNT];
+	struct sk_rx_desc	sk_rx_ring[SK_RX_RING_CNT];
+};
+
+#define SK_TX_RING_ADDR(sc, i) \
+    ((sc)->sk_ring_map->dm_segs[0].ds_addr + \
+     offsetof(struct sk_ring_data, sk_tx_ring[(i)]))
+
+#define SK_RX_RING_ADDR(sc, i) \
+    ((sc)->sk_ring_map->dm_segs[0].ds_addr + \
+     offsetof(struct sk_ring_data, sk_rx_ring[(i)]))
+
+struct sk_bcom_hack {
+	int			reg;
+	int			val;
+};
+
+#define SK_INC(x, y)	(x) = (x + 1) % y
+
+/* Forward decl. */
+struct sk_if_softc;
+
+/* Softc for the GEnesis controller. */
+struct sk_softc {
+	struct device		sk_dev;		/* generic device */
+	bus_space_handle_t	sk_bhandle;	/* bus space handle */
+	bus_space_tag_t		sk_btag;	/* bus space tag */
+	void			*sk_intrhand;	/* irq handler handle */
+	struct resource		*sk_irq;	/* IRQ resource handle */
+	struct resource		*sk_res;	/* I/O or shared mem handle */
+	u_int8_t		sk_type;
+	char			*sk_vpd_prodname;
+	char			*sk_vpd_readonly;
+	u_int32_t		sk_rboff;	/* RAMbuffer offset */
+	u_int32_t		sk_ramsize;	/* amount of RAM on NIC */
+	u_int32_t		sk_pmd;		/* physical media type */
+	u_int32_t		sk_intrmask;
+	bus_dma_tag_t		sc_dmatag;
+	struct sk_if_softc	*sk_if[2];
+};
+
+/* Softc for each logical interface */
+struct sk_if_softc {
+	struct device		sk_dev;		/* generic device */
+	struct ethercom		sk_ethercom;	/* interface info */
+	struct mii_data		sk_mii;
+	u_int8_t                sk_enaddr[ETHER_ADDR_LEN]; /* station addr */
+	u_int8_t		sk_port;	/* port # on controller */
+	u_int8_t		sk_xmac_rev;	/* XMAC chip rev (B2 or C1) */
+	u_int32_t		sk_rx_ramstart;
+	u_int32_t		sk_rx_ramend;
+	u_int32_t		sk_tx_ramstart;
+	u_int32_t		sk_tx_ramend;
+	int			sk_phytype;
+	int			sk_phyaddr;
+	int			sk_cnt;
+	int			sk_link;
+	struct callout		sk_tick_ch;
+	struct sk_chain_data	sk_cdata;
+	struct sk_ring_data	*sk_rdata;
+	bus_dmamap_t		sk_ring_map;
+	struct sk_softc		*sk_softc;	/* parent controller */
+	int			sk_tx_bmu;	/* TX BMU register */
+	int			sk_if_flags;
+	LIST_HEAD(__sk_jfreehead, sk_jpool_entry)	sk_jfree_listhead;
+	LIST_HEAD(__sk_jinusehead, sk_jpool_entry)	sk_jinuse_listhead;
+	SLIST_HEAD(__sk_txmaphead, sk_txmap_entry)	sk_txmap_listhead;
+};
+
+struct skc_attach_args {
+	u_int16_t	skc_port;
+};
+
+#endif /* _DEV_PCI_IF_SKVAR_H_ */
+
Index: sys/dev/pci/pcidevs
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs,v
retrieving revision 1.564
diff -u -r1.564 pcidevs
--- sys/dev/pci/pcidevs	2003/08/14 23:39:22	1.564
+++ sys/dev/pci/pcidevs	2003/08/17 07:04:02
@@ -608,6 +608,7 @@
 product 3COM 3C985	0x0001	3c985 Gigabit Ethernet
 product 3COM 3C996	0x0003	3c996 10/100/1000 Ethernet
 product 3COM 3C556MODEM	0x1007	3c556 V.90 MiniPCI Modem
+product 3COM 3C940	0x1700	3c940 Gigabit Ethernet
 product 3COM 3C450TX	0x4500	3c450-TX 10/100 Ethernet
 product 3COM 3C590	0x5900	3c590 Ethernet
 product 3COM 3C595TX	0x5950	3c595-TX 10/100 Ethernet
@@ -2290,6 +2291,7 @@
 /* Schneider & Koch (really SysKonnect) products */
 product SCHNEIDERKOCH	SKNET_FDDI	0x4000	SK-NET FDDI-xP
 product SCHNEIDERKOCH	SKNET_GE	0x4300	SK-NET GE
+product SCHNEIDERKOCH 	SK9821v2	0x4320  SK-9821 v2.0
 product SCHNEIDERKOCH	SK_9DX1		0x4400	SK-NET SK-9DX1 Gigabit Ethernet
 /* These next two are are really subsystem IDs */
 product SCHNEIDERKOCH	SK_9D21		0x4421	SK-9D21 1000BASE-T
Index: sys/dev/pci/pcidevs.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs.h,v
retrieving revision 1.564
diff -u -r1.564 pcidevs.h
--- sys/dev/pci/pcidevs.h	2003/08/14 23:39:47	1.564
+++ sys/dev/pci/pcidevs.h	2003/08/17 07:04:06
@@ -615,6 +615,7 @@
 #define	PCI_PRODUCT_3COM_3C985	0x0001		/* 3c985 Gigabit Ethernet */
 #define	PCI_PRODUCT_3COM_3C996	0x0003		/* 3c996 10/100/1000 Ethernet */
 #define	PCI_PRODUCT_3COM_3C556MODEM	0x1007		/* 3c556 V.90 MiniPCI Modem */
+#define	PCI_PRODUCT_3COM_3C940	0x1700		/* 3c940 Gigabit Ethernet */
 #define	PCI_PRODUCT_3COM_3C450TX	0x4500		/* 3c450-TX 10/100 Ethernet */
 #define	PCI_PRODUCT_3COM_3C590	0x5900		/* 3c590 Ethernet */
 #define	PCI_PRODUCT_3COM_3C595TX	0x5950		/* 3c595-TX 10/100 Ethernet */
@@ -2297,6 +2298,7 @@
 /* Schneider & Koch (really SysKonnect) products */
 #define	PCI_PRODUCT_SCHNEIDERKOCH_SKNET_FDDI	0x4000		/* SK-NET FDDI-xP */
 #define	PCI_PRODUCT_SCHNEIDERKOCH_SKNET_GE	0x4300		/* SK-NET GE */
+#define	PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2	0x4320		/* SK-9821 v2.0 */
 #define	PCI_PRODUCT_SCHNEIDERKOCH_SK_9DX1	0x4400		/* SK-NET SK-9DX1 Gigabit Ethernet */
 /* These next two are are really subsystem IDs */
 #define	PCI_PRODUCT_SCHNEIDERKOCH_SK_9D21	0x4421		/* SK-9D21 1000BASE-T */
Index: sys/dev/pci/pcidevs_data.h
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/pcidevs_data.h,v
retrieving revision 1.562
diff -u -r1.562 pcidevs_data.h
--- sys/dev/pci/pcidevs_data.h	2003/08/14 23:39:47	1.562
+++ sys/dev/pci/pcidevs_data.h	2003/08/17 07:04:11
@@ -58,6 +58,12 @@
 	    "3c556 V.90 MiniPCI Modem",
 	},
 	{
+	    PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C940,
+	    0,
+	    "3Com",
+	    "3c940 Gigabit Ethernet",
+	},
+	{
 	    PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C450TX,
 	    0,
 	    "3Com",
@@ -7990,6 +7996,12 @@
 	    "SK-NET GE",
 	},
 	{
+	    PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2,
+	    0,
+	    "Schneider & Koch",
+	    "SK-9821 v2.0",
+	},
+	{
 	    PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK_9DX1,
 	    0,
 	    "Schneider & Koch",
Index: sys/dev/pci/xmaciireg.h
===================================================================
RCS file: xmaciireg.h
diff -N xmaciireg.h
--- /dev/null	Thu Jul 11 11:18:53 2002
+++ sys/dev/pci/xmaciireg.h	Sun Aug 17 07:04:15 2003
@@ -0,0 +1,439 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*	$OpenBSD: xmaciireg.h,v 1.2.4.1 2001/05/14 22:26:01 niklas Exp $	*/
+
+/*
+ * Copyright (c) 1997, 1998, 1999
+ *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: /c/ncvs/src/sys/pci/xmaciireg.h,v 1.3 2000/04/22 02:16:37 wpaul Exp $
+ */
+
+/*
+ * Registers and data structures for the XaQti Corporation XMAC II
+ * Gigabit Ethernet MAC. Datasheet is available from http://www.xaqti.com.
+ * The XMAC can be programmed for 16-bit or 32-bit register access modes.
+ * The SysKonnect gigabit ethernet adapters use 16-bit mode, so that's
+ * how the registers are laid out here.
+ */
+
+#define XM_DEVICEID		0x00E0AE20
+#define XM_XAQTI_OUI		0x00E0AE
+
+#define XM_XMAC_REV(x)		(((x) & 0x000000E0) >> 5)
+
+#define XM_XMAC_REV_B2		0x0
+#define XM_XMAC_REV_C1		0x1
+
+#define XM_MMUCMD		0x0000
+#define XM_POFF			0x0008
+#define XM_BURST		0x000C
+#define XM_VLAN_TAGLEV1		0x0010
+#define XM_VLAN_TAGLEV2		0x0014
+#define XM_TXCMD		0x0020
+#define XM_TX_RETRYLIMIT	0x0024
+#define XM_TX_SLOTTIME		0x0028
+#define XM_TX_IPG		0x003C
+#define XM_RXCMD		0x0030
+#define XM_PHY_ADDR		0x0034
+#define XM_PHY_DATA		0x0038
+#define XM_GPIO			0x0040
+#define XM_IMR			0x0044
+#define XM_ISR			0x0048
+#define XM_HWCFG		0x004C
+#define XM_TX_LOWAT		0x0060
+#define XM_TX_HIWAT		0x0062
+#define XM_TX_REQTHRESH_LO	0x0064
+#define XM_TX_REQTHRESH_HI	0x0066
+#define XM_TX_REQTHRESH		XM_TX_REQTHRESH_LO
+#define XM_PAUSEDST0		0x0068
+#define XM_PAUSEDST1		0x006A
+#define XM_PAUSEDST2		0x006C
+#define XM_CTLPARM_LO		0x0070
+#define XM_CTLPARM_HI		0x0072
+#define XM_CTLPARM		XM_CTLPARM_LO
+#define XM_OPCODE_PAUSE_TIMER	0x0074
+#define XM_TXSTAT_LIFO		0x0078
+
+/*
+ * Perfect filter registers. The XMAC has a table of 16 perfect
+ * filter entries, spaced 8 bytes apart. This is in addition to
+ * the station address registers, which appear below.
+ */
+#define XM_RXFILT_BASE		0x0080
+#define XM_RXFILT_END		0x0107
+#define XM_RXFILT_MAX		16
+#define XM_RXFILT_ENTRY(ent)		(XM_RXFILT_BASE + ((ent * 8)))
+
+/* Primary station address. */
+#define XM_PAR0			0x0108
+#define XM_PAR1			0x010A
+#define XM_PAR2			0x010C
+
+/* 64-bit multicast hash table registers */
+#define XM_MAR0			0x0110
+#define XM_MAR1			0x0112
+#define XM_MAR2			0x0114
+#define XM_MAR3			0x0116
+#define XM_RX_LOWAT		0x0118
+#define XM_RX_HIWAT		0x011A
+#define XM_RX_REQTHRESH_LO	0x011C
+#define XM_RX_REQTHRESH_HI	0x011E
+#define XM_RX_REQTHRESH		XM_RX_REQTHRESH_LO
+#define XM_DEVID_LO		0x0120
+#define XM_DEVID_HI		0x0122
+#define XM_DEVID		XM_DEVID_LO
+#define XM_MODE_LO		0x0124
+#define XM_MODE_HI		0x0126
+#define XM_MODE			XM_MODE_LO
+#define XM_LASTSRC0		0x0128
+#define XM_LASTSRC1		0x012A
+#define XM_LASTSRC2		0x012C
+#define XM_TSTAMP_READ		0x0130
+#define XM_TSTAMP_LOAD		0x0134
+#define XM_STATS_CMD		0x0200
+#define XM_RXCNT_EVENT_LO	0x0204
+#define XM_RXCNT_EVENT_HI	0x0206
+#define XM_RXCNT_EVENT		XM_RXCNT_EVENT_LO
+#define XM_TXCNT_EVENT_LO	0x0208
+#define XM_TXCNT_EVENT_HI	0x020A
+#define XM_TXCNT_EVENT		XM_TXCNT_EVENT_LO
+#define XM_RXCNT_EVMASK_LO	0x020C
+#define XM_RXCNT_EVMASK_HI	0x020E
+#define XM_RXCNT_EVMASK		XM_RXCNT_EVMASK_LO
+#define XM_TXCNT_EVMASK_LO	0x0210
+#define XM_TXCNT_EVMASK_HI	0x0212
+#define XM_TXCNT_EVMASK		XM_TXCNT_EVMASK_LO
+
+/* Statistics command register */
+#define XM_STATCMD_CLR_TX	0x0001
+#define XM_STATCMD_CLR_RX	0x0002
+#define XM_STATCMD_COPY_TX	0x0004
+#define XM_STATCMD_COPY_RX	0x0008
+#define XM_STATCMD_SNAP_TX	0x0010
+#define XM_STATCMD_SNAP_RX	0x0020
+
+/* TX statistics registers */
+#define XM_TXSTATS_PKTSOK	0x280
+#define XM_TXSTATS_BYTESOK_HI	0x284
+#define XM_TXSTATS_BYTESOK_LO	0x288
+#define XM_TXSTATS_BCASTSOK	0x28C
+#define XM_TXSTATS_MCASTSOK	0x290
+#define XM_TXSTATS_UCASTSOK	0x294
+#define XM_TXSTATS_GIANTS	0x298
+#define XM_TXSTATS_BURSTCNT	0x29C
+#define XM_TXSTATS_PAUSEPKTS	0x2A0
+#define XM_TXSTATS_MACCTLPKTS	0x2A4
+#define XM_TXSTATS_SINGLECOLS	0x2A8
+#define XM_TXSTATS_MULTICOLS	0x2AC
+#define XM_TXSTATS_EXCESSCOLS	0x2B0
+#define XM_TXSTATS_LATECOLS	0x2B4
+#define XM_TXSTATS_DEFER	0x2B8
+#define XM_TXSTATS_EXCESSDEFER	0x2BC
+#define XM_TXSTATS_UNDERRUN	0x2C0
+#define XM_TXSTATS_CARRIERSENSE	0x2C4
+#define XM_TXSTATS_UTILIZATION	0x2C8
+#define XM_TXSTATS_64		0x2D0
+#define XM_TXSTATS_65_127	0x2D4
+#define XM_TXSTATS_128_255	0x2D8
+#define XM_TXSTATS_256_511	0x2DC
+#define XM_TXSTATS_512_1023	0x2E0
+#define XM_TXSTATS_1024_MAX	0x2E4
+
+/* RX statistics registers */
+#define XM_RXSTATS_PKTSOK	0x300
+#define XM_RXSTATS_BYTESOK_HI	0x304
+#define XM_RXSTATS_BYTESOK_LO	0x308
+#define XM_RXSTATS_BCASTSOK	0x30C
+#define XM_RXSTATS_MCASTSOK	0x310
+#define XM_RXSTATS_UCASTSOK	0x314
+#define XM_RXSTATS_PAUSEPKTS	0x318
+#define XM_RXSTATS_MACCTLPKTS	0x31C
+#define XM_RXSTATS_BADPAUSEPKTS	0x320
+#define XM_RXSTATS_BADMACCTLPKTS	0x324
+#define XM_RXSTATS_BURSTCNT	0x328
+#define XM_RXSTATS_MISSEDPKTS	0x32C
+#define XM_RXSTATS_FRAMEERRS	0x330
+#define XM_RXSTATS_OVERRUN	0x334
+#define XM_RXSTATS_JABBER	0x338
+#define XM_RXSTATS_CARRLOSS	0x33C
+#define XM_RXSTATS_INRNGLENERR	0x340
+#define XM_RXSTATS_SYMERR	0x344
+#define XM_RXSTATS_SHORTEVENT	0x348
+#define XM_RXSTATS_RUNTS	0x34C
+#define XM_RXSTATS_GIANTS	0x350
+#define XM_RXSTATS_CRCERRS	0x354
+#define XM_RXSTATS_CEXTERRS	0x35C
+#define XM_RXSTATS_UTILIZATION	0x360
+#define XM_RXSTATS_64		0x368
+#define XM_RXSTATS_65_127	0x36C
+#define XM_RXSTATS_128_255	0x370
+#define XM_RXSTATS_256_511	0x374
+#define XM_RXSTATS_512_1023	0x378
+#define XM_RXSTATS_1024_MAX	0x37C
+
+#define XM_MMUCMD_TX_ENB	0x0001
+#define XM_MMUCMD_RX_ENB	0x0002
+#define XM_MMUCMD_GMIILOOP	0x0004
+#define XM_MMUCMD_RATECTL	0x0008
+#define XM_MMUCMD_GMIIFDX	0x0010
+#define XM_MMUCMD_NO_MGMT_PRMB	0x0020
+#define XM_MMUCMD_SIMCOL	0x0040
+#define XM_MMUCMD_FORCETX	0x0080
+#define XM_MMUCMD_LOOPENB	0x0200
+#define XM_MMUCMD_IGNPAUSE	0x0400
+#define XM_MMUCMD_PHYBUSY	0x0800
+#define XM_MMUCMD_PHYDATARDY	0x1000
+
+#define XM_TXCMD_AUTOPAD	0x0001
+#define XM_TXCMD_NOCRC		0x0002
+#define XM_TXCMD_NOPREAMBLE	0x0004
+#define XM_TXCMD_NOGIGAMODE	0x0008
+#define XM_TXCMD_SAMPLELINE	0x0010
+#define XM_TXCMD_ENCBYPASS	0x0020
+#define XM_TXCMD_XMITBK2BK	0x0040
+#define XM_TXCMD_FAIRSHARE	0x0080
+
+#define XM_RXCMD_DISABLE_CEXT	0x0001
+#define XM_RXCMD_STRIPPAD	0x0002
+#define XM_RXCMD_SAMPLELINE	0x0004
+#define XM_RXCMD_SELFRX		0x0008
+#define XM_RXCMD_STRIPFCS	0x0010
+#define XM_RXCMD_TRANSPARENT	0x0020
+#define XM_RXCMD_IPGCAPTURE	0x0040
+#define XM_RXCMD_BIGPKTOK	0x0080
+#define XM_RXCMD_LENERROK	0x0100
+
+#define XM_GPIO_GP0_SET		0x0001
+#define XM_GPIO_RESETSTATS	0x0004
+#define XM_GPIO_RESETMAC	0x0008
+#define XM_GPIO_FORCEINT	0x0020
+#define XM_GPIO_ANEGINPROG	0x0040
+
+#define XM_IMR_RX_EOF		0x0001
+#define XM_IMR_TX_EOF		0x0002
+#define XM_IMR_TX_UNDERRUN	0x0004
+#define XM_IMR_RX_OVERRUN	0x0008
+#define XM_IMR_TX_STATS_OFLOW	0x0010
+#define XM_IMR_RX_STATS_OFLOW	0x0020
+#define XM_IMR_TSTAMP_OFLOW	0x0040
+#define XM_IMR_AUTONEG_DONE	0x0080
+#define XM_IMR_NEXTPAGE_RDY	0x0100
+#define XM_IMR_PAGE_RECEIVED	0x0200
+#define XM_IMR_LP_REQCFG	0x0400
+#define XM_IMR_GP0_SET		0x0800
+#define XM_IMR_FORCEINTR	0x1000
+#define XM_IMR_TX_ABORT		0x2000
+#define XM_IMR_LINKEVENT	0x4000
+
+#define XM_INTRS	\
+	(~(XM_IMR_GP0_SET|XM_IMR_AUTONEG_DONE|XM_IMR_TX_UNDERRUN))
+
+#define XM_ISR_RX_EOF		0x0001
+#define XM_ISR_TX_EOF		0x0002
+#define XM_ISR_TX_UNDERRUN	0x0004
+#define XM_ISR_RX_OVERRUN	0x0008
+#define XM_ISR_TX_STATS_OFLOW	0x0010
+#define XM_ISR_RX_STATS_OFLOW	0x0020
+#define XM_ISR_TSTAMP_OFLOW	0x0040
+#define XM_ISR_AUTONEG_DONE	0x0080
+#define XM_ISR_NEXTPAGE_RDY	0x0100
+#define XM_ISR_PAGE_RECEIVED	0x0200
+#define XM_ISR_LP_REQCFG	0x0400
+#define XM_ISR_GP0_SET		0x0800
+#define XM_ISR_FORCEINTR	0x1000
+#define XM_ISR_TX_ABORT		0x2000
+#define XM_ISR_LINKEVENT	0x4000
+
+#define XM_HWCFG_GENEOP		0x0008
+#define XM_HWCFG_SIGSTATCKH	0x0004
+#define XM_HWCFG_GMIIMODE	0x0001
+
+#define XM_MODE_FLUSH_RXFIFO	0x00000001
+#define XM_MODE_FLUSH_TXFIFO	0x00000002
+#define XM_MODE_BIGENDIAN	0x00000004
+#define XM_MODE_RX_PROMISC	0x00000008
+#define XM_MODE_RX_NOBROAD	0x00000010
+#define XM_MODE_RX_NOMULTI	0x00000020
+#define XM_MODE_RX_NOUNI	0x00000040
+#define XM_MODE_RX_BADFRAMES	0x00000080
+#define XM_MODE_RX_CRCERRS	0x00000100
+#define XM_MODE_RX_GIANTS	0x00000200
+#define XM_MODE_RX_INRANGELEN	0x00000400
+#define XM_MODE_RX_RUNTS	0x00000800
+#define XM_MODE_RX_MACCTL	0x00001000
+#define XM_MODE_RX_USE_PERFECT	0x00002000
+#define XM_MODE_RX_USE_STATION	0x00004000
+#define XM_MODE_RX_USE_HASH	0x00008000
+#define XM_MODE_RX_ADDRPAIR	0x00010000
+#define XM_MODE_PAUSEONHI	0x00020000
+#define XM_MODE_PAUSEONLO	0x00040000
+#define XM_MODE_TIMESTAMP	0x00080000
+#define XM_MODE_SENDPAUSE	0x00100000
+#define XM_MODE_SENDCONTINUOUS	0x00200000
+#define XM_MODE_LE_STATUSWORD	0x00400000
+#define XM_MODE_AUTOFIFOPAUSE	0x00800000
+#define XM_MODE_EXPAUSEGEN	0x02000000
+#define XM_MODE_RX_INVERSE	0x04000000
+
+#define XM_RXSTAT_MACCTL	0x00000001
+#define XM_RXSTAT_ERRFRAME	0x00000002
+#define XM_RXSTAT_CRCERR	0x00000004
+#define XM_RXSTAT_GIANT		0x00000008
+#define XM_RXSTAT_RUNT		0x00000010
+#define XM_RXSTAT_FRAMEERR	0x00000020
+#define XM_RXSTAT_INRANGEERR	0x00000040
+#define XM_RXSTAT_CARRIERERR	0x00000080
+#define XM_RXSTAT_COLLERR	0x00000100
+#define XM_RXSTAT_802_3		0x00000200
+#define XM_RXSTAT_CARREXTERR	0x00000400
+#define XM_RXSTAT_BURSTMODE	0x00000800
+#define XM_RXSTAT_UNICAST	0x00002000
+#define XM_RXSTAT_MULTICAST	0x00004000
+#define XM_RXSTAT_BROADCAST	0x00008000
+#define XM_RXSTAT_VLAN_LEV1	0x00010000
+#define XM_RXSTAT_VLAN_LEV2	0x00020000
+#define XM_RXSTAT_LEN		0xFFFC0000
+
+/*
+ * XMAC PHY registers, indirectly accessed through
+ * XM_PHY_ADDR and XM_PHY_REG.
+ */
+
+#define XM_PHY_BMCR		0x0000	/* control */
+#define XM_PHY_BMSR		0x0001	/* status */
+#define XM_PHY_VENID		0x0002	/* vendor id */
+#define XM_PHY_DEVID		0x0003	/* device id */
+#define XM_PHY_ANAR		0x0004	/* autoneg advertisenemt */
+#define XM_PHY_LPAR		0x0005	/* link partner ability */
+#define XM_PHY_ANEXP		0x0006	/* autoneg expansion */
+#define XM_PHY_NEXTP		0x0007	/* nextpage */
+#define XM_PHY_LPNEXTP		0x0008	/* link partner's nextpage */
+#define XM_PHY_EXTSTS		0x000F	/* extented status */
+#define XM_PHY_RESAB		0x0010	/* resolved ability */
+
+#define XM_BMCR_DUPLEX		0x0100
+#define XM_BMCR_RENEGOTIATE	0x0200
+#define XM_BMCR_AUTONEGENBL	0x1000
+#define XM_BMCR_LOOPBACK	0x4000
+#define XM_BMCR_RESET		0x8000
+
+#define XM_BMSR_EXTCAP		0x0001
+#define XM_BMSR_LINKSTAT	0x0004
+#define XM_BMSR_AUTONEGABLE	0x0008
+#define XM_BMSR_REMFAULT	0x0010
+#define XM_BMSR_AUTONEGDONE	0x0020
+#define XM_BMSR_EXTSTAT		0x0100
+
+#define XM_VENID_XAQTI		0xD14C
+#define XM_DEVID_XMAC		0x0002
+
+#define XM_ANAR_FULLDUPLEX	0x0020
+#define XM_ANAR_HALFDUPLEX	0x0040
+#define XM_ANAR_PAUSEBITS	0x0180
+#define XM_ANAR_REMFAULTBITS	0x1800
+#define XM_ANAR_ACK		0x4000
+#define XM_ANAR_NEXTPAGE	0x8000
+
+#define XM_LPAR_FULLDUPLEX	0x0020
+#define XM_LPAR_HALFDUPLEX	0x0040
+#define XM_LPAR_PAUSEBITS	0x0180
+#define XM_LPAR_REMFAULTBITS	0x1800
+#define XM_LPAR_ACK		0x4000
+#define XM_LPAR_NEXTPAGE	0x8000
+
+#define XM_PAUSE_NOPAUSE	0x0000
+#define XM_PAUSE_SYMPAUSE	0x0080
+#define XM_PAUSE_ASYMPAUSE	0x0100
+#define XM_PAUSE_BOTH		0x0180
+
+#define XM_REMFAULT_LINKOK	0x0000
+#define XM_REMFAULT_LINKFAIL	0x0800
+#define XM_REMFAULT_OFFLINE	0x1000
+#define XM_REMFAULT_ANEGERR	0x1800
+
+#define XM_ANEXP_GOTPAGE	0x0002
+#define XM_ANEXP_NEXTPAGE_SELF	0x0004
+#define XM_ANEXP_NEXTPAGE_LP	0x0008
+
+#define XM_NEXTP_MESSAGE	0x07FF
+#define XM_NEXTP_TOGGLE		0x0800
+#define XM_NEXTP_ACK2		0x1000
+#define XM_NEXTP_MPAGE		0x2000
+#define XM_NEXTP_ACK1		0x4000
+#define XM_NEXTP_NPAGE		0x8000
+
+#define XM_LPNEXTP_MESSAGE	0x07FF
+#define XM_LPNEXTP_TOGGLE	0x0800
+#define XM_LPNEXTP_ACK2		0x1000
+#define XM_LPNEXTP_MPAGE	0x2000
+#define XM_LPNEXTP_ACK1		0x4000
+#define XM_LPNEXTP_NPAGE	0x8000
+
+#define XM_EXTSTS_HALFDUPLEX	0x4000
+#define XM_EXTSTS_FULLDUPLEX	0x8000
+
+#define XM_RESAB_PAUSEMISMATCH	0x0008
+#define XM_RESAB_ABLMISMATCH	0x0010
+#define XM_RESAB_FDMODESEL	0x0020
+#define XM_RESAB_HDMODESEL	0x0040
+#define XM_RESAB_PAUSEBITS	0x0180
Index: sys/dev/pci/yukonreg.h
===================================================================
RCS file: yukonreg.h
diff -N yukonreg.h
--- /dev/null	Thu Jul 11 11:18:53 2002
+++ sys/dev/pci/yukonreg.h	Sun Aug 17 07:04:15 2003
@@ -0,0 +1,202 @@
+/* $NetBSD$ */
+/*-
+ * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*	$OpenBSD: yukonreg.h,v 1.2 2003/08/12 05:23:06 nate Exp $ */
+/*
+ * 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.
+ */
+
+/* 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 */

>Release-Note:
>Audit-Trail:
>Unformatted: