summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2014-01-31 06:05:41 +0000
committerBrad Smith <brad@cvs.openbsd.org>2014-01-31 06:05:41 +0000
commit37176aef8ce58596ad32e36f75fd05a2c6565e38 (patch)
treebfa1c8601aab7fa7e3c0f7bae83b8c8ed0198a09 /sys
parentff29ab6a842ead3cd1fc758b8876fd36391089c1 (diff)
Rewrite the receive filter handling code, reinstate the hash filter and cleanup
the ioctl bits. Tested by brad@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_tl.c109
-rw-r--r--sys/dev/pci/if_tlreg.h3
2 files changed, 40 insertions, 72 deletions
diff --git a/sys/dev/pci/if_tl.c b/sys/dev/pci/if_tl.c
index 367112c0d88..7148fb2b7e4 100644
--- a/sys/dev/pci/if_tl.c
+++ b/sys/dev/pci/if_tl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tl.c,v 1.57 2013/11/26 09:50:33 mpi Exp $ */
+/* $OpenBSD: if_tl.c,v 1.58 2014/01/31 06:05:40 brad Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -277,10 +277,8 @@ void tl_miibus_writereg(struct device *, int, int, int);
void tl_miibus_statchg(struct device *);
void tl_setmode(struct tl_softc *, int);
-#if 0
int tl_calchash(caddr_t);
-#endif
-void tl_setmulti(struct tl_softc *);
+void tl_iff(struct tl_softc *);
void tl_setfilt(struct tl_softc *, caddr_t, int);
void tl_softreset(struct tl_softc *, int);
void tl_hardreset(struct device *);
@@ -744,7 +742,6 @@ tl_setmode(struct tl_softc *sc, int media)
}
}
-#if 0
/*
* Calculate the hash of a MAC address for programming the multicast hash
* table. This hash is simply the address split into 6-bit chunks
@@ -763,7 +760,6 @@ tl_calchash(caddr_t addr)
(addr[2] ^ addr[5]);
return ((t >> 18) ^ (t >> 12) ^ (t >> 6) ^ t) & 0x3f;
}
-#endif
/*
* The ThunderLAN has a perfect MAC address filter in addition to
@@ -801,36 +797,41 @@ tl_setfilt(struct tl_softc *sc, caddr_t addr, int slot)
* update the multicast filter.
*/
void
-tl_setmulti(struct tl_softc *sc)
+tl_iff(struct tl_softc *sc)
{
- struct ifnet *ifp;
- u_int32_t hashes[2] = { 0, 0 };
- int h;
- struct arpcom *ac = &sc->arpcom;
+ struct ifnet *ifp = &sc->arpcom.ac_if;
+ struct arpcom *ac = &sc->arpcom;
struct ether_multistep step;
struct ether_multi *enm;
- ifp = &sc->arpcom.ac_if;
-
- tl_dio_write32(sc, TL_HASH1, 0);
- tl_dio_write32(sc, TL_HASH2, 0);
+ u_int32_t hashes[2];
+ int h = 0;
+ tl_dio_clrbit(sc, TL_NETCMD, (TL_CMD_CAF | TL_CMD_NOBRX));
+ bzero(hashes, sizeof(hashes));
ifp->if_flags &= ~IFF_ALLMULTI;
- ETHER_FIRST_MULTI(step, ac, enm);
- h = 0;
- while (enm != NULL) {
- h++;
- ETHER_NEXT_MULTI(step, enm);
- }
- if (h) {
- hashes[0] = hashes[1] = 0xffffffff;
+
+ if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
ifp->if_flags |= IFF_ALLMULTI;
- } else
- hashes[0] = hashes[1] = 0x00000000;
+ if (ifp->if_flags & IFF_PROMISC)
+ tl_dio_setbit(sc, TL_NETCMD, TL_CMD_CAF);
+ else
+ hashes[0] = hashes[1] = 0xffffffff;
+ } else {
+ ETHER_FIRST_MULTI(step, ac, enm);
+ while (enm != NULL) {
+ h = tl_calchash(enm->enm_addrlo);
+
+ if (h < 32)
+ hashes[0] |= (1 << h);
+ else
+ hashes[1] |= (1 << (h - 32));
+
+ ETHER_NEXT_MULTI(step, enm);
+ }
+ }
tl_dio_write32(sc, TL_HASH1, hashes[0]);
tl_dio_write32(sc, TL_HASH2, hashes[1]);
-
- return;
}
/*
@@ -1569,29 +1570,13 @@ tl_init(void *xsc)
/* Set PCI burst size */
tl_dio_write8(sc, TL_BSIZEREG, TL_RXBURST_16LONG|TL_TXBURST_16LONG);
- /*
- * Set 'capture all frames' bit for promiscuous mode.
- */
- if (ifp->if_flags & IFF_PROMISC)
- tl_dio_setbit(sc, TL_NETCMD, TL_CMD_CAF);
- else
- tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_CAF);
-
- /*
- * Set capture broadcast bit to capture broadcast frames.
- */
- if (ifp->if_flags & IFF_BROADCAST)
- tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_NOBRX);
- else
- tl_dio_setbit(sc, TL_NETCMD, TL_CMD_NOBRX);
-
tl_dio_write16(sc, TL_MAXRX, MCLBYTES);
/* Init our MAC address */
tl_setfilt(sc, (caddr_t)&sc->arpcom.ac_enaddr, 0);
- /* Init multicast filter, if needed. */
- tl_setmulti(sc);
+ /* Program promiscuous mode and multicast filters. */
+ tl_iff(sc);
/* Init circular RX list. */
if (tl_list_rx_init(sc) == ENOBUFS) {
@@ -1688,40 +1673,24 @@ tl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch(command) {
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
+ if (!(ifp->if_flags & IFF_RUNNING))
tl_init(sc);
+#ifdef INET
+ if (ifa->ifa_addr->sa_family == AF_INET)
arp_ifinit(&sc->arpcom, ifa);
- break;
-#endif /* INET */
- default:
- tl_init(sc);
- break;
- }
+#endif
break;
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_flags & IFF_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->tl_if_flags & IFF_PROMISC)) {
- tl_dio_setbit(sc, TL_NETCMD, TL_CMD_CAF);
- tl_setmulti(sc);
- } else if (ifp->if_flags & IFF_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->tl_if_flags & IFF_PROMISC) {
- tl_dio_clrbit(sc, TL_NETCMD, TL_CMD_CAF);
- tl_setmulti(sc);
- } else
+ if (ifp->if_flags & IFF_RUNNING)
+ error = ENETRESET;
+ else
tl_init(sc);
} else {
- if (ifp->if_flags & IFF_RUNNING) {
+ if (ifp->if_flags & IFF_RUNNING)
tl_stop(sc);
- }
}
- sc->tl_if_flags = ifp->if_flags;
- error = 0;
break;
case SIOCSIFMEDIA:
@@ -1739,7 +1708,7 @@ tl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if (error == ENETRESET) {
if (ifp->if_flags & IFF_RUNNING)
- tl_setmulti(sc);
+ tl_iff(sc);
error = 0;
}
diff --git a/sys/dev/pci/if_tlreg.h b/sys/dev/pci/if_tlreg.h
index 7765a284a88..6e577203d4c 100644
--- a/sys/dev/pci/if_tlreg.h
+++ b/sys/dev/pci/if_tlreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tlreg.h,v 1.9 2005/12/17 07:31:27 miod Exp $ */
+/* $OpenBSD: if_tlreg.h,v 1.10 2014/01/31 06:05:40 brad Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -127,7 +127,6 @@ struct tl_softc {
bus_dma_tag_t sc_dmat;
struct tl_type *tl_dinfo; /* ThunderLAN adapter info */
struct tl_type *tl_pinfo; /* PHY info struct */
- int tl_if_flags;
u_int8_t tl_ctlr; /* chip number */
u_int8_t tl_eeaddr;
struct tl_list_data *tl_ldata; /* TX/RX lists and mbufs */