diff options
author | Nathan Binkert <nate@cvs.openbsd.org> | 2003-08-01 04:46:14 +0000 |
---|---|---|
committer | Nathan Binkert <nate@cvs.openbsd.org> | 2003-08-01 04:46:14 +0000 |
commit | f203f1be59e60223513093434d858a54ae8b27bb (patch) | |
tree | d8c89db561d50857ce24ae6372f3f9aa8978bb24 /sys/dev/pci | |
parent | 3ca3347233410b4f18ecadf6b631ceede1ab7539 (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.c | 833 | ||||
-rw-r--r-- | sys/dev/pci/if_skreg.h | 276 | ||||
-rw-r--r-- | sys/dev/pci/yukonreg.h | 181 |
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 */ |