summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-05-17 23:50:24 +0000
committerjlemon <jlemon@FreeBSD.org>2001-05-17 23:50:24 +0000
commite208983bc11a22dabb0e35b0305e390b363b2778 (patch)
tree789accadee2f9fe1f3f8b26c0dffa9e5692bb0d9 /sys
parentc88d6fada26aa2ff18660921351d7c68188efce7 (diff)
downloadFreeBSD-src-e208983bc11a22dabb0e35b0305e390b363b2778.zip
FreeBSD-src-e208983bc11a22dabb0e35b0305e390b363b2778.tar.gz
Add workaround for embedded NICs, in particular, the 815E boards.
There appears to be a bug where the chip will lock up when running in 10Mb/s mode.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/fxp/if_fxp.c59
-rw-r--r--sys/dev/fxp/if_fxpvar.h2
2 files changed, 44 insertions, 17 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 34fef8d..5af7911 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -199,6 +199,7 @@ static void fxp_miibus_writereg(device_t dev, int phy, int reg,
static __inline void fxp_lwcopy(volatile u_int32_t *src,
volatile u_int32_t *dst);
static __inline void fxp_scb_wait(struct fxp_softc *sc);
+static __inline void fxp_scb_cmd(struct fxp_softc *sc, int cmd);
static __inline void fxp_dma_wait(volatile u_int16_t *status,
struct fxp_softc *sc);
@@ -267,6 +268,17 @@ fxp_scb_wait(struct fxp_softc *sc)
}
static __inline void
+fxp_scb_cmd(struct fxp_softc *sc, int cmd)
+{
+
+ if (cmd == FXP_SCB_COMMAND_CU_RESUME && sc->cu_resume_bug) {
+ CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_CB_COMMAND_NOP);
+ fxp_scb_wait(sc);
+ }
+ CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, cmd);
+}
+
+static __inline void
fxp_dma_wait(volatile u_int16_t *status, struct fxp_softc *sc)
{
int i = 10000;
@@ -459,6 +471,13 @@ fxp_attach(device_t dev)
sc->chip = FXP_CHIP_82557;
/*
+ * Enable workarounds for certain chip revision deficiencies.
+ */
+ i = pci_get_device(dev);
+ if (i == 0x2449 || (i > 0x1030 && i < 0x1039))
+ sc->flags |= FXP_FLAG_CU_RESUME_BUG;
+
+ /*
* If we are not a 82557 chip, we can enable extended features.
*/
if (sc->chip != FXP_CHIP_82557) {
@@ -485,9 +504,10 @@ fxp_attach(device_t dev)
sc->arpcom.ac_enaddr, ":",
sc->flags & FXP_FLAG_SERIAL_MEDIA ? ", 10Mbps" : "");
if (bootverbose) {
- device_printf(dev, "PCI IDs: %04x %04x %04x %04x\n",
+ device_printf(dev, "PCI IDs: %04x %04x %04x %04x %04x\n",
pci_get_vendor(dev), pci_get_device(dev),
- pci_get_subvendor(dev), pci_get_subdevice(dev));
+ pci_get_subvendor(dev), pci_get_subdevice(dev),
+ pci_get_revid(dev));
device_printf(dev, "Chip Type: %d\n", sc->chip);
}
@@ -594,6 +614,9 @@ fxp_detach(device_t dev)
struct fxp_softc *sc = device_get_softc(dev);
int s;
+ /* disable interrupts */
+ CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
+
s = splimp();
/*
@@ -968,7 +991,7 @@ tbdinit:
*/
if (txp != NULL) {
fxp_scb_wait(sc);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
}
}
@@ -982,7 +1005,6 @@ fxp_intr(void *xsc)
struct ifnet *ifp = &sc->sc_if;
u_int8_t statack;
-
if (sc->suspended) {
return;
}
@@ -1096,8 +1118,7 @@ rcvloop:
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL,
vtophys(sc->rfa_headm->m_ext.ext_buf) +
RFA_ALIGNMENT_FUDGE);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND,
- FXP_SCB_COMMAND_RU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
}
}
}
@@ -1188,8 +1209,7 @@ fxp_tick(void *xsc)
/*
* Start another stats dump.
*/
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND,
- FXP_SCB_COMMAND_CU_DUMPRESET);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMPRESET);
} else {
/*
* A previous command is still waiting to be accepted.
@@ -1315,17 +1335,17 @@ fxp_init(void *xsc)
* sets it up for regular linear addressing.
*/
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_BASE);
fxp_scb_wait(sc);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_BASE);
/*
* Initialize base of dump-stats buffer.
*/
fxp_scb_wait(sc);
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(sc->fxp_stats));
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_DUMP_ADR);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_DUMP_ADR);
/*
* We temporarily use memory that contains the TxCB list to
@@ -1434,7 +1454,7 @@ fxp_init(void *xsc)
*/
fxp_scb_wait(sc);
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status));
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
/* ...and wait for it to complete. */
fxp_dma_wait(&cbp->cb_status, sc);
@@ -1454,7 +1474,7 @@ fxp_init(void *xsc)
* Start the IAS (Individual Address Setup) command/DMA.
*/
fxp_scb_wait(sc);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
/* ...and wait for it to complete. */
fxp_dma_wait(&cb_ias->cb_status, sc);
@@ -1484,7 +1504,7 @@ fxp_init(void *xsc)
sc->tx_queued = 1;
fxp_scb_wait(sc);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
/*
* Initialize receiver buffer area - RFA.
@@ -1492,7 +1512,7 @@ fxp_init(void *xsc)
fxp_scb_wait(sc);
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL,
vtophys(sc->rfa_headm->m_ext.ext_buf) + RFA_ALIGNMENT_FUDGE);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_RU_START);
/*
* Set current media.
@@ -1556,6 +1576,11 @@ fxp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
+
+ if (ifmr->ifm_status & IFM_10_T && sc->flags & FXP_FLAG_CU_RESUME_BUG)
+ sc->cu_resume_bug = 1;
+ else
+ sc->cu_resume_bug = 0;
}
/*
@@ -1811,7 +1836,7 @@ fxp_mc_setup(struct fxp_softc *sc)
* Issue a resume in case the CU has just suspended.
*/
fxp_scb_wait(sc);
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
/*
* Set a 5 second timer just in case we don't hear from the
* card again.
@@ -1874,7 +1899,7 @@ fxp_mc_setup(struct fxp_softc *sc)
*/
fxp_scb_wait(sc);
CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&mcsp->cb_status));
- CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
ifp->if_timer = 2;
return;
diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h
index d993888..b2a27a9 100644
--- a/sys/dev/fxp/if_fxpvar.h
+++ b/sys/dev/fxp/if_fxpvar.h
@@ -113,6 +113,7 @@ struct fxp_softc {
device_t dev;
int eeprom_size; /* size of serial EEPROM */
int suspended; /* 0 = normal 1 = suspended (APM) */
+ int cu_resume_bug;
int chip;
int flags;
u_int32_t saved_maps[5]; /* pci data */
@@ -131,6 +132,7 @@ struct fxp_softc {
#define FXP_FLAG_SERIAL_MEDIA 0x0010 /* 10Mbps serial interface */
#define FXP_FLAG_LONG_PKT_EN 0x0020 /* enable long packet reception */
#define FXP_FLAG_ALL_MCAST 0x0040 /* accept all multicast frames */
+#define FXP_FLAG_CU_RESUME_BUG 0x0080 /* requires workaround for CU_RESUME */
/* Macros to ease CSR access. */
#define CSR_READ_1(sc, reg) \
OpenPOWER on IntegriCloud