summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-10-10 23:39:16 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-10-10 23:39:16 +0000
commit2c727643c8903b3b8cee7a5e242eae444c6e5775 (patch)
tree8631a867259474839b684b471c01877de9ab03a2 /sys/dev/pci
parent8ca93970a3617bd5afb77fde247976d0229437ea (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.c166
-rw-r--r--sys/dev/pci/if_xgereg.h3
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)