Modify the Adaptec "starfire" driver to reset the PHY on the MII bus
before selecting a mode. The Seeq PHY chips on the Adaptec cards that use the AIC-6915 controller seem to need it in order to get them to change modes correctly. This corrects a problem that I noticed where my ANA-62022 board failed to correctly program the full duplex bit in the macconfig1 register when the interface was brought up. Running ifconfig sf0 would mask this problem in some cases because polling the PHY status would cause the miibus code to notice that full duplex was now needed and the statchg callback would be invoked to configure the duplex setting. However it would still get it wrong other times. Also changed sf_miibus_statchg() to program the IPG register to match the duplex setting in accordance with Adaptec manual's recommendations (0x15 for full duplex, 0x11 for half duplex).
This commit is contained in:
parent
1dab24f283
commit
c32cda93bb
@ -415,8 +415,10 @@ static void sf_miibus_statchg(dev)
|
||||
|
||||
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_FDX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_HDX);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -487,6 +489,13 @@ static int sf_ifmedia_upd(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
sc->sf_link = 0;
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list))
|
||||
mii_phy_reset(miisc);
|
||||
}
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
@ -532,11 +541,21 @@ static int sf_ioctl(ifp, command, data)
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
sf_init(sc);
|
||||
if (ifp->if_flags & IFF_RUNNING &&
|
||||
ifp->if_flags & IFF_PROMISC &&
|
||||
!(sc->sf_if_flags & IFF_PROMISC)) {
|
||||
SF_SETBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
|
||||
} else if (ifp->if_flags & IFF_RUNNING &&
|
||||
!(ifp->if_flags & IFF_PROMISC) &&
|
||||
sc->sf_if_flags & IFF_PROMISC) {
|
||||
SF_CLRBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
|
||||
} else if (!(ifp->if_flags & IFF_RUNNING))
|
||||
sf_init(sc);
|
||||
} else {
|
||||
if (ifp->if_flags & IFF_RUNNING)
|
||||
sf_stop(sc);
|
||||
}
|
||||
sc->sf_if_flags = ifp->if_flags;
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
@ -785,7 +804,7 @@ static int sf_attach(dev)
|
||||
if (mii_phy_probe(dev, &sc->sf_miibus,
|
||||
sf_ifmedia_upd, sf_ifmedia_sts)) {
|
||||
printf("sf%d: MII without any phy!\n", sc->sf_unit);
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
contigfree(sc->sf_ldata,sizeof(struct sf_list_data),M_DEVBUF);
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
@ -842,7 +861,7 @@ static int sf_detach(dev)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF);
|
||||
|
||||
splx(s);
|
||||
|
||||
@ -1209,13 +1228,6 @@ static void sf_init(xsc)
|
||||
/* Enable autopadding of short TX frames. */
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
|
||||
|
||||
/* Make sure the duplex mode is set correctly. */
|
||||
if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
/* Enable interrupts. */
|
||||
csr_write_4(sc, SF_IMR, SF_INTRS);
|
||||
SF_SETBIT(sc, SF_PCI_DEVCFG, SF_PCIDEVCFG_INTR_ENB);
|
||||
@ -1224,7 +1236,8 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB);
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
|
||||
|
||||
mii_mediachg(mii);
|
||||
/*mii_mediachg(mii);*/
|
||||
sf_ifmedia_upd(ifp);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
@ -1309,6 +1322,9 @@ static void sf_start(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
if (!sc->sf_link)
|
||||
return;
|
||||
|
||||
if (ifp->if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
@ -1370,6 +1386,8 @@ static void sf_stop(sc)
|
||||
csr_write_4(sc, SF_TXDQ_CTL, 0);
|
||||
sf_reset(sc);
|
||||
|
||||
sc->sf_link = 0;
|
||||
|
||||
for (i = 0; i < SF_RX_DLIST_CNT; i++) {
|
||||
if (sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf != NULL) {
|
||||
m_freem(sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf);
|
||||
@ -1425,6 +1443,14 @@ static void sf_stats_update(xsc)
|
||||
stats.sf_tx_multi_colls + stats.sf_tx_excess_colls;
|
||||
|
||||
mii_tick(mii);
|
||||
if (!sc->sf_link) {
|
||||
mii_pollstat(mii);
|
||||
if (mii->mii_media_status & IFM_ACTIVE &&
|
||||
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
|
||||
sc->sf_link++;
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
sf_start(ifp);
|
||||
}
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
|
@ -612,6 +612,14 @@
|
||||
#define SF_MACCFG1_MIILOOPBK 0x00004000
|
||||
#define SF_MACCFG1_SOFTRESET 0x00008000
|
||||
|
||||
/*
|
||||
* There are the recommended IPG nibble counter settings
|
||||
* specified in the Adaptec manual for full duplex and
|
||||
* half duplex operation.
|
||||
*/
|
||||
#define SF_IPGT_FDX 0x15
|
||||
#define SF_IPGT_HDX 0x11
|
||||
|
||||
/*
|
||||
* RX filter registers 0x6000 to 0x6FFF
|
||||
*/
|
||||
@ -1033,6 +1041,8 @@ struct sf_softc {
|
||||
u_int8_t sf_unit; /* interface number */
|
||||
struct sf_list_data *sf_ldata;
|
||||
int sf_tx_cnt;
|
||||
u_int8_t sf_link;
|
||||
int sf_if_flags;
|
||||
struct callout_handle sf_stat_ch;
|
||||
};
|
||||
|
||||
|
@ -415,8 +415,10 @@ static void sf_miibus_statchg(dev)
|
||||
|
||||
if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_FDX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
csr_write_4(sc, SF_BKTOBKIPG, SF_IPGT_HDX);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -487,6 +489,13 @@ static int sf_ifmedia_upd(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->sf_miibus);
|
||||
sc->sf_link = 0;
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list))
|
||||
mii_phy_reset(miisc);
|
||||
}
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
@ -532,11 +541,21 @@ static int sf_ioctl(ifp, command, data)
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
sf_init(sc);
|
||||
if (ifp->if_flags & IFF_RUNNING &&
|
||||
ifp->if_flags & IFF_PROMISC &&
|
||||
!(sc->sf_if_flags & IFF_PROMISC)) {
|
||||
SF_SETBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
|
||||
} else if (ifp->if_flags & IFF_RUNNING &&
|
||||
!(ifp->if_flags & IFF_PROMISC) &&
|
||||
sc->sf_if_flags & IFF_PROMISC) {
|
||||
SF_CLRBIT(sc, SF_RXFILT, SF_RXFILT_PROMISC);
|
||||
} else if (!(ifp->if_flags & IFF_RUNNING))
|
||||
sf_init(sc);
|
||||
} else {
|
||||
if (ifp->if_flags & IFF_RUNNING)
|
||||
sf_stop(sc);
|
||||
}
|
||||
sc->sf_if_flags = ifp->if_flags;
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
@ -785,7 +804,7 @@ static int sf_attach(dev)
|
||||
if (mii_phy_probe(dev, &sc->sf_miibus,
|
||||
sf_ifmedia_upd, sf_ifmedia_sts)) {
|
||||
printf("sf%d: MII without any phy!\n", sc->sf_unit);
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
contigfree(sc->sf_ldata,sizeof(struct sf_list_data),M_DEVBUF);
|
||||
bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
@ -842,7 +861,7 @@ static int sf_detach(dev)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq);
|
||||
bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res);
|
||||
|
||||
free(sc->sf_ldata, M_DEVBUF);
|
||||
contigfree(sc->sf_ldata, sizeof(struct sf_list_data), M_DEVBUF);
|
||||
|
||||
splx(s);
|
||||
|
||||
@ -1209,13 +1228,6 @@ static void sf_init(xsc)
|
||||
/* Enable autopadding of short TX frames. */
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
|
||||
|
||||
/* Make sure the duplex mode is set correctly. */
|
||||
if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
} else {
|
||||
SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX);
|
||||
}
|
||||
|
||||
/* Enable interrupts. */
|
||||
csr_write_4(sc, SF_IMR, SF_INTRS);
|
||||
SF_SETBIT(sc, SF_PCI_DEVCFG, SF_PCIDEVCFG_INTR_ENB);
|
||||
@ -1224,7 +1236,8 @@ static void sf_init(xsc)
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB);
|
||||
SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB);
|
||||
|
||||
mii_mediachg(mii);
|
||||
/*mii_mediachg(mii);*/
|
||||
sf_ifmedia_upd(ifp);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
@ -1309,6 +1322,9 @@ static void sf_start(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
if (!sc->sf_link)
|
||||
return;
|
||||
|
||||
if (ifp->if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
@ -1370,6 +1386,8 @@ static void sf_stop(sc)
|
||||
csr_write_4(sc, SF_TXDQ_CTL, 0);
|
||||
sf_reset(sc);
|
||||
|
||||
sc->sf_link = 0;
|
||||
|
||||
for (i = 0; i < SF_RX_DLIST_CNT; i++) {
|
||||
if (sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf != NULL) {
|
||||
m_freem(sc->sf_ldata->sf_rx_dlist_big[i].sf_mbuf);
|
||||
@ -1425,6 +1443,14 @@ static void sf_stats_update(xsc)
|
||||
stats.sf_tx_multi_colls + stats.sf_tx_excess_colls;
|
||||
|
||||
mii_tick(mii);
|
||||
if (!sc->sf_link) {
|
||||
mii_pollstat(mii);
|
||||
if (mii->mii_media_status & IFM_ACTIVE &&
|
||||
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
|
||||
sc->sf_link++;
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
sf_start(ifp);
|
||||
}
|
||||
|
||||
sc->sf_stat_ch = timeout(sf_stats_update, sc, hz);
|
||||
|
||||
|
@ -612,6 +612,14 @@
|
||||
#define SF_MACCFG1_MIILOOPBK 0x00004000
|
||||
#define SF_MACCFG1_SOFTRESET 0x00008000
|
||||
|
||||
/*
|
||||
* There are the recommended IPG nibble counter settings
|
||||
* specified in the Adaptec manual for full duplex and
|
||||
* half duplex operation.
|
||||
*/
|
||||
#define SF_IPGT_FDX 0x15
|
||||
#define SF_IPGT_HDX 0x11
|
||||
|
||||
/*
|
||||
* RX filter registers 0x6000 to 0x6FFF
|
||||
*/
|
||||
@ -1033,6 +1041,8 @@ struct sf_softc {
|
||||
u_int8_t sf_unit; /* interface number */
|
||||
struct sf_list_data *sf_ldata;
|
||||
int sf_tx_cnt;
|
||||
u_int8_t sf_link;
|
||||
int sf_if_flags;
|
||||
struct callout_handle sf_stat_ch;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user