The following diff rewrites parts of the code for promiscuous mode
and multicast handling for the xl(4) driver. Please test promisc
mode and multicast mode of operation with any xl(4) adapters.
Please provide a dmesg.
Index: xl.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/xl.c,v
retrieving revision 1.86
diff -u -p -r1.86 xl.c
--- xl.c 2 Jun 2009 07:55:10 -0000 1.86
+++ xl.c 23 Jun 2009 17:53:12 -0000
@@ -178,9 +178,9 @@ int xl_mii_writereg(struct xl_softc *, s
void xl_setcfg(struct xl_softc *);
void xl_setmode(struct xl_softc *, int);
-void xl_setmulti(struct xl_softc *);
-void xl_setmulti_hash(struct xl_softc *);
-void xl_setpromisc(struct xl_softc *);
+void xl_iff(struct xl_softc *);
+void xl_iff_90x(struct xl_softc *);
+void xl_iff_905b(struct xl_softc *);
void xl_reset(struct xl_softc *);
int xl_list_rx_init(struct xl_softc *);
int xl_list_tx_init(struct xl_softc *);
@@ -556,110 +556,107 @@ xl_read_eeprom(struct xl_softc *sc, cadd
return (err ? 1 : 0);
}
+void
+xl_iff(struct xl_softc *sc)
+{
+ if (sc->xl_type == XL_TYPE_905B)
+ xl_iff_905b(sc);
+ else
+ xl_iff_90x(sc);
+}
+
/*
* NICs older than the 3c905B have only one multicast option, which
* is to enable reception of all multicast frames.
*/
void
-xl_setmulti(struct xl_softc *sc)
+xl_iff_90x(struct xl_softc *sc)
{
- struct ifnet *ifp;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
struct arpcom *ac = &sc->sc_arpcom;
u_int8_t rxfilt;
- ifp = &sc->sc_arpcom.ac_if;
-
XL_SEL_WIN(5);
+
rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
+ rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI);
+ ifp->if_flags &= ~IFF_ALLMULTI;
- if (ifp->if_flags & IFF_ALLMULTI) {
- rxfilt |= XL_RXFILTER_ALLMULTI;
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
- return;
+ /*
+ * Always accept broadcast frames.
+ * Always accept frames destined to our station address.
+ */
+ rxfilt |= XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL;
+
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multicnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ if (ifp->if_flags & IFF_PROMISC)
+ rxfilt |= XL_RXFILTER_ALLFRAMES;
+ else
+ rxfilt |= XL_RXFILTER_ALLMULTI;
}
- if (ac->ac_multicnt > 0)
- rxfilt |= XL_RXFILTER_ALLMULTI;
- else
- rxfilt &= ~XL_RXFILTER_ALLMULTI;
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT | rxfilt);
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
+ XL_SEL_WIN(7);
}
/*
* 3c905B adapters have a hash filter that we can program.
*/
void
-xl_setmulti_hash(struct xl_softc *sc)
+xl_iff_905b(struct xl_softc *sc)
{
- struct ifnet *ifp;
- int h = 0, i;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
struct arpcom *ac = &sc->sc_arpcom;
+ int h = 0, i;
struct ether_multi *enm;
struct ether_multistep step;
u_int8_t rxfilt;
- int mcnt = 0;
-
- ifp = &sc->sc_arpcom.ac_if;
XL_SEL_WIN(5);
- rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
- if (ifp->if_flags & IFF_ALLMULTI) {
-allmulti:
- rxfilt |= XL_RXFILTER_ALLMULTI;
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
- return;
- } else
- rxfilt &= ~XL_RXFILTER_ALLMULTI;
-
-
- /* first, zot all the existing hash bits */
- for (i = 0; i < XL_HASHFILT_SIZE; i++)
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
+ rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
+ rxfilt &= ~(XL_RXFILTER_ALLFRAMES | XL_RXFILTER_ALLMULTI |
+ XL_RXFILTER_MULTIHASH);
+ ifp->if_flags &= ~IFF_ALLMULTI;
- /* now program new ones */
- ETHER_FIRST_MULTI(step, ac, enm);
- while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
- ifp->if_flags |= IFF_ALLMULTI;
- goto allmulti;
- }
- h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) &
- 0x000000FF;
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|XL_HASH_SET|h);
- mcnt++;
- ETHER_NEXT_MULTI(step, enm);
- }
+ /*
+ * Always accept broadcast frames.
+ * Always accept frames destined to our station address.
+ */
+ rxfilt |= XL_RXFILTER_BROADCAST | XL_RXFILTER_INDIVIDUAL;
- if (mcnt)
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ if (ifp->if_flags & IFF_PROMISC)
+ rxfilt |= XL_RXFILTER_ALLFRAMES;
+ else
+ rxfilt |= XL_RXFILTER_ALLMULTI;
+ } else {
rxfilt |= XL_RXFILTER_MULTIHASH;
- else
- rxfilt &= ~XL_RXFILTER_MULTIHASH;
-
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
-}
-void
-xl_setpromisc(struct xl_softc *sc)
-{
- struct ifnet *ifp;
- u_int8_t rxfilt;
+ /* first, zot all the existing hash bits */
+ for (i = 0; i < XL_HASHFILT_SIZE; i++)
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
- ifp = &sc->sc_arpcom.ac_if;
+ /* now program new ones */
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) &
+ 0x000000FF;
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH |
+ XL_HASH_SET | h);
- XL_SEL_WIN(5);
- rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ }
- if (ifp->if_flags & IFF_PROMISC)
- rxfilt |= XL_RXFILTER_ALLFRAMES;
- else
- rxfilt &= ~XL_RXFILTER_ALLFRAMES;
+ CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT | rxfilt);
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
+ XL_SEL_WIN(7);
}
-
#ifdef notdef
void
xl_testpacket(struct xl_softc *sc)
@@ -1936,7 +1933,6 @@ xl_init(void *xsc)
struct xl_softc *sc = xsc;
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
int s, i;
- u_int16_t rxfilt = 0;
struct mii_data *mii = NULL;
s = splnet();
@@ -2014,37 +2010,8 @@ xl_init(void *xsc)
XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4));
}
- /* Set RX filter bits. */
- XL_SEL_WIN(5);
- rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
-
- /* Set the individual bit to receive frames for this host only. */
- rxfilt |= XL_RXFILTER_INDIVIDUAL;
-
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
-
- /* Set promiscuous mode. */
- xl_setpromisc(sc);
-
- rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
-
- /*
- * Set capture broadcast bit to capture broadcast frames.
- */
- if (ifp->if_flags & IFF_BROADCAST)
- rxfilt |= XL_RXFILTER_BROADCAST;
- else
- rxfilt &= ~XL_RXFILTER_BROADCAST;
-
- CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
-
- /*
- * Program the multicast filter, if necessary.
- */
- if (sc->xl_type == XL_TYPE_905B)
- xl_setmulti_hash(sc);
- else
- xl_setmulti(sc);
+ /* Program promiscuous mode and multicast filters. */
+ xl_iff(sc);
/*
* Load the address of the RX list. We have to
@@ -2278,27 +2245,21 @@ xl_ioctl(struct ifnet *ifp, u_long comma
#ifdef INET
if (ifa->ifa_addr->sa_family == AF_INET)
arp_ifinit(&sc->sc_arpcom, ifa);
-#endif /* INET */
+#endif
break;
case SIOCSIFFLAGS:
- XL_SEL_WIN(5);
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- (ifp->if_flags ^ sc->xl_if_flags) &
- IFF_PROMISC) {
- xl_setpromisc(sc);
- XL_SEL_WIN(7);
- } else {
- if (!(ifp->if_flags & IFF_RUNNING))
- xl_init(sc);
- }
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
+ xl_init(sc);
} else {
if (ifp->if_flags & IFF_RUNNING)
xl_stop(sc);
}
- sc->xl_if_flags = ifp->if_flags;
break;
+
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
if (sc->xl_hasmii != 0)
@@ -2310,17 +2271,14 @@ xl_ioctl(struct ifnet *ifp, u_long comma
error = ifmedia_ioctl(ifp, ifr,
&mii->mii_media, command);
break;
+
default:
error = ether_ioctl(ifp, &sc->sc_arpcom, command, data);
}
if (error == ENETRESET) {
- if (ifp->if_flags & IFF_RUNNING) {
- if (sc->xl_type == XL_TYPE_905B)
- xl_setmulti_hash(sc);
- else
- xl_setmulti(sc);
- }
+ if (ifp->if_flags & IFF_RUNNING)
+ xl_iff(sc);
error = 0;
}
Index: xlreg.h
===================================================================
RCS file: /cvs/src/sys/dev/ic/xlreg.h,v
retrieving revision 1.19
diff -u -p -r1.19 xlreg.h
--- xlreg.h 30 May 2004 23:49:39 -0000 1.19
+++ xlreg.h 6 Jun 2009 11:08:50 -0000
@@ -591,7 +591,6 @@ struct xl_softc {
u_int16_t xl_caps;
u_int8_t xl_stats_no_timeout;
u_int16_t xl_tx_thresh;
- int xl_if_flags;
struct xl_list_data *xl_ldata;
struct xl_chain_data xl_cdata;
int xl_flags;
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.