diff options
author | jlemon <jlemon@FreeBSD.org> | 2001-05-17 23:50:24 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2001-05-17 23:50:24 +0000 |
commit | e208983bc11a22dabb0e35b0305e390b363b2778 (patch) | |
tree | 789accadee2f9fe1f3f8b26c0dffa9e5692bb0d9 /sys | |
parent | c88d6fada26aa2ff18660921351d7c68188efce7 (diff) | |
download | FreeBSD-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.c | 59 | ||||
-rw-r--r-- | sys/dev/fxp/if_fxpvar.h | 2 |
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) \ |