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.
This commit is contained in:
parent
120bcabcbf
commit
2e2b823898
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=76777
@ -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 @@ fxp_start(struct ifnet *ifp)
|
||||
*/
|
||||
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 @@ fxp_intr(void *xsc)
|
||||
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;
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user