aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/sf/if_sf.c
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1999-12-05 20:02:45 +0000
committerBill Paul <wpaul@FreeBSD.org>1999-12-05 20:02:45 +0000
commitd25bb2d0263f88f63009e741a5408f82b3d67c6a (patch)
tree5ec526a949567d33d224fdec68836ef0258f43bb /sys/dev/sf/if_sf.c
parent46db6cf83bce6b8db17b545c02fa247190c1cea2 (diff)
downloadsrc-d25bb2d0263f88f63009e741a5408f82b3d67c6a.tar.gz
src-d25bb2d0263f88f63009e741a5408f82b3d67c6a.zip
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).
Notes
Notes: svn path=/head/; revision=54161
Diffstat (limited to 'sys/dev/sf/if_sf.c')
-rw-r--r--sys/dev/sf/if_sf.c48
1 files changed, 37 insertions, 11 deletions
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c
index d0fb709c830d..5af924b0658d 100644
--- a/sys/dev/sf/if_sf.c
+++ b/sys/dev/sf/if_sf.c
@@ -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);