diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-10-10 23:39:16 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-10-10 23:39:16 +0000 |
commit | 2c727643c8903b3b8cee7a5e242eae444c6e5775 (patch) | |
tree | 8631a867259474839b684b471c01877de9ab03a2 /sys/dev/pci | |
parent | 8ca93970a3617bd5afb77fde247976d0229437ea (diff) |
- Only use the MAC address workaround for the Xframe chipset.
- For the Xfrme II chipset, bring EOI out of reset before XGXS.
- Check for the adapter status bit RIC_RUNNING before trying to
access any registers with the Xframe II chipset.
- Add new DTX_Control values for the Xframe II chipset to
initialize the XGXS transciever.
- Make sure to clear IFF_RUNNING/IFF_OACTIVE in xge_stop().
From Veena Parat @ Neterion
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_xge.c | 166 | ||||
-rw-r--r-- | sys/dev/pci/if_xgereg.h | 3 |
2 files changed, 122 insertions, 47 deletions
diff --git a/sys/dev/pci/if_xge.c b/sys/dev/pci/if_xge.c index 3194ce74290..1dcc46e020e 100644 --- a/sys/dev/pci/if_xge.c +++ b/sys/dev/pci/if_xge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_xge.c,v 1.31 2006/08/25 00:55:37 brad Exp $ */ +/* $OpenBSD: if_xge.c,v 1.32 2006/10/10 23:39:15 brad Exp $ */ /* $NetBSD: if_xge.c,v 1.1 2005/09/09 10:30:27 ragge Exp $ */ /* @@ -155,6 +155,26 @@ static uint64_t fix_mac[] = { 0x0040600000000000ULL, 0x0060600000000000ULL, }; +/* + * Constants to be programmed into Hercules's registers, to configure + * the XGXS transciever. + */ +#define END_SIGN 0x0 +static uint64_t herc_dtx_cfg[] = { + 0x8000051536750000ULL, 0x80000515367500E0ULL, + 0x8000051536750004ULL, 0x80000515367500E4ULL, + + 0x80010515003F0000ULL, 0x80010515003F00E0ULL, + 0x80010515003F0004ULL, 0x80010515003F00E4ULL, + + 0x801205150D440000ULL, 0x801205150D4400E0ULL, + 0x801205150D440004ULL, 0x801205150D4400E4ULL, + + 0x80020515F2100000ULL, 0x80020515F21000E0ULL, + 0x80020515F2100004ULL, 0x80020515F21000E4ULL, + + END_SIGN +}; struct xge_softc { struct device sc_dev; @@ -189,8 +209,6 @@ struct xge_softc { int sc_nextrx; /* next descriptor to check */ }; -#define XGE_DEBUG - #ifdef XGE_DEBUG #define DPRINTF(x) if (xgedebug) printf x #define DPRINTFN(n,x) if (xgedebug >= (n)) printf x @@ -210,7 +228,8 @@ void xge_shutdown(void *); int xge_add_rxbuf(struct xge_softc *, int); void xge_setmulti(struct xge_softc *); void xge_setpromisc(struct xge_softc *); -int xge_setup_xgxs(struct xge_softc *); +int xge_setup_xgxs_xena(struct xge_softc *); +int xge_setup_xgxs_herc(struct xge_softc *); int xge_ioctl(struct ifnet *, u_long, caddr_t); int xge_init(struct ifnet *); void xge_ifmedia_status(struct ifnet *, struct ifmediareq *); @@ -329,19 +348,16 @@ xge_attach(struct device *parent, struct device *self, void *aux) pci_chipset_tag_t pc = pa->pa_pc; uint8_t enaddr[ETHER_ADDR_LEN]; uint64_t val; - int i, pcisize; + int i; sc = (struct xge_softc *)self; sc->sc_dmat = pa->pa_dmat; - if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETERION_XFRAME) { + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_NETERION_XFRAME) sc->xge_type = XGE_TYPE_XENA; - pcisize = XGE_PCISIZE_XENA; - } else { + else sc->xge_type = XGE_TYPE_HERC; - pcisize = XGE_PCISIZE_HERC; - } /* Get BAR0 address */ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, XGE_PIF_BAR); @@ -358,9 +374,11 @@ xge_attach(struct device *parent, struct device *self, void *aux) return; } - /* Save PCI config space */ - for (i = 0; i < pcisize; i += 4) - sc->sc_pciregs[i/4] = pci_conf_read(pa->pa_pc, pa->pa_tag, i); + if (sc->xge_type == XGE_TYPE_XENA) { + /* Save PCI config space */ + for (i = 0; i < XGE_PCISIZE_XENA; i += 4) + sc->sc_pciregs[i/4] = pci_conf_read(pa->pa_pc, pa->pa_tag, i); + } #if BYTE_ORDER == LITTLE_ENDIAN val = (uint64_t)0xFFFFFFFFFFFFFFFFULL; @@ -380,52 +398,91 @@ xge_attach(struct device *parent, struct device *self, void *aux) } /* - * The MAC addr may be all FF's, which is not good. - * Resolve it by writing some magics to GPIO_CONTROL and - * force a chip reset to read in the serial eeprom again. - */ - for (i = 0; i < sizeof(fix_mac)/sizeof(fix_mac[0]); i++) { - PIF_WCSR(GPIO_CONTROL, fix_mac[i]); - PIF_RCSR(GPIO_CONTROL); - } - - /* - * Reset the chip and restore the PCI registers. - */ - PIF_WCSR(SW_RESET, XGXS_RESET(0xA5)); - DELAY(500000); - for (i = 0; i < pcisize; i += 4) - pci_conf_write(pa->pa_pc, pa->pa_tag, i, sc->sc_pciregs[i/4]); + * Fix for all "FFs" MAC address problems observed on + * Alpha platforms. Not needed for Herc. + */ + if (sc->xge_type == XGE_TYPE_XENA) { + /* + * The MAC addr may be all FF's, which is not good. + * Resolve it by writing some magics to GPIO_CONTROL and + * force a chip reset to read in the serial eeprom again. + */ + for (i = 0; i < sizeof(fix_mac)/sizeof(fix_mac[0]); i++) { + PIF_WCSR(GPIO_CONTROL, fix_mac[i]); + PIF_RCSR(GPIO_CONTROL); + } - /* - * Restore the byte order registers. - */ + /* + * Reset the chip and restore the PCI registers. + */ + PIF_WCSR(SW_RESET, 0xa5a5a50000000000ULL); + DELAY(500000); + for (i = 0; i < XGE_PCISIZE_XENA; i += 4) + pci_conf_write(pa->pa_pc, pa->pa_tag, i, sc->sc_pciregs[i/4]); + + /* + * Restore the byte order registers. + */ #if BYTE_ORDER == LITTLE_ENDIAN - val = (uint64_t)0xFFFFFFFFFFFFFFFFULL; - val &= ~(TxF_R_SE|RxF_W_SE); - PIF_WCSR(SWAPPER_CTRL, val); - PIF_WCSR(SWAPPER_CTRL, val); + val = (uint64_t)0xFFFFFFFFFFFFFFFFULL; + val &= ~(TxF_R_SE|RxF_W_SE); + PIF_WCSR(SWAPPER_CTRL, val); + PIF_WCSR(SWAPPER_CTRL, val); #elif BYTE_ORDER == BIG_ENDIAN - /* do nothing */ + /* do nothing */ #else #error bad endianness! #endif - if ((val = PIF_RCSR(PIF_RD_SWAPPER_Fb)) != SWAPPER_MAGIC) { - printf(": failed configuring endian2, %llx != %llx!\n", - (unsigned long long)val, SWAPPER_MAGIC); - return; + if ((val = PIF_RCSR(PIF_RD_SWAPPER_Fb)) != SWAPPER_MAGIC) { + printf(": failed configuring endian2, %llx != %llx!\n", + (unsigned long long)val, SWAPPER_MAGIC); + return; + } } /* * XGXS initialization. */ - /* 29, reset */ - PIF_WCSR(SW_RESET, 0); + + /* + * For Herc, bring EOI out of reset before XGXS. + */ + if (sc->xge_type == XGE_TYPE_HERC) { + val = PIF_RCSR(SW_RESET); + val &= 0xffff00ffffffffffULL; + PIF_WCSR(SW_RESET,val); + delay(1000*1000); //wait for 1 sec + } + + /* 29, Bring adapter out of reset */ + val = PIF_RCSR(SW_RESET); + val &= 0xffffff00ffffffffULL; + PIF_WCSR(SW_RESET, val); DELAY(500000); + /* Ensure that it's safe to access registers by checking + * RIC_RUNNING bit is reset. Check is valid only for XframeII. + */ + if (sc->xge_type == XGE_TYPE_HERC){ + for (i = 0; i < 50; i++) { + val = PIF_RCSR(ADAPTER_STATUS); + if (!(val & RIC_RUNNING)) + break; + delay(20*1000); + } + + if (i == 50) { + printf(": not safe to access registers\n"); + return; + } + } + /* 30, configure XGXS transceiver */ - xge_setup_xgxs(sc); + if (sc->xge_type == XGE_TYPE_XENA) + xge_setup_xgxs_xena(sc); + else if(sc->xge_type == XGE_TYPE_HERC) + xge_setup_xgxs_herc(sc); /* 33, program MAC address (not needed here) */ /* Get ethernet address */ @@ -658,7 +715,6 @@ xge_enable(struct xge_softc *sc) #ifdef XGE_DEBUG printf("%s: link up\n", XNAME); #endif - } int @@ -701,6 +757,7 @@ xge_init(struct ifnet *ifp) PIF_WCSR(ADAPTER_CONTROL, val); xge_enable(sc); + /* * Enable all interrupts */ @@ -709,6 +766,7 @@ xge_init(struct ifnet *ifp) PIF_WCSR(GENERAL_INT_MASK, 0); PIF_WCSR(TXPIC_INT_MASK, 0); PIF_WCSR(RXPIC_INT_MASK, 0); + PIF_WCSR(MAC_INT_MASK, MAC_TMAC_INT); /* only from RMAC */ PIF_WCSR(MAC_RMAC_ERR_MASK, ~RMAC_LINK_STATE_CHANGE_INT); @@ -729,6 +787,8 @@ xge_stop(struct ifnet *ifp, int disable) struct xge_softc *sc = ifp->if_softc; uint64_t val; + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + val = PIF_RCSR(ADAPTER_CONTROL); val &= ~ADAPTER_EN; PIF_WCSR(ADAPTER_CONTROL, val); @@ -1313,7 +1373,7 @@ xge_add_rxbuf(struct xge_softc *sc, int id) * This magic comes from the FreeBSD driver. */ int -xge_setup_xgxs(struct xge_softc *sc) +xge_setup_xgxs_xena(struct xge_softc *sc) { /* The magic numbers are described in the users guide */ @@ -1399,3 +1459,17 @@ xge_setup_xgxs(struct xge_softc *sc) #endif return (0); } + +int +xge_setup_xgxs_herc(struct xge_softc *sc) +{ + int dtx_cnt = 0; + + while (herc_dtx_cfg[dtx_cnt] != END_SIGN) { + PIF_WCSR(DTX_CONTROL, herc_dtx_cfg[dtx_cnt]); + DELAY(100); + dtx_cnt++; + } + + return (0); +} diff --git a/sys/dev/pci/if_xgereg.h b/sys/dev/pci/if_xgereg.h index fac200e6d1c..82b7e525695 100644 --- a/sys/dev/pci/if_xgereg.h +++ b/sys/dev/pci/if_xgereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_xgereg.h,v 1.1 2006/05/01 00:34:12 brad Exp $ */ +/* $OpenBSD: if_xgereg.h,v 1.2 2006/10/10 23:39:15 brad Exp $ */ /* $NetBSD: if_xgereg.h,v 1.1 2005/09/09 10:30:27 ragge Exp $ */ /* @@ -69,6 +69,7 @@ #define RMAC_LOCAL_FAULT (1ULL<<56) #define MC_DRAM_READY (1ULL<<39) #define MC_QUEUES_READY (1ULL<<38) +#define RIC_RUNNING (1ULL<<37) #define M_PLL_LOCK (1ULL<<33) #define P_PLL_LOCK (1ULL<<32) #define ADAPTER_CONTROL DCSRB(0x0110) |