From f51370fc86258c3833f6802d2f6a9b299b6b75f5 Mon Sep 17 00:00:00 2001 From: Aaron Campbell Date: Wed, 8 Dec 1999 00:25:55 +0000 Subject: Sync with FreeBSD: - Reset the PHY before selecting a mode. - Program IPG register to match duplex setting in accordance with Adaptec manual recommendations. --- sys/dev/pci/if_sf.c | 45 +++++++++++++++++++++++++++++++++++---------- sys/dev/pci/if_sfreg.h | 10 ++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) (limited to 'sys/dev') diff --git a/sys/dev/pci/if_sf.c b/sys/dev/pci/if_sf.c index e3417d2d43a..56892f8300f 100644 --- a/sys/dev/pci/if_sf.c +++ b/sys/dev/pci/if_sf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sf.c,v 1.1 1999/11/03 02:45:08 aaron Exp $ */ +/* $OpenBSD: if_sf.c,v 1.2 1999/12/08 00:25:54 aaron Exp $ */ /* * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. @@ -372,8 +372,10 @@ void sf_miibus_statchg(self) 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; @@ -443,6 +445,13 @@ int sf_ifmedia_upd(ifp) sc = ifp->if_softc; mii = &sc->sc_mii; + 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); @@ -501,11 +510,21 @@ 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: @@ -1107,13 +1126,6 @@ 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); @@ -1122,7 +1134,7 @@ 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); + sf_ifmedia_upd(ifp); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -1207,6 +1219,9 @@ void sf_start(ifp) sc = ifp->if_softc; + if (!sc->sf_link) + return; + if (ifp->if_flags & IFF_OACTIVE) return; @@ -1270,6 +1285,8 @@ 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); @@ -1325,6 +1342,14 @@ 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); + } timeout(sf_stats_update, sc, hz); diff --git a/sys/dev/pci/if_sfreg.h b/sys/dev/pci/if_sfreg.h index b76206cf321..9736dfd456a 100644 --- a/sys/dev/pci/if_sfreg.h +++ b/sys/dev/pci/if_sfreg.h @@ -609,6 +609,14 @@ #define SF_MACCFG1_MIILOOPBK 0x00004000 #define SF_MACCFG1_SOFTRESET 0x00008000 +/* + * These 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 */ @@ -1038,6 +1046,8 @@ struct sf_softc { struct sf_list_data *sf_ldata; caddr_t sf_ldata_ptr; int sf_tx_cnt; + u_int8_t sf_link; + int sf_if_flags; }; #define SF_TIMEOUT 1000 -- cgit v1.2.3