summaryrefslogtreecommitdiffstats
path: root/sys/dev/fxp
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2002-01-07 15:08:54 +0000
committerjlemon <jlemon@FreeBSD.org>2002-01-07 15:08:54 +0000
commitda24d835d08fab4e11e2594a8f57dffe09390c35 (patch)
tree29db9fd5acd4410c8994e3c4f6cd7d661d64f0b4 /sys/dev/fxp
parent889a3dbc7030de5ba0090d0f89dd8ffa40b2334f (diff)
downloadFreeBSD-src-da24d835d08fab4e11e2594a8f57dffe09390c35.zip
FreeBSD-src-da24d835d08fab4e11e2594a8f57dffe09390c35.tar.gz
Explicitly reload the multicast filters when the hardware is reinitialized
instead of relying on the previous filters to be present. Back out r1.125, as a reset is needed to unload any existing microcode, (which clears the multicast addresses), as it is superceded by this change.
Diffstat (limited to 'sys/dev/fxp')
-rw-r--r--sys/dev/fxp/if_fxp.c82
1 files changed, 57 insertions, 25 deletions
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index 8cbd58b..006a2e8 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -180,6 +180,7 @@ static int fxp_ioctl(struct ifnet *ifp, u_long command,
caddr_t data);
static void fxp_watchdog(struct ifnet *ifp);
static int fxp_add_rfabuf(struct fxp_softc *sc, struct mbuf *oldm);
+static int fxp_mc_addrs(struct fxp_softc *sc);
static void fxp_mc_setup(struct fxp_softc *sc);
static u_int16_t fxp_eeprom_getword(struct fxp_softc *sc, int offset,
int autosize);
@@ -1471,7 +1472,7 @@ fxp_stop(struct fxp_softc *sc)
* Issue software reset, which also unloads the microcode.
*/
sc->flags &= ~FXP_FLAG_UCODE;
- CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
+ CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET);
DELAY(50);
/*
@@ -1532,6 +1533,7 @@ fxp_init(void *xsc)
struct fxp_cb_config *cbp;
struct fxp_cb_ias *cb_ias;
struct fxp_cb_tx *txp;
+ struct fxp_cb_mcs *mcsp;
int i, prm, s;
s = splimp();
@@ -1566,6 +1568,24 @@ fxp_init(void *xsc)
fxp_load_ucode(sc);
/*
+ * Initialize the multicast address list.
+ */
+ if (fxp_mc_addrs(sc)) {
+ mcsp = sc->mcsp;
+ mcsp->cb_status = 0;
+ mcsp->cb_command = FXP_CB_COMMAND_MCAS | FXP_CB_COMMAND_EL;
+ mcsp->link_addr = -1;
+ /*
+ * Start the multicast setup command.
+ */
+ fxp_scb_wait(sc);
+ CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&mcsp->cb_status));
+ fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
+ /* ...and wait for it to complete. */
+ fxp_dma_wait(&mcsp->cb_status, sc);
+ }
+
+ /*
* We temporarily use memory that contains the TxCB list to
* construct the config CB. The TxCB list memory is rebuilt
* later.
@@ -1995,6 +2015,41 @@ fxp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
/*
+ * Fill in the multicast address list and return number of entries.
+ */
+static int
+fxp_mc_addrs(struct fxp_softc *sc)
+{
+ struct fxp_cb_mcs *mcsp = sc->mcsp;
+ struct ifnet *ifp = &sc->sc_if;
+ struct ifmultiaddr *ifma;
+ int nmcasts;
+
+ nmcasts = 0;
+ if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
+#if __FreeBSD_version < 500000
+ LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+#else
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+#endif
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (nmcasts >= MAXMCADDR) {
+ sc->flags |= FXP_FLAG_ALL_MCAST;
+ nmcasts = 0;
+ break;
+ }
+ bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
+ (void *)(uintptr_t)(volatile void *)
+ &sc->mcsp->mc_addr[nmcasts][0], 6);
+ nmcasts++;
+ }
+ }
+ mcsp->mc_cnt = nmcasts * 6;
+ return (nmcasts);
+}
+
+/*
* Program the multicast filter.
*
* We have an artificial restriction that the multicast setup command
@@ -2013,8 +2068,6 @@ fxp_mc_setup(struct fxp_softc *sc)
{
struct fxp_cb_mcs *mcsp = sc->mcsp;
struct ifnet *ifp = &sc->sc_if;
- struct ifmultiaddr *ifma;
- int nmcasts;
int count;
/*
@@ -2074,28 +2127,7 @@ fxp_mc_setup(struct fxp_softc *sc)
mcsp->cb_command = FXP_CB_COMMAND_MCAS |
FXP_CB_COMMAND_S | FXP_CB_COMMAND_I;
mcsp->link_addr = vtophys(&sc->cbl_base->cb_status);
-
- nmcasts = 0;
- if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
-#if __FreeBSD_version < 500000
- LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#else
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-#endif
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (nmcasts >= MAXMCADDR) {
- sc->flags |= FXP_FLAG_ALL_MCAST;
- nmcasts = 0;
- break;
- }
- bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
- (void *)(uintptr_t)(volatile void *)
- &sc->mcsp->mc_addr[nmcasts][0], 6);
- nmcasts++;
- }
- }
- mcsp->mc_cnt = nmcasts * 6;
+ (void) fxp_mc_addrs(sc);
sc->cbl_first = sc->cbl_last = (struct fxp_cb_tx *) mcsp;
sc->tx_queued = 1;
OpenPOWER on IntegriCloud