Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 May 2011 11:07:30 GMT
From:      cumay <164837122@qq.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   i386/157378: fxp.ich.patch
Message-ID:  <201105281107.p4SB7U7D012249@red.freebsd.org>
Resent-Message-ID: <201105281110.p4SBA9RM042296@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         157378
>Category:       i386
>Synopsis:       fxp.ich.patch
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-i386
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat May 28 11:10:09 UTC 2011
>Closed-Date:
>Last-Modified:
>Originator:     cumay
>Release:        freebsd 4.11
>Organization:
no
>Environment:
freebsd 4.11
>Description:
I got a patch fxp.ich.patch whitch can fix this problem .but it can't be used for freebsd 4.11.  badlly expecting freebsd team can modify fxp.ich.patch for freebsd 4.11.

I like 4.11 very much. 
Thanks for your great help.
>How-To-Repeat:
I got a patch fxp.ich.patch whitch can fix this problem .but it can't be used for freebsd 4.11.  badlly expecting freebsd team can modify fxp.ich.patch for freebsd 4.11.

I like 4.11 very much. 
Thanks for your great help.
>Fix:


Patch attached with submission follows:

Index: sys/dev/fxp/if_fxpvar.h
===================================================================
--- sys/dev/fxp/if_fxpvar.h	(revision 194231)
+++ sys/dev/fxp/if_fxpvar.h	(working copy)
@@ -142,6 +142,13 @@
 	bus_dma_tag_t rx_tag;
 };
 
+struct fxp_ident {
+	uint16_t	devid;
+	int16_t		revid;		/* -1 matches anything */
+	uint8_t		ich;
+	char 		*name;
+};
+
 /*
  * NOTE: Elements are ordered for optimal cacheline behavior, and NOT
  *	 for functional grouping.
@@ -151,8 +158,10 @@
 	struct resource	*fxp_res[2];	/* I/O and IRQ resources */
 	struct resource_spec *fxp_spec;	/* the resource spec we used */
 	void *ih;			/* interrupt handler cookie */
+	struct fxp_ident *ident;
 	struct mtx sc_mtx;
-	bus_dma_tag_t fxp_mtag;		/* bus DMA tag for mbufs */
+	bus_dma_tag_t fxp_txmtag;	/* bus DMA tag for Tx mbufs */
+	bus_dma_tag_t fxp_rxmtag;	/* bus DMA tag for Rx mbufs */
 	bus_dma_tag_t fxp_stag;		/* bus DMA tag for stats */
 	bus_dmamap_t fxp_smap;		/* bus DMA map for stats */
 	bus_dma_tag_t cbl_tag;		/* DMA tag for the TxCB list */
@@ -164,7 +173,6 @@
 	int maxtxseg;			/* maximum # of TX segments */
 	int maxsegsize;			/* maximum size of a TX segment */
 	int tx_queued;			/* # of active TxCB's */
-	int need_mcsetup;		/* multicast filter needs programming */
 	struct fxp_stats *fxp_stats;	/* Pointer to interface stats */
 	uint32_t stats_addr;		/* DMA address of the stats structure */
 	int rx_idle_secs;		/* # of seconds RX has been idle */
@@ -184,6 +192,7 @@
 	int cu_resume_bug;
 	int revision;
 	int flags;
+	int if_flags;
 	uint8_t rfa_size;
 	uint32_t tx_cmd;
 };
@@ -194,7 +203,6 @@
 #define FXP_FLAG_EXT_TXCB	0x0008	/* enable use of extended TXCB */
 #define FXP_FLAG_SERIAL_MEDIA	0x0010	/* 10Mbps serial interface */
 #define FXP_FLAG_LONG_PKT_EN	0x0020	/* enable long packet reception */
-#define FXP_FLAG_ALL_MCAST	0x0040	/* accept all multicast frames */
 #define FXP_FLAG_CU_RESUME_BUG	0x0080	/* requires workaround for CU_RESUME */
 #define FXP_FLAG_UCODE		0x0100	/* ucode is loaded */
 #define FXP_FLAG_DEFERRED_RNR	0x0200	/* DEVICE_POLLING deferred RNR */
@@ -203,6 +211,7 @@
 #define FXP_FLAG_82559_RXCSUM	0x1000	/* 82559 compatible RX checksum */
 #define FXP_FLAG_WOLCAP		0x2000	/* WOL capability */
 #define FXP_FLAG_WOL		0x4000	/* WOL active */
+#define FXP_FLAG_RXBUG		0x8000	/* Rx lock-up bug */
 
 /* Macros to ease CSR access. */
 #define	CSR_READ_1(sc, reg)		bus_read_1(sc->fxp_res[0], reg)
Index: sys/dev/fxp/if_fxp.c
===================================================================
--- sys/dev/fxp/if_fxp.c	(revision 194231)
+++ sys/dev/fxp/if_fxp.c	(working copy)
@@ -140,12 +140,6 @@
 	0x5	/* 21 */
 };
 
