diff options
Diffstat (limited to 'sys/dev/sf/if_sf.c')
-rw-r--r-- | sys/dev/sf/if_sf.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c index d0fb709..5af924b 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); |