summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2003-08-01 04:46:14 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2003-08-01 04:46:14 +0000
commitf203f1be59e60223513093434d858a54ae8b27bb (patch)
treed8c89db561d50857ce24ae6372f3f9aa8978bb24 /sys/dev/pci
parent3ca3347233410b4f18ecadf6b631ceede1ab7539 (diff)
Support for new Marvell based Gigabit Ethernet adapters
ok deraadt@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/if_sk.c833
-rw-r--r--sys/dev/pci/if_skreg.h276
-rw-r--r--sys/dev/pci/yukonreg.h181
3 files changed, 1105 insertions, 185 deletions
diff --git a/sys/dev/pci/if_sk.c b/sys/dev/pci/if_sk.c
index 12166ab7a04..a89fe0cfa55 100644
--- a/sys/dev/pci/if_sk.c
+++ b/sys/dev/pci/if_sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sk.c,v 1.31 2003/05/14 01:54:15 nate Exp $ */
+/* $OpenBSD: if_sk.c,v 1.32 2003/08/01 04:46:13 nate Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -108,21 +108,22 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
-#define SK_USEIOSPACE
#define SK_VERBOSE
+/* #define SK_USEIOSPACE */
#include <dev/pci/if_skreg.h>
#include <dev/pci/xmaciireg.h>
+#include <dev/pci/yukonreg.h>
int skc_probe(struct device *, void *, void *);
void skc_attach(struct device *, struct device *self, void *aux);
int sk_probe(struct device *, void *, void *);
void sk_attach(struct device *, struct device *self, void *aux);
int skcprint(void *, const char *);
-int sk_attach_xmac(struct sk_softc *, int);
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 *);
@@ -130,6 +131,7 @@ void sk_start(struct ifnet *);
int sk_ioctl(struct ifnet *, u_long, caddr_t);
void sk_init(void *);
void sk_init_xmac(struct sk_if_softc *);
+void sk_init_yukon(struct sk_if_softc *);
void sk_stop(struct sk_if_softc *);
void sk_watchdog(struct ifnet *);
void sk_shutdown(void *);
@@ -139,26 +141,37 @@ 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_int32_t sk_win_read_4(struct sk_softc *, int);
-u_int16_t sk_win_read_2(struct sk_softc *, int);
-u_int8_t sk_win_read_1(struct sk_softc *, int);
-void sk_win_write_4(struct sk_softc *, int, u_int32_t);
-void sk_win_write_2(struct sk_softc *, int, u_int32_t);
-void sk_win_write_1(struct sk_softc *, int, u_int32_t);
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_miibus_readreg(struct device *, int, int);
-void sk_miibus_writereg(struct device *, int, int, int);
-void sk_miibus_statchg(struct device *);
+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 *);
+#ifdef SK_DEBUG
+#define DPRINTF(x) if (skdebug) printf x
+#define DPRINTFN(n,x) if (skdebug >= (n)) printf x
+int skdebug = 0;
+
+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)
@@ -177,46 +190,77 @@ void sk_tick(void *);
#define SK_WIN_CLRBIT_2(sc, reg, x) \
sk_win_write_2(sc, reg, sk_win_read_2(sc, reg) & ~x)
-u_int32_t
-sk_win_read_4(struct sk_softc *sc, int reg)
+/* supported device vendors */
+const struct pci_matchid skc_devices[] = {
+ { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C940},
+ { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_GE},
+ { PCI_VENDOR_SCHNEIDERKOCH, PCI_PRODUCT_SCHNEIDERKOCH_SK9821v2},
+};
+
+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)));
+ return CSR_READ_4(sc, SK_WIN_BASE + SK_REG(reg));
+#else
+ return CSR_READ_4(sc, reg);
+#endif
}
-u_int16_t
-sk_win_read_2(struct sk_softc *sc, int reg)
+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)));
+ return CSR_READ_2(sc, SK_WIN_BASE + SK_REG(reg));
+#else
+ return CSR_READ_2(sc, reg);
+#endif
}
-u_int8_t
-sk_win_read_1(struct sk_softc *sc, int reg)
+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)));
+ return CSR_READ_1(sc, SK_WIN_BASE + SK_REG(reg));
+#else
+ return CSR_READ_1(sc, reg);
+#endif
}
-void
-sk_win_write_4(struct sk_softc *sc, int reg, u_int32_t val)
+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), val);
+ CSR_WRITE_4(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+ CSR_WRITE_4(sc, reg, x);
+#endif
}
-void
-sk_win_write_2(struct sk_softc *sc, int reg, u_int32_t val)
+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), (u_int32_t)val);
+ CSR_WRITE_2(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+ CSR_WRITE_2(sc, reg, x);
+#endif
}
-void
-sk_win_write_1(struct sk_softc *sc, int reg, u_int32_t val)
+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), val);
+ CSR_WRITE_1(sc, SK_WIN_BASE + SK_REG(reg), x);
+#else
+ CSR_WRITE_1(sc, reg, x);
+#endif
}
/*
@@ -307,11 +351,13 @@ sk_vpd_read(struct sk_softc *sc)
}
int
-sk_miibus_readreg(struct device *dev, int phy, int reg)
+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);
@@ -336,11 +382,13 @@ sk_miibus_readreg(struct device *dev, int phy, int reg)
}
void
-sk_miibus_writereg(struct device *dev, int phy, int reg, int val)
+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))
@@ -365,11 +413,13 @@ sk_miibus_writereg(struct device *dev, int phy, int reg, int val)
}
void
-sk_miibus_statchg(struct device *dev)
+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.
@@ -383,8 +433,82 @@ sk_miibus_statchg(struct device *dev)
}
}
-#define SK_POLY 0xEDB88320
+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)
@@ -415,7 +539,8 @@ sk_setfilt(struct sk_if_softc *sc_if, caddr_t addr, int slot)
void
sk_setmulti(struct sk_if_softc *sc_if)
{
- struct ifnet *ifp = &sc_if->arpcom.ac_if;
+ struct sk_softc *sc = sc_if->sk_softc;
+ struct ifnet *ifp= &sc_if->arpcom.ac_if;
u_int32_t hashes[2] = { 0, 0 };
int h, i;
struct arpcom *ac = &sc_if->arpcom;
@@ -424,10 +549,21 @@ sk_setmulti(struct sk_if_softc *sc_if)
u_int8_t dummy[] = { 0, 0, 0, 0, 0 ,0 };
/* First, zot all the existing filters. */
- for (i = 1; i < XM_RXFILT_MAX; i++)
- sk_setfilt(sc_if, (caddr_t)&dummy, i);
- SK_XM_WRITE_4(sc_if, XM_MAR0, 0);
- SK_XM_WRITE_4(sc_if, XM_MAR2, 0);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ for (i = 1; i < XM_RXFILT_MAX; i++)
+ sk_setfilt(sc_if, (caddr_t)&dummy, i);
+
+ SK_XM_WRITE_4(sc_if, XM_MAR0, 0);
+ SK_XM_WRITE_4(sc_if, XM_MAR2, 0);
+ break;
+ case SK_YUKON:
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH1, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH2, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH3, 0);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH4, 0);
+ break;
+ }
/* Now program new ones. */
allmulti:
@@ -439,7 +575,8 @@ allmulti:
/* First find the tail of the list. */
ETHER_FIRST_MULTI(step, ac, enm);
while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+ if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
+ ETHER_ADDR_LEN)) {
ifp->if_flags |= IFF_ALLMULTI;
goto allmulti;
}
@@ -448,7 +585,7 @@ allmulti:
* into the perfect filter. For all others,
* use the hash table.
*/
- if (i < XM_RXFILT_MAX) {
+ if (sc->sk_type == SK_GENESIS && i < XM_RXFILT_MAX) {
sk_setfilt(sc_if, enm->enm_addrlo, i);
i++;
}
@@ -464,10 +601,20 @@ allmulti:
}
}
- SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH|
- XM_MODE_RX_USE_PERFECT);
- SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
- SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_SETBIT_4(sc_if, XM_MODE, XM_MODE_RX_USE_HASH|
+ XM_MODE_RX_USE_PERFECT);
+ SK_XM_WRITE_4(sc_if, XM_MAR0, hashes[0]);
+ SK_XM_WRITE_4(sc_if, XM_MAR2, hashes[1]);
+ break;
+ case SK_YUKON:
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH1, hashes[0] & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH2, (hashes[0] >> 16) & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH3, hashes[1] & 0xffff);
+ SK_YU_WRITE_2(sc_if, YUKON_MCAH4, (hashes[1] >> 16) & 0xffff);
+ break;
+ }
}
int
@@ -644,6 +791,7 @@ 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;
@@ -683,14 +831,31 @@ sk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (ifp->if_flags & IFF_RUNNING &&
ifp->if_flags & IFF_PROMISC &&
!(sc_if->sk_if_flags & IFF_PROMISC)) {
- SK_XM_SETBIT_4(sc_if, XM_MODE,
- XM_MODE_RX_PROMISC);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_SETBIT_4(sc_if, XM_MODE,
+ XM_MODE_RX_PROMISC);
+ break;
+ case SK_YUKON:
+ SK_YU_CLRBIT_2(sc_if, YUKON_RCR,
+ YU_RCR_UFLEN | YU_RCR_MUFLEN);
+ break;
+ }
sk_setmulti(sc_if);
} else if (ifp->if_flags & IFF_RUNNING &&
!(ifp->if_flags & IFF_PROMISC) &&
sc_if->sk_if_flags & IFF_PROMISC) {
- SK_XM_CLRBIT_4(sc_if, XM_MODE,
- XM_MODE_RX_PROMISC);
+ switch(sc->sk_type) {
+ case SK_GENESIS:
+ SK_XM_CLRBIT_4(sc_if, XM_MODE,
+ XM_MODE_RX_PROMISC);
+ break;
+ case SK_YUKON:
+ SK_YU_SETBIT_2(sc_if, YUKON_RCR,
+ YU_RCR_UFLEN | YU_RCR_MUFLEN);
+ break;
+ }
+
sk_setmulti(sc_if);
} else
sk_init(sc_if);
@@ -738,13 +903,8 @@ sk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
int
skc_probe(struct device *parent, void *match, void *aux)
{
- struct pci_attach_args *pa = aux;
-
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SCHNEIDERKOCH &&
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SCHNEIDERKOCH_GE)
- return (1);
-
- return (0);
+ return (pci_matchbyid((struct pci_attach_args *)aux, skc_devices,
+ sizeof(skc_devices)/sizeof(skc_devices[0])));
}
/*
@@ -752,18 +912,32 @@ skc_probe(struct device *parent, void *match, void *aux)
*/
void sk_reset(struct sk_softc *sc)
{
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_SW_RESET);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_MASTER_RESET);
- DELAY(1000);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_SW_UNRESET);
- CSR_WRITE_4(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
+ 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);
- /* Configure packet arbiter */
- sk_win_write_2(sc, SK_PKTARB_CTL, SK_PKTARBCTL_UNRESET);
- sk_win_write_2(sc, SK_RXPA1_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_TXPA1_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_RXPA2_TINIT, SK_PKTARB_TIMEOUT);
- sk_win_write_2(sc, SK_TXPA2_TINIT, SK_PKTARB_TIMEOUT);
+ DELAY(1000);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_SW_UNRESET);
+ DELAY(2);
+ CSR_WRITE_2(sc, SK_CSR, SK_CSR_MASTER_UNRESET);
+ if (sc->sk_type == SK_YUKON)
+ CSR_WRITE_2(sc, SK_LINK_CTRL, SK_LINK_RESET_CLEAR);
+
+ 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);
@@ -816,7 +990,9 @@ sk_attach(struct device *parent, struct device *self, void *aux)
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
@@ -867,6 +1043,11 @@ sk_attach(struct device *parent, struct device *self, void *aux)
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) {
@@ -876,6 +1057,9 @@ sk_attach(struct device *parent, struct device *self, void *aux)
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);
@@ -933,11 +1117,34 @@ sk_attach(struct device *parent, struct device *self, void *aux)
/*
* Do miibus setup.
*/
- sk_init_xmac(sc_if);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_init_xmac(sc_if);
+ break;
+ case SK_YUKON:
+ sk_init_yukon(sc_if);
+ break;
+ 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;
- sc_if->sk_mii.mii_readreg = sk_miibus_readreg;
- sc_if->sk_mii.mii_writereg = sk_miibus_writereg;
- sc_if->sk_mii.mii_statchg = sk_miibus_statchg;
+ 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,
@@ -945,7 +1152,7 @@ sk_attach(struct device *parent, struct device *self, void *aux)
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);
+ 0, NULL);
ifmedia_set(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL);
}
else
@@ -954,12 +1161,16 @@ sk_attach(struct device *parent, struct device *self, void *aux)
timeout_set(&sc_if->sk_tick_ch, sk_tick, sc_if);
timeout_add(&sc_if->sk_tick_ch, hz);
+ DPRINTFN(2, ("sk_attach: 1\n"));
+
/*
* Call MI attach routines.
*/
if_attach(ifp);
ether_ifattach(ifp);
+ DPRINTFN(2, ("sk_attach: end\n"));
+
return;
fail:
@@ -997,14 +1208,16 @@ skc_attach(struct device *parent, struct device *self, void *aux)
int s;
u_int32_t command;
+ DPRINTFN(2, ("begin skc_attach\n"));
+
s = splimp();
/*
* Handle power management nonsense.
*/
command = pci_conf_read(pc, pa->pa_tag, SK_PCI_CAPID) & 0x000000FF;
- if (command == 0x01) {
+ 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;
@@ -1039,6 +1252,19 @@ skc_attach(struct device *parent, struct device *self, void *aux)
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_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");
@@ -1070,9 +1296,13 @@ skc_attach(struct device *parent, struct device *self, void *aux)
goto fail;
}
sc->sk_btag = pa->pa_memt;
+
+ DPRINTFN(2, ("skc_attach: iobase=%#x, iosize=%#x\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");
@@ -1096,29 +1326,43 @@ skc_attach(struct device *parent, struct device *self, void *aux)
/* Read and save vital product data from EEPROM. */
sk_vpd_read(sc);
- /* Read and save RAM size and RAMbuffer offset */
- switch(sk_win_read_1(sc, SK_EPROM0)) {
- case SK_RAMSIZE_512K_64:
- sc->sk_ramsize = 0x80000;
- sc->sk_rboff = SK_RBOFF_0;
- break;
- case SK_RAMSIZE_1024K_64:
- sc->sk_ramsize = 0x100000;
- sc->sk_rboff = SK_RBOFF_80000;
- break;
- case SK_RAMSIZE_1024K_128:
- sc->sk_ramsize = 0x100000;
- sc->sk_rboff = SK_RBOFF_0;
- break;
- case SK_RAMSIZE_2048K_128:
- sc->sk_ramsize = 0x200000;
+ if (sc->sk_type == SK_GENESIS) {
+ 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;
- break;
- default:
- printf("%s: unknown ram size: %d\n",
- sc->sk_dev.dv_xname, sk_win_read_1(sc, SK_EPROM0));
- goto fail;
- break;
+
+ 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 */
@@ -1169,24 +1413,40 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
struct sk_txmap_entry *entry;
bus_dmamap_t txmap;
+ DPRINTFN(2, ("sk_encap\n"));
+
entry = SLIST_FIRST(&sc_if->sk_txmap_listhead);
- if (entry == NULL)
- return (ENOBUFS);
+ if (entry == NULL) {
+ DPRINTFN(2, ("sk_encap: no txmap available\n"));
+ return ENOBUFS;
+ }
txmap = entry->dmamap;
cur = frag = *txidx;
+#ifdef SK_DEBUG
+ if (skdebug >= 2)
+ 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))
+ if (bus_dmamap_load_mbuf(sc->sc_dmatag, txmap, m_head,
+ BUS_DMA_NOWAIT)) {
+ DPRINTFN(2, ("sk_encap: dmamap failed\n"));
return(ENOBUFS);
+ }
+
+ DPRINTFN(2, ("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)
+ if ((SK_TX_RING_CNT - (sc_if->sk_cdata.sk_tx_cnt + cnt)) < 2) {
+ DPRINTFN(2, ("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;
@@ -1194,6 +1454,7 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
f->sk_ctl |= SK_TXCTL_FIRSTFRAG;
else
f->sk_ctl |= SK_TXCTL_OWN;
+
cur = frag;
SK_INC(frag, SK_TX_RING_CNT);
cnt++;
@@ -1207,8 +1468,21 @@ sk_encap(struct sk_if_softc *sc_if, struct mbuf *m_head, u_int32_t *txidx)
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 >= 2) {
+ 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(2, ("sk_encap: completed successfully\n"));
+
return(0);
}
@@ -1221,6 +1495,8 @@ sk_start(struct ifnet *ifp)
u_int32_t idx = sc_if->sk_cdata.sk_tx_prod;
int pkts = 0;
+ DPRINTFN(2, ("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)
@@ -1275,6 +1551,8 @@ sk_shutdown(void *v)
{
struct sk_softc *sc = v;
+ DPRINTFN(2, ("sk_shutdown\n"));
+
/* Turn off the 'driver is loaded' LED. */
CSR_WRITE_2(sc, SK_LED, SK_LED_GREEN_OFF);
@@ -1296,6 +1574,8 @@ sk_rxeof(struct sk_if_softc *sc_if)
u_int32_t rxstat;
bus_dmamap_t dmamap;
+ DPRINTFN(2, ("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)) {
@@ -1367,6 +1647,8 @@ sk_txeof(struct sk_if_softc *sc_if)
u_int32_t idx;
struct sk_txmap_entry *entry;
+ DPRINTFN(2, ("sk_txeof\n"));
+
/*
* Go through our tx ring and free mbufs for those
* frames that have been sent.
@@ -1374,6 +1656,10 @@ sk_txeof(struct sk_if_softc *sc_if)
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 >= 2)
+ sk_dump_txdesc(cur_tx, idx);
+#endif
if (cur_tx->sk_ctl & SK_TXCTL_OWN)
break;
if (cur_tx->sk_ctl & SK_TXCTL_LASTFRAG)
@@ -1410,6 +1696,8 @@ sk_tick(void *xsc_if)
struct ifnet *ifp = &sc_if->arpcom.ac_if;
int i;
+ DPRINTFN(2, ("sk_tick\n"));
+
if (!(ifp->if_flags & IFF_UP))
return;
@@ -1450,13 +1738,16 @@ sk_intr_bcom(struct sk_if_softc *sc_if)
struct ifnet *ifp = &sc_if->arpcom.ac_if;
int status;
+
+ DPRINTFN(2, ("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_miibus_readreg((struct device *)sc_if,
+ status = sk_xmac_miibus_readreg((struct device *)sc_if,
SK_PHYADDR_BCOM, BRGPHY_MII_ISR);
if (!(ifp->if_flags & IFF_RUNNING)) {
@@ -1466,7 +1757,7 @@ sk_intr_bcom(struct sk_if_softc *sc_if)
if (status & (BRGPHY_ISR_LNK_CHG|BRGPHY_ISR_AN_PR)) {
int lstat;
- lstat = sk_miibus_readreg((struct device *)sc_if,
+ lstat = sk_xmac_miibus_readreg((struct device *)sc_if,
SK_PHYADDR_BCOM, BRGPHY_MII_AUXSTS);
if (!(lstat & BRGPHY_AUXSTS_LINK) && sc_if->sk_link) {
@@ -1476,7 +1767,7 @@ sk_intr_bcom(struct sk_if_softc *sc_if)
SK_LINKLED1_CTL, SK_LINKLED_OFF);
sc_if->sk_link = 0;
} else if (status & BRGPHY_ISR_LNK_CHG) {
- sk_miibus_writereg((struct device *)sc_if,
+ sk_xmac_miibus_writereg((struct device *)sc_if,
SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFF00);
mii_tick(mii);
sc_if->sk_link = 1;
@@ -1499,6 +1790,8 @@ sk_intr_xmac(struct sk_if_softc *sc_if)
{
u_int16_t status = SK_XM_READ_2(sc_if, XM_ISR);
+ DPRINTFN(2, ("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);
@@ -1517,6 +1810,17 @@ sk_intr_xmac(struct sk_if_softc *sc_if)
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(2, ("sk_intr_yukon status=%#x\n", status));
+}
+
int
sk_intr(void *xsc)
{
@@ -1534,6 +1838,8 @@ sk_intr(void *xsc)
for (;;) {
status = CSR_READ_4(sc, SK_ISSR);
+ DPRINTFN(2, ("sk_intr: status=%#x\n", status));
+
if (!(status & sc->sk_intrmask))
break;
@@ -1564,18 +1870,28 @@ sk_intr(void *xsc)
}
/* Then MAC interrupts. */
- if (status & SK_ISR_MAC1 &&
- ifp0->if_flags & IFF_RUNNING)
- sk_intr_xmac(sc_if0);
+ if (status & SK_ISR_MAC1 && (ifp0->if_flags & IFF_RUNNING)) {
+ if (sc->sk_type == SK_GENESIS)
+ sk_intr_xmac(sc_if0);
+ else
+ sk_intr_yukon(sc_if0);
+ }
+
+ if (status & SK_ISR_MAC2 && (ifp1->if_flags & IFF_RUNNING)) {
+ if (sc->sk_type == SK_GENESIS)
+ sk_intr_xmac(sc_if1);
+ else
+ sk_intr_yukon(sc_if1);
- if (status & SK_ISR_MAC2 &&
- ifp1->if_flags & IFF_RUNNING)
- sk_intr_xmac(sc_if1);
+ }
if (status & SK_ISR_EXTERNAL_REG) {
- if (ifp0 != NULL)
+ if (ifp0 != NULL &&
+ sc_if0->sk_phytype == SK_PHYTYPE_BCOM)
sk_intr_bcom(sc_if0);
- if (ifp1 != NULL)
+
+ if (ifp1 != NULL &&
+ sc_if1->sk_phytype == SK_PHYTYPE_BCOM)
sk_intr_bcom(sc_if1);
}
}
@@ -1601,6 +1917,8 @@ sk_init_xmac(struct sk_if_softc *sc_if)
{ 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
{ 0, 0 } };
+ DPRINTFN(2, ("sk_init_xmac\n"));
+
/* Unreset the XMAC. */
SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_UNRESET);
DELAY(1000);
@@ -1631,11 +1949,11 @@ sk_init_xmac(struct sk_if_softc *sc_if)
/* Enable GMII mode on the XMAC. */
SK_XM_SETBIT_2(sc_if, XM_HWCFG, XM_HWCFG_GMIIMODE);
- sk_miibus_writereg((struct device *)sc_if, SK_PHYADDR_BCOM,
- BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
+ sk_xmac_miibus_writereg((struct device *)sc_if,
+ SK_PHYADDR_BCOM, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
DELAY(10000);
- sk_miibus_writereg((struct device *)sc_if, SK_PHYADDR_BCOM,
- BRGPHY_MII_IMR, 0xFFF0);
+ sk_xmac_miibus_writereg((struct device *)sc_if,
+ SK_PHYADDR_BCOM, BRGPHY_MII_IMR, 0xFFF0);
/*
* Early versions of the BCM5400 apparently have
@@ -1643,10 +1961,10 @@ sk_init_xmac(struct sk_if_softc *sc_if)
* registers initialized to some magic values. I don't
* know what the numbers do, I'm just the messenger.
*/
- if (sk_miibus_readreg((struct device *)sc_if,
+ if (sk_xmac_miibus_readreg((struct device *)sc_if,
SK_PHYADDR_BCOM, 0x03) == 0x6041) {
while(bhack[i].reg) {
- sk_miibus_writereg((struct device *)sc_if,
+ sk_xmac_miibus_writereg((struct device *)sc_if,
SK_PHYADDR_BCOM, bhack[i].reg,
bhack[i].val);
i++;
@@ -1753,6 +2071,131 @@ sk_init_xmac(struct sk_if_softc *sc_if)
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(2, ("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->arpcom.ac_enaddr[i * 2] |
+ sc_if->arpcom.ac_enaddr[i * 2 + 1] << 8);
+ }
+
+ for (i = 0; i < 3; i++) {
+ reg = sk_win_read_2(sc_if->sk_softc,
+ SK_MAC1_0 + i * 2 + sc_if->sk_port * 8);
+ SK_YU_WRITE_2(sc_if, YUKON_SAL2 + i * 4, reg);
+ }
+
+ /* clear all Multicast filter hash registers */
+ 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.
@@ -1766,35 +2209,51 @@ sk_init(void *xsc_if)
struct mii_data *mii = &sc_if->sk_mii;
int s;
+ DPRINTFN(2, ("sk_init\n"));
+
s = splimp();
/* Cancel pending I/O and free all RX/TX buffers. */
sk_stop(sc_if);
- /* Configure LINK_SYNC LED */
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON);
- SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_LINKSYNC_ON);
-
- /* Configure RX LED */
- SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL, SK_RXLEDCTL_COUNTER_START);
-
- /* Configure TX LED */
- SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL, SK_TXLEDCTL_COUNTER_START);
+ if (sc->sk_type == SK_GENESIS) {
+ /* Configure LINK_SYNC LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL, SK_LINKLED_ON);
+ SK_IF_WRITE_1(sc_if, 0, SK_LINKLED1_CTL,
+ SK_LINKLED_LINKSYNC_ON);
+
+ /* Configure RX LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_RXLED1_CTL,
+ SK_RXLEDCTL_COUNTER_START);
+
+ /* Configure TX LED */
+ SK_IF_WRITE_1(sc_if, 0, SK_TXLED1_CTL,
+ SK_TXLEDCTL_COUNTER_START);
+ }
/* Configure I2C registers */
/* Configure XMAC(s) */
- sk_init_xmac(sc_if);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ sk_init_xmac(sc_if);
+ break;
+ case SK_YUKON:
+ sk_init_yukon(sc_if);
+ break;
+ }
mii_mediachg(mii);
- /* Configure MAC FIFOs */
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
-
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
- SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
+ if (sc->sk_type == SK_GENESIS) {
+ /* Configure MAC FIFOs */
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_UNRESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_END, SK_FIFO_END);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_ON);
+
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_UNRESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_END, SK_FIFO_END);
+ SK_IF_WRITE_4(sc_if, 0, SK_TXF1_CTL, SK_FIFO_ON);
+ }
/* Configure transmit arbiter(s) */
SK_IF_WRITE_1(sc_if, 0, SK_TXAR1_COUNTERCTL,
@@ -1858,9 +2317,20 @@ sk_init(void *xsc_if)
/* Start BMUs. */
SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_RX_START);
- /* Enable XMACs TX and RX state machines */
- SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE);
- SK_XM_SETBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+ if (sc->sk_type == SK_GENESIS) {
+ /* Enable XMACs TX and RX state machines */
+ SK_XM_CLRBIT_2(sc_if, XM_MMUCMD, XM_MMUCMD_IGNPAUSE);
+ SK_XM_SETBIT_2(sc_if, XM_MMUCMD,
+ XM_MMUCMD_TX_ENB|XM_MMUCMD_RX_ENB);
+ }
+
+ if (sc->sk_type == SK_YUKON) {
+ u_int16_t reg = SK_YU_READ_2(sc_if, YUKON_GPCR);
+ reg |= YU_GPCR_TXEN | YU_GPCR_RXEN;
+ reg &= ~(YU_GPCR_SPEED_EN | YU_GPCR_DPLX_EN);
+ SK_YU_WRITE_2(sc_if, YUKON_GPCR, reg);
+ }
+
ifp->if_flags |= IFF_RUNNING;
ifp->if_flags &= ~IFF_OACTIVE;
@@ -1875,6 +2345,8 @@ sk_stop(struct sk_if_softc *sc_if)
struct ifnet *ifp = &sc_if->arpcom.ac_if;
int i;
+ DPRINTFN(2, ("sk_stop\n"));
+
timeout_del(&sc_if->sk_tick_ch);
if (sc_if->sk_phytype == SK_PHYTYPE_BCOM) {
@@ -1894,8 +2366,17 @@ sk_stop(struct sk_if_softc *sc_if)
/* Turn off various components of this interface. */
SK_XM_SETBIT_2(sc_if, XM_GPIO, XM_GPIO_RESETMAC);
- SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL, SK_TXMACCTL_XMAC_RESET);
- SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
+ switch (sc->sk_type) {
+ case SK_GENESIS:
+ SK_IF_WRITE_2(sc_if, 0, SK_TXF1_MACCTL,
+ SK_TXMACCTL_XMAC_RESET);
+ SK_IF_WRITE_4(sc_if, 0, SK_RXF1_CTL, SK_FIFO_RESET);
+ break;
+ case SK_YUKON:
+ SK_IF_WRITE_1(sc_if,0, SK_RXMF1_CTRL_TEST, SK_RFCTL_RESET_SET);
+ SK_IF_WRITE_1(sc_if,0, SK_TXMF1_CTRL_TEST, SK_TFCTL_RESET_SET);
+ break;
+ }
SK_IF_WRITE_4(sc_if, 0, SK_RXQ1_BMU_CSR, SK_RXBMU_OFFLINE);
SK_IF_WRITE_4(sc_if, 0, SK_RXRB1_CTLTST, SK_RBCTL_RESET|SK_RBCTL_OFF);
SK_IF_WRITE_4(sc_if, 1, SK_TXQS1_BMU_CSR, SK_TXBMU_OFFLINE);
@@ -1949,3 +2430,75 @@ struct cfattach sk_ca = {
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=%#lx, m->m_pkthdr.len=%#d\n", m, m->m_pkthdr.len);
+
+ while (count > 0 && m) {
+ printf("m=%#lx, m->m_data=%#lx, 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
diff --git a/sys/dev/pci/if_skreg.h b/sys/dev/pci/if_skreg.h
index ceecb2469df..fc5197c6ce4 100644
--- a/sys/dev/pci/if_skreg.h
+++ b/sys/dev/pci/if_skreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_skreg.h,v 1.8 2003/05/14 01:54:15 nate Exp $ */
+/* $OpenBSD: if_skreg.h,v 1.9 2003/08/01 04:46:13 nate Exp $ */
/*
* Copyright (c) 1997, 1998, 1999, 2000
@@ -34,15 +34,9 @@
* $FreeBSD: /c/ncvs/src/sys/pci/if_skreg.h,v 1.9 2000/04/22 02:16:37 wpaul Exp $
*/
-/*
- * SysKonnect PCI vendor ID
- */
-#define SK_VENDORID 0x1148
-
-/*
- * SK-NET gigabit ethernet device ID
- */
-#define SK_DEVICEID_GE 0x4300
+/* 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
@@ -330,6 +324,8 @@
#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.
@@ -338,6 +334,7 @@
#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
@@ -807,6 +804,29 @@
#define SK_FIFO_END 0x3F
+/* Receive MAC FIFO 1 (Yukon Only) */
+#define SK_RXMF1_END 0x0C40
+#define SK_RXMF1_THRESHOLD 0x0C44
+#define SK_RXMF1_CTRL_TEST 0x0C48
+#define SK_RXMF1_WRITE_PTR 0x0C60
+#define SK_RXMF1_WRITE_LEVEL 0x0C68
+#define SK_RXMF1_READ_PTR 0x0C70
+#define SK_RXMF1_READ_LEVEL 0x0C78
+
+#define SK_RFCTL_WR_PTR_TST_ON 0x00004000 /* Write pointer test on*/
+#define SK_RFCTL_WR_PTR_TST_OFF 0x00002000 /* Write pointer test off */
+#define SK_RFCTL_WR_PTR_STEP 0x00001000 /* Write pointer increment */
+#define SK_RFCTL_RD_PTR_TST_ON 0x00000400 /* Read pointer test on */
+#define SK_RFCTL_RD_PTR_TST_OFF 0x00000200 /* Read pointer test off */
+#define SK_RFCTL_RD_PTR_STEP 0x00000100 /* Read pointer increment */
+#define SK_RFCTL_RX_FIFO_OVER 0x00000040 /* Clear IRQ RX FIFO Overrun */
+#define SK_RFCTL_FRAME_RX_DONE 0x00000010 /* Clear IRQ Frame RX Done */
+#define SK_RFCTL_OPERATION_ON 0x00000008 /* Operational mode on */
+#define SK_RFCTL_OPERATION_OFF 0x00000004 /* Operational mode off */
+#define SK_RFCTL_RESET_CLEAR 0x00000002 /* MAC FIFO Reset Clear */
+#define SK_RFCTL_RESET_SET 0x00000001 /* MAC FIFO Reset Set */
+
+
/* Block 25 -- RX MAC FIFO 2 regisrers and LINK_SYNC counter */
#define SK_RXF2_END 0x0C80
#define SK_RXF2_WPTR 0x0C84
@@ -866,6 +886,31 @@
#define SK_TXLED1_CTL 0x0D28
#define SK_TXLED1_TST 0x0D29
+/* Receive MAC FIFO 1 (Yukon Only) */
+#define SK_TXMF1_END 0x0D40
+#define SK_TXMF1_THRESHOLD 0x0D44
+#define SK_TXMF1_CTRL_TEST 0x0D48
+#define SK_TXMF1_WRITE_PTR 0x0D60
+#define SK_TXMF1_WRITE_SHADOW 0x0D64
+#define SK_TXMF1_WRITE_LEVEL 0x0D68
+#define SK_TXMF1_READ_PTR 0x0D70
+#define SK_TXMF1_RESTART_PTR 0x0D74
+#define SK_TXMF1_READ_LEVEL 0x0D78
+
+#define SK_TFCTL_WR_PTR_TST_ON 0x00004000 /* Write pointer test on*/
+#define SK_TFCTL_WR_PTR_TST_OFF 0x00002000 /* Write pointer test off */
+#define SK_TFCTL_WR_PTR_STEP 0x00001000 /* Write pointer increment */
+#define SK_TFCTL_RD_PTR_TST_ON 0x00000400 /* Read pointer test on */
+#define SK_TFCTL_RD_PTR_TST_OFF 0x00000200 /* Read pointer test off */
+#define SK_TFCTL_RD_PTR_STEP 0x00000100 /* Read pointer increment */
+#define SK_TFCTL_TX_FIFO_UNDER 0x00000040 /* Clear IRQ TX FIFO Under */
+#define SK_TFCTL_FRAME_TX_DONE 0x00000020 /* Clear IRQ Frame TX Done */
+#define SK_TFCTL_IRQ_PARITY_ER 0x00000010 /* Clear IRQ Parity Error */
+#define SK_TFCTL_OPERATION_ON 0x00000008 /* Operational mode on */
+#define SK_TFCTL_OPERATION_OFF 0x00000004 /* Operational mode off */
+#define SK_TFCTL_RESET_CLEAR 0x00000002 /* MAC FIFO Reset Clear */
+#define SK_TFCTL_RESET_SET 0x00000001 /* MAC FIFO Reset Set */
+
/* Block 27 -- TX MAC FIFO 2 regisrers */
#define SK_TXF2_END 0x0D80
#define SK_TXF2_WPTR 0x0D84
@@ -905,35 +950,148 @@
#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
-#define SK_XMAC1_END 0x23FF
+
+/* Block 0x50 to 0x5F -- MARV 1 registers */
+#define SK_MARV1_BASE 0x2800
/* Block 0x60 to 0x6F -- XMAC 2 registers */
#define SK_XMAC2_BASE 0x3000
-#define SK_XMAC2_END 0x33FF
-
-/* Compute relative offset of an XMAC register in the XMAC window(s). */
-#define SK_XMAC_REG(reg, mac) (((reg) * 2) + SK_XMAC1_BASE + \
- (mac * (SK_XMAC2_BASE - SK_XMAC1_BASE)))
-#define SK_XM_READ_4(sc, reg) \
- (sk_win_read_2(sc->sk_softc, \
- SK_XMAC_REG(reg, sc->sk_port)) & 0xFFFF) | \
- ((sk_win_read_2(sc->sk_softc, \
- SK_XMAC_REG(reg + 2, sc->sk_port)) << 16) & 0xFFFF0000)
+/* Block 0x70 to 0x7F -- MARV 2 registers */
+#define SK_MARV2_BASE 0x3800
-#define SK_XM_WRITE_4(sc, reg, val) \
- sk_win_write_2(sc->sk_softc, \
- SK_XMAC_REG(reg, sc->sk_port), ((val) & 0xFFFF)); \
- sk_win_write_2(sc->sk_softc, \
- SK_XMAC_REG(reg + 2, sc->sk_port), ((val) >> 16) & 0xFFFF);
-
-#define SK_XM_READ_2(sc, reg) \
- sk_win_read_2(sc->sk_softc, SK_XMAC_REG(reg, sc->sk_port))
-
-#define SK_XM_WRITE_2(sc, reg, val) \
- sk_win_write_2(sc->sk_softc, SK_XMAC_REG(reg, sc->sk_port), val)
+/* 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))
@@ -947,6 +1105,34 @@
#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
@@ -1019,19 +1205,19 @@ struct vpd_key {
#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)
+#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;
diff --git a/sys/dev/pci/yukonreg.h b/sys/dev/pci/yukonreg.h
new file mode 100644
index 00000000000..d0280e46f27
--- /dev/null
+++ b/sys/dev/pci/yukonreg.h
@@ -0,0 +1,181 @@
+/* $OpenBSD: yukonreg.h,v 1.1 2003/08/01 04:46:13 nate Exp $ */
+/*
+ * Copyright (c) 2003 Nathan L. Binkert
+ * All rights reserved.
+ *
+ * Permission to redistribute, use, copy, and modify this software
+ * without fee is hereby granted, provided that the following
+ * conditions are met:
+ *
+ * 1. This entire notice is included in all source code copies of any
+ * software which is or includes a copy or modification of this
+ * software.
+ * 2. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/* 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 */