-struct fxp_ident {
-	uint16_t	devid;
-	int16_t		revid;		/* -1 matches anything */
-	char 		*name;
-};
-
 /*
  * Claim various Intel PCI device identifiers for this driver.  The
  * sub-vendor and sub-device field are extensively used to identify
@@ -153,52 +147,52 @@
  * them.
  */
 static struct fxp_ident fxp_ident_table[] = {
-    { 0x1029,	-1,	"Intel 82559 PCI/CardBus Pro/100" },
-    { 0x1030,	-1,	"Intel 82559 Pro/100 Ethernet" },
-    { 0x1031,	-1,	"Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
-    { 0x1032,	-1,	"Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
-    { 0x1033,	-1,	"Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
-    { 0x1034,	-1,	"Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
-    { 0x1035,	-1,	"Intel 82801CAM (ICH3) Pro/100 Ethernet" },
-    { 0x1036,	-1,	"Intel 82801CAM (ICH3) Pro/100 Ethernet" },
-    { 0x1037,	-1,	"Intel 82801CAM (ICH3) Pro/100 Ethernet" },
-    { 0x1038,	-1,	"Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
-    { 0x1039,	-1,	"Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
-    { 0x103A,	-1,	"Intel 82801DB (ICH4) Pro/100 Ethernet" },
-    { 0x103B,	-1,	"Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
-    { 0x103C,	-1,	"Intel 82801DB (ICH4) Pro/100 Ethernet" },
-    { 0x103D,	-1,	"Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
-    { 0x103E,	-1,	"Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
-    { 0x1050,	-1,	"Intel 82801BA (D865) Pro/100 VE Ethernet" },
-    { 0x1051,	-1,	"Intel 82562ET (ICH5/ICH5R) Pro/100 VE Ethernet" },
-    { 0x1059,	-1,	"Intel 82551QM Pro/100 M Mobile Connection" },
-    { 0x1064,	-1,	"Intel 82562EZ (ICH6)" },
-    { 0x1065,	-1,	"Intel 82562ET/EZ/GT/GZ PRO/100 VE Ethernet" },
-    { 0x1068,	-1,	"Intel 82801FBM (ICH6-M) Pro/100 VE Ethernet" },
-    { 0x1069,	-1,	"Intel 82562EM/EX/GX Pro/100 Ethernet" },
-    { 0x1091,	-1,	"Intel 82562GX Pro/100 Ethernet" },
-    { 0x1092,	-1,	"Intel Pro/100 VE Network Connection" },
-    { 0x1093,	-1,	"Intel Pro/100 VM Network Connection" },
-    { 0x1094,	-1,	"Intel Pro/100 946GZ (ICH7) Network Connection" },
-    { 0x1209,	-1,	"Intel 82559ER Embedded 10/100 Ethernet" },
-    { 0x1229,	0x01,	"Intel 82557 Pro/100 Ethernet" },
-    { 0x1229,	0x02,	"Intel 82557 Pro/100 Ethernet" },
-    { 0x1229,	0x03,	"Intel 82557 Pro/100 Ethernet" },
-    { 0x1229,	0x04,	"Intel 82558 Pro/100 Ethernet" },
-    { 0x1229,	0x05,	"Intel 82558 Pro/100 Ethernet" },
-    { 0x1229,	0x06,	"Intel 82559 Pro/100 Ethernet" },
-    { 0x1229,	0x07,	"Intel 82559 Pro/100 Ethernet" },
-    { 0x1229,	0x08,	"Intel 82559 Pro/100 Ethernet" },
-    { 0x1229,	0x09,	"Intel 82559ER Pro/100 Ethernet" },
-    { 0x1229,	0x0c,	"Intel 82550 Pro/100 Ethernet" },
-    { 0x1229,	0x0d,	"Intel 82550 Pro/100 Ethernet" },
-    { 0x1229,	0x0e,	"Intel 82550 Pro/100 Ethernet" },
-    { 0x1229,	0x0f,	"Intel 82551 Pro/100 Ethernet" },
-    { 0x1229,	0x10,	"Intel 82551 Pro/100 Ethernet" },
-    { 0x1229,	-1,	"Intel 82557/8/9 Pro/100 Ethernet" },
-    { 0x2449,	-1,	"Intel 82801BA/CAM (ICH2/3) Pro/100 Ethernet" },
-    { 0x27dc,	-1,	"Intel 82801GB (ICH7) 10/100 Ethernet" },
-    { 0,	-1,	NULL },
+    { 0x1029,	-1,	0, "Intel 82559 PCI/CardBus Pro/100" },
+    { 0x1030,	-1,	0, "Intel 82559 Pro/100 Ethernet" },
+    { 0x1031,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
+    { 0x1032,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 VE Ethernet" },
+    { 0x1033,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+    { 0x1034,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+    { 0x1035,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+    { 0x1036,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+    { 0x1037,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 Ethernet" },
+    { 0x1038,	-1,	3, "Intel 82801CAM (ICH3) Pro/100 VM Ethernet" },
+    { 0x1039,	-1,	4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
+    { 0x103A,	-1,	4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
+    { 0x103B,	-1,	4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
+    { 0x103C,	-1,	4, "Intel 82801DB (ICH4) Pro/100 Ethernet" },
+    { 0x103D,	-1,	4, "Intel 82801DB (ICH4) Pro/100 VE Ethernet" },
+    { 0x103E,	-1,	4, "Intel 82801DB (ICH4) Pro/100 VM Ethernet" },
+    { 0x1050,	-1,	5, "Intel 82801BA (D865) Pro/100 VE Ethernet" },
+    { 0x1051,	-1,	5, "Intel 82562ET (ICH5/ICH5R) Pro/100 VE Ethernet" },
+    { 0x1059,	-1,	0, "Intel 82551QM Pro/100 M Mobile Connection" },
+    { 0x1064,	-1,	6, "Intel 82562EZ (ICH6)" },
+    { 0x1065,	-1,	6, "Intel 82562ET/EZ/GT/GZ PRO/100 VE Ethernet" },
+    { 0x1068,	-1,	6, "Intel 82801FBM (ICH6-M) Pro/100 VE Ethernet" },
+    { 0x1069,	-1,	6, "Intel 82562EM/EX/GX Pro/100 Ethernet" },
+    { 0x1091,	-1,	7, "Intel 82562GX Pro/100 Ethernet" },
+    { 0x1092,	-1,	7, "Intel Pro/100 VE Network Connection" },
+    { 0x1093,	-1,	7, "Intel Pro/100 VM Network Connection" },
+    { 0x1094,	-1,	7, "Intel Pro/100 946GZ (ICH7) Network Connection" },
+    { 0x1209,	-1,	0, "Intel 82559ER Embedded 10/100 Ethernet" },
+    { 0x1229,	0x01,	0, "Intel 82557 Pro/100 Ethernet" },
+    { 0x1229,	0x02,	0, "Intel 82557 Pro/100 Ethernet" },
+    { 0x1229,	0x03,	0, "Intel 82557 Pro/100 Ethernet" },
+    { 0x1229,	0x04,	0, "Intel 82558 Pro/100 Ethernet" },
+    { 0x1229,	0x05,	0, "Intel 82558 Pro/100 Ethernet" },
+    { 0x1229,	0x06,	0, "Intel 82559 Pro/100 Ethernet" },
+    { 0x1229,	0x07,	0, "Intel 82559 Pro/100 Ethernet" },
+    { 0x1229,	0x08,	0, "Intel 82559 Pro/100 Ethernet" },
+    { 0x1229,	0x09,	0, "Intel 82559ER Pro/100 Ethernet" },
+    { 0x1229,	0x0c,	0, "Intel 82550 Pro/100 Ethernet" },
+    { 0x1229,	0x0d,	0, "Intel 82550 Pro/100 Ethernet" },
+    { 0x1229,	0x0e,	0, "Intel 82550 Pro/100 Ethernet" },
+    { 0x1229,	0x0f,	0, "Intel 82551 Pro/100 Ethernet" },
+    { 0x1229,	0x10,	0, "Intel 82551 Pro/100 Ethernet" },
+    { 0x1229,	-1,	0, "Intel 82557/8/9 Pro/100 Ethernet" },
+    { 0x2449,	-1,	2, "Intel 82801BA/CAM (ICH2/3) Pro/100 Ethernet" },
+    { 0x27dc,	-1,	7, "Intel 82801GB (ICH7) 10/100 Ethernet" },
+    { 0,	-1,	0, NULL },
 };
 
 #ifdef FXP_IP_CSUM_WAR
@@ -214,6 +208,7 @@
 static int		fxp_suspend(device_t dev);
 static int		fxp_resume(device_t dev);
 
+static struct fxp_ident	*fxp_find_ident(device_t dev);
 static void		fxp_intr(void *xsc);
 static void		fxp_rxcsum(struct fxp_softc *sc, struct ifnet *ifp,
 			    struct mbuf *m, uint16_t status, int pos);
@@ -360,11 +355,8 @@
 		device_printf(sc->dev, "DMA timeout\n");
 }
 
-/*
- * Return identification string if this device is ours.
- */
-static int
-fxp_probe(device_t dev)
+static struct fxp_ident *
+fxp_find_ident(device_t dev)
 {
 	uint16_t devid;
 	uint8_t revid;
@@ -376,11 +368,26 @@
 		for (ident = fxp_ident_table; ident->name != NULL; ident++) {
 			if (ident->devid == devid &&
 			    (ident->revid == revid || ident->revid == -1)) {
-				device_set_desc(dev, ident->name);
-				return (BUS_PROBE_DEFAULT);
+				return (ident);
 			}
 		}
 	}
+	return (NULL);
+}
+
+/*
+ * Return identification string if this device is ours.
+ */
+static int
+fxp_probe(device_t dev)
+{
+	struct fxp_ident *ident;
+
+	ident = fxp_find_ident(dev);
+	if (ident != NULL) {
+		device_set_desc(dev, ident->name);
+		return (BUS_PROBE_DEFAULT);
+	}
 	return (ENXIO);
 }
 
@@ -466,10 +473,14 @@
 	}
 
 	/*
-	 * Reset to a stable state.
+	 * Put CU/RU idle state and prepare full reset.
 	 */
 	CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);
 	DELAY(10);
+	/* Full reset and disable interrupts. */
+	CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SOFTWARE_RESET);
+	DELAY(10);
+	CSR_WRITE_1(sc, FXP_CSR_SCB_INTRCNTL, FXP_SCB_INTR_DISABLE);
 
 	/*
 	 * Find out how large of an SEEPROM we have.
@@ -479,11 +490,17 @@
 	/*
 	 * Find out the chip revision; lump all 82557 revs together.
 	 */
-	fxp_read_eeprom(sc, &data, 5, 1);
-	if ((data >> 8) == 1)
-		sc->revision = FXP_REV_82557;
-	else
-		sc->revision = pci_get_revid(dev);
+	sc->ident = fxp_find_ident(dev);
+	if (sc->ident->ich > 0) {
+		/* Assume ICH controllers are 82559. */
+		sc->revision = FXP_REV_82559_A0;
+	} else {
+		fxp_read_eeprom(sc, &data, 5, 1);
+		if ((data >> 8) == 1)
+			sc->revision = FXP_REV_82557;
+		else
+			sc->revision = pci_get_revid(dev);
+	}
 
 	/*
 	 * Check availability of WOL. 82559ER does not support WOL.
@@ -496,6 +513,13 @@
 			sc->flags |= FXP_FLAG_WOLCAP;
 	}
 
+	/* Receiver lock-up workaround detection. */
+	fxp_read_eeprom(sc, &data, 3, 1);
+	if ((data & 0x03) != 0x03) {
+		sc->flags |= FXP_FLAG_RXBUG;
+		device_printf(dev, "Enabling Rx lock-up workaround\n");
+	}
+
 	/*
 	 * Determine whether we must use the 503 serial interface.
 	 */
@@ -549,9 +573,8 @@
 	 *
 	 * See Intel 82801BA/82801BAM Specification Update, Errata #30.
 	 */
-	i = pci_get_device(dev);
-	if (i == 0x2449 || (i > 0x1030 && i < 0x1039) ||
-	    sc->revision >= FXP_REV_82559_A0) {
+	if ((sc->ident->ich >= 2 && sc->ident->ich <= 3) ||
+	    (sc->ident->ich == 0 && sc->revision >= FXP_REV_82559_A0)) {
 		fxp_read_eeprom(sc, &data, 10, 1);
 		if (data & 0x02) {			/* STB enable */
 			uint16_t cksum;
@@ -642,29 +665,40 @@
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 	    sc->maxsegsize * sc->maxtxseg + sizeof(struct ether_vlan_header),
 	    sc->maxtxseg, sc->maxsegsize, 0,
-	    busdma_lock_mutex, &Giant, &sc->fxp_mtag);
+	    busdma_lock_mutex, &Giant, &sc->fxp_txmtag);
 	if (error) {
-		device_printf(dev, "could not allocate dma tag\n");
+		device_printf(dev, "could not create TX DMA tag\n");
 		goto fail;
 	}
 
+	error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0,
+	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+	    MCLBYTES, 1, MCLBYTES, 0,
+	    busdma_lock_mutex, &Giant, &sc->fxp_rxmtag);
+	if (error) {
+		device_printf(dev, "could not create RX DMA tag\n");
+		goto fail;
+	}
+
 	error = bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0,
 	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
 	    sizeof(struct fxp_stats), 1, sizeof(struct fxp_stats), 0,
 	    busdma_lock_mutex, &Giant, &sc->fxp_stag);
 	if (error) {
-		device_printf(dev, "could not allocate dma tag\n");
+		device_printf(dev, "could not create stats DMA tag\n");
 		goto fail;
 	}
 
 	error = bus_dmamem_alloc(sc->fxp_stag, (void **)&sc->fxp_stats,
 	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->fxp_smap);
-	if (error)
+	if (error) {
+		device_printf(dev, "could not allocate stats DMA memory\n");
 		goto fail;
+	}
 	error = bus_dmamap_load(sc->fxp_stag, sc->fxp_smap, sc->fxp_stats,
 	    sizeof(struct fxp_stats), fxp_dma_map_addr, &sc->stats_addr, 0);
 	if (error) {
-		device_printf(dev, "could not map the stats buffer\n");
+		device_printf(dev, "could not load the stats DMA buffer\n");
 		goto fail;
 	}
 
@@ -673,20 +707,22 @@
 	    FXP_TXCB_SZ, 1, FXP_TXCB_SZ, 0,
 	    busdma_lock_mutex, &Giant, &sc->cbl_tag);
 	if (error) {
-		device_printf(dev, "could not allocate dma tag\n");
+		device_printf(dev, "could not create TxCB DMA tag\n");
 		goto fail;
 	}
 
 	error = bus_dmamem_alloc(sc->cbl_tag, (void **)&sc->fxp_desc.cbl_list,
 	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->cbl_map);
-	if (error)
+	if (error) {
+		device_printf(dev, "could not allocate TxCB DMA memory\n");
 		goto fail;
+	}
 
 	error = bus_dmamap_load(sc->cbl_tag, sc->cbl_map,
 	    sc->fxp_desc.cbl_list, FXP_TXCB_SZ, fxp_dma_map_addr,
 	    &sc->fxp_desc.cbl_addr, 0);
 	if (error) {
-		device_printf(dev, "could not map DMA memory\n");
+		device_printf(dev, "could not load TxCB DMA buffer\n");
 		goto fail;
 	}
 
@@ -695,18 +731,23 @@
 	    sizeof(struct fxp_cb_mcs), 1, sizeof(struct fxp_cb_mcs), 0,
 	    busdma_lock_mutex, &Giant, &sc->mcs_tag);
 	if (error) {
-		device_printf(dev, "could not allocate dma tag\n");
+		device_printf(dev,
+		    "could not create multicast setup DMA tag\n");
 		goto fail;
 	}
 
 	error = bus_dmamem_alloc(sc->mcs_tag, (void **)&sc->mcsp,
-	    BUS_DMA_NOWAIT, &sc->mcs_map);
-	if (error)
+	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->mcs_map);
+	if (error) {
+		device_printf(dev,
+		    "could not allocate multicast setup DMA memory\n");
 		goto fail;
+	}
 	error = bus_dmamap_load(sc->mcs_tag, sc->mcs_map, sc->mcsp,
 	    sizeof(struct fxp_cb_mcs), fxp_dma_map_addr, &sc->mcs_addr, 0);
 	if (error) {
-		device_printf(dev, "can't map the multicast setup command\n");
+		device_printf(dev,
+		    "can't load the multicast setup DMA buffer\n");
 		goto fail;
 	}
 
@@ -718,13 +759,13 @@
 	tcbp = sc->fxp_desc.cbl_list;
 	for (i = 0; i < FXP_NTXCB; i++) {
 		txp[i].tx_cb = tcbp + i;
-		error = bus_dmamap_create(sc->fxp_mtag, 0, &txp[i].tx_map);
+		error = bus_dmamap_create(sc->fxp_txmtag, 0, &txp[i].tx_map);
 		if (error) {
 			device_printf(dev, "can't create DMA map for TX\n");
 			goto fail;
 		}
 	}
-	error = bus_dmamap_create(sc->fxp_mtag, 0, &sc->spare_map);
+	error = bus_dmamap_create(sc->fxp_rxmtag, 0, &sc->spare_map);
 	if (error) {
 		device_printf(dev, "can't create spare DMA map\n");
 		goto fail;
@@ -736,7 +777,7 @@
 	sc->fxp_desc.rx_head = sc->fxp_desc.rx_tail = NULL;
 	for (i = 0; i < FXP_NRFABUFS; i++) {
 		rxp = &sc->fxp_desc.rx_list[i];
-		error = bus_dmamap_create(sc->fxp_mtag, 0, &rxp->rx_map);
+		error = bus_dmamap_create(sc->fxp_rxmtag, 0, &rxp->rx_map);
 		if (error) {
 			device_printf(dev, "can't create DMA map for RX\n");
 			goto fail;
@@ -910,29 +951,32 @@
 		bus_dmamem_free(sc->mcs_tag, sc->mcsp, sc->mcs_map);
 	}
 	bus_release_resources(sc->dev, sc->fxp_spec, sc->fxp_res);
-	if (sc->fxp_mtag) {
+	if (sc->fxp_rxmtag) {
 		for (i = 0; i < FXP_NRFABUFS; i++) {
 			rxp = &sc->fxp_desc.rx_list[i];
 			if (rxp->rx_mbuf != NULL) {
-				bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map,
+				bus_dmamap_sync(sc->fxp_rxmtag, rxp->rx_map,
 				    BUS_DMASYNC_POSTREAD);
-				bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map);
+				bus_dmamap_unload(sc->fxp_rxmtag, rxp->rx_map);
 				m_freem(rxp->rx_mbuf);
 			}
-			bus_dmamap_destroy(sc->fxp_mtag, rxp->rx_map);
+			bus_dmamap_destroy(sc->fxp_rxmtag, rxp->rx_map);
 		}
-		bus_dmamap_destroy(sc->fxp_mtag, sc->spare_map);
+		bus_dmamap_destroy(sc->fxp_rxmtag, sc->spare_map);
+		bus_dma_tag_destroy(sc->fxp_rxmtag);
+	}
+	if (sc->fxp_txmtag) {
 		for (i = 0; i < FXP_NTXCB; i++) {
 			txp = &sc->fxp_desc.tx_list[i];
 			if (txp->tx_mbuf != NULL) {
-				bus_dmamap_sync(sc->fxp_mtag, txp->tx_map,
+				bus_dmamap_sync(sc->fxp_txmtag, txp->tx_map,
 				    BUS_DMASYNC_POSTWRITE);
-				bus_dmamap_unload(sc->fxp_mtag, txp->tx_map);
+				bus_dmamap_unload(sc->fxp_txmtag, txp->tx_map);
 				m_freem(txp->tx_mbuf);
 			}
-			bus_dmamap_destroy(sc->fxp_mtag, txp->tx_map);
+			bus_dmamap_destroy(sc->fxp_txmtag, txp->tx_map);
 		}
-		bus_dma_tag_destroy(sc->fxp_mtag);
+		bus_dma_tag_destroy(sc->fxp_txmtag);
 	}
 	if (sc->fxp_stag)
 		bus_dma_tag_destroy(sc->fxp_stag);
@@ -960,7 +1004,6 @@
 #endif
 
 	FXP_LOCK(sc);
-	sc->suspended = 1;	/* Do same thing as we do for suspend */
 	/*
 	 * Stop DMA and drop transmit queue, but disable interrupts first.
 	 */
@@ -970,6 +1013,14 @@
 	callout_drain(&sc->stat_ch);
 
 	/*
+	 * Force off IFF_UP flag, otherwise active BPF listeners
+	 * can call fxp_ioctl to clear promiscuous mode and fxp_init
+	 * will rearm fxp_tick which in turn will panic the system
+	 * when kernel tries to call fxp_tick which is not present
+	 * anymore.
+	 */
+	sc->ifp->if_flags &= ~IFF_UP;
+	/*
 	 * Close down routes etc.
 	 */
 	ether_ifdetach(sc->ifp);
@@ -1279,12 +1330,8 @@
 
 	FXP_LOCK_ASSERT(sc, MA_OWNED);
 
-	/*
-	 * See if we need to suspend xmit until the multicast filter
-	 * has been reprogrammed (which can only be done at the head
-	 * of the command chain).
-	 */
-	if (sc->need_mcsetup)
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING)
 		return;
 
 	if (sc->tx_queued > FXP_NTXCB_HIWAT)
@@ -1324,7 +1371,8 @@
 	 * going again if suspended.
 	 */
 	if (txqueued > 0) {
-		bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE);
+		bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
+		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 		fxp_scb_wait(sc);
 		fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
 		/*
@@ -1498,7 +1546,7 @@
 		*m_head = m;
 	}
 
-	error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, *m_head,
+	error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map, *m_head,
 	    segs, &nseg, 0);
 	if (error == EFBIG) {
 		m = m_collapse(*m_head, M_DONTWAIT, sc->maxtxseg);
@@ -1508,7 +1556,7 @@
 			return (ENOMEM);
 		}
 		*m_head = m;
-		error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map,
+		error = bus_dmamap_load_mbuf_sg(sc->fxp_txmtag, txp->tx_map,
 	    	    *m_head, segs, &nseg, 0);
 		if (error != 0) {
 			m_freem(*m_head);
@@ -1524,7 +1572,7 @@
 	}
 
 	KASSERT(nseg <= sc->maxtxseg, ("too many DMA segments"));
-	bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->fxp_txmtag, txp->tx_map, BUS_DMASYNC_PREWRITE);
 
 	cbp = txp->tx_cb;
 	for (i = 0; i < nseg; i++) {
@@ -1694,7 +1742,8 @@
 		 * First ACK all the interrupts in this pass.
 		 */
 		CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);
-		fxp_intr_body(sc, ifp, statack, -1);
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			fxp_intr_body(sc, ifp, statack, -1);
 	}
 	FXP_UNLOCK(sc);
 }
@@ -1706,14 +1755,15 @@
 	struct fxp_tx *txp;
 
 	ifp = sc->ifp;
-	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREREAD);
+	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
+	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
 	for (txp = sc->fxp_desc.tx_first; sc->tx_queued &&
 	    (le16toh(txp->tx_cb->cb_status) & FXP_CB_STATUS_C) != 0;
 	    txp = txp->tx_next) {
 		if (txp->tx_mbuf != NULL) {
-			bus_dmamap_sync(sc->fxp_mtag, txp->tx_map,
+			bus_dmamap_sync(sc->fxp_txmtag, txp->tx_map,
 			    BUS_DMASYNC_POSTWRITE);
-			bus_dmamap_unload(sc->fxp_mtag, txp->tx_map);
+			bus_dmamap_unload(sc->fxp_txmtag, txp->tx_map);
 			m_freem(txp->tx_mbuf);
 			txp->tx_mbuf = NULL;
 			/* clear this to reset csum offload bits */
@@ -1723,12 +1773,10 @@
 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	}
 	sc->fxp_desc.tx_first = txp;
-	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE);
-	if (sc->tx_queued == 0) {
+	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	if (sc->tx_queued == 0)
 		sc->watchdog_timer = 0;
-		if (sc->need_mcsetup)
-			fxp_mc_setup(sc);
-	}
 }
 
 static void
@@ -1878,7 +1926,7 @@
 		m = rxp->rx_mbuf;
 		rfa = (struct fxp_rfa *)(m->m_ext.ext_buf +
 		    RFA_ALIGNMENT_FUDGE);
-		bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map,
+		bus_dmamap_sync(sc->fxp_rxmtag, rxp->rx_map,
 		    BUS_DMASYNC_POSTREAD);
 
 #ifdef DEVICE_POLLING /* loop at most count times if count >=0 */
@@ -1952,6 +2000,8 @@
 			(*ifp->if_input)(ifp, m);
 			FXP_LOCK(sc);
 			rx_npkts++;
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+				return (rx_npkts);
 		} else {
 			/* Reuse RFA and loaded DMA map. */
 			ifp->if_iqdrops++;
@@ -1993,7 +2043,7 @@
 	if (sp->rx_good) {
 		ifp->if_ipackets += le32toh(sp->rx_good);
 		sc->rx_idle_secs = 0;
-	} else {
+	} else if (sc->flags & FXP_FLAG_RXBUG) {
 		/*
 		 * Receiver's been idle for another second.
 		 */
@@ -2035,7 +2085,9 @@
 	 */
 	if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {
 		sc->rx_idle_secs = 0;
-		fxp_mc_setup(sc);
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			fxp_init_body(sc);
+		return;
 	}
 	/*
 	 * If there is no pending command, start another stats
@@ -2113,9 +2165,10 @@
 	if (txp != NULL) {
 		for (i = 0; i < FXP_NTXCB; i++) {
  			if (txp[i].tx_mbuf != NULL) {
-				bus_dmamap_sync(sc->fxp_mtag, txp[i].tx_map,
+				bus_dmamap_sync(sc->fxp_txmtag, txp[i].tx_map,
 				    BUS_DMASYNC_POSTWRITE);
-				bus_dmamap_unload(sc->fxp_mtag, txp[i].tx_map);
+				bus_dmamap_unload(sc->fxp_txmtag,
+				    txp[i].tx_map);
 				m_freem(txp[i].tx_mbuf);
 				txp[i].tx_mbuf = NULL;
 				/* clear this to reset csum offload bits */
@@ -2123,7 +2176,8 @@
 			}
 		}
 	}
-	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	sc->tx_queued = 0;
 }
 
@@ -2175,7 +2229,6 @@
 	struct fxp_cb_ias *cb_ias;
 	struct fxp_cb_tx *tcbp;
 	struct fxp_tx *txp;
-	struct fxp_cb_mcs *mcsp;
 	int i, prm;
 
 	FXP_LOCK_ASSERT(sc, MA_OWNED);
@@ -2213,30 +2266,19 @@
 
 	/*
 	 * Attempt to load microcode if requested.
+	 * For ICH based controllers do not load microcode.
 	 */
-	if (ifp->if_flags & IFF_LINK0 && (sc->flags & FXP_FLAG_UCODE) == 0)
-		fxp_load_ucode(sc);
+	if (sc->ident->ich == 0) {
+		if (ifp->if_flags & IFF_LINK0 &&
+		    (sc->flags & FXP_FLAG_UCODE) == 0)
+			fxp_load_ucode(sc);
+	}
 
 	/*
-	 * Initialize the multicast address list.
+	 * Set IFF_ALLMULTI status. It's needed in configure action
+	 * command.
 	 */
-	if (fxp_mc_addrs(sc)) {
-		mcsp = sc->mcsp;
-		mcsp->cb_status = 0;
-		mcsp->cb_command =
-		    htole16(FXP_CB_COMMAND_MCAS | FXP_CB_COMMAND_EL);
-		mcsp->link_addr = 0xffffffff;
-		/*
-	 	 * Start the multicast setup command.
-		 */
-		fxp_scb_wait(sc);
-		bus_dmamap_sync(sc->mcs_tag, sc->mcs_map,
-		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-		CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->mcs_addr);
-		fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
-		/* ...and wait for it to complete. */
-		fxp_dma_wait(sc, &mcsp->cb_status, sc->mcs_tag, sc->mcs_map);
-	}
+	fxp_mc_addrs(sc);
 
 	/*
 	 * We temporarily use memory that contains the TxCB list to
@@ -2310,7 +2352,7 @@
 	cbp->force_fdx =	0;	/* (don't) force full duplex */
 	cbp->fdx_pin_en =	1;	/* (enable) FDX# pin */
 	cbp->multi_ia =		0;	/* (don't) accept multiple IAs */
-	cbp->mc_all =		sc->flags & FXP_FLAG_ALL_MCAST ? 1 : 0;
+	cbp->mc_all =		ifp->if_flags & IFF_ALLMULTI ? 1 : 0;
 	cbp->gamla_rx =		sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0;
 	cbp->vlan_strip_en =	((sc->flags & FXP_FLAG_EXT_RFA) != 0 &&
 	    (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) ? 1 : 0;
@@ -2366,11 +2408,17 @@
 	fxp_scb_wait(sc);
 	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->fxp_desc.cbl_addr);
 	fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
 	/* ...and wait for it to complete. */
 	fxp_dma_wait(sc, &cb_ias->cb_status, sc->cbl_tag, sc->cbl_map);
 
 	/*
+	 * Initialize the multicast address list.
+	 */
+	fxp_mc_setup(sc);
+
+	/*
 	 * Initialize transmit control block (TxCB) list.
 	 */
 	txp = sc->fxp_desc.tx_list;
@@ -2395,11 +2443,13 @@
 	 * unit. It will execute the NOP and then suspend.
 	 */
 	tcbp->cb_command = htole16(FXP_CB_COMMAND_NOP | FXP_CB_COMMAND_S);
-	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->cbl_tag, sc->cbl_map,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	sc->fxp_desc.tx_first = sc->fxp_desc.tx_last = txp;
 	sc->tx_queued = 1;
 
 	fxp_scb_wait(sc);
+	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->fxp_desc.cbl_addr);
 	fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
 
 	/*
@@ -2545,7 +2595,7 @@
 	le32enc(&rfa->rbd_addr, 0xffffffff);
 
 	/* Map the RFA into DMA memory. */
-	error = bus_dmamap_load(sc->fxp_mtag, sc->spare_map, rfa,
+	error = bus_dmamap_load(sc->fxp_rxmtag, sc->spare_map, rfa,
 	    MCLBYTES - RFA_ALIGNMENT_FUDGE, fxp_dma_map_addr,
 	    &rxp->rx_addr, 0);
 	if (error) {
@@ -2554,13 +2604,13 @@
 	}
 
 	if (rxp->rx_mbuf != NULL)
-		bus_dmamap_unload(sc->fxp_mtag, rxp->rx_map);
+		bus_dmamap_unload(sc->fxp_rxmtag, rxp->rx_map);
 	tmp_map = sc->spare_map;
 	sc->spare_map = rxp->rx_map;
 	rxp->rx_map = tmp_map;
 	rxp->rx_mbuf = m;
 
-	bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map,
+	bus_dmamap_sync(sc->fxp_rxmtag, rxp->rx_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	return (0);
 }
@@ -2582,7 +2632,7 @@
 		p_rx->rx_next = rxp;
 		le32enc(&p_rfa->link_addr, rxp->rx_addr);
 		p_rfa->rfa_control = 0;
-		bus_dmamap_sync(sc->fxp_mtag, p_rx->rx_map,
+		bus_dmamap_sync(sc->fxp_rxmtag, p_rx->rx_map,
 		    BUS_DMASYNC_PREWRITE);
 	} else {
 		rxp->rx_next = NULL;
@@ -2626,7 +2676,7 @@
 	le32enc(&rfa->link_addr, 0xffffffff);
 	le32enc(&rfa->rbd_addr, 0xffffffff);
 
-	bus_dmamap_sync(sc->fxp_mtag, rxp->rx_map,
+	bus_dmamap_sync(sc->fxp_rxmtag, rxp->rx_map,
 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 }
 
@@ -2680,11 +2730,6 @@
 	switch (command) {
 	case SIOCSIFFLAGS:
 		FXP_LOCK(sc);
-		if (ifp->if_flags & IFF_ALLMULTI)
-			sc->flags |= FXP_FLAG_ALL_MCAST;
-		else
-			sc->flags &= ~FXP_FLAG_ALL_MCAST;
-
 		/*
 		 * If interface is marked up and not running, then start it.
 		 * If it is marked down and running, stop it.
@@ -2692,35 +2737,24 @@
 		 * such as IFF_PROMISC are handled.
 		 */
 		if (ifp->if_flags & IFF_UP) {
-			fxp_init_body(sc);
+			if (((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) &&
+			    ((ifp->if_flags ^ sc->if_flags) &
+			    (IFF_PROMISC | IFF_ALLMULTI | IFF_LINK0)) != 0)
+				fxp_init_body(sc);
+			else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+				fxp_init_body(sc);
 		} else {
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
 				fxp_stop(sc);
 		}
+		sc->if_flags = ifp->if_flags;
 		FXP_UNLOCK(sc);
 		break;
 
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
-		FXP_LOCK(sc);
-		if (ifp->if_flags & IFF_ALLMULTI)
-			sc->flags |= FXP_FLAG_ALL_MCAST;
-		else
-			sc->flags &= ~FXP_FLAG_ALL_MCAST;
-		/*
-		 * Multicast list has changed; set the hardware filter
-		 * accordingly.
-		 */
-		if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0)
-			fxp_mc_setup(sc);
-		/*
-		 * fxp_mc_setup() can set FXP_FLAG_ALL_MCAST, so check it
-		 * again rather than else {}.
-		 */
-		if (sc->flags & FXP_FLAG_ALL_MCAST)
-			fxp_init_body(sc);
-		FXP_UNLOCK(sc);
-		error = 0;
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+			fxp_init(sc);
 		break;
 
 	case SIOCSIFMEDIA:
@@ -2824,13 +2858,13 @@
 	int nmcasts;
 
 	nmcasts = 0;
-	if ((sc->flags & FXP_FLAG_ALL_MCAST) == 0) {
+	if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
 		IF_ADDR_LOCK(ifp);
 		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 			if (ifma->ifma_addr->sa_family != AF_LINK)
 				continue;
 			if (nmcasts >= MAXMCADDR) {
-				sc->flags |= FXP_FLAG_ALL_MCAST;
+				ifp->if_flags |= IFF_ALLMULTI;
 				nmcasts = 0;
 				break;
 			}
@@ -2855,87 +2889,28 @@
  * points to the TxCB ring, but the mcsetup descriptor itself is not part
  * of it. We then can do 'CU_START' on the mcsetup descriptor and have it
  * lead into the regular TxCB ring when it completes.
- *
- * This function must be called at splimp.
  */
 static void
 fxp_mc_setup(struct fxp_softc *sc)
 {
-	struct fxp_cb_mcs *mcsp = sc->mcsp;
-	struct fxp_tx *txp;
+	struct fxp_cb_mcs *mcsp;
 	int count;
 
 	FXP_LOCK_ASSERT(sc, MA_OWNED);
-	/*
-	 * If there are queued commands, we must wait until they are all
-	 * completed. If we are already waiting, then add a NOP command
-	 * with interrupt option so that we're notified when all commands
-	 * have been completed - fxp_start() ensures that no additional
-	 * TX commands will be added when need_mcsetup is true.
-	 */
-	if (sc->tx_queued) {
-		/*
-		 * need_mcsetup will be true if we are already waiting for the
-		 * NOP command to be completed (see below). In this case, bail.
-		 */
-		if (sc->need_mcsetup)
-			return;
-		sc->need_mcsetup = 1;
 
-		/*
-		 * Add a NOP command with interrupt so that we are notified
-		 * when all TX commands have been processed.
-		 */
-		txp = sc->fxp_desc.tx_last->tx_next;
-		txp->tx_mbuf = NULL;
-		txp->tx_cb->cb_status = 0;
-		txp->tx_cb->cb_command = htole16(FXP_CB_COMMAND_NOP |
-		    FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);
-		/*
-		 * Advance the end of list forward.
-		 */
-		sc->fxp_desc.tx_last->tx_cb->cb_command &=
-		    htole16(~FXP_CB_COMMAND_S);
-		bus_dmamap_sync(sc->cbl_tag, sc->cbl_map, BUS_DMASYNC_PREWRITE);
-		sc->fxp_desc.tx_last = txp;
-		sc->tx_queued++;
-		/*
-		 * Issue a resume in case the CU has just suspended.
-		 */
-		fxp_scb_wait(sc);
-		fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_RESUME);
-		/*
-		 * Set a 5 second timer just in case we don't hear from the
-		 * card again.
-		 */
-		sc->watchdog_timer = 5;
-
-		return;
-	}
-	sc->need_mcsetup = 0;
-
-	/*
-	 * Initialize multicast setup descriptor.
-	 */
+	mcsp = sc->mcsp;
 	mcsp->cb_status = 0;
-	mcsp->cb_command = htole16(FXP_CB_COMMAND_MCAS |
-	    FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);
-	mcsp->link_addr = htole32(sc->fxp_desc.cbl_addr);
-	txp = &sc->fxp_desc.mcs_tx;
-	txp->tx_mbuf = NULL;
-	txp->tx_cb = (struct fxp_cb_tx *)sc->mcsp;
-	txp->tx_next = sc->fxp_desc.tx_list;
-	(void) fxp_mc_addrs(sc);
-	sc->fxp_desc.tx_first = sc->fxp_desc.tx_last = txp;
-	sc->tx_queued = 1;
+	mcsp->cb_command = htole16(FXP_CB_COMMAND_MCAS | FXP_CB_COMMAND_EL);
+	mcsp->link_addr = 0xffffffff;
+	fxp_mc_addrs(sc);
 
 	/*
-	 * Wait until command unit is not active. This should never
-	 * be the case when nothing is queued, but make sure anyway.
+	 * Wait until command unit is idle. This should never be the
+	 * case when nothing is queued, but make sure anyway.
 	 */
 	count = 100;
-	while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) ==
-	    FXP_SCB_CUS_ACTIVE && --count)
+	while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) !=
+	    FXP_SCB_CUS_IDLE && --count)
 		DELAY(10);
 	if (count == 0) {
 		device_printf(sc->dev, "command queue timeout\n");
@@ -2946,12 +2921,12 @@
 	 * Start the multicast setup command.
 	 */
 	fxp_scb_wait(sc);
-	bus_dmamap_sync(sc->mcs_tag, sc->mcs_map, BUS_DMASYNC_PREWRITE);
+	bus_dmamap_sync(sc->mcs_tag, sc->mcs_map,
+	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
 	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, sc->mcs_addr);
 	fxp_scb_cmd(sc, FXP_SCB_COMMAND_CU_START);
-
-	sc->watchdog_timer = 2;
-	return;
+	/* ...and wait for it to complete. */
+	fxp_dma_wait(sc, &mcsp->cb_status, sc->mcs_tag, sc->mcs_map);
 }
 
 static uint32_t fxp_ucode_d101a[] = D101_A_RCVBUNDLE_UCODE;


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105281107.p4SB7U7D012249>