diff options
-rw-r--r-- | sys/dev/ic/dc.c | 256 | ||||
-rw-r--r-- | sys/dev/ic/dcreg.h | 3 |
2 files changed, 111 insertions, 148 deletions
diff --git a/sys/dev/ic/dc.c b/sys/dev/ic/dc.c index d441e2a7b29..32d81e7244f 100644 --- a/sys/dev/ic/dc.c +++ b/sys/dev/ic/dc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dc.c,v 1.128 2013/11/20 08:36:36 mpi Exp $ */ +/* $OpenBSD: dc.c,v 1.129 2013/12/02 23:40:41 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -887,16 +887,14 @@ dc_crc_le(struct dc_softc *sc, caddr_t addr) void dc_setfilt_21143(struct dc_softc *sc) { - struct dc_desc *sframe; - u_int32_t h, *sp; struct arpcom *ac = &sc->sc_arpcom; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct ether_multi *enm; struct ether_multistep step; - struct ifnet *ifp; + struct dc_desc *sframe; + u_int32_t h, *sp; int i; - ifp = &sc->sc_arpcom.ac_if; - i = sc->dc_cdata.dc_tx_prod; DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT); sc->dc_cdata.dc_tx_cnt++; @@ -912,32 +910,31 @@ dc_setfilt_21143(struct dc_softc *sc) sc->dc_cdata.dc_tx_chain[i].sd_mbuf = (struct mbuf *)&sc->dc_ldata->dc_sbuf[0]; - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC)); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ac->ac_multirangecnt > 0) + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; - - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - + if (ifp->if_flags & IFF_PROMISC) + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + else + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + } else { ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { h = dc_crc_le(sc, enm->enm_addrlo); + sp[h >> 4] |= htole32(1 << (h & 0xF)); + ETHER_NEXT_MULTI(step, enm); } } - if (ifp->if_flags & IFF_BROADCAST) { - h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); - sp[h >> 4] |= htole32(1 << (h & 0xF)); - } + /* + * Always accept broadcast frames. + */ + h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); + sp[h >> 4] |= htole32(1 << (h & 0xF)); /* Set our MAC address */ sp[39] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 0); @@ -972,59 +969,46 @@ dc_setfilt_21143(struct dc_softc *sc) void dc_setfilt_admtek(struct dc_softc *sc) { - struct ifnet *ifp; struct arpcom *ac = &sc->sc_arpcom; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct ether_multi *enm; struct ether_multistep step; + u_int32_t hashes[2]; int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - - ifp = &sc->sc_arpcom.ac_if; - - /* Init our MAC address */ - CSR_WRITE_4(sc, DC_AL_PAR0, ac->ac_enaddr[3] << 24 | - ac->ac_enaddr[2] << 16 | ac->ac_enaddr[1] << 8 | ac->ac_enaddr[0]); - CSR_WRITE_4(sc, DC_AL_PAR1, ac->ac_enaddr[5] << 8 | ac->ac_enaddr[4]); - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC)); + bzero(hashes, sizeof(hashes)); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ac->ac_multirangecnt > 0) + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + else + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + } else { + /* now program new ones */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + if (DC_IS_CENTAUR(sc)) + h = dc_crc_le(sc, enm->enm_addrlo); + else + h = dc_crc_be(enm->enm_addrlo); - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - - /* first, zot all the existing hash bits */ - CSR_WRITE_4(sc, DC_AL_MAR0, 0); - CSR_WRITE_4(sc, DC_AL_MAR1, 0); - - /* - * If we're already in promisc or allmulti mode, we - * don't have to bother programming the multicast filter. - */ - if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) - return; + if (h < 32) + hashes[0] |= (1 << h); + else + hashes[1] |= (1 << (h - 32)); - /* now program new ones */ - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - if (DC_IS_CENTAUR(sc)) - h = dc_crc_le(sc, enm->enm_addrlo); - else - h = dc_crc_be(enm->enm_addrlo); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - ETHER_NEXT_MULTI(step, enm); + ETHER_NEXT_MULTI(step, enm); + } } + /* Init our MAC address */ + CSR_WRITE_4(sc, DC_AL_PAR0, ac->ac_enaddr[3] << 24 | + ac->ac_enaddr[2] << 16 | ac->ac_enaddr[1] << 8 | ac->ac_enaddr[0]); + CSR_WRITE_4(sc, DC_AL_PAR1, ac->ac_enaddr[5] << 8 | ac->ac_enaddr[4]); + CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]); CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]); } @@ -1032,14 +1016,43 @@ dc_setfilt_admtek(struct dc_softc *sc) void dc_setfilt_asix(struct dc_softc *sc) { - struct ifnet *ifp; struct arpcom *ac = &sc->sc_arpcom; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct ether_multi *enm; struct ether_multistep step; + u_int32_t hashes[2]; int h = 0; - u_int32_t hashes[2] = { 0, 0 }; - ifp = &sc->sc_arpcom.ac_if; + DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_AX_NETCFG_RX_BROAD | + DC_NETCFG_RX_PROMISC)); + bzero(hashes, sizeof(hashes)); + ifp->if_flags &= ~IFF_ALLMULTI; + + /* + * Always accept broadcast frames. + */ + DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); + + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + else + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + } else { + /* now program new ones */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + h = dc_crc_be(enm->enm_addrlo); + + if (h < 32) + hashes[0] |= (1 << h); + else + hashes[1] |= (1 << (h - 32)); + + ETHER_NEXT_MULTI(step, enm); + } + } /* Init our MAC address */ CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0); @@ -1049,50 +1062,6 @@ dc_setfilt_asix(struct dc_softc *sc) CSR_WRITE_4(sc, DC_AX_FILTDATA, *(u_int32_t *)(&sc->sc_arpcom.ac_enaddr[4])); - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - - /* - * The ASIX chip has a special bit to enable reception - * of broadcast frames. - */ - if (ifp->if_flags & IFF_BROADCAST) - DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); - else - DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD); - - /* first, zot all the existing hash bits */ - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); - CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); - CSR_WRITE_4(sc, DC_AX_FILTDATA, 0); - - /* - * If we're already in promisc or allmulti mode, we - * don't have to bother programming the multicast filter. - */ - if (ifp->if_flags & (IFF_PROMISC|IFF_ALLMULTI)) - return; - - /* now program new ones */ - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - h = dc_crc_be(enm->enm_addrlo); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - ETHER_NEXT_MULTI(step, enm); - } - CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0); CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]); CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1); @@ -1102,15 +1071,14 @@ dc_setfilt_asix(struct dc_softc *sc) void dc_setfilt_xircom(struct dc_softc *sc) { - struct dc_desc *sframe; struct arpcom *ac = &sc->sc_arpcom; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct ether_multi *enm; struct ether_multistep step; + struct dc_desc *sframe; u_int32_t h, *sp; - struct ifnet *ifp; int i; - ifp = &sc->sc_arpcom.ac_if; DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON|DC_NETCFG_RX_ON)); i = sc->dc_cdata.dc_tx_prod; @@ -1128,30 +1096,33 @@ dc_setfilt_xircom(struct dc_softc *sc) sc->dc_cdata.dc_tx_chain[i].sd_mbuf = (struct mbuf *)&sc->dc_ldata->dc_sbuf[0]; - /* If we want promiscuous mode, set the allframes bit. */ - if (ifp->if_flags & IFF_PROMISC) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ALLMULTI | DC_NETCFG_RX_PROMISC)); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ifp->if_flags & IFF_ALLMULTI) - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); - else - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC); + else + DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI); + } else { + /* now program new ones */ + ETHER_FIRST_MULTI(step, ac, enm); + while (enm != NULL) { + h = dc_crc_le(sc, enm->enm_addrlo); - /* now program new ones */ - ETHER_FIRST_MULTI(step, ac, enm); - while (enm != NULL) { - h = dc_crc_le(sc, enm->enm_addrlo); - sp[h >> 4] |= htole32(1 << (h & 0xF)); - ETHER_NEXT_MULTI(step, enm); - } + sp[h >> 4] |= htole32(1 << (h & 0xF)); - if (ifp->if_flags & IFF_BROADCAST) { - h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); - sp[h >> 4] |= htole32(1 << (h & 0xF)); + ETHER_NEXT_MULTI(step, enm); + } } + /* + * Always accept broadcast frames. + */ + h = dc_crc_le(sc, (caddr_t)ðerbroadcastaddr); + sp[h >> 4] |= htole32(1 << (h & 0xF)); + /* Set our MAC address */ sp[0] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 0); sp[1] = DC_SP_FIELD(sc->sc_arpcom.ac_enaddr, 1); @@ -2964,7 +2935,6 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) struct dc_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; struct ifaddr *ifa = (struct ifaddr *)data; - struct mii_data *mii; int s, error = 0; s = splnet(); @@ -2981,26 +2951,20 @@ dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - if (ifp->if_flags & IFF_RUNNING && - (ifp->if_flags ^ sc->dc_if_flags) & - IFF_PROMISC) { - dc_setfilt(sc); - } else { - if (!(ifp->if_flags & IFF_RUNNING)) { - sc->dc_txthresh = 0; - dc_init(sc); - } + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else { + sc->dc_txthresh = 0; + dc_init(sc); } } else { if (ifp->if_flags & IFF_RUNNING) dc_stop(sc, 0); } - sc->dc_if_flags = ifp->if_flags; break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - mii = &sc->sc_mii; - error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); + error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command); #ifdef SRM_MEDIA if (sc->dc_srm_media) sc->dc_srm_media = 0; diff --git a/sys/dev/ic/dcreg.h b/sys/dev/ic/dcreg.h index b2b999a2580..7c592463478 100644 --- a/sys/dev/ic/dcreg.h +++ b/sys/dev/ic/dcreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dcreg.h,v 1.48 2010/09/07 16:21:42 deraadt Exp $ */ +/* $OpenBSD: dcreg.h,v 1.49 2013/12/02 23:40:41 brad Exp $ */ /* * Copyright (c) 1997, 1998, 1999 @@ -730,7 +730,6 @@ struct dc_softc { int dc_romwidth; int dc_pnic_rx_bug_save; unsigned char *dc_pnic_rx_buf; - int dc_if_flags; int dc_if_media; u_int32_t dc_flags; u_int32_t dc_txthresh; |