diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 34fef8d67a4..5af791193b9 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); @@ -266,6 +267,17 @@ fxp_scb_wait(struct fxp_softc *sc) CSR_READ_2(sc, FXP_CSR_FLOWCONTROL)); } +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) { @@ -458,6 +470,13 @@ fxp_attach(device_t dev) if ((data >> 8) == 1) 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. */ @@ -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 d9938886f0a..b2a27a9e70a 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) \