summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/dc.c256
-rw-r--r--sys/dev/ic/dcreg.h3
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)&etherbroadcastaddr);
- sp[h >> 4] |= htole32(1 << (h & 0xF));
- }
+ /*
+ * Always accept broadcast frames.
+ */
+ h = dc_crc_le(sc, (caddr_t)&etherbroadcastaddr);
+ 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)&etherbroadcastaddr);
- sp[h >> 4] |= htole32(1 << (h & 0xF));
+ ETHER_NEXT_MULTI(step, enm);
+ }
}
+ /*
+ * Always accept broadcast frames.
+ */
+ h = dc_crc_le(sc, (caddr_t)&etherbroadcastaddr);
+ 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;