changeset 4404:a0cc4e7d9fb5

PSARC 2007/243 Eri Conversion To GLDv3 4891285 RFE to add debug kstat counter for promiscuous mode to eri driver 6490162 eri passes packets upstream before the stream is in the DL_IDLE state 6549493 convert eri to GLDv3
author gd78059
date Thu, 07 Jun 2007 06:48:35 -0700
parents 77da60925cac
children 6d1bc9962bf5
files usr/src/uts/sparc/eri/Makefile usr/src/uts/sun/io/eri.c usr/src/uts/sun/sys/eri.h usr/src/uts/sun/sys/eri_common.h usr/src/uts/sun/sys/eri_mac.h usr/src/uts/sun/sys/eri_msg.h
diffstat 6 files changed, 1274 insertions(+), 4871 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/sparc/eri/Makefile	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sparc/eri/Makefile	Thu Jun 07 06:48:35 2007 -0700
@@ -23,7 +23,7 @@
 #
 #ident	"%Z%%M%	%I%	%E% SMI"
 #
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 #	This makefile drives the production of the eri driver
@@ -66,17 +66,7 @@
 #	Overrides.
 #
 CFLAGS		+= $(CCVERBOSE)
-
-#
-# For now, disable these lint checks; maintainers should endeavor
-# to investigate and remove these for maximum lint coverage.
-# Please do not carry these forward to new Makefiles.
-#
-LINTTAGS	+= -erroff=E_BAD_PTR_CAST_ALIGN
-LINTTAGS	+= -erroff=E_PTRDIFF_OVERFLOW
-LINTTAGS	+= -erroff=E_ASSIGN_NARROW_CONV
-LINTTAGS	+= -erroff=E_STATIC_UNUSED
-LINTTAGS	+= -erroff=E_SUSPICIOUS_COMPARISON
+LDFLAGS		+= -dy -N misc/mac -N drv/ip
 
 #
 #	Default build targets.
--- a/usr/src/uts/sun/io/eri.c	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sun/io/eri.c	Thu Jun 07 06:48:35 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,7 +35,6 @@
 #include	<sys/stream.h>
 #include	<sys/strlog.h>
 #include	<sys/strsubr.h>
-#include	<sys/vtrace.h>
 #include	<sys/kmem.h>
 #include	<sys/crc32.h>
 #include	<sys/ddi.h>
@@ -45,12 +44,14 @@
 #include	<sys/cpu.h>
 #include	<sys/kstat.h>
 #include	<inet/common.h>
-#include	<sys/dlpi.h>
 #include	<sys/pattr.h>
 #include	<inet/mi.h>
 #include	<inet/nd.h>
 #include	<sys/ethernet.h>
 #include	<sys/policy.h>
+#include	<sys/mac.h>
+#include	<sys/mac_ether.h>
+#include	<sys/dlpi.h>
 
 #include	<sys/pci.h>
 
@@ -71,42 +72,29 @@
  * Entry points (man9e)
  */
 static	int	eri_attach(dev_info_t *, ddi_attach_cmd_t);
-static	int	eri_close(queue_t *);
 static	int	eri_detach(dev_info_t *, ddi_detach_cmd_t);
-static	uint_t	eri_intr();
-static	int	eri_open(queue_t *, dev_t *, int, int, cred_t *);
-#ifdef	 ERI_SERVICE_ROUTINE
-static	int	eri_rsrv(queue_t *);
-#endif
-static	int	eri_wput(queue_t *, mblk_t *);
-static	int	eri_wsrv(queue_t *);
-static	void	eri_wenable(struct eri *);
-static	void 	eri_sendup(struct eri *, mblk_t *, struct eristr *(*)());
+static	uint_t	eri_intr(caddr_t);
 
 /*
  * I/O (Input/Output) Functions
  */
-static	int	eri_start(queue_t *, mblk_t *, struct eri *);
-static  void    eri_read_dma(struct eri *, volatile struct rmd *,
-			volatile int, uint64_t flags);
+static	boolean_t	eri_send_msg(struct eri *, mblk_t *);
+static  mblk_t		*eri_read_dma(struct eri *, volatile struct rmd *,
+			    volatile int, uint64_t flags);
 
 /*
  * Initialization Functions
  */
-static  int	eri_init(struct eri *);
+static  boolean_t	eri_init(struct eri *);
 static	int	eri_allocthings(struct eri *);
 static  int	eri_init_xfer_params(struct eri *);
 static  void	eri_statinit(struct eri *);
 static	int	eri_burstsize(struct eri *);
 
 static	void	eri_setup_mac_address(struct eri *, dev_info_t *);
-static 	char	*eri_ether_sprintf(struct ether_addr *);
 
 static	uint32_t eri_init_rx_channel(struct eri *);
 static	void	eri_init_rx(struct eri *);
-#ifdef	LATER_SPLIT_TX_RX
-static	void	eri_init_tx_channel(struct eri *);
-#endif
 static	void	eri_init_txmac(struct eri *);
 
 /*
@@ -117,14 +105,11 @@
 static	int	eri_stop(struct eri *);
 static	void	eri_uninit(struct eri *erip);
 static	int	eri_freebufs(struct eri *);
-static	uint_t	eri_reclaim(struct eri *, uint32_t);
+static	boolean_t	eri_reclaim(struct eri *, uint32_t);
 
 /*
  * Transceiver (xcvr) Functions
  */
-#ifdef	XCVR
-static	int	eri_init_xcvr_info(struct eri *, int);
-#endif
 static	int	eri_new_xcvr(struct eri *); /* Initializes & detects xcvrs */
 static	int	eri_reset_xcvr(struct eri *);
 
@@ -135,8 +120,7 @@
 static	void	eri_mif_poll(struct eri *, soft_mif_enable_t);
 static	void	eri_check_link(struct eri *);
 static	uint32_t eri_check_link_noind(struct eri *);
-static	void	eri_display_link_status(struct eri *);
-static	uint32_t eri_mif_check(struct eri *, uint16_t, uint16_t);
+static	link_state_t eri_mif_check(struct eri *, uint16_t, uint16_t);
 static	void    eri_mii_write(struct eri *, uint8_t, uint16_t);
 static	uint32_t eri_mii_read(struct eri *, uint8_t, uint16_t *);
 
@@ -159,8 +143,7 @@
 /*
  * Hardening Functions
  */
-static void eri_fault_msg(char *, uint_t, struct eri *, uint_t,
-			    msg_t, char *, ...);
+static void eri_fault_msg(struct eri *, uint_t, msg_t, const char *, ...);
 
 /*
  * Misc Functions
@@ -171,15 +154,6 @@
 static	void	eri_start_timer(struct eri *erip, fptrv_t func, clock_t msec);
 
 static	void eri_bb_force_idle(struct eri *);
-static	int eri_mcmatch(struct eristr *, struct ether_addr *);
-static	struct eristr *eri_paccept(struct eristr *, struct eri *, int,
-	struct	ether_addr *);
-
-static	struct eristr *eri_accept(struct eristr *, struct eri *, int,
-	struct ether_addr *);
-
-static	mblk_t *eri_addudind(struct eri *, mblk_t *, struct ether_addr *,
-	struct ether_addr *, int, uint32_t);
 
 /*
  * Utility Functions
@@ -188,7 +162,6 @@
 static	mblk_t *eri_allocb_sp(size_t size);
 static	int	eri_param_get(queue_t *q, mblk_t *mp, caddr_t cp);
 static	int	eri_param_set(queue_t *, mblk_t *, char *, caddr_t);
-static	long	eri_strtol(char *, char **, int);
 
 /*
  * Functions to support ndd
@@ -201,50 +174,41 @@
 static	int	eri_nd_getset(queue_t *q, caddr_t nd_param, MBLKP mp);
 static	void	eri_param_cleanup(struct eri *);
 static	int	eri_param_register(struct eri *, param_t *, int);
-static	void	eri_process_ndd_ioctl(queue_t *wq, mblk_t *mp, int cmd);
-
-static	void    eri_cable_down_msg(struct eri *);
+static	void	eri_process_ndd_ioctl(struct eri *, queue_t *, mblk_t *, int);
+static	int	eri_mk_mblk_tail_space(mblk_t *, mblk_t **, size_t);
+
+
+static	void eri_loopback(struct eri *, queue_t *, mblk_t *);
+
+static uint32_t	eri_ladrf_bit(const uint8_t *);
+
 
 /*
- * DLPI Functions
+ * Nemo (GLDv3) Functions.
  */
-
-static	void eri_proto(queue_t *, mblk_t *);
-static	void eri_ioctl(queue_t *, mblk_t *);
-static	void eri_loopback(queue_t *, mblk_t *);
-static	void eri_mctl(queue_t *q, MBLKP mp);
-static	void eri_dodetach(struct eristr *);
-
-static	void eri_dl_ioc_hdr_info(queue_t *, mblk_t *);
-
-static	void eri_areq(queue_t *, mblk_t *);
-static	void eri_dreq(queue_t *, mblk_t *);
-static	void eri_breq(queue_t *, mblk_t *);
-static	void eri_ubreq(queue_t *, mblk_t *);
-static	void eri_ireq(queue_t *, mblk_t *);
-static	void eri_ponreq(queue_t *, mblk_t *);
-static	void eri_poffreq(queue_t *, mblk_t *);
-static	void eri_emreq(queue_t *, mblk_t *);
-static	void eri_dmreq(queue_t *, mblk_t *);
-static	void eri_pareq(queue_t *, mblk_t *);
-static	void eri_spareq(queue_t *, mblk_t *);
-static	void eri_udreq(queue_t *, mblk_t *);
-static	void eri_nreq(queue_t *, mblk_t *);
-static	void eri_dlcap_req(queue_t *, mblk_t *);
-static	mblk_t *eri_dlcap_all(queue_t *);
-static	void eri_dlcap_enable(queue_t *, mblk_t *);
-
-static	void eri_notify_ind(struct eri *, uint32_t);
-static	void eri_send_notifications(struct eri *, uint32_t);
-
-static	void eri_setipq(struct eri *);
-
-static uint32_t	eri_ladrf_bit(struct ether_addr *addr);
-
-static	void 	eri_process_ndd_ioctl(queue_t *wq, mblk_t *mp, int cmd);
-
-static	int eri_mk_mblk_tail_space(mblk_t *, mblk_t **, size_t);
-
+static	int		eri_m_stat(void *, uint_t, uint64_t *);
+static	int		eri_m_start(void *);
+static	void		eri_m_stop(void *);
+static	int		eri_m_promisc(void *, boolean_t);
+static	int		eri_m_multicst(void *, boolean_t, const uint8_t *);
+static	int		eri_m_unicst(void *, const uint8_t *);
+static	void		eri_m_ioctl(void *, queue_t *, mblk_t *);
+static	boolean_t	eri_m_getcapab(void *, mac_capab_t, void *);
+static	mblk_t		*eri_m_tx(void *, mblk_t *);
+
+static mac_callbacks_t eri_m_callbacks = {
+	MC_IOCTL | MC_GETCAPAB,
+	eri_m_stat,
+	eri_m_start,
+	eri_m_stop,
+	eri_m_promisc,
+	eri_m_multicst,
+	eri_m_unicst,
+	eri_m_tx,
+	NULL,
+	eri_m_ioctl,
+	eri_m_getcapab
+};
 
 /*
  * Define PHY Vendors: Matches to IEEE
@@ -263,99 +227,26 @@
 #define	FORCE_SPEED		1
 
 /*
- * link_up kstat variable states
- */
-#define	ERI_LINK_DOWN		0
-#define	ERI_LINK_UP		1
-
-/*
- * States for kstat variable link_duplex
- */
-#define	ERI_UNKNOWN_DUPLEX	0
-#define	ERI_HALF_DUPLEX		1
-#define	ERI_FULL_DUPLEX		2
-
-/*
- * tcp and ip data structures used to grab some length
- * and type information in eri_read_dma().
- */
-#ifdef ERI_RCV_CKSUM
-typedef struct ip {
-	uint8_t		ip_v:4;		/* version */
-	uint8_t		ip_hl:4;	/* header length */
-	uint8_t		ip_tos;		/* type of service */
-	int16_t		ip_len;		/* total length */
-	uint16_t	ip_id;		/* identification */
-	int16_t		ip_off;		/* fragment offset field */
-	uint8_t		ip_ttl;		/* time to live */
-	uint8_t		ip_p;		/* protocol */
-	uint16_t	ip_sum;		/* checksum */
-	uint32_t	ip_src;		/* src address */
-	uint32_t	ip_dst;		/* dest address */
-} ip_t;
-
-typedef struct tcphdr {
-	uint16_t	th_sport;	/* source port */
-	uint16_t	th_dport;	/* destination port */
-	uint32_t	th_seq;		/* sequence number */
-	uint32_t	th_ack;		/* acknowledgement number */
-	uint8_t		th_off:4,	/* data offset */
-			th_x2:4;	/* (unused) */
-	uint8_t		th_flags;
-	uint16_t	th_win;		/* window */
-	uint16_t	th_sum;		/* checksum */
-	uint16_t	th_urp;		/* urgent pointer */
-} tcp_t;
-
-#endif
-
-/*
  * MIB II broadcast/multicast packets
  */
-#define	IS_NOT_MULTICAST(ehp) \
-		((ehp->ether_dhost.ether_addr_octet[0] & 01) == 0)
-
-#define	IS_BROADCAST(ehp) \
-		(ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0)
-#define	IS_MULTICAST(ehp) \
-		((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)
-#define	BUMP_InNUcast(erip, ehp) \
-		if (IS_BROADCAST(ehp)) { \
+
+#define	IS_BROADCAST(pkt) (bcmp(pkt, &etherbroadcastaddr, ETHERADDRL) == 0)
+#define	IS_MULTICAST(pkt) ((pkt[0] & 01) == 1)
+
+#define	BUMP_InNUcast(erip, pkt) \
+		if (IS_BROADCAST(pkt)) { \
 			HSTAT(erip, brdcstrcv); \
-		} else if (IS_MULTICAST(ehp)) { \
+		} else if (IS_MULTICAST(pkt)) { \
 			HSTAT(erip, multircv); \
 		}
 
-#define	BUMP_OutNUcast(erip, ehp) \
-		if (IS_BROADCAST(ehp)) { \
+#define	BUMP_OutNUcast(erip, pkt) \
+		if (IS_BROADCAST(pkt)) { \
 			HSTAT(erip, brdcstxmt); \
-		} else if (IS_MULTICAST(ehp)) { \
+		} else if (IS_MULTICAST(pkt)) { \
 			HSTAT(erip, multixmt); \
 		}
 
-	/*
-	 * ERI 1.0 has a bug  in which  the last byte of the MAC address is
-	 * ehp->ether_dhost.ether_addr_octet[5]
-	 * not filtered thus accepting all the packets with the first five bytes
-	 * match. Here we filter out the packets which are not intended for us.
-	 *
-	 *  !(ehp->ether_dhost.ether_addr_octet[0] & 0x1) checks if the packet
-	 * is not mutlicast.
-	 *
-	 * (ehp->ether_dhost.ether_addr_octet[1] &
-	 * ehp->ether_dhost.ether_addr_octet[5]) != 0xff ), checks if the
-	 * the packet could be a broadcast. If it were broadcast, both bytes
-	 * would be 0xff. This could be never true for unicast because
-	 * the vendor portion for Sun would 8:0:20.
-	 */
-
-#define	INVALID_MAC_ADDRESS(erip, ehp) \
-		(!(erip->flags & ERI_PROMISC) && \
-		(IS_NOT_MULTICAST(ehp) && ~IS_BROADCAST(ehp) && \
-		(erip->ouraddr.ether_addr_octet[5] != \
-		ehp->ether_dhost.ether_addr_octet[5])))
-
-
 #define	NEXTTMDP(tbasep, tmdlimp, tmdp)	(((tmdp) + 1) == tmdlimp	\
 	? tbasep : ((tmdp) + 1))
 
@@ -364,12 +255,8 @@
 #ifdef	ERI_RCV_CKSUM
 #define	ERI_PROCESS_READ(erip, bp, sum)				\
 {								\
-	queue_t *ipq;						\
 	t_uscalar_t	type;					\
-	struct	ether_header *ehp;				\
-	uint_t	sb_flags;					\
 	uint_t	start_offset, end_offset;			\
-	ehp = (struct ether_header *)bp->b_rptr;		\
 								\
 	*(bp->b_wptr) = 0;	/* pad byte */			\
 								\
@@ -378,33 +265,15 @@
 	 */							\
 	HSTAT(erip, ipackets64);				\
 	HSTATN(erip, rbytes64, len);				\
-	BUMP_InNUcast(erip, ehp);				\
-	type = get_ether_type(ehp);				\
-	ipq = erip->ip4q;					\
-	if (type == ETHERTYPE_IPV6)				\
-		ipq = erip->ip6q;				\
-	if ((type == ETHERTYPE_IPV4 || type == ETHERTYPE_IPV6) && \
-		(IS_NOT_MULTICAST(ehp)) && (ipq) && 		\
-		(((ether_cmp(ehp, &erip->ouraddr) == 0) || 	\
-		(ether_cmp(ehp, &etherbroadcastaddr) == 0)))) { \
-		bp->b_rptr += ETHERHEADER_SIZE;			\
+	BUMP_InNUcast(erip, bp->b_rptr);			\
+	type = get_ether_type(bp->b_rptr);			\
+	if (type == ETHERTYPE_IP || type == ETHERTYPE_IPV6) {	\
 		start_offset = 0;				\
-		end_offset = bp->b_wptr - bp->b_rptr;		\
-		sb_flags = ((struct eristr *)ipq->q_ptr)->sb_flags;\
-		if ((sb_flags & ERI_SCKSUM) &&			\
-			(sb_flags & ERI_SFAST)) {		\
-				(void) hcksum_assoc(bp, NULL, 	\
-				    NULL, start_offset, 0, 	\
-				    end_offset, sum, 		\
-				    HCK_PARTIALCKSUM, 0);	\
-		}						\
-		if (canputnext(ipq))				\
-			(void) putnext(ipq, bp);		\
-		else {						\
-			freemsg(bp);				\
-			HSTAT(erip, nocanput);			\
-			HSTAT(erip, ierrors);			\
-		}						\
+		end_offset = bp->b_wptr - 			\
+			(bp->b_rptr + ETHERHEADER_SIZE);	\
+		(void) hcksum_assoc(bp, NULL, NULL,		\
+			start_offset, 0, end_offset, sum, 	\
+			HCK_PARTIALCKSUM, 0);			\
 	} else {						\
 		/*						\
 		 * Strip the PADS for 802.3			\
@@ -412,43 +281,27 @@
 		if (type <= ETHERMTU)				\
 			bp->b_wptr = bp->b_rptr +		\
 				ETHERHEADER_SIZE + type;	\
-		eri_sendup(erip, bp, eri_accept);		\
 	}							\
 }
 #else
 
 #define	ERI_PROCESS_READ(erip, bp)				\
 {								\
-	queue_t *ipq;						\
 	t_uscalar_t	type;					\
-	struct	ether_header *ehp;				\
-	uint_t	sb_flags;					\
-	ehp = (struct ether_header *)bp->b_rptr;		\
-	type = get_ether_type(ehp);				\
-	ipq = erip->ip4q;					\
-	if (type == ETHERTYPE_IPV6)				\
-		ipq = erip->ip6q;				\
-	if ((type == ETHERTYPE_IPV4 || type == ETHERTYPE_IPV6) && \
-		(IS_NOT_MULTICAST(ehp)) && (ipq) && 		\
-		(((ether_cmp(ehp, &erip->ouraddr) == 0) || 	\
-		(ether_cmp(ehp, &etherbroadcastaddr) == 0)))) { \
-		bp->b_rptr += ETHERHEADER_SIZE;			\
-		if (canputnext(ipq))				\
-			(void) putnext(ipq, bp);		\
-		else {						\
-			freemsg(bp);				\
-			HSTAT(erip, nocanput);			\
-			HSTAT(erip, ierrors);			\
-		}						\
-	} else {						\
-		/*						\
-		 * Strip the PADS for 802.3			\
-		 */						\
-		if (type <= ETHERMTU)				\
-			bp->b_wptr = bp->b_rptr +		\
-				ETHERHEADER_SIZE + type;	\
-		eri_sendup(erip, bp, eri_accept);		\
-	}							\
+	type = get_ether_type(bp->b_rptr);			\
+								\
+	/*							\
+	 * update MIB II statistics				\
+	 */							\
+	HSTAT(erip, ipackets64);				\
+	HSTATN(erip, rbytes64, len);				\
+	BUMP_InNUcast(erip, bp->b_rptr);			\
+	/*							\
+	 * Strip the PADS for 802.3				\
+	 */							\
+	if (type <= ETHERMTU)					\
+		bp->b_wptr = bp->b_rptr + ETHERHEADER_SIZE + 	\
+			type;					\
 }
 #endif  /* ERI_RCV_CKSUM */
 
@@ -460,29 +313,10 @@
 /*
  * Ethernet broadcast address definition.
  */
-static struct ether_addr	etherbroadcastaddr = {
+static uint8_t	etherbroadcastaddr[] = {
 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff
 };
 
-#define	ERI_SAPMATCH(sap, type, flags) ((sap == type)? 1 : \
-	((flags & ERI_SALLSAP)? 1 : \
-	((sap <= ETHERMTU) && (sap >= (t_uscalar_t)0) && \
-	(type <= ETHERMTU))? 1 : 0))
-
-/*
- * Linked list of active (inuse) driver Streams.
- */
-static	struct	eristr	*eristrup = NULL;
-static	krwlock_t	eristruplock;
-
-/*
- * Single private "global" lock for the few rare conditions
- * we want single-threaded.
- */
-static	kmutex_t	erilock;
-static	kmutex_t	eriwenlock;
-static	struct eri *eriup = NULL;
-
 /*
  * The following variables are used for configuring various features
  */
@@ -678,7 +512,6 @@
 
 static	int	eri_force_mlf = 0; 	/* to enable mif poll */
 static	int	eri_phy_mintrans = 1;	/* Lu3X31T mintrans algorithm */
-static	int	eri_hash_filter = 1;	/* use hash filter vs group bit */
 /*
  * For the MII interface, the External Transceiver is selected when present.
  * The following variable is used to select the Internal Transceiver even
@@ -686,7 +519,6 @@
  */
 static	int	use_int_xcvr = 0;
 static	int	pace_size = 0;	/* Do not use pacing for now */
-static	int	device = -1;
 
 static	int	eri_use_dvma_rx = 0;	/* =1:use dvma */
 static	int	eri_use_dvma_tx = 1;	/* =1:use dvma */
@@ -720,198 +552,52 @@
 /* ------------------------------------------------------------------------- */
 
 static  param_t	param_arr[] = {
-	/* min		max		value		name */
-	{  0,		2,		2,		"transceiver_inuse"},
-	{  0,		1,		0,		"link_status"},
-	{  0,		1,		0,		"link_speed"},
-	{  0,		1,		0,		"link_mode"},
-	{  0,		255,		8,		"ipg1"},
-	{  0,		255,		4,		"ipg2"},
-	{  0,		1,		0,		"use_int_xcvr"},
-	{  0,		255,		0,		"pace_size"},
-	{  0,		1,		1,		"adv_autoneg_cap"},
-	{  0,		1,		1,		"adv_100T4_cap"},
-	{  0,		1,		1,		"adv_100fdx_cap"},
-	{  0,		1,		1,		"adv_100hdx_cap"},
-	{  0,		1,		1,		"adv_10fdx_cap"},
-	{  0,		1,		1,		"adv_10hdx_cap"},
-	{  0,		1,		1,		"autoneg_cap"},
-	{  0,		1,		1,		"100T4_cap"},
-	{  0,		1,		1,		"100fdx_cap"},
-	{  0,		1,		1,		"100hdx_cap"},
-	{  0,		1,		1,		"10fdx_cap"},
-	{  0,		1,		1,		"10hdx_cap"},
-	{  0,		1,		0,		"lp_autoneg_cap"},
-	{  0,		1,		0,		"lp_100T4_cap"},
-	{  0,		1,		0,		"lp_100fdx_cap"},
-	{  0,		1,		0,		"lp_100hdx_cap"},
-	{  0,		1,		0,		"lp_10fdx_cap"},
-	{  0,		1,		0,		"lp_10hdx_cap"},
-	{  0,		255,		0,		"instance"},
-	{  0,		1,		1,		"lance_mode"},
-	{  0,		31,		8,		"ipg0"},
-	{  0,		127,		6,		"intr_blank_time"},
-	{  0,		255,		8,		"intr_blank_packets"},
-	{  0,		1,		1,		"serial-link"},
-	{  0,		2,		1,		"non-serial-link"},
-	{  0,		1,		0,		"select-link"},
-	{  0,		1,		0,		"default-link"},
-	{  0,		2,		0,		"link-in-use"},
-	{  0,		1,		1,		"adv_1000autoneg_cap"},
-	{  0,		1,		1,		"adv_1000fdx_cap"},
-	{  0,		1,		1,		"adv_1000hdx_cap"},
-	{  0,		1,		1,		"adv_asm_dir_cap"},
-	{  0,		1,		1,		"adv_pause_cap"},
-	{  0,		1,		0,		"1000autoneg_cap"},
-	{  0,		1,		0,		"1000fdx_cap"},
-	{  0,		1,		0,		"1000hdx_cap"},
-	{  0,		1,		0,		"asm_dir_cap"},
-	{  0,		1,		0,		"pause_cap"},
-	{  0,		1,		0,		"lp_1000autoneg_cap"},
-	{  0,		1,		0,		"lp_1000fdx_cap"},
-	{  0,		1,		0,		"lp_1000hdx_cap"},
-	{  0,		1,		0,		"lp_asm_dir_cap"},
-	{  0,		1,		0,		"lp_pause_cap"},
+	/* min		max		value	r/w/hidden+name */
+	{  0,		2,		2,	"-transceiver_inuse"},
+	{  0,		1,		0,	"-link_status"},
+	{  0,		1,		0,	"-link_speed"},
+	{  0,		1,		0,	"-link_mode"},
+	{  0,		255,		8,	"+ipg1"},
+	{  0,		255,		4,	"+ipg2"},
+	{  0,		1,		0,	"+use_int_xcvr"},
+	{  0,		255,		0,	"+pace_size"},
+	{  0,		1,		1,	"+adv_autoneg_cap"},
+	{  0,		1,		1,	"+adv_100T4_cap"},
+	{  0,		1,		1,	"+adv_100fdx_cap"},
+	{  0,		1,		1,	"+adv_100hdx_cap"},
+	{  0,		1,		1,	"+adv_10fdx_cap"},
+	{  0,		1,		1,	"+adv_10hdx_cap"},
+	{  0,		1,		1,	"-autoneg_cap"},
+	{  0,		1,		1,	"-100T4_cap"},
+	{  0,		1,		1,	"-100fdx_cap"},
+	{  0,		1,		1,	"-100hdx_cap"},
+	{  0,		1,		1,	"-10fdx_cap"},
+	{  0,		1,		1,	"-10hdx_cap"},
+	{  0,		1,		0,	"-lp_autoneg_cap"},
+	{  0,		1,		0,	"-lp_100T4_cap"},
+	{  0,		1,		0,	"-lp_100fdx_cap"},
+	{  0,		1,		0,	"-lp_100hdx_cap"},
+	{  0,		1,		0,	"-lp_10fdx_cap"},
+	{  0,		1,		0,	"-lp_10hdx_cap"},
+	{  0,		1,		1,	"+lance_mode"},
+	{  0,		31,		8,	"+ipg0"},
+	{  0,		127,		6,	"+intr_blank_time"},
+	{  0,		255,		8,	"+intr_blank_packets"},
+	{  0,		1,		1,	"!serial-link"},
+	{  0,		2,		1,	"!non-serial-link"},
+	{  0,		1,		0,	"%select-link"},
+	{  0,		1,		0,	"%default-link"},
+	{  0,		2,		0,	"!link-in-use"},
+	{  0,		1,		1,	"%adv_asm_dir_cap"},
+	{  0,		1,		1,	"%adv_pause_cap"},
+	{  0,		1,		0,	"!asm_dir_cap"},
+	{  0,		1,		0,	"!pause_cap"},
+	{  0,		1,		0,	"!lp_asm_dir_cap"},
+	{  0,		1,		0,	"!lp_pause_cap"},
 };
 
-#define	DISPLAY_PARAM	1
-#define	DONT_DISPLAY	0
-
-
-static  uint32_t	param_display_mii[] = {
-/* DISPLAY */
-DISPLAY_PARAM,		/* transceiver_inuse */
-DISPLAY_PARAM,		/* link_status */
-DISPLAY_PARAM,		/* link_speed */
-DISPLAY_PARAM,		/* link_mode */
-DISPLAY_PARAM,		/* ipg1 */
-DISPLAY_PARAM,		/* ipg2 */
-DISPLAY_PARAM,		/* use_int_xcvr */
-DISPLAY_PARAM,		/* pace_size */
-DISPLAY_PARAM,		/* adv_autoneg_cap */
-DISPLAY_PARAM,		/* adv_100T4_cap */
-DISPLAY_PARAM,		/* adv_100fdx_cap */
-DISPLAY_PARAM,		/* adv_100hdx_cap */
-DISPLAY_PARAM,		/* adv_10fdx_cap */
-DISPLAY_PARAM,		/* adv_10hdx_cap */
-DISPLAY_PARAM,		/* autoneg_cap */
-DISPLAY_PARAM,		/* 100T4_cap */
-DISPLAY_PARAM,		/* 100fdx_cap */
-DISPLAY_PARAM,		/* 100hdx_cap */
-DISPLAY_PARAM,		/* 10fdx_cap */
-DISPLAY_PARAM,		/* 10hdx_cap */
-DISPLAY_PARAM,		/* lp_autoneg_cap */
-DISPLAY_PARAM,		/* lp_100T4_cap */
-DISPLAY_PARAM,		/* lp_100fdx_cap */
-DISPLAY_PARAM,		/* lp_100hdx_cap */
-DISPLAY_PARAM,		/* lp_10fdx_cap */
-DISPLAY_PARAM,		/* lp_10hdx_cap */
-DISPLAY_PARAM,		/* instance */
-DISPLAY_PARAM,		/* lance_mode */
-DISPLAY_PARAM,		/* ipg0 */
-DISPLAY_PARAM,		/* intr_blank_time */
-DISPLAY_PARAM,		/* intr_blank_packets */
-DONT_DISPLAY,		/* serial-link */
-DONT_DISPLAY,		/* non-serial-link */
-DONT_DISPLAY,		/* select-link */
-DONT_DISPLAY,		/* default-link */
-DONT_DISPLAY,		/* link-in-use */
-DONT_DISPLAY,		/* adv_1000autoneg_cap */
-DONT_DISPLAY,		/* adv_1000fdx_cap */
-DONT_DISPLAY,		/* adv_1000hdx_cap */
-DONT_DISPLAY,		/* adv_asm_dir */
-DONT_DISPLAY,		/* adv_pause */
-DONT_DISPLAY,		/* 1000autoneg_cap */
-DONT_DISPLAY,		/* 1000fdx_cap */
-DONT_DISPLAY,		/* 1000hdx_cap */
-DONT_DISPLAY,		/* asm_dir_cap */
-DONT_DISPLAY,		/* pause_cap */
-DONT_DISPLAY,		/* lp_1000autoneg_cap */
-DONT_DISPLAY,		/* lp_1000fdx_cap */
-DONT_DISPLAY,		/* lp_1000hdx_cap */
-DONT_DISPLAY,		/* lp_asm_dir */
-DONT_DISPLAY,		/* lp_pause */
-};
-
-
-static	struct	module_info	eriinfo = {
-	ERI_IDNUM,	/* mi_idnum */
-	ERI_NAME,	/* mi_idname */
-	ERI_MINPSZ,	/* mi_minpsz */
-	ERI_MAXPSZ,	/* mi_maxpsz */
-	ERI_HIWAT,	/* mi_hiwat */
-	ERI_LOWAT	/* mi_lowat */
-};
-
-static	struct	qinit	eri_rinit = {
-	NULL,		/* qi_putp */
-#ifdef ERI_SERVICE_ROUTINE
-	eri_rsrv,	/* qi_srvp */
-#else
-	NULL,		/* qi_srvp */
-#endif
-	eri_open,	/* qi_qopen */
-	eri_close,	/* qi_qclose */
-	NULL,		/* qi_qadmin */
-	&eriinfo,	/* qi_minfo */
-	NULL		/* qi_mstat */
-};
-
-static	struct	qinit	eri_winit = {
-	eri_wput,	/* qi_putp */
-	eri_wsrv,	/* qi_srvp */
-	NULL,		/* qi_qopen */
-	NULL,		/* qi_qclose */
-	NULL,		/* qi_qadmin */
-	&eriinfo,	/* qi_minfo */
-	NULL		/* qi_mstat */
-};
-
-static struct	streamtab	er_info = {
-	&eri_rinit,	/* st_rdinit */
-	&eri_winit,	/* st_wrinit */
-	NULL,		/* st_muxrinit */
-	NULL		/* st_muxwrinit */
-};
-
-static	struct	cb_ops	cb_eri_ops = {
-	nodev,			/* cb_open */
-	nodev,			/* cb_close */
-	nodev,			/* cb_strategy */
-	nodev,			/* cb_print */
-	nodev,			/* cb_dump */
-	nodev,			/* cb_read */
-	nodev,			/* cb_write */
-	nodev,			/* cb_ioctl */
-	nodev,			/* cb_devmap */
-	nodev,			/* cb_mmap */
-	nodev,			/* cb_segmap */
-	nochpoll,		/* cb_chpoll */
-	ddi_prop_op,		/* cb_prop_op */
-	&er_info,		/* cb_stream */
-	D_MP | D_HOTPLUG,	/* cb_flag */
-	CB_REV,			/* rev */
-	nodev,			/* int (*cb_aread() */
-	nodev			/* int (*cb_awrite() */
-};
-
-static	struct	dev_ops	eri_ops = {
-	DEVO_REV,		/* devo_rev */
-	0,			/* devo_refcnt */
-	ddi_no_info,		/* devo_getinfo */
-	nulldev,		/* devo_identify */
-	nulldev,		/* devo_probe */
-	eri_attach,		/* devo_attach */
-	eri_detach,		/* devo_detach */
-	nodev,			/* devo_reset */
-	&cb_eri_ops,		/* devo_cb_ops */
-	(struct bus_ops *)NULL,	/* devo_bus_ops */
-	NULL			/* devo_power */
-};
-
-#ifndef lint
-char _depends_on[] = "drv/ip";
-#endif
+DDI_DEFINE_STREAM_OPS(eri_dev_ops, nulldev, nulldev, eri_attach, eri_detach,
+	nodev, NULL, D_MP, NULL);
 
 /*
  * This is the loadable module wrapper.
@@ -923,8 +609,8 @@
  */
 static struct modldrv modldrv = {
 	&mod_driverops,	/* Type of module.  This one is a driver */
-	"10/100 Mb Ethernet Driver v%I% ",
-	&eri_ops,	/* driver ops */
+	"Sun RIO 10/100 Mb Ethernet",
+	&eri_dev_ops,	/* driver ops */
 };
 
 static struct modlinkage modlinkage = {
@@ -932,15 +618,6 @@
 };
 
 /*
- * XXX Autoconfiguration lock:  We want to initialize all the global
- * locks at _init().  However, we do not have the cookie required which
- * is returned in ddi_add_intr(), which in turn is usually called at attach
- * time.
- */
-
-static	kmutex_t	eriautolock;
-
-/*
  * Hardware Independent Functions
  * New Section
  */
@@ -950,47 +627,29 @@
 {
 	int	status;
 
-	mutex_init(&eriautolock, NULL, MUTEX_DRIVER, NULL);
-
-	status = mod_install(&modlinkage);
-	if (status != 0)
-		mutex_destroy(&eriautolock);
-
-	ERI_DEBUG_MSG2(NULL, MODCTL_MSG,
-			"_init status = 0x%X", status);
+	mac_init_ops(&eri_dev_ops, "eri");
+	if ((status = mod_install(&modlinkage)) != 0) {
+		mac_fini_ops(&eri_dev_ops);
+	}
 	return (status);
 }
 
 int
 _fini(void)
 {
-	int	status;
+	int status;
 
 	status = mod_remove(&modlinkage);
-	if (status != 0)
-		goto _fini_exit;
-
-	mutex_destroy(&erilock);
-	mutex_destroy(&eriwenlock);
-	rw_destroy(&eristruplock);
-	mutex_destroy(&eriautolock);
-
-_fini_exit:
-	ERI_DEBUG_MSG2(NULL, MODCTL_MSG,
-			"_fini status = 0x%X", status);
+	if (status == 0) {
+		mac_fini_ops(&eri_dev_ops);
+	}
 	return (status);
 }
 
-
 int
 _info(struct modinfo *modinfop)
 {
-	int	status;
-
-	status = mod_info(&modlinkage, modinfop);
-	ERI_DEBUG_MSG2(NULL, MODCTL_MSG,
-			"_info status = 0x%X", status);
-	return (status);
+	return (mod_info(&modlinkage, modinfop));
 }
 
 
@@ -1002,15 +661,12 @@
 static int
 eri_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 {
-	struct eri *erip;
-	static int	once = 1;
+	struct eri *erip = NULL;
+	mac_register_t *macp = NULL;
 	int	regno;
-
-	uint8_t	mutex_inited = 0;
-	uint8_t intr_add = 0;
-	uint8_t minor_node_created = 0;
-
-	ERI_DEBUG_MSG1(NULL, AUTOCONFIG_MSG, "eri_attach");
+	boolean_t	doinit;
+	boolean_t	mutex_inited = B_FALSE;
+	boolean_t	intr_add = B_FALSE;
 
 	switch (cmd) {
 	case DDI_ATTACH:
@@ -1020,40 +676,29 @@
 		if ((erip = ddi_get_driver_private(dip)) == NULL)
 			return (DDI_FAILURE);
 
+		mutex_enter(&erip->intrlock);
 		erip->flags &= ~ERI_SUSPENDED;
 		erip->init_macregs = 1;
 		param_linkup = 0;
-		erip->stats.link_up = ERI_LINK_DOWN;
+		erip->stats.link_up = LINK_STATE_DOWN;
 		erip->linkcheck = 0;
-		{
-			struct eristr	*sqp;
-			int doeriinit = 0;
-			rw_enter(&eristruplock, RW_READER);
-			/*
-			 * Do eri_init() only for active interface
-			 */
-			for (sqp = eristrup; sqp; sqp = sqp->sb_nextp)
-				if (sqp->sb_erip == erip) {
-					doeriinit = 1;
-					break;
-				}
-
-			rw_exit(&eristruplock);
-			if (doeriinit)
-				(void) eri_init(erip);
+
+		doinit =  (erip->flags & ERI_STARTED) ? B_TRUE : B_FALSE;
+		mutex_exit(&erip->intrlock);
+
+		if (doinit && !eri_init(erip)) {
+			return (DDI_FAILURE);
 		}
 		return (DDI_SUCCESS);
 
 	default:
-		ERI_DEBUG_MSG1(NULL, DEFAULT_MSG,
-				attach_bad_cmd_msg);
 		return (DDI_FAILURE);
 	}
 
 	/*
 	 * Allocate soft device data structure
 	 */
-	erip = GETSTRUCT(struct eri, 1);
+	erip = kmem_zalloc(sizeof (struct eri), KM_SLEEP);
 
 	/*
 	 * Initialize as many elements as possible.
@@ -1062,9 +707,21 @@
 	erip->dip = dip;			/* dip	*/
 	erip->instance = ddi_get_instance(dip);	/* instance */
 	erip->flags = 0;
-	erip->promisc_cnt = 0;
-	erip->all_multi_cnt = 0;
-	erip->all_sap_cnt = 0;
+	erip->multi_refcnt = 0;
+	erip->promisc = B_FALSE;
+
+	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
+		ERI_FAULT_MSG1(erip, SEVERITY_HIGH, ERI_VERB_MSG,
+		    "mac_alloc failed");
+		goto attach_fail;
+	}
+	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+	macp->m_driver = erip;
+	macp->m_dip = dip;
+	macp->m_src_addr = erip->ouraddr;
+	macp->m_callbacks = &eri_m_callbacks;
+	macp->m_min_sdu = 0;
+	macp->m_max_sdu = ETHERMTU;
 
 	/*
 	 * Map in the device registers.
@@ -1079,18 +736,16 @@
 
 	if (ddi_dev_nregs(dip, &regno) != (DDI_SUCCESS)) {
 		ERI_FAULT_MSG2(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-				"ddi_dev_nregs failed, returned %d", regno);
+		    "ddi_dev_nregs failed, returned %d", regno);
 		goto attach_fail;
 	}
 
 	/*
 	 * Map the PCI config space
 	 */
-	if (pci_config_setup(dip, &erip->pci_config_handle) !=
-		DDI_SUCCESS) {
+	if (pci_config_setup(dip, &erip->pci_config_handle) != DDI_SUCCESS) {
 		ERI_FAULT_MSG2(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-			"%s pci_config_setup()",
-			config_space_fatal_msg);
+		    "%s pci_config_setup()", config_space_fatal_msg);
 		goto attach_fail;
 	}
 
@@ -1101,12 +756,9 @@
 	erip->dev_attr.devacc_attr_dataorder =	DDI_STRICTORDER_ACC;
 	erip->dev_attr.devacc_attr_endian_flags =	DDI_STRUCTURE_LE_ACC;
 
-	if (ddi_regs_map_setup(dip, 1,
-			(caddr_t *)&(erip->globregp), 0, 0,
-			&erip->dev_attr, &erip->globregh)) {
-			    ERI_DEBUG_MSG1(erip, AUTOCONFIG_MSG,
-						mregs_4global_reg_fail_msg);
-				goto attach_fail;
+	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&(erip->globregp), 0, 0,
+	    &erip->dev_attr, &erip->globregh)) {
+		goto attach_fail;
 	}
 	erip->etxregh =		erip->globregh;
 	erip->erxregh =		erip->globregh;
@@ -1119,18 +771,16 @@
 	erip->mifregp =  (void *)(((caddr_t)erip->globregp) + 0x6200);
 
 	ERI_DEBUG_MSG4(erip, AUTOCONFIG_MSG,
-		"eri_attach: gloregp %p alias %X gintmask %X",
-		erip->globregp, GET_GLOBREG(status_alias),
-			GET_GLOBREG(intmask));
+	    "eri_attach: gloregp %p alias %X gintmask %X",
+	    erip->globregp, GET_GLOBREG(status_alias), GET_GLOBREG(intmask));
 	/*
 	 * Map the software reset register.
 	 */
-	if (ddi_regs_map_setup(dip, 1,
-		(caddr_t *)&(erip->sw_reset_reg), 0x1010, 4,
-		&erip->dev_attr, &erip->sw_reset_regh)) {
+	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&(erip->sw_reset_reg),
+	    0x1010, 4, &erip->dev_attr, &erip->sw_reset_regh)) {
 		ERI_FAULT_MSG1(erip, SEVERITY_MID, ERI_VERB_MSG,
-				mregs_4soft_reset_fail_msg);
-			goto attach_fail;
+		    mregs_4soft_reset_fail_msg);
+		goto attach_fail;
 	}
 
 	/*
@@ -1144,12 +794,11 @@
 	 * set PCI latency timer register.
 	 */
 	pci_config_put8(erip->pci_config_handle, PCI_CONF_LATENCY_TIMER,
-		(uchar_t)eri_pci_latency_timer);
+	    (uchar_t)eri_pci_latency_timer);
 
 	ERI_DEBUG_MSG4(erip, AUTOCONFIG_MSG,
-		"eri_attach: gloregp %p alias %X gintmask %X",
-		erip->globregp, GET_GLOBREG(status_alias),
-		GET_GLOBREG(intmask));
+	    "eri_attach: globregp %p alias %X gintmask %X",
+	    erip->globregp, GET_GLOBREG(status_alias), GET_GLOBREG(intmask));
 
 	if (ddi_intr_hilevel(dip, 0)) {
 		ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
@@ -1172,63 +821,27 @@
 	mutex_init(&erip->linklock, NULL, MUTEX_DRIVER, (void *)erip->cookie);
 	mutex_init(&erip->xcvrlock, NULL, MUTEX_DRIVER, (void *)erip->cookie);
 
-#ifdef XMIT_SERIAL_QUEUE
-	/*
-	 * A syncq implementation.
-	 */
-	mutex_init(&erip->sqlock, NULL, MUTEX_DRIVER, (void *)erip->cookie);
-#endif
-	mutex_inited = 1;
+	mutex_inited = B_TRUE;
 
 	/*
 	 * Add interrupt to system
 	 */
-	ERI_DEBUG_MSG1(erip, AUTOCONFIG_MSG,
-			"eri_att: add intr");
-	if (ddi_add_intr(dip, 0, &erip->cookie, 0, eri_intr,
-			(caddr_t)erip) == DDI_SUCCESS)
-		intr_add = 1;
+	if (ddi_add_intr(dip, 0, &erip->cookie, 0, eri_intr, (caddr_t)erip) ==
+	    DDI_SUCCESS)
+		intr_add = B_TRUE;
 	else {
-		ERI_DEBUG_MSG1(erip, AUTOCONFIG_MSG,
-				add_intr_fail_msg);
 		goto attach_fail;
 	}
 
-	ERI_DEBUG_MSG1(erip, AUTOCONFIG_MSG,
-			"eri_att: DONE: add intr");
 	/*
 	 * Set up the ethernet mac address.
 	 */
 	(void) eri_setup_mac_address(erip, dip);
 
-	/*
-	 * Create the filesystem device node.
-	 */
-	if (ddi_create_minor_node(dip, "eri", S_IFCHR, erip->instance,
-				DDI_NT_NET, CLONE_DEV) == DDI_SUCCESS)
-		minor_node_created = 1;
-	else {
-		ERI_DEBUG_MSG1(erip, AUTOCONFIG_MSG,
-				create_minor_node_fail_msg);
-		goto attach_fail;
-	}
-
-	mutex_enter(&eriautolock);
-	if (once) {
-		once = 0;
-		rw_init(&eristruplock, NULL, RW_DRIVER, (void *)erip->cookie);
-		mutex_init(&erilock, NULL, MUTEX_DRIVER,
-		    (void *)erip->cookie);
-		mutex_init(&eriwenlock, NULL, MUTEX_DRIVER,
-		    (void *)erip->cookie);
-	}
-	mutex_exit(&eriautolock);
-
 	if (eri_init_xfer_params(erip))
 		goto attach_fail;
 
 	if (eri_burstsize(erip) == DDI_FAILURE) {
-		ERI_DEBUG_MSG1(erip, INIT_MSG, burst_size_msg);
 		goto attach_fail;
 	}
 
@@ -1244,44 +857,28 @@
 
 	erip->stats.pmcap = ERI_PMCAP_NONE;
 	if (pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000) ==
-		DDI_SUCCESS)
+	    DDI_SUCCESS)
 		erip->stats.pmcap = ERI_PMCAP_4MHZ;
 
-	ERI_DEBUG_MSG2(erip, AUTOCONFIG_MSG,
-		"eri_attach: PMCAP %d", erip->stats.pmcap);
-
-	/*
-	 * lock eri structure while manipulating link list of eri structs
-	 */
-	mutex_enter(&erilock);
-	erip->nextp = eriup;
-	eriup = erip;
-	mutex_exit(&erilock);
-
-	ddi_report_dev(dip);
-
-	ERI_DEBUG_MSG1(erip, EXIT_MSG, "eri_attach pass");
+	if (mac_register(macp, &erip->mh) != 0)
+		goto attach_fail;
+
+	mac_free(macp);
+
 	return (DDI_SUCCESS);
 
 attach_fail:
 	if (erip->pci_config_handle)
 		(void) pci_config_teardown(&erip->pci_config_handle);
 
-	if (minor_node_created)
-		ddi_remove_minor_node(dip, NULL);
-
 	if (mutex_inited) {
 		mutex_destroy(&erip->xmitlock);
 		mutex_destroy(&erip->intrlock);
 		mutex_destroy(&erip->linklock);
 		mutex_destroy(&erip->xcvrlock);
-#ifdef XMIT_SERIAL_QUEUE
-		mutex_destroy(&erip->sqlock);
-#endif
 	}
 
-	ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-			attach_fail_msg);
+	ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG, attach_fail_msg);
 
 	if (intr_add)
 		ddi_remove_intr(dip, 0, erip->cookie);
@@ -1289,37 +886,24 @@
 	if (erip->globregh)
 		ddi_regs_map_free(&erip->globregh);
 
-	erip->etxregh =		NULL;
-	erip->erxregh =		NULL;
-	erip->bmacregh =	NULL;
-	erip->mifregh =		NULL;
-	erip->globregh =	NULL;
-
-	if (erip)
-		kmem_free((caddr_t)erip, sizeof (*erip));
-
-	ERI_DEBUG_MSG1(NULL, EXIT_MSG, "eri_attach: !Success");
+	if (macp != NULL)
+		mac_free(macp);
+	if (erip != NULL)
+		kmem_free(erip, sizeof (*erip));
+
 	return (DDI_FAILURE);
 }
 
 static int
 eri_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 {
-	struct eri 	*erip, *eritmp, **eripp;
+	struct eri 	*erip;
 	int i;
 
-	if (dip == NULL) {
-		ERI_DEBUG_MSG1(NULL, AUTOCONFIG_MSG,
-				"detach: dip == NULL");
-		return (DDI_FAILURE);
-	}
-
 	if ((erip = ddi_get_driver_private(dip)) == NULL) {
 		/*
 		 * No resources allocated.
 		 */
-		ERI_DEBUG_MSG1(NULL, AUTOCONFIG_MSG,
-				"detach: !erip ");
 		return (DDI_FAILURE);
 	}
 
@@ -1333,8 +917,6 @@
 		return (DDI_SUCCESS);
 
 	default:
-		ERI_DEBUG_MSG1(erip, DEFAULT_MSG,
-				detach_bad_cmd_msg);
 		return (DDI_FAILURE);
 	}
 
@@ -1343,13 +925,15 @@
 		return (DDI_FAILURE);
 	}
 
+	if (mac_unregister(erip->mh) != 0) {
+		return (DDI_FAILURE);
+	}
+
 	/*
 	 * Make the device quiescent
 	 */
 	(void) eri_stop(erip);
 
-	ddi_remove_minor_node(dip, NULL);
-
 	/*
 	 * Remove instance of the intr
 	 */
@@ -1359,18 +943,6 @@
 		(void) pci_config_teardown(&erip->pci_config_handle);
 
 	/*
-	 * Remove erip from the linked list of device structures
-	 */
-	mutex_enter(&erilock);
-	for (eripp = &eriup; (eritmp = *eripp) != NULL;
-	    eripp = &eritmp->nextp)
-		if (eritmp == erip) {
-			*eripp = eritmp->nextp;
-			break;
-		}
-	mutex_exit(&erilock);
-
-	/*
 	 * Destroy all mutexes and data structures allocated during
 	 * attach time.
 	 */
@@ -1397,9 +969,6 @@
 	mutex_destroy(&erip->linklock);
 	mutex_destroy(&erip->xcvrlock);
 
-#ifdef XMIT_SERIAL_QUEUE
-	mutex_destroy(&erip->sqlock);
-#endif
 	if (erip->md_h) {
 		if (ddi_dma_unbind_handle(erip->md_h) ==
 		    DDI_FAILURE)
@@ -1474,125 +1043,71 @@
 static void
 eri_setup_mac_address(struct eri *erip, dev_info_t *dip)
 {
-	char	*prop;
-	int	prop_len = sizeof (int);
-
-	erip->addrflags = 0;
+	uchar_t			*prop;
+	char			*uselocal;
+	unsigned		prop_len;
+	uint32_t		addrflags = 0;
+	struct ether_addr	factaddr;
 
 	/*
 	 * Check if it is an adapter with its own local mac address
 	 * If it is present, save it as the "factory-address"
 	 * for this adapter.
 	 */
-	if (ddi_getlongprop(DDI_DEV_T_ANY,
-		dip, DDI_PROP_DONTPASS, "local-mac-address",
-		(caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
+	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "local-mac-address", &prop, &prop_len) == DDI_PROP_SUCCESS) {
 		if (prop_len == ETHERADDRL) {
-			erip->addrflags = ERI_FACTADDR_PRESENT;
-			ether_bcopy((caddr_t)prop, &erip->factaddr);
+			addrflags = ERI_FACTADDR_PRESENT;
+			bcopy(prop, &factaddr, ETHERADDRL);
 			ERI_FAULT_MSG2(erip, SEVERITY_NONE, ERI_VERB_MSG,
-				lether_addr_msg,
-				eri_ether_sprintf(&erip->factaddr));
+			    lether_addr_msg, ether_sprintf(&factaddr));
 		}
-		kmem_free(prop, prop_len);
+		ddi_prop_free(prop);
 	}
 	/*
 	 * Check if the adapter has published "mac-address" property.
 	 * If it is present, use it as the mac address for this device.
 	 */
-	if (ddi_getlongprop(DDI_DEV_T_ANY,
-		dip, DDI_PROP_DONTPASS, "mac-address",
-		(caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
+	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "mac-address", &prop, &prop_len) == DDI_PROP_SUCCESS) {
 		if (prop_len >= ETHERADDRL) {
-			ether_bcopy((caddr_t)prop, &erip->ouraddr);
+			bcopy(prop, erip->ouraddr, ETHERADDRL);
 			kmem_free(prop, prop_len);
 			return;
 		}
-		kmem_free(prop, prop_len);
+		ddi_prop_free(prop);
 	}
 
-	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 0, "local-mac-address?",
-		(caddr_t)&prop, &prop_len) == DDI_PROP_SUCCESS) {
-		if ((strncmp("true", prop, prop_len) == 0) &&
-			(erip->addrflags & ERI_FACTADDR_PRESENT)) {
-			erip->addrflags |= ERI_FACTADDR_USE;
-			ether_bcopy(&erip->factaddr, &erip->ouraddr);
-			kmem_free(prop, prop_len);
+	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, "local-mac-address?",
+	    &uselocal) == DDI_PROP_SUCCESS) {
+		if ((strcmp("true", uselocal) == 0) &&
+		    (addrflags & ERI_FACTADDR_PRESENT)) {
+			addrflags |= ERI_FACTADDR_USE;
+			bcopy(&factaddr, erip->ouraddr, ETHERADDRL);
+			ddi_prop_free(uselocal);
 			ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-					lmac_addr_msg);
+			    lmac_addr_msg);
 			return;
 		}
-		kmem_free(prop, prop_len);
+		ddi_prop_free(uselocal);
 	}
 
 	/*
 	 * Get the system ethernet address.
 	 */
-	(void) localetheraddr((struct ether_addr *)NULL, &erip->ouraddr);
-}
-
-/*
- * Convert Ethernet address to printable (loggable) representation.
- */
-static char *
-eri_ether_sprintf(struct ether_addr *addr)
-{
-	uint8_t *ap = (uint8_t *)addr;
-	int i;
-	static char etherbuf[18];
-	char *cp = etherbuf;
-	static char digits[] = "0123456789abcdef";
-
-	for (i = 0; i < 6; i++) {
-		if (*ap > 0x0f)
-			*cp++ = digits[*ap >> 4];
-		*cp++ = digits[*ap++ & 0xf];
-		*cp++ = ':';
-	}
-	*--cp = 0;
-	return (etherbuf);
+	(void) localetheraddr(NULL, &factaddr);
+	bcopy(&factaddr, erip->ouraddr, ETHERADDRL);
 }
 
 
 /*
- * DLPI (Data Link Provider Interface) Functions
- * New Section
- */
-/*
- * Our DL_INFO_ACK template.
- */
-static	dl_info_ack_t infoack = {
-	DL_INFO_ACK,				/* dl_primitive */
-	ETHERMTU,				/* dl_max_sdu */
-	0,					/* dl_min_sdu */
-	ERI_ADDRL,				/* dl_addr_length */
-	DL_ETHER,				/* dl_mac_type */
-	0,					/* dl_reserved */
-	0,					/* dl_current_state */
-	-2,					/* dl_sap_length */
-	DL_CLDLS,				/* dl_service_mode */
-	0,					/* dl_qos_length */
-	0,					/* dl_qos_offset */
-	0,					/* dl_range_length */
-	0,					/* dl_range_offset */
-	DL_STYLE2,				/* dl_provider_style */
-	sizeof (dl_info_ack_t),			/* dl_addr_offset */
-	DL_VERSION_2,				/* dl_version */
-	ETHERADDRL,				/* dl_brdcst_addr_length */
-	sizeof (dl_info_ack_t) + ERI_ADDRL,	/* dl_brdcst_addr_offset */
-	0					/* dl_growth */
-};
-
-
-
-/*
  * Calculate the bit in the multicast address filter that selects the given
  * address.
  * Note: For ERI, the last 8-bits are used.
  */
 
 static uint32_t
-eri_ladrf_bit(struct ether_addr *addr)
+eri_ladrf_bit(const uint8_t *addr)
 {
 	uint32_t crc;
 
@@ -1604,451 +1119,43 @@
 	return ((~crc) >> 24);
 }
 
-
-/*
- * Assorted DLPI V2 routines.
- */
-
 static void
-eri_proto(queue_t *wq, mblk_t *mp)
-{
-	union	DL_primitives	*dlp;
-	struct	eristr	*sbp;
-	uint32_t	prim;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	dlp = (union DL_primitives *)mp->b_rptr;
-	prim = dlp->dl_primitive;
-
-	ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-			"eri_proto Entered");
-	mutex_enter(&sbp->sb_lock);
-
-	switch (prim) {
-	case	DL_UNITDATA_REQ:
-		eri_udreq(wq, mp);
-		break;
-
-	case	DL_ATTACH_REQ:
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_proto : ATTACH_REQ");
-		eri_areq(wq, mp);
-		break;
-
-	case	DL_DETACH_REQ:
-		eri_dreq(wq, mp);
-		break;
-
-	case	DL_BIND_REQ:
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_proto : BIND_REQ");
-		eri_breq(wq, mp);
-		break;
-
-	case	DL_UNBIND_REQ:
-		eri_ubreq(wq, mp);
-		break;
-
-	case	DL_INFO_REQ:
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_proto : INFO_REQ");
-		eri_ireq(wq, mp);
-		break;
-
-	case	DL_PROMISCON_REQ:
-		eri_ponreq(wq, mp);
-		break;
-
-	case	DL_PROMISCOFF_REQ:
-		eri_poffreq(wq, mp);
-		break;
-
-	case	DL_ENABMULTI_REQ:
-		eri_emreq(wq, mp);
-		break;
-
-	case	DL_DISABMULTI_REQ:
-		eri_dmreq(wq, mp);
-		break;
-
-	case	DL_PHYS_ADDR_REQ:
-		eri_pareq(wq, mp);
-		break;
-
-	case	DL_SET_PHYS_ADDR_REQ:
-		eri_spareq(wq, mp);
-		break;
-
-	case	DL_NOTIFY_REQ:
-		eri_nreq(wq, mp);
-		break;
-
-	case DL_CAPABILITY_REQ:
-		eri_dlcap_req(wq, mp);
-		break;
-
-	default:
-		dlerrorack(wq, mp, prim, DL_UNSUPPORTED, 0);
-		break;
-	}
-	mutex_exit(&sbp->sb_lock);
-}
-
-/*ARGSUSED*/
-static int
-eri_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
+eri_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
 {
-	struct	eristr	*sbp;
-	struct	eristr	**prevsbp;
-	minor_t	minordev;
-	int	rc = 0;
-
-	ASSERT(sflag != MODOPEN);
-	ERI_DEBUG_MSG1(NULL, INIT_MSG,
-			"eri_open Entered");
-
-	/*
-	 * Serialize all driver open and closes.
-	 */
-	rw_enter(&eristruplock, RW_WRITER);
-	mutex_enter(&eriwenlock);
-
-	/*
-	 * Determine minor device number.
-	 */
-	prevsbp = &eristrup;
-	if (sflag == CLONEOPEN) {
-		minordev = 0;
-		for (; (sbp = *prevsbp) != NULL; prevsbp = &sbp->sb_nextp) {
-			if (minordev < sbp->sb_minor)
-				break;
-			minordev++;
-		}
-		*devp = makedevice(getmajor(*devp), minordev);
-	} else
-		minordev = getminor(*devp);
-
-	if (rq->q_ptr)
-		goto done;
-
-	sbp = GETSTRUCT(struct eristr, 1);
-
-	ERI_DEBUG_MSG2(NULL, INIT_MSG,
-			"eri_open: sbp = %X\n", sbp);
-
-	sbp->sb_minor = minordev;
-	sbp->sb_rq = rq;
-	sbp->sb_state = DL_UNATTACHED;
-	sbp->sb_sap = 0;
-	sbp->sb_flags = 0;
-	sbp->sb_erip = NULL;
-
-	mutex_init(&sbp->sb_lock, NULL, MUTEX_DRIVER, (void *)0);
-
-	/*
-	 * Link new entry into the list of active entries.
-	 */
-	sbp->sb_nextp = *prevsbp;
-	*prevsbp = sbp;
-
-	rq->q_ptr = WR(rq)->q_ptr = (char *)sbp;
-
-	/*
-	 * Disable automatic enabling of our write service procedure.
-	 * We control this explicitly.
-	 */
-	noenable(WR(rq));
-
-done:
-	mutex_exit(&eriwenlock);
-	rw_exit(&eristruplock);
-
-	/* inform framework that we are a good citizen */
-	(void) qassociate(rq, -1);
-
-	qprocson(rq);
-	return (rc);
-}
-
-static int
-eri_close(queue_t *rq)
-{
-	struct	eristr	*sbp;
-	struct	eristr	**prevsbp;
-
-	ASSERT(rq->q_ptr);
-
-	qprocsoff(rq);
-
-	sbp = (struct eristr *)rq->q_ptr;
-
-
-	/*
-	 * Implicit detach Stream from interface.
-	 */
-	if (sbp->sb_erip)
-		eri_dodetach(sbp);
-
-	/* dissociate queue */
-	(void) qassociate(rq, -1);
-
-	rw_enter(&eristruplock, RW_WRITER);
-	mutex_enter(&eriwenlock);
+	struct	eri	*erip = arg;
+	struct	iocblk	*iocp = (void *)mp->b_rptr;
+	int	err;
+
+	ASSERT(erip != NULL);
 
 	/*
-	 * Unlink the per-Stream entry from the active list and free it.
+	 * Privilege checks.
 	 */
-	for (prevsbp = &eristrup; (sbp = *prevsbp) != NULL;
-		prevsbp = &sbp->sb_nextp)
-		if (sbp == (struct eristr *)rq->q_ptr)
-			break;
-	ASSERT(sbp);
-	*prevsbp = sbp->sb_nextp;
-
-	mutex_destroy(&sbp->sb_lock);
-	kmem_free((char *)sbp, sizeof (struct eristr));
-
-	rq->q_ptr = WR(rq)->q_ptr = NULL;
-
-	mutex_exit(&eriwenlock);
-	rw_exit(&eristruplock);
-	return (0);
-}
-
-/*
- * Enqueue M_PROTO/M_PCPROTO (always) and M_DATA (sometimes) on the wq.
- *
- * Processing of some of the M_PROTO/M_PCPROTO msgs involves acquiring
- * internal locks that are held across upstream putnext calls.
- * Specifically there's the problem of eri_intr() holding eri_intrlock
- * and eristruplock when it calls putnext() and that thread looping
- * back around to call eri_wput() and, eventually, eri_init() to create a
- * recursive lock panic.  There are two obvious ways of solving this
- * problem: (1) have eri_intr() do putq instead of putnext which provides
- * the loopback "cutout" right at the rq, or (2) allow eri_intr() to putnext
- * and put the loopback "cutout" around eri_proto().  We choose the latter
- * for performance reasons.
- *
- * M_DATA messages are enqueued on the wq *only* when the xmit side
- * is out of tbufs or tmds.  Once the xmit resource is available again,
- * wsrv() is enabled and tries to xmit all the messages on the wq.
- */
-static int
-eri_wsrv(queue_t *wq)
-{
-	mblk_t	*mp;
-	struct	eristr	*sbp;
-	struct	eri	*erip;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	erip = sbp->sb_erip;
-	while (mp = getq(wq))
-		switch (DB_TYPE(mp)) {
-		case	M_DATA:
-			if (erip) {
-				if (eri_start(wq, mp, erip))
-					goto done;
-			} else
-				freemsg(mp);
-			break;
-
-		case	M_PROTO:
-		case	M_PCPROTO:
-			eri_proto(wq, mp);
-			break;
-
-		default:
-			ASSERT(0);
-			break;
+	switch (iocp->ioc_cmd) {
+	case ERI_SET_LOOP_MODE:
+	case ERI_ND_SET:
+		err = secpolicy_net_config(iocp->ioc_cr, B_FALSE);
+		if (err != 0) {
+			miocnak(wq, mp, 0, err);
+			return;
 		}
-done:
-	return (0);
-}
-
-#ifdef XMIT_SERIAL_QUEUE
-static int
-eri_wput_serialize(queue_t *wq, mblk_t *mp, struct eri *erip)
-{
-
-	mblk_t *smp;
-	int	refed;
-	int	ret = 0;
-
-	mutex_enter(&erip->sqlock);
-	if (erip->sqrefcnt) {
-		smp = mp;
-		mp = NULL;
-		refed = 0;
-		goto last;
-	}
-	erip->sqrefcnt++;
-next:
-	refed = 1;
-	if (erip->sqfirst) {
-		/*
-		 * Mblk chain on syncq, so just add ours, if any
-		 * to the end and get the first one.
-		 */
-		smp = mp;
-		mp = erip->sqfirst;
-		if ((erip->sqfirst = mp->b_next) == NULL)
-			erip->sqlast = NULL;
-		else
-			mp->b_next = NULL;
-	} else
-		smp = NULL;
-
-last:
-	if (smp) {
-		/*
-		 * Mblk chain to save, so just add it to
-		 * the end of the sycnq.
-		 */
-		smp->b_next = NULL;
-		if (erip->sqlast)
-			erip->sqlast->b_next = smp;
-		else
-			erip->sqfirst = smp;
-		erip->sqlast = smp;
-	}
-
-	if (mp == NULL) {
-		/*
-		 * Nothing more todo ...
-		 */
-		if (refed)
-			erip->sqrefcnt--;
-
-		mutex_exit(&erip->sqlock);
-		return (ret);
-	}
-
-	mutex_exit(&erip->sqlock);
-	ret = eri_start(wq, mp, erip);
-	mp = NULL;
-	mutex_enter(&erip->sqlock);
-	goto next;
-no_bwg:
-	HSTAT(erip, oerrors);
-	freemsg(mp);
-	return (0);
-}
-
-#endif
-
-
-static int
-eri_wput(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr	*sbp = (struct eristr *)wq->q_ptr;
-	struct	eri	*erip;
-
-	switch (DB_TYPE(mp)) {
-	case M_DATA:		/* "fastpath" */
-		erip = sbp->sb_erip;
-
-		if (((sbp->sb_flags & (ERI_SFAST | ERI_SRAW)) == 0) ||
-			(sbp->sb_state != DL_IDLE) ||
-			(erip == NULL)) {
-			merror(wq, mp, EPROTO);
-			break;
-		}
-
-		/*
-		 * If any msgs already enqueued or the interface will
-		 * loop back up the message (due to ERI_PROMISC), then
-		 * enqueue the msg.  Otherwise just xmit it directly.
-		 */
-		if (wq->q_first) {
-			(void) putq(wq, mp);
-			erip->wantw = 1;
-			qenable(wq);
-		} else if (erip->flags & ERI_PROMISC) {
-			(void) putq(wq, mp);
-			qenable(wq);
-		} else
-#ifdef XMIT_SERIAL_QUEUE
-			(void) eri_wput_serialize(wq, mp, erip);
-#else
-			(void) eri_start(wq, mp, erip);
-#endif
-
 		break;
-
-	case M_PROTO:
-	case M_PCPROTO:
-		/*
-		 * Break the association between the current thread
-		 * and the thread that calls eri_proto() to resolve the
-		 * problem of eri_intr() threads which loop back around
-		 * to call eri_proto() and try to recursively acquire
-		 * internal locks.
-		 */
-		(void) putq(wq, mp);
-		qenable(wq);
-		break;
-
-	case M_IOCTL:
-		eri_ioctl(wq, mp);
-		break;
-
-	case M_CTL:
-		eri_mctl(wq, mp);
-		break;
-
-	case M_FLUSH:
-		if (*mp->b_rptr & FLUSHW) {
-			flushq(wq, FLUSHALL);
-			*mp->b_rptr &= ~FLUSHW;
-		}
-
-		if (*mp->b_rptr & FLUSHR) {
-#ifdef ERI_SERVICE_ROUTINE
-			flushq(RD(wq), FLUSHALL);
-#endif
-			qreply(wq, mp);
-		} else
-			freemsg(mp);
-		break;
-
 	default:
-		freemsg(mp);
 		break;
 	}
-	return (0);
-}
-
-static void
-eri_ioctl(queue_t *wq, mblk_t *mp)
-{
-	struct	iocblk	*iocp = (struct iocblk *)mp->b_rptr;
-	struct	eristr	*sbp = (struct eristr *)wq->q_ptr;
-	struct	eri	*erip = sbp->sb_erip;
-
-	ERI_DEBUG_MSG1(NULL, IOCTL_MSG,
-			"eri_ioctl Entered");
+
 	switch (iocp->ioc_cmd) {
-	case DLIOCRAW:		/* raw M_DATA mode */
-		sbp = (struct eristr *)wq->q_ptr;
-		sbp->sb_flags |= ERI_SRAW;
-		miocack(wq, mp, 0, 0);
-		break;
-
-	case DL_IOC_HDR_INFO:	/* M_DATA "fastpath" info request */
-		eri_dl_ioc_hdr_info(wq, mp);
-		break;
-
 	case ERI_ND_GET:
 	case ERI_ND_SET:
-		eri_process_ndd_ioctl(wq, mp, iocp->ioc_cmd);
+		eri_process_ndd_ioctl(erip, wq, mp, iocp->ioc_cmd);
 		break;
 
 	case ERI_SET_LOOP_MODE:
 	case ERI_GET_LOOP_MODE:
-		if (erip == NULL)
-			miocnak(wq, mp, 0, EPROTO);
-		else
-			eri_loopback(wq, mp);
+		/*
+		 * XXX: Consider updating this to the new netlb ioctls.
+		 */
+		eri_loopback(erip, wq, mp);
 		break;
 
 	default:
@@ -2056,78 +1163,60 @@
 		break;
 	}
 
-	if (erip)
-		ASSERT(!MUTEX_HELD(&erip->linklock));
+	ASSERT(!MUTEX_HELD(&erip->linklock));
 }
 
 static void
-eri_loopback(queue_t *wq, mblk_t *mp)
+eri_loopback(struct eri *erip, queue_t *wq, mblk_t *mp)
 {
-	struct  eristr	*sbp = (struct eristr *)wq->q_ptr;
-	struct	eri	*erip = sbp->sb_erip;
-	struct	iocblk	*iocp = (struct iocblk *)mp->b_rptr;
+	struct	iocblk	*iocp = (void *)mp->b_rptr;
 	loopback_t	*al;
 
-	ERI_DEBUG_MSG1(NULL, LOOPBACK_MSG,
-			"eri_loopback Entered");
-
-	if (mp->b_cont == NULL ||
-		MBLKL(mp->b_cont) < sizeof (loopback_t)) {
+	/*LINTED E_PTRDIFF_OVERFLOW*/
+	if (mp->b_cont == NULL || MBLKL(mp->b_cont) < sizeof (loopback_t)) {
 		miocnak(wq, mp, 0, EINVAL);
 		return;
 	}
 
-	al = (loopback_t *)mp->b_cont->b_rptr;
+	al = (void *)mp->b_cont->b_rptr;
 
 	switch (iocp->ioc_cmd) {
 	case ERI_SET_LOOP_MODE:
-		ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-				"ERI_SET_LOOP_MODE\n");
 		switch (al->loopback) {
 		case ERI_LOOPBACK_OFF:
-			ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-					"ERI_LOOPBACK_OFF\n");
-			sbp->sb_flags &= (~ERI_SMACLPBK & ~ERI_SSERLPBK);
-			erip->flags &= (~ERI_MACLOOPBACK &
-					~ERI_SERLOOPBACK);
+			erip->flags &= (~ERI_MACLOOPBACK & ~ERI_SERLOOPBACK);
 			/* force link status to go down */
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 			(void) eri_init(erip);
 			break;
 
 		case ERI_MAC_LOOPBACK_ON:
-			ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-					"ERI_MAC_LOOPBACK_ON\n");
-			sbp->sb_flags |= ERI_SMACLPBK;
 			erip->flags |= ERI_MACLOOPBACK;
+			erip->flags &= ~ERI_SERLOOPBACK;
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 			(void) eri_init(erip);
 			break;
 
 		case ERI_PCS_LOOPBACK_ON:
-			ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-					"ERI_PCS_LOOPBACK_ON\n");
 			break;
 
 		case ERI_SER_LOOPBACK_ON:
-			ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-					"ERI_SER_LOOPBACK_ON\n");
-			sbp->sb_flags |= ERI_SSERLPBK;
 			erip->flags |= ERI_SERLOOPBACK;
+			erip->flags &= ~ERI_MACLOOPBACK;
 			/* force link status to go down */
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 			(void) eri_init(erip);
 			break;
 
 		default:
 			ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-					loopback_val_default);
+			    loopback_val_default);
 			miocnak(wq, mp, 0, EINVAL);
 			return;
 		}
@@ -2135,1193 +1224,309 @@
 		break;
 
 	case ERI_GET_LOOP_MODE:
-		ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-				"ERI_GET_LOOP_MODE\n");
-		al->loopback =	ERI_MAC_LOOPBACK_ON |
-				ERI_PCS_LOOPBACK_ON |
-				ERI_SER_LOOPBACK_ON;
+		al->loopback =	ERI_MAC_LOOPBACK_ON | ERI_PCS_LOOPBACK_ON |
+		    ERI_SER_LOOPBACK_ON;
 		miocack(wq, mp, sizeof (loopback_t), 0);
 		break;
 
 	default:
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				loopback_cmd_default);
+		    loopback_cmd_default);
 	}
 }
 
-/*
- * M_DATA "fastpath" info request.
- * Following the M_IOCTL mblk should come a DL_UNITDATA_REQ mblk.
- * We ack with an M_IOCACK pointing to the original DL_UNITDATA_REQ mblk
- * followed by an mblk containing the raw ethernet header corresponding
- * to the destination address.  Subsequently, we may receive M_DATA
- * msgs which start with this header and may send up
- * up M_DATA msgs with b_rptr pointing to a (uint32_t) group address
- * indicator followed by the network-layer data (IP packet header).
- * This is all selectable on a per-Stream basis.
- */
-static void
-eri_dl_ioc_hdr_info(queue_t *wq, mblk_t *mp)
-{
-	mblk_t			*nmp;
-	struct	eristr		*sbp;
-	struct	eridladdr	*dlap;
-	dl_unitdata_req_t	*dludp;
-	struct	ether_header	*headerp;
-	struct	eri		*erip;
-	t_uscalar_t		off, len;
-	int			error;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	erip = sbp->sb_erip;
-	if (erip == NULL) {
-		miocnak(wq, mp, 0, EINVAL);
-		return;
-	}
-
-	error = miocpullup(mp, sizeof (dl_unitdata_req_t) + ERI_ADDRL);
-	if (error != 0) {
-		miocnak(wq, mp, 0, error);
-		return;
-	}
-
-	/*
-	 * Sanity check the DL_UNITDATA_REQ destination address
-	 * offset and length values.
-	 */
-	dludp = (dl_unitdata_req_t *)mp->b_cont->b_rptr;
-	off = dludp->dl_dest_addr_offset;
-	len = dludp->dl_dest_addr_length;
-	if (dludp->dl_primitive != DL_UNITDATA_REQ ||
-	    !MBLKIN(mp->b_cont, off, len) || len != ERI_ADDRL) {
-		miocnak(wq, mp, 0, EINVAL);
-		return;
-	}
-
-	dlap = (struct eridladdr *)(mp->b_cont->b_rptr + off);
-
-	/*
-	 * Allocate a new mblk to hold the ether header.
-	 */
-	if ((nmp = allocb(ETHERHEADER_SIZE, BPRI_MED)) == NULL) {
-		miocnak(wq, mp, 0, ENOMEM);
-		return;
-	}
-	nmp->b_wptr += ETHERHEADER_SIZE;
-
-	/*
-	 * Fill in the ether header.
-	 */
-	headerp = (struct ether_header *)nmp->b_rptr;
-	ether_bcopy(&dlap->dl_phys, &headerp->ether_dhost);
-	ether_bcopy(&erip->ouraddr, &headerp->ether_shost);
-	put_ether_type(headerp, dlap->dl_sap);
-
-	/*
-	 * Link new mblk in after the "request" mblks.
-	 */
-	linkb(mp, nmp);
-
-	sbp->sb_flags |= ERI_SFAST;
-	miocack(wq, mp, msgsize(mp->b_cont), 0);
-}
-
-/* ARGSUSED */
-static void
-eri_mctl(queue_t *wq, mblk_t  *mp)
-{
-	freemsg(mp);
-} /* eri_mctl */
-
-static void
-eri_areq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr		*sbp;
-	union	DL_primitives	*dlp;
-	struct	eri		*erip = NULL;
-	t_uscalar_t 		ppa;
-	uint32_t		promisc = 0;
-	uint32_t		all_multi = 0;
-	uint32_t		all_sap = 0;
-	int			init = B_FALSE;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	dlp = (union DL_primitives *)mp->b_rptr;
-
-	if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_areq: Bad REQ Size");
-		return;
-	}
-
-	if (sbp->sb_state != DL_UNATTACHED) {
-		dlerrorack(wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_areq: DL_OUTSTATE");
-		return;
-	}
-
-	/*
-	 * Count the number of snoop/promisc modes.
-	 */
-	if (sbp->sb_flags & ERI_SALLPHYS) {
-		promisc++;
-		init = B_TRUE;
-	}
-	if (sbp->sb_flags & ERI_SALLSAP) {
-		all_sap++;
-		init = B_TRUE;
-	}
-	if (sbp->sb_flags & ERI_SALLMULTI) {
-		all_multi++;
-		init = B_TRUE;
-	}
-
-	ppa = dlp->attach_req.dl_ppa;
-
-	/*
-	 * Valid ppa?
-	 */
-	if (ppa == -1 || qassociate(wq, ppa) != 0) {
-		dlerrorack(wq, mp, dlp->dl_primitive, DL_BADPPA, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_areq: erip == NULL");
-		return;
-	}
-	mutex_enter(&erilock);
-	for (erip = eriup; erip; erip = erip->nextp)
-		if (ppa == erip->instance) {
-			ERI_DEBUG_MSG1(erip, PROTO_MSG,
-				"got instance");
-			break;
-		}
-	mutex_exit(&erilock);
-	ASSERT(erip != NULL);
-
-	/* Set link to device and update our state. */
-	sbp->sb_erip = erip;
-	sbp->sb_state = DL_UNBOUND;
-
-	/*
-	 * Has device been initialized?  Do so if necessary.
-	 * Also check if promiscuous mode is set via the ALLPHYS and
-	 * ALLMULTI flags, for the stream.  If so, initialize the
-	 * interface.
-	 */
-	if ((erip->flags & ERI_RUNNING) == 0) {
-		if (eri_init(erip)) {
-			dlerrorack(wq, mp, dlp->dl_primitive, DL_INITFAILED, 0);
-			sbp->sb_erip = NULL;
-			sbp->sb_state = DL_UNATTACHED;
-			ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-					"eri_areq: eri_init FAILED");
-			(void) qassociate(wq, -1);
-			return;
-		}
-
-	} else {
-		if (init) {
-			mutex_enter(&erip->intrlock);
-			erip->promisc_cnt += promisc;
-			erip->all_multi_cnt += all_multi;
-			erip->all_sap_cnt += all_sap;
-			/*
-			 * Reinitialize rx mac
-			 */
-			eri_init_rx(erip);
-			mutex_exit(&erip->intrlock);
-		}
-		if (erip->promisc_cnt == 1)
-			eri_notify_ind(erip, DL_NOTE_PROMISC_ON_PHYS);
-	}
-
-	dlokack(wq, mp, DL_ATTACH_REQ);
-	ERI_DEBUG_MSG1(NULL, PROTO_MSG, "eri_areq: Normal exit");
-}
-
-static void
-eri_dreq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr	*sbp;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	if (MBLKL(mp) < DL_DETACH_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (sbp->sb_state != DL_UNBOUND) {
-		dlerrorack(wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	eri_dodetach(sbp);
-
-	/* dissociate queue */
-	(void) qassociate(wq, -1);
-
-	dlokack(wq, mp, DL_DETACH_REQ);
-}
-
-/*
- * Detach a Stream from an interface.
- */
-static void
-eri_dodetach(struct eristr *sbp)
+static int
+eri_m_promisc(void *arg, boolean_t on)
 {
-	struct	eristr	*tsbp;
-	struct	eri	*erip;
-	int	reinit = 0, i;
-	uint32_t promisc = 0;
-	uint32_t all_multi = 0;
-	uint32_t all_sap = 0;
-
-	ASSERT(sbp->sb_erip);
-
-	erip = sbp->sb_erip;
-	sbp->sb_erip = NULL;
-
-	/* Disable promiscuous mode if on. */
-	if (sbp->sb_flags & ERI_SALLPHYS) {
-		sbp->sb_flags &= ~ERI_SALLPHYS;
-		promisc++;
-		reinit = 1;
-	}
-
-	/* Disable ALLSAP mode if on. */
-	if (sbp->sb_flags & ERI_SALLSAP) {
-		sbp->sb_flags &= ~ERI_SALLSAP;
-		all_sap++;
-	}
-
-	/* Disable ALLMULTI mode if on. */
-	if (sbp->sb_flags & ERI_SALLMULTI) {
-		sbp->sb_flags &= ~ERI_SALLMULTI;
-		all_multi++;
-		reinit = 1;
-	}
-
-	/* Disable MULTI mode if on. */
-	if (sbp->sb_flags & ERI_SMULTI) {
-		sbp->sb_flags &= ~ERI_SMULTI;
-		reinit = 2;
-	}
-
-	/* Disable any Multicast Addresses. */
-
-	for (i = 0; i < NMCHASH; i++) {
-		if (sbp->sb_mctab[i]) {
-			reinit = 2;
-			kmem_free(sbp->sb_mctab[i], sbp->sb_mcsize[i] *
-			    sizeof (struct ether_addr));
-			sbp->sb_mctab[i] = NULL;
-		}
-		sbp->sb_mccount[i] = sbp->sb_mcsize[i] = 0;
-	}
-
-	for (i = 0; i < NMCFILTER_BITS/16; i++)
-		sbp->sb_ladrf[i] = 0;
-
-	for (i = 0; i < NMCFILTER_BITS; i++)
-		sbp->sb_ladrf_refcnt[i] = 0;
-
-	sbp->sb_state = DL_UNATTACHED;
-
-	/*
-	 * Detach from device structure.
-	 * Uninit the device and update power management property
-	 * when no other streams are attached to it.
-	 */
-
-	rw_enter(&eristruplock, RW_READER);
-
-	for (tsbp = eristrup; tsbp; tsbp = tsbp->sb_nextp)
-		if (tsbp->sb_erip == erip)
-			break;
-
-	rw_exit(&eristruplock);
-
-	if (tsbp == NULL) {
-		eri_uninit(erip);
-	} else if (reinit) {
-		boolean_t needind;
-
-		mutex_enter(&erip->intrlock);
-		erip->promisc_cnt -= promisc;
-		erip->all_multi_cnt -= all_multi;
-		erip->all_sap_cnt -= all_sap;
-		if (erip->promisc_cnt == 0 || erip->all_multi_cnt == 0 ||
-		    reinit == 2)
-			eri_init_rx(erip);
-		needind = (erip->promisc_cnt == 0);
-
-		mutex_exit(&erip->intrlock);
-
-		if (needind)
-			eri_notify_ind(erip, DL_NOTE_PROMISC_OFF_PHYS);
-	}
-	eri_setipq(erip);
-}
-
-static void
-eri_breq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr		*sbp;
-	union	DL_primitives	*dlp;
-	struct	eri		*erip;
-	struct	eridladdr	eriaddr;
-	t_uscalar_t sap;
-	t_uscalar_t xidtest;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_breq: Bad REQ Size");
-		return;
-	}
-
-	if (sbp->sb_state != DL_UNBOUND) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_breq: Bad DL_OUTSTATE");
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	erip = sbp->sb_erip;
-	sap = dlp->bind_req.dl_sap;
-	xidtest = dlp->bind_req.dl_xidtest_flg;
-
-	ASSERT(erip);
-
-	if (xidtest) {
-		dlerrorack(wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_breq: Bad DL_NOAUTO");
-		return;
-	}
-
-	if (sap > ETHERTYPE_MAX) {
-		dlerrorack(wq, mp, dlp->dl_primitive, DL_BADSAP, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_breq: DL_BADSAP");
-		return;
-	}
-
-	/*
-	 * Save SAP value for this Stream and change state.
-	 */
-	sbp->sb_sap = sap;
-	sbp->sb_state = DL_IDLE;
-
-	eriaddr.dl_sap = sap;
-	ether_bcopy(&erip->ouraddr, &eriaddr.dl_phys);
-	dlbindack(wq, mp, sap, &eriaddr, ERI_ADDRL, 0, 0);
-
-	eri_setipq(erip);
-
-}
-
-static void
-eri_ubreq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr	*sbp;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (sbp->sb_state != DL_IDLE) {
-		dlerrorack(wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	sbp->sb_state = DL_UNBOUND;
-	sbp->sb_sap = 0;
-
-	dlokack(wq, mp, DL_UNBIND_REQ);
-
-	eri_setipq(sbp->sb_erip);
-}
-
-static void
-eri_ireq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr	*sbp;
-	dl_info_ack_t	*dlip;
-	struct	eridladdr	*dlap;
-	struct	ether_addr	*ep;
-	size_t	size;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_INFO_REQ, DL_BADPRIM, 0);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_ireq: < DL_INFO_REQ_SIZE");
-		return;
-	}
-
-	/* Exchange current msg for a DL_INFO_ACK. */
-	size = sizeof (dl_info_ack_t) + ERI_ADDRL + ETHERADDRL;
-	mp = mexchange(wq, mp, size, M_PCPROTO, DL_INFO_ACK);
-	if (mp == NULL) {
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_ireq: mp == NULL");
-		return;
-	}
-
-	/* Fill in the DL_INFO_ACK fields and reply. */
-	dlip = (dl_info_ack_t *)mp->b_rptr;
-	*dlip = infoack;
-	dlip->dl_current_state = sbp->sb_state;
-	dlap = (struct eridladdr *)(mp->b_rptr + dlip->dl_addr_offset);
-	dlap->dl_sap = sbp->sb_sap;
-
-	if (sbp->sb_erip) {
-		ether_bcopy(&sbp->sb_erip->ouraddr, &dlap->dl_phys);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_ireq: sbp->sb_erip");
-	} else {
-		bzero((caddr_t)&dlap->dl_phys, ETHERADDRL);
-		ERI_DEBUG_MSG1(NULL, PROTO_MSG,
-				"eri_ireq: !sbp->sb_erip");
-	}
-
-	ep = (struct ether_addr *)(mp->b_rptr + dlip->dl_brdcst_addr_offset);
-	ether_bcopy(&etherbroadcastaddr, ep);
-
-	qreply(wq, mp);
-}
-
-static void
-eri_ponreq(queue_t *wq, mblk_t *mp)
-{
-	struct	eri	*erip;
-	struct	eristr	*sbp;
-	int	phy_flag = 0;
-	int	sap_flag = 0;
-	int	allmulti_flag = 0;
-	boolean_t needind;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	/*
-	 * Do not increment counter if already set.
-	 */
-	if (sbp->sb_flags & ERI_SALLPHYS)
-		phy_flag = 1;
-	if (sbp->sb_flags & ERI_SALLSAP)
-		sap_flag = 1;
-	if (sbp->sb_flags & ERI_SALLMULTI)
-		allmulti_flag = 1;
-
-	switch (((dl_promiscon_req_t *)mp->b_rptr)->dl_level) {
-	case DL_PROMISC_PHYS:
-		sbp->sb_flags |= ERI_SALLPHYS;
-		break;
-
-	case DL_PROMISC_SAP:
-		sbp->sb_flags |= ERI_SALLSAP;
-		break;
-
-	case DL_PROMISC_MULTI:
-		sbp->sb_flags |= ERI_SALLMULTI;
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	erip = sbp->sb_erip;
-	if (erip) {
-		mutex_enter(&erip->intrlock);
-		if ((sbp->sb_flags & ERI_SALLPHYS) && (phy_flag == 0))
-			erip->promisc_cnt++;
-		if ((sbp->sb_flags & ERI_SALLSAP) && (sap_flag == 0))
-			erip->all_sap_cnt++;
-		if ((sbp->sb_flags & ERI_SALLMULTI) && (allmulti_flag == 0))
-			erip->all_multi_cnt++;
-		if (erip->promisc_cnt == 1 || erip->all_multi_cnt == 1) {
-			eri_init_rx(sbp->sb_erip);
-			needind = B_TRUE;
-		} else {
-			needind = B_FALSE;
-		}
-		mutex_exit(&erip->intrlock);
-		if (needind)
-			eri_notify_ind(erip, DL_NOTE_PROMISC_ON_PHYS);
-
-		eri_setipq(sbp->sb_erip);
-	}
-	dlokack(wq, mp, DL_PROMISCON_REQ);
-}
-
-static void
-eri_poffreq(queue_t *wq, mblk_t *mp)
-{
-	struct	eri	*erip;
-	struct	eristr	*sbp;
-	int	flag;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	switch (((dl_promiscoff_req_t *)mp->b_rptr)->dl_level) {
-	case DL_PROMISC_PHYS:
-		flag = ERI_SALLPHYS;
-		break;
-
-	case DL_PROMISC_SAP:
-		flag = ERI_SALLSAP;
-		break;
-
-	case DL_PROMISC_MULTI:
-		flag = ERI_SALLMULTI;
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	if ((sbp->sb_flags & flag) == 0) {
-		dlerrorack(wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
-		return;
-	}
-
-	sbp->sb_flags &= ~flag;
-
-	erip = sbp->sb_erip;
-	if (erip) {
-		boolean_t needind;
-
-		mutex_enter(&erip->intrlock);
-		if (flag == ERI_SALLPHYS)
-			erip->promisc_cnt--;
-		if (flag == ERI_SALLSAP)
-			erip->all_sap_cnt--;
-		if (flag == ERI_SALLMULTI)
-			erip->all_multi_cnt--;
-		if (((flag == ERI_SALLPHYS) && (erip->promisc_cnt == 0)) ||
-		    ((flag == ERI_SALLMULTI) && (erip->all_multi_cnt == 0))) {
-			eri_init_rx(sbp->sb_erip);
-			needind = (flag == ERI_SALLPHYS);
-		} else {
-			needind = B_FALSE;
-		}
-		mutex_exit(&erip->intrlock);
-
-		if (needind)
-			eri_notify_ind(erip, DL_NOTE_PROMISC_OFF_PHYS);
-
-		eri_setipq(sbp->sb_erip);
-	}
-	dlokack(wq, mp, DL_PROMISCOFF_REQ);
+	struct	eri	*erip = arg;
+
+	mutex_enter(&erip->intrlock);
+	erip->promisc = on;
+	eri_init_rx(erip);
+	mutex_exit(&erip->intrlock);
+	return (0);
 }
 
 /*
  * This is to support unlimited number of members
  * in Multicast.
  */
-static void
-eri_emreq(queue_t	*wq, mblk_t *mp)
+static int
+eri_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
 {
-	struct	eristr	*sbp;
-	union	DL_primitives	*dlp;
-	struct	ether_addr	*addrp;
-	t_uscalar_t off;
-	t_uscalar_t len;
-	uint32_t mchash;
-	struct	ether_addr	*mcbucket;
-	uint32_t ladrf_bit;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	if (MBLKL(mp) < DL_ENABMULTI_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (sbp->sb_state == DL_UNATTACHED) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	len = dlp->enabmulti_req.dl_addr_length;
-	off = dlp->enabmulti_req.dl_addr_offset;
-	addrp = (struct ether_addr *)(mp->b_rptr + off);
-
-	if ((len != ETHERADDRL) ||
-		!MBLKIN(mp, off, len) ||
-		((addrp->ether_addr_octet[0] & 01) == 0)) {
-		dlerrorack(wq, mp, DL_ENABMULTI_REQ, DL_BADADDR, 0);
-		return;
-	}
-
-	/*
-	 * Calculate hash value and bucket.
-	 */
-
-	mchash = MCHASH(addrp);
-	mcbucket = sbp->sb_mctab[mchash];
-
-	/*
-	 * Allocate hash bucket if it's not there.
-	 */
-
-	if (mcbucket == NULL) {
-		sbp->sb_mctab[mchash] = mcbucket =
-			kmem_alloc(INIT_BUCKET_SIZE *
-				sizeof (struct ether_addr),
-				KM_SLEEP);
-		sbp->sb_mcsize[mchash] = INIT_BUCKET_SIZE;
-	}
-
-	/*
-	 * We no longer bother checking to see if the address is already
-	 * in the table.  We won't reinitialize the
-	 * hardware, since we'll find the mc bit is already set.
-	 */
-
-	/*
-	 * Expand table if necessary.
-	 */
-	if (sbp->sb_mccount[mchash] >= sbp->sb_mcsize[mchash]) {
-		struct	ether_addr	*newbucket;
-		int		newsize;
-
-		newsize = sbp->sb_mcsize[mchash] * 2;
-
-		newbucket = kmem_alloc(newsize * sizeof (struct ether_addr),
-			KM_SLEEP);
-		bcopy(mcbucket, newbucket,
-		    sbp->sb_mcsize[mchash] * sizeof (struct ether_addr));
-		kmem_free(mcbucket, sbp->sb_mcsize[mchash] *
-		    sizeof (struct ether_addr));
-
-		sbp->sb_mctab[mchash] = mcbucket = newbucket;
-		sbp->sb_mcsize[mchash] = newsize;
-	}
-
-	/*
-	 * Add address to the table.
-	 */
-	mcbucket[sbp->sb_mccount[mchash]++] = *addrp;
+	struct eri		*erip = arg;
+	uint32_t 		ladrf_bit;
 
 	/*
 	 * If this address's bit was not already set in the local address
 	 * filter, add it and re-initialize the Hardware.
 	 */
-	ladrf_bit = eri_ladrf_bit(addrp);
-
-	if (sbp->sb_ladrf_refcnt[ladrf_bit] == 0) {
-		sbp->sb_ladrf[15-(ladrf_bit/16)] |=
-		    1 << (ladrf_bit % 16);
-		sbp->sb_flags |= ERI_SMULTI;
-		mutex_enter(&sbp->sb_erip->intrlock);
-		eri_init_rx(sbp->sb_erip);
-		mutex_exit(&sbp->sb_erip->intrlock);
-	}
-	sbp->sb_ladrf_refcnt[ladrf_bit]++;
-
-	dlokack(wq, mp, DL_ENABMULTI_REQ);
-}
-
-static void
-eri_dmreq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr	*sbp;
-	union	DL_primitives	*dlp;
-	struct	ether_addr	*addrp;
-	t_uscalar_t off;
-	t_uscalar_t len;
-	int	i;
-	uint32_t mchash;
-	struct	ether_addr	*mcbucket;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	if (MBLKL(mp) < DL_DISABMULTI_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	if (sbp->sb_state == DL_UNATTACHED) {
-		dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	len = dlp->disabmulti_req.dl_addr_length;
-	off = dlp->disabmulti_req.dl_addr_offset;
-	addrp = (struct ether_addr *)(mp->b_rptr + off);
-
-	if ((len != ETHERADDRL) || !MBLKIN(mp, off, len)) {
-		dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_BADADDR, 0);
-		return;
-	}
-
-	/*
-	 * Calculate hash value, get pointer to hash bucket for this address.
-	 */
-
-	mchash = MCHASH(addrp);
-	mcbucket = sbp->sb_mctab[mchash];
-
-	/*
-	 * Try and delete the address if we can find it.
-	 */
-	if (mcbucket) {
-		for (i = 0; i < sbp->sb_mccount[mchash]; i++) {
-			if (ether_cmp(addrp, &mcbucket[i]) == 0) {
-				uint32_t ladrf_bit;
-
-				/*
-				 * If there's more than one address in this
-				 * bucket, delete the unwanted one by moving
-				 * the last one in the list over top of it;
-				 * otherwise, just free the bucket.
-				 */
-				if (sbp->sb_mccount[mchash] > 1) {
-					mcbucket[i] =
-					    mcbucket[sbp->sb_mccount[mchash]-1];
-				} else {
-					kmem_free(mcbucket,
-					    sbp->sb_mcsize[mchash] *
-					    sizeof (struct ether_addr));
-					sbp->sb_mctab[mchash] = NULL;
-				}
-				sbp->sb_mccount[mchash]--;
-
-				/*
-				 * If this address's bit should no longer be
-				 * set in the local address filter, clear it and
-				 * re-initialize the Hardware
-				 */
-
-				ladrf_bit = eri_ladrf_bit(addrp);
-				sbp->sb_ladrf_refcnt[ladrf_bit]--;
-
-				if (sbp->sb_ladrf_refcnt[ladrf_bit] == 0) {
-					sbp->sb_ladrf[15-(ladrf_bit/16)] &=
-						~(1 << (ladrf_bit % 16));
-					mutex_enter(&sbp->sb_erip->intrlock);
-					eri_init_rx(sbp->sb_erip);
-					mutex_exit(&sbp->sb_erip->intrlock);
-				}
-
-				dlokack(wq, mp, DL_DISABMULTI_REQ);
-				return;
-			}
+	ladrf_bit = eri_ladrf_bit(mca);
+
+	mutex_enter(&erip->intrlock);
+	if (add) {
+		erip->ladrf_refcnt[ladrf_bit]++;
+		if (erip->ladrf_refcnt[ladrf_bit] == 1) {
+			LADRF_SET(erip, ladrf_bit);
+			erip->multi_refcnt++;
+			eri_init_rx(erip);
+		}
+	} else {
+		erip->ladrf_refcnt[ladrf_bit]--;
+		if (erip->ladrf_refcnt[ladrf_bit] == 0) {
+			LADRF_CLR(erip, ladrf_bit);
+			erip->multi_refcnt--;
+			eri_init_rx(erip);
 		}
 	}
-	dlerrorack(wq, mp, DL_DISABMULTI_REQ, DL_NOTENAB, 0);
-}
-
-static void
-eri_pareq(queue_t *wq, mblk_t *mp)
-{
-	struct	eristr		*sbp;
-	union	DL_primitives	*dlp;
-	uint32_t type;
-	struct	eri		*erip;
-	struct	ether_addr	addr;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	if (MBLKL(mp) < DL_PHYS_ADDR_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	type = dlp->physaddr_req.dl_addr_type;
-	erip = sbp->sb_erip;
-	if (erip == NULL) {
-		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	switch (type) {
-	case	DL_FACT_PHYS_ADDR:
-		if (erip->addrflags & ERI_FACTADDR_PRESENT)
-			ether_bcopy(&erip->factaddr, &addr);
-		else
-			(void) localetheraddr((struct ether_addr *)NULL, &addr);
-		break;
-
-	case	DL_CURR_PHYS_ADDR:
-		ether_bcopy(&erip->ouraddr, &addr);
-		break;
-
-	default:
-		dlerrorack(wq, mp, DL_PHYS_ADDR_REQ, DL_NOTSUPPORTED, 0);
-		return;
-	}
-
-	dlphysaddrack(wq, mp, &addr, ETHERADDRL);
+	mutex_exit(&erip->intrlock);
+	return (0);
 }
 
-static void
-eri_spareq(queue_t *wq, mblk_t *mp)
+static int
+eri_m_unicst(void *arg, const uint8_t *macaddr)
 {
-	struct	eristr		*sbp;
-	union	DL_primitives	*dlp;
-	t_uscalar_t off;
-	t_uscalar_t len;
-	struct	ether_addr	*addrp;
-	struct	eri		*erip;
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (MBLKL(mp) < DL_SET_PHYS_ADDR_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	dlp = (union DL_primitives *)mp->b_rptr;
-	len = dlp->set_physaddr_req.dl_addr_length;
-	off = dlp->set_physaddr_req.dl_addr_offset;
-
-	if (!MBLKIN(mp, off, len)) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	addrp = (struct ether_addr *)(mp->b_rptr + off);
-
-	/*
-	 * Error if length of address isn't right or the address
-	 * specified is a multicast or broadcast address.
-	 */
-	if ((len != ETHERADDRL) ||
-		((addrp->ether_addr_octet[0] & 01) == 1) ||
-		(ether_cmp(addrp, &etherbroadcastaddr) == 0)) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADADDR, 0);
-		return;
-	}
-
-	/*
-	 * Error if this stream is not attached to a device.
-	 */
-	if ((erip = sbp->sb_erip) == NULL) {
-		dlerrorack(wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
-		return;
-	}
+	struct	eri	*erip = arg;
 
 	/*
 	 * Set new interface local address and re-init device.
 	 * This is destructive to any other streams attached
 	 * to this device.
 	 */
-	ether_bcopy(addrp, &erip->ouraddr);
 	mutex_enter(&erip->intrlock);
-	eri_init_rx(sbp->sb_erip);
+	bcopy(macaddr, &erip->ouraddr, ETHERADDRL);
+	eri_init_rx(erip);
 	mutex_exit(&erip->intrlock);
-
-	dlokack(wq, mp, DL_SET_PHYS_ADDR_REQ);
+	return (0);
 }
 
-static void
-eri_udreq(queue_t *wq, mblk_t *mp)
+/*ARGSUSED*/
+static boolean_t
+eri_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
 {
-	struct	eristr		*sbp;
-	struct	eri		*erip;
-	dl_unitdata_req_t	*dludp;
-	mblk_t	*nmp;
-	struct	eridladdr	*dlap;
-	struct	ether_header	*headerp;
-	t_uscalar_t off, len, sap;
-	uint_t	start_offset = 0;
-	uint_t	stuff_offset = 0;
-	uint_t	end_offset = 0;
-	uint_t	value = 0;
-	uint_t	flags = 0;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	erip = sbp->sb_erip;
-	if (sbp->sb_state != DL_IDLE) {
-		dlerrorack(wq, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	dludp = (dl_unitdata_req_t *)mp->b_rptr;
-
-	off = dludp->dl_dest_addr_offset;
-	len = dludp->dl_dest_addr_length;
-
-	/*
-	 * Validate destination address format.
-	 */
-	if (!MBLKIN(mp, off, len) || (len != ERI_ADDRL)) {
-		dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADADDR, 0);
-		return;
-	}
-
-	/*
-	 * Error if no M_DATA follows.
-	 */
-	nmp = mp->b_cont;
-	if (nmp == NULL) {
-		dluderrorind(wq, mp, mp->b_rptr + off, len, DL_BADDATA, 0);
-		return;
+	switch (cap) {
+	case MAC_CAPAB_HCKSUM: {
+		uint32_t *hcksum_txflags = cap_data;
+		*hcksum_txflags = HCKSUM_INET_PARTIAL;
+		return (B_TRUE);
 	}
-
-	dlap = (struct eridladdr *)(mp->b_rptr + off);
-
-	/*
-	 * Create ethernet header by either prepending it onto the
-	 * next mblk if possible, or reusing the M_PROTO block if not.
-	 */
-	if ((DB_REF(nmp) == 1) &&
-	    (MBLKHEAD(nmp) >= sizeof (struct ether_header)) &&
-	    (((uintptr_t)nmp->b_rptr & 0x1) == 0)) {
-		nmp->b_rptr -= sizeof (struct ether_header);
-		headerp = (struct ether_header *)nmp->b_rptr;
-		ether_bcopy(&dlap->dl_phys, &headerp->ether_dhost);
-		ether_bcopy(&erip->ouraddr, &headerp->ether_shost);
-		sap = (uint16_t)((((uchar_t *)(&dlap->dl_sap))[0] << 8) |
-			((uchar_t *)(&dlap->dl_sap))[1]);
-		freeb(mp);
-		mp = nmp;
-	} else {
-		DB_TYPE(mp) = M_DATA;
-		headerp = (struct ether_header *)mp->b_rptr;
-		mp->b_wptr = mp->b_rptr + sizeof (struct ether_header);
-		ether_bcopy(&dlap->dl_phys, &headerp->ether_dhost);
-		ether_bcopy(&erip->ouraddr, &headerp->ether_shost);
-		sap = (uint16_t)((((uchar_t *)(&dlap->dl_sap))[0] << 8) |
-			((uchar_t *)(&dlap->dl_sap))[1]);
-#ifdef ERI_HWCSUM
-		if (sbp->sb_flags & ERI_SCKSUM) {
-			hcksum_retrieve(nmp, NULL, NULL, &start_offset,
-			    &stuff_offset, &end_offset, &value, &flags);
-
-			if (flags & HCK_PARTIALCKSUM) {
-				(void) hcksum_assoc(mp, NULL, NULL,
-				    start_offset, stuff_offset, end_offset,
-				    0, flags, 0);
-				ERI_DEBUG_MSG1(erip, HWCSUM_MSG,
-				    "eri_udreq: added new buffer\n");
-			}
-		}
-#endif /* ERI_HWCSUM */
+	case MAC_CAPAB_POLL:
+	default:
+		return (B_FALSE);
 	}
-
-	/*
-	 * In 802.3 mode, the driver looks at the
-	 * sap field of the DL_BIND_REQ being 0 in addition to the destination
-	 * sap field in the range [0-1500]. If either is true, then the driver
-	 * computes the length of the message, not including initial M_PROTO
-	 * mblk (message block), of all subsequent DL_UNITDATA_REQ messages and
-	 * transmits 802.3 frames that have this value in the MAC frame header
-	 * length field.
-	 */
-	if (sap <= ETHERMTU || (sbp->sb_sap == 0)) {
-		put_ether_type(headerp,
-			(msgsize(mp) - sizeof (struct ether_header)));
-	} else {
-		put_ether_type(headerp, sap);
+}
+
+static int
+eri_m_start(void *arg)
+{
+	struct eri	*erip = arg;
+
+	mutex_enter(&erip->intrlock);
+	erip->flags |= ERI_STARTED;
+	mutex_exit(&erip->intrlock);
+
+	if (!eri_init(erip)) {
+		mutex_enter(&erip->intrlock);
+		erip->flags &= ~ERI_STARTED;
+		mutex_exit(&erip->intrlock);
+		return (EIO);
 	}
-	(void) eri_start(wq, mp, erip);
+	return (0);
 }
 
 static void
-eri_nreq(queue_t *wq, mblk_t *mp)
+eri_m_stop(void *arg)
 {
-	struct eristr	*sbp;
-	dl_notify_req_t	*dlip;
-	dl_notify_ind_t	*dlnip;
-	struct eri	*erip = NULL;
-	mblk_t		*nmp;
-	uint32_t	dl_notification;
-
-	if (MBLKL(mp) < DL_NOTIFY_REQ_SIZE) {
-		dlerrorack(wq, mp, DL_NOTIFY_REQ, DL_BADPRIM, 0);
-		return;
-	}
-
-	dlip = (dl_notify_req_t *)mp->b_rptr;
-
-	dl_notification = dlip->dl_notifications & (DL_NOTE_PROMISC_ON_PHYS |
-						DL_NOTE_PROMISC_OFF_PHYS |
-						DL_NOTE_LINK_DOWN |
-						DL_NOTE_LINK_UP |
-						DL_NOTE_SPEED);
-
-	sbp = (struct eristr *)wq->q_ptr;
-
-	if (sbp->sb_state != DL_IDLE) {
-		dlerrorack(wq, mp, DL_NOTIFY_REQ, DL_OUTSTATE, 0);
-		return;
-	}
-
-	erip = sbp->sb_erip;
-
-	sbp->sb_notifications |= dl_notification;
-
-	dlip->dl_notifications = DL_NOTE_PROMISC_ON_PHYS |
-				DL_NOTE_PROMISC_OFF_PHYS |
-				DL_NOTE_LINK_DOWN |
-				DL_NOTE_LINK_UP |
-				DL_NOTE_SPEED;
-
-	dlip->dl_primitive = DL_NOTIFY_ACK;
-	mp->b_wptr = mp->b_rptr + DL_NOTIFY_ACK_SIZE;
-	qreply(wq, mp);
-
-	while (dl_notification) {
-		if ((nmp = allocb(DL_NOTIFY_IND_SIZE, BPRI_HI)) == NULL)
-			break;
-		nmp->b_datap->db_type = M_PROTO;
-		dlnip = (dl_notify_ind_t *)nmp->b_rptr;
-		dlnip->dl_primitive = DL_NOTIFY_IND;
-		dlnip->dl_notification = 0;
-		dlnip->dl_data = 0;
-		dlnip->dl_addr_length = 0;
-		dlnip->dl_addr_offset = 0;
-		if (dl_notification & DL_NOTE_PROMISC_ON_PHYS) {
-			dl_notification &= ~DL_NOTE_PROMISC_ON_PHYS;
-			if (erip->promisc_cnt)
-				dlnip->dl_notification =
-					DL_NOTE_PROMISC_ON_PHYS;
-		} else if (dl_notification & DL_NOTE_PROMISC_OFF_PHYS) {
-			dl_notification &= ~DL_NOTE_PROMISC_OFF_PHYS;
-			if (erip->promisc_cnt == 0)
-				dlnip->dl_notification =
-					DL_NOTE_PROMISC_OFF_PHYS;
-		} else if (dl_notification & DL_NOTE_LINK_DOWN) {
-			dl_notification &= ~DL_NOTE_LINK_DOWN;
-			if (!param_linkup)
-				dlnip->dl_notification = DL_NOTE_LINK_DOWN;
-		} else if (dl_notification & DL_NOTE_LINK_UP) {
-			dl_notification &= ~DL_NOTE_LINK_UP;
-			if (param_linkup)
-				dlnip->dl_notification = DL_NOTE_LINK_UP;
-		} else if (dl_notification & DL_NOTE_SPEED) {
-			dl_notification &= ~DL_NOTE_SPEED;
-			dlnip->dl_data = erip->stats.ifspeed * 1000;
-			dlnip->dl_notification = DL_NOTE_SPEED;
-		}
-		if (dlnip->dl_notification) {
-			nmp->b_wptr = nmp->b_rptr + DL_NOTIFY_IND_SIZE;
-			qreply(wq, nmp);
-		} else
-			freemsg(nmp);
-	}
+	struct eri	*erip = arg;
+
+	mutex_enter(&erip->intrlock);
+	erip->flags &= ~ERI_STARTED;
+	mutex_exit(&erip->intrlock);
+	eri_uninit(erip);
 }
 
-static void
-eri_notify_ind(struct eri *erip, uint32_t notification)
+static int
+eri_m_stat(void *arg, uint_t stat, uint64_t *val)
 {
-	struct eristr	*sbp;
-	mblk_t		*mp;
-	dl_notify_ind_t	*dlnip;
-
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip != erip)
-			continue;
-		if (notification & sbp->sb_notifications) {
-			if ((mp = allocb(DL_NOTIFY_IND_SIZE, BPRI_HI))
-			    == NULL) {
-				HSTAT(erip, allocbfail);
-				break;
-			}
-			mp->b_datap->db_type = M_PROTO;
-			dlnip = (dl_notify_ind_t *)mp->b_rptr;
-			dlnip->dl_primitive = DL_NOTIFY_IND;
-			dlnip->dl_notification = notification;
-			if (notification == DL_NOTE_SPEED)
-				dlnip->dl_data = erip->stats.ifspeed * 1000;
-			else
-				dlnip->dl_data = 0;
-			dlnip->dl_addr_length = 0;
-			dlnip->dl_addr_offset = 0;
-			mp->b_wptr = mp->b_rptr + DL_NOTIFY_IND_SIZE;
-			qreply(WR(sbp->sb_rq), mp);
-		}
+	struct eri	*erip = arg;
+	struct stats	*esp;
+	boolean_t	macupdate = B_FALSE;
+
+	esp = &erip->stats;
+
+	mutex_enter(&erip->xmitlock);
+	if ((erip->flags & ERI_RUNNING) && (erip->flags & ERI_TXINIT)) {
+		erip->tx_completion =
+		    GET_ETXREG(tx_completion) & ETX_COMPLETION_MASK;
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 	}
-}
-
-static void
-eri_send_notifications(struct eri *erip, uint32_t linkflags)
-{
-	if (linkflags & DL_NOTE_LINK_DOWN) {
-		eri_notify_ind(erip, DL_NOTE_LINK_DOWN);
+	mutex_exit(&erip->xmitlock);
+	if (macupdate)
+		mac_tx_update(erip->mh);
+
+	eri_savecntrs(erip);
+
+	switch (stat) {
+	case MAC_STAT_IFSPEED:
+		*val = esp->ifspeed * 1000000ULL;
+		break;
+	case MAC_STAT_MULTIRCV:
+		*val = esp->multircv;
+		break;
+	case MAC_STAT_BRDCSTRCV:
+		*val = esp->brdcstrcv;
+		break;
+	case MAC_STAT_IPACKETS:
+		*val = esp->ipackets64;
+		break;
+	case MAC_STAT_RBYTES:
+		*val = esp->rbytes64;
+		break;
+	case MAC_STAT_OBYTES:
+		*val = esp->obytes64;
+		break;
+	case MAC_STAT_OPACKETS:
+		*val = esp->opackets64;
+		break;
+	case MAC_STAT_IERRORS:
+		*val = esp->ierrors;
+		break;
+	case MAC_STAT_OERRORS:
+		*val = esp->oerrors;
+		break;
+	case MAC_STAT_MULTIXMT:
+		*val = esp->multixmt;
+		break;
+	case MAC_STAT_BRDCSTXMT:
+		*val = esp->brdcstxmt;
+		break;
+	case MAC_STAT_NORCVBUF:
+		*val = esp->norcvbuf;
+		break;
+	case MAC_STAT_NOXMTBUF:
+		*val = esp->noxmtbuf;
+		break;
+	case MAC_STAT_UNDERFLOWS:
+		*val = esp->txmac_urun;
+		break;
+	case MAC_STAT_OVERFLOWS:
+		*val = esp->rx_overflow;
+		break;
+	case MAC_STAT_COLLISIONS:
+		*val = esp->collisions;
+		break;
+	case ETHER_STAT_ALIGN_ERRORS:
+		*val = esp->rx_align_err;
+		break;
+	case ETHER_STAT_FCS_ERRORS:
+		*val = esp->rx_crc_err;
+		break;
+	case ETHER_STAT_EX_COLLISIONS:
+		*val = esp->excessive_coll;
+		break;
+	case ETHER_STAT_TX_LATE_COLLISIONS:
+		*val = esp->late_coll;
+		break;
+	case ETHER_STAT_FIRST_COLLISIONS:
+		*val = esp->first_coll;
+		break;
+	case ETHER_STAT_LINK_DUPLEX:
+		*val = esp->link_duplex;
+		break;
+	case ETHER_STAT_TOOLONG_ERRORS:
+		*val = esp->rx_toolong_pkts;
+		break;
+	case ETHER_STAT_TOOSHORT_ERRORS:
+		*val = esp->rx_runt;
+		break;
+
+	case ETHER_STAT_XCVR_ADDR:
+		*val = erip->phyad;
+		break;
+
+	case ETHER_STAT_XCVR_INUSE:
+		*val = XCVR_100X;	/* should always be 100X for now */
+		break;
+
+	case ETHER_STAT_CAP_100FDX:
+		*val = param_bmsr_100fdx;
+		break;
+	case ETHER_STAT_CAP_100HDX:
+		*val = param_bmsr_100hdx;
+		break;
+	case ETHER_STAT_CAP_10FDX:
+		*val = param_bmsr_10fdx;
+		break;
+	case ETHER_STAT_CAP_10HDX:
+		*val = param_bmsr_10hdx;
+		break;
+	case ETHER_STAT_CAP_AUTONEG:
+		*val = param_bmsr_ancap;
+		break;
+	case ETHER_STAT_CAP_ASMPAUSE:
+		*val = param_bmsr_asm_dir;
+		break;
+	case ETHER_STAT_CAP_PAUSE:
+		*val = param_bmsr_pause;
+		break;
+	case ETHER_STAT_ADV_CAP_100FDX:
+		*val = param_anar_100fdx;
+		break;
+	case ETHER_STAT_ADV_CAP_100HDX:
+		*val = param_anar_100hdx;
+		break;
+	case ETHER_STAT_ADV_CAP_10FDX:
+		*val = param_anar_10fdx;
+		break;
+	case ETHER_STAT_ADV_CAP_10HDX:
+		*val = param_anar_10hdx;
+		break;
+	case ETHER_STAT_ADV_CAP_AUTONEG:
+		*val = param_autoneg;
+		break;
+	case ETHER_STAT_ADV_CAP_ASMPAUSE:
+		*val = param_anar_asm_dir;
+		break;
+	case ETHER_STAT_ADV_CAP_PAUSE:
+		*val = param_anar_pause;
+		break;
+	case ETHER_STAT_LP_CAP_100FDX:
+		*val = param_anlpar_100fdx;
+		break;
+	case ETHER_STAT_LP_CAP_100HDX:
+		*val = param_anlpar_100hdx;
+		break;
+	case ETHER_STAT_LP_CAP_10FDX:
+		*val = param_anlpar_10fdx;
+		break;
+	case ETHER_STAT_LP_CAP_10HDX:
+		*val = param_anlpar_10hdx;
+		break;
+	case ETHER_STAT_LP_CAP_AUTONEG:
+		*val = param_aner_lpancap;
+		break;
+	case ETHER_STAT_LP_CAP_ASMPAUSE:
+		*val = param_anlpar_pauseTX;
+		break;
+	case ETHER_STAT_LP_CAP_PAUSE:
+		*val = param_anlpar_pauseRX;
+		break;
+	case ETHER_STAT_LINK_PAUSE:
+		*val = esp->pausing;
+		break;
+	case ETHER_STAT_LINK_ASMPAUSE:
+		*val = param_anar_asm_dir &&
+		    param_anlpar_pauseTX &&
+		    (param_anar_pause != param_anlpar_pauseRX);
+		break;
+	case ETHER_STAT_LINK_AUTONEG:
+		*val = param_autoneg && param_aner_lpancap;
+		break;
 	}
-	if (linkflags & DL_NOTE_LINK_UP) {
-		eri_notify_ind(erip, DL_NOTE_LINK_UP);
-		eri_notify_ind(erip, DL_NOTE_SPEED);
-	}
+	return (0);
 }
 
 /*
- * Set or clear the device ipq pointer.
- * XXX Assumes IPv4 and IPv6 are ERIFAST.
- */
-static void
-eri_setipq(struct eri *erip)
-{
-	struct	eristr	*sbp;
-	int	ok4 = 1;
-	int	ok6 = 1;
-	queue_t	*ip4q = NULL;
-	queue_t	*ip6q = NULL;
-
-	rw_enter(&eristruplock, RW_READER);
-
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & (ERI_SALLPHYS|ERI_SALLSAP)) {
-				ok4 = 0;
-				ok6 = 0;
-				break;
-			}
-			if (sbp->sb_sap == ETHERTYPE_IPV4) {
-				if (ip4q == NULL)
-					ip4q = sbp->sb_rq;
-				else
-					ok4 = 0;
-			}
-			if (sbp->sb_sap == ETHERTYPE_IPV6) {
-				if (ip6q == NULL)
-					ip6q = sbp->sb_rq;
-				else
-					ok6 = 0;
-			}
-		}
-	}
-
-	if (ok4)
-		erip->ip4q = ip4q;
-	else
-		erip->ip4q = NULL;
-
-	if (ok6)
-		erip->ip6q = ip6q;
-	else
-		erip->ip6q = NULL;
-
-	rw_exit(&eristruplock);
-}
-
-
-/*
  * Hardware Functions
  * New Section
  */
@@ -3334,12 +1539,7 @@
  */
 static void
 eri_init_macregs_generic(struct eri *erip)
-
 {
-	struct	eristr	*sbp;
-	uint16_t	ladrf[NMCFILTER_BITS/16];
-	int i;
-
 	/*
 	 * set up the MAC parameter registers once
 	 * after power cycle. SUSPEND/RESUME also requires
@@ -3361,8 +1561,7 @@
 		PUT_MACREG(alimit, BMAC_ATTEMPT_LIMIT);
 		PUT_MACREG(macctl_type, BMAC_CONTROL_TYPE);
 		PUT_MACREG(rseed,
-			((erip->ouraddr.ether_addr_octet[0] & 0x3) << 8) |
-			erip->ouraddr.ether_addr_octet[1]);
+		    ((erip->ouraddr[0] & 0x3) << 8) | erip->ouraddr[1]);
 
 		PUT_MACREG(madd3, BMAC_ADDRESS_3);
 		PUT_MACREG(madd4, BMAC_ADDRESS_4);
@@ -3396,59 +1595,6 @@
 		PUT_MACREG(spcmd, BMAC_SEND_PAUSE_CMD);
 	else
 		PUT_MACREG(spcmd, 0);
-	/*
-	 * Program BigMAC with local individual ethernet address.
-	 */
-	PUT_MACREG(madd0, (erip->ouraddr.ether_addr_octet[4] << 8) |
-		erip->ouraddr.ether_addr_octet[5]);
-	PUT_MACREG(madd1, (erip->ouraddr.ether_addr_octet[2] << 8) |
-		erip->ouraddr.ether_addr_octet[3]);
-	PUT_MACREG(madd2, (erip->ouraddr.ether_addr_octet[0] << 8) |
-		erip->ouraddr.ether_addr_octet[1]);
-
-	/*
-	 * Set up multicast address filter by passing all multicast
-	 * addresses through a crc generator, and then using the
-	 * low order 8 bits as a index into the 256 bit logical
-	 * address filter. The high order four bits select the word,
-	 * while the rest of the bits select the bit within the word.
-	 */
-
-	bzero((caddr_t)ladrf, NMCFILTER_BITS/16 * sizeof (uint16_t));
-
-	/*
-	 * Here we initialize the MC Hash bits
-	 */
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & ERI_SALLMULTI) {
-				for (i = 0; i < NMCFILTER_BITS/16; i++) {
-					ladrf[i] = 0xffff;
-				}
-				break;	/* All bits are already on */
-			}
-			for (i = 0; i < NMCFILTER_BITS/16; i++)
-				ladrf[i] |= sbp->sb_ladrf[i];
-		}
-	}
-
-	PUT_MACREG(hash0, ladrf[0]);
-	PUT_MACREG(hash1, ladrf[1]);
-	PUT_MACREG(hash2, ladrf[2]);
-	PUT_MACREG(hash3, ladrf[3]);
-	PUT_MACREG(hash4, ladrf[4]);
-	PUT_MACREG(hash5, ladrf[5]);
-	PUT_MACREG(hash6, ladrf[6]);
-	PUT_MACREG(hash7, ladrf[7]);
-	PUT_MACREG(hash8, ladrf[8]);
-	PUT_MACREG(hash9, ladrf[9]);
-	PUT_MACREG(hash10, ladrf[10]);
-	PUT_MACREG(hash11, ladrf[11]);
-	PUT_MACREG(hash12, ladrf[12]);
-	PUT_MACREG(hash13, ladrf[13]);
-	PUT_MACREG(hash14, ladrf[14]);
-	PUT_MACREG(hash15, ladrf[15]);
-
 }
 
 static int
@@ -3499,7 +1645,7 @@
 		if (erip->rmblkp[i]) {
 			if (erip->eri_dvmarh)
 				dvma_unload(erip->eri_dvmarh, 2 * i,
-						DDI_DMA_SYNC_FORCPU);
+				    DDI_DMA_SYNC_FORCPU);
 			else if ((ddi_dma_unbind_handle(erip->ndmarh[i]) ==
 			    DDI_FAILURE))
 				status = -1;
@@ -3550,24 +1696,21 @@
 	for (i = 0; i < ERI_RPENDING; i++) {
 		if ((bp = eri_allocb(ERI_BUFSIZE)) == NULL) {
 			status = -1;
-			ERI_DEBUG_MSG1(erip, RESOURCE_MSG,
-					"eri_init_rxbufs allocb failed");
 			continue;
 		}
 		/* Load data buffer to DVMA space */
 		if (erip->eri_dvmarh)
-			(void) dvma_kaddr_load(erip->eri_dvmarh,
-			(caddr_t)bp->b_rptr, ERI_BUFSIZE,
-			2 * i, &dma_cookie);
+			dvma_kaddr_load(erip->eri_dvmarh,
+			    (caddr_t)bp->b_rptr, ERI_BUFSIZE,
+			    2 * i, &dma_cookie);
 /*
  *		Bind data buffer to DMA handle
  */
 		else if (ddi_dma_addr_bind_handle(erip->ndmarh[i], NULL,
-			(caddr_t)bp->b_rptr, ERI_BUFSIZE,
-			DDI_DMA_READ | DDI_DMA_CONSISTENT,
-			DDI_DMA_DONTWAIT, 0,
-			&dma_cookie, &ccnt) != DDI_DMA_MAPPED)
-				status = -1;
+		    (caddr_t)bp->b_rptr, ERI_BUFSIZE,
+		    DDI_DMA_READ | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
+		    &dma_cookie, &ccnt) != DDI_DMA_MAPPED)
+			status = -1;
 
 		PUT_RMD((&erip->rmdp[i]), dma_cookie);
 		erip->rmblkp[i] = bp;	/* save for later use */
@@ -3576,8 +1719,8 @@
 	/*
 	 * sync RXDMA descriptors.
 	 */
-	ERI_SYNCIOPB(erip, erip->rmdp,
-		(ERI_RPENDING * sizeof (struct rmd)), DDI_DMA_SYNC_FORDEV);
+	ERI_SYNCIOPB(erip, erip->rmdp, (ERI_RPENDING * sizeof (struct rmd)),
+	    DDI_DMA_SYNC_FORDEV);
 	/*
 	 * Reset RMD 'walking' pointers.
 	 */
@@ -3624,8 +1767,6 @@
 static int
 eri_stop(struct eri *erip)
 {
-	ERI_DEBUG_MSG1(erip, INIT_MSG,
-			"eri_stop");
 	(void) eri_erx_reset(erip);
 	(void) eri_etx_reset(erip);
 
@@ -3639,13 +1780,13 @@
 		erip->global_reset_issued = 2;
 	} else {
 		param_linkup = 0;
-		erip->stats.link_up = ERI_LINK_DOWN;
-		erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+		erip->stats.link_up = LINK_STATE_DOWN;
+		erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 		erip->global_reset_issued = -1;
 	}
 
 	ERI_DELAY((GET_SWRSTREG(reset) == ERI_CACHE_LINE_SIZE),
-			ERI_MAX_RST_DELAY);
+	    ERI_MAX_RST_DELAY);
 	erip->rx_reset_issued = -1;
 	erip->tx_reset_issued = -1;
 
@@ -3658,8 +1799,6 @@
 	if (GET_SWRSTREG(reset) == ERI_CACHE_LINE_SIZE) {
 		return (0);
 	} else {
-		ERI_DEBUG_MSG1(erip, XCVR_MSG,
-			"cannot stop eri");
 		return (1);
 	}
 }
@@ -3684,7 +1823,7 @@
 	ERI_DELAY(((GET_ERXREG(config) &  1) == 0), ERI_MAX_RST_DELAY);
 	if ((GET_ERXREG(config) & 1) != 0)
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				disable_erx_msg);
+		    disable_erx_msg);
 
 	drv_usecwait(5000); /* Delay to insure no RX DMA activity */
 
@@ -3693,16 +1832,11 @@
 	 * Wait until the reset is completed which is indicated by
 	 * the reset bit cleared or time out..
 	 */
-	ERI_DELAY(((GET_SWRSTREG(reset) &  (ERI_G_RESET_ERX)) ==
-		ERI_CACHE_LINE_SIZE), ERI_MAX_RST_DELAY);
+	ERI_DELAY(((GET_SWRSTREG(reset) & (ERI_G_RESET_ERX)) ==
+	    ERI_CACHE_LINE_SIZE), ERI_MAX_RST_DELAY);
 	erip->rx_reset_issued = -1;
 
-	if (GET_SWRSTREG(reset) & (ERI_G_RESET_ERX)) {
-		ERI_DEBUG_MSG1(erip, INIT_MSG,
-				"Can not reset erx");
-		return (1);
-	} else
-		return (0);
+	return ((GET_SWRSTREG(reset) & (ERI_G_RESET_ERX)) ? 1 : 0);
 }
 
 /*
@@ -3725,14 +1859,14 @@
 	ERI_DELAY(((GET_ETXREG(config) &  1) == 0), ERI_MAX_RST_DELAY);
 	if ((GET_ETXREG(config) &  1) != 0)
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				disable_etx_msg);
+		    disable_etx_msg);
 	drv_usecwait(5000); /* Delay  to ensure DMA completed (if any). */
 #endif
 	drv_usecwait(5000); /* Delay  to ensure DMA completed (if any). */
 	ERI_DELAY(((GET_ETXREG(config) &  1) == 0), ERI_MAX_RST_DELAY);
 	if ((GET_ETXREG(config) &  1) != 0)
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				disable_etx_msg);
+		    disable_etx_msg);
 
 	PUT_SWRSTREG(reset, ERI_G_RESET_ETX | ERI_CACHE_LINE_SIZE);
 
@@ -3741,12 +1875,10 @@
 	 * cleared or time out..
 	 */
 	ERI_DELAY(((GET_SWRSTREG(reset) & (ERI_G_RESET_ETX)) ==
-		ERI_CACHE_LINE_SIZE), ERI_MAX_RST_DELAY);
+	    ERI_CACHE_LINE_SIZE), ERI_MAX_RST_DELAY);
 	erip->tx_reset_issued = -1;
 
 	if (GET_SWRSTREG(reset) &  (ERI_G_RESET_ETX)) {
-		ERI_DEBUG_MSG1(erip, INIT_MSG,
-				"cannot reset eri etx");
 		return (1);
 	} else
 		return (0);
@@ -3762,9 +1894,6 @@
 
 	uint32_t	i;
 	uint64_t	tx_ring;
-#ifdef	DEBUG
-	uint32_t	txfifoth = ETX_CONFIG_THRESHOLD;
-#endif
 
 	/*
 	 * Initialize ETX Registers:
@@ -3797,14 +1926,10 @@
 		break;
 	default:
 		ERI_FAULT_MSG2(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-			unk_tx_descr_sze_msg, ERI_TPENDING);
+		    unk_tx_descr_sze_msg, ERI_TPENDING);
 		return (1);
 	}
 
-	ERI_DEBUG_MSG2(erip, INIT_MSG,
-		"eri_init_txregs: tx fifo threshold %X",
-		txfifoth);
-
 	i <<= ERI_TX_RINGSZ_SHIFT;
 	PUT_ETXREG(config, ETX_CONFIG_THRESHOLD | i);
 	ENABLE_TXDMA(erip);
@@ -3865,20 +1990,19 @@
 		break;
 	default:
 		ERI_FAULT_MSG2(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-			unk_rx_descr_sze_msg, ERI_RPENDING);
+		    unk_rx_descr_sze_msg, ERI_RPENDING);
 		return (1);
 	}
 
 	i <<= ERI_RX_RINGSZ_SHIFT;
 	i |=  (ERI_FSTBYTE_OFFSET << ERI_RX_CONFIG_FBO_SHIFT) |
-		(sizeof (struct ether_header) <<
-			ERI_RX_CONFIG_RX_CSSTART_SHIFT) |
-		(ERI_RX_FIFOTH_1024 << ERI_RX_CONFIG_RXFIFOTH_SHIFT);
+	    (ETHERHEADER_SIZE << ERI_RX_CONFIG_RX_CSSTART_SHIFT) |
+	    (ERI_RX_FIFOTH_1024 << ERI_RX_CONFIG_RXFIFOTH_SHIFT);
 
 	PUT_ERXREG(config, i);
 	PUT_ERXREG(rx_blanking,
-		(param_intr_blank_time << ERI_RX_BLNK_INTR_TIME_SHIFT) |
-		param_intr_blank_packets);
+	    (param_intr_blank_time << ERI_RX_BLNK_INTR_TIME_SHIFT) |
+	    param_intr_blank_packets);
 
 	PUT_ERXREG(rx_pause_threshold, rx_pause_threshold);
 	erip->rxfifo_size = GET_ERXREG(rxfifo_size);
@@ -3913,9 +2037,8 @@
 	/*
 	 * sync RXDMA descriptors.
 	 */
-	ERI_SYNCIOPB(erip, erip->rmdp,
-		    (ERI_RPENDING * sizeof (struct rmd)),
-		    DDI_DMA_SYNC_FORDEV);
+	ERI_SYNCIOPB(erip, erip->rmdp, (ERI_RPENDING * sizeof (struct rmd)),
+	    DDI_DMA_SYNC_FORDEV);
 	/*
 	 * Reset RMD 'walking' pointers.
 	 */
@@ -3949,9 +2072,7 @@
 static void
 eri_init_rx(struct eri *erip)
 {
-	struct  eristr  *sbp;
-	uint16_t	ladrf[NMCFILTER_BITS/16];
-	int i;
+	uint16_t	*ladrf;
 
 	/*
 	 * First of all make sure the Receive MAC is stop.
@@ -3962,24 +2083,9 @@
 	 * Program BigMAC with local individual ethernet address.
 	 */
 
-	PUT_MACREG(madd0, (erip->ouraddr.ether_addr_octet[4] << 8) |
-	    erip->ouraddr.ether_addr_octet[5]);
-	PUT_MACREG(madd1, (erip->ouraddr.ether_addr_octet[2] << 8) |
-	    erip->ouraddr.ether_addr_octet[3]);
-	PUT_MACREG(madd2, (erip->ouraddr.ether_addr_octet[0] << 8) |
-	    erip->ouraddr.ether_addr_octet[1]);
-
-	/*
-	 * XXX moved here setting erip->flags from end of this fn.
-	 */
-	if (erip->promisc_cnt)
-		erip->flags |= ERI_PROMISC;
-	else
-		erip->flags &= ~ERI_PROMISC;
-	if (erip->all_multi_cnt)
-		erip->flags |= ERI_ALLMULTI;
-	else
-		erip->flags &= ~ERI_ALLMULTI;
+	PUT_MACREG(madd0, (erip->ouraddr[4] << 8) | erip->ouraddr[5]);
+	PUT_MACREG(madd1, (erip->ouraddr[2] << 8) | erip->ouraddr[3]);
+	PUT_MACREG(madd2, (erip->ouraddr[0] << 8) | erip->ouraddr[1]);
 
 	/*
 	 * Set up multicast address filter by passing all multicast
@@ -3989,40 +2095,7 @@
 	 * while the rest of the bits select the bit within the word.
 	 */
 
-	bzero(ladrf, sizeof (ladrf));
-
-	rw_enter(&eristruplock, RW_READER);
-
-	/*
-	 * Here we initialize the MC Hash bits
-	 */
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & ERI_SALLMULTI) {
-				for (i = 0; i < NMCFILTER_BITS/16; i++) {
-					ladrf[i] = 0xffff;
-				}
-				break;	/* All bits are already on */
-			}
-			for (i = 0; i < NMCFILTER_BITS/16; i++)
-				ladrf[i] |= sbp->sb_ladrf[i];
-		}
-	}
-
-	/*
-	 * Determine if Multicast mode.
-	 */
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & ERI_SMULTI)
-				erip->flags |= ERI_MULTICAST;
-			else
-				erip->flags &= ~ERI_MULTICAST;
-			break;
-		}
-	}
-
-	rw_exit(&eristruplock);
+	ladrf = erip->ladrf;
 
 	PUT_MACREG(hash0, ladrf[0]);
 	PUT_MACREG(hash1, ladrf[1]);
@@ -4043,76 +2116,21 @@
 
 #ifdef ERI_DONT_STRIP_CRC
 	PUT_MACREG(rxcfg,
-	    ((erip->flags & ERI_PROMISC ? BMAC_RXCFG_PROMIS : 0) |
-	    (erip->flags & ERI_MULTICAST ? BMAC_RXCFG_HASH : 0) |
-	    (erip->flags & ERI_ALLMULTI ? BMAC_RXCFG_GRPROM : 0) |
+	    ((erip->promisc ? BMAC_RXCFG_PROMIS : 0) |
+	    (erip->multi_refcnt ? BMAC_RXCFG_HASH : 0) |
 	    BMAC_RXCFG_ENAB));
 #else
 	PUT_MACREG(rxcfg,
-	    ((erip->flag & ERI_PROMISC ? BMAC_RXCFG_PROMIS : 0) |
-	    (erip->flags & ERI_MULTICAST ? BMAC_RXCFG_HASH : 0) |
-	    (erip->flags & ERI_ALLMULTI ? BMAC_RXCFG_GRPROM : 0) |
+	    ((erip->promisc ? BMAC_RXCFG_PROMIS : 0) |
+	    (erip->multi_refcnt ? BMAC_RXCFG_HASH : 0) |
 	    BMAC_RXCFG_ENAB | BMAC_RXCFG_STRIP_CRC));
 #endif
 	/* wait after setting Hash Enable bit */
 	/* drv_usecwait(10); */
 
 	HSTAT(erip, rx_inits);
-
-#if 0
-	/*
-	 * XXX why is this here?
-	 * should be moved before setting h/w register.
-	 */
-
-	if (erip->promisc_cnt)
-		erip->flags |= ERI_PROMISC;
-	else
-		erip->flags &= ~ERI_PROMISC;
-	if (erip->all_multi)
-		erip->flags |= ERI_ALLMULTI;
-	else
-		erip->flags &= ~ERI_ALLMULTI;
-#endif
-
 }
 
-#ifdef	LATER_SPLIT_TX_RX
-/*
- * This routine is used to reset the TX DMA only.
- *	&erip->xmitlock is held before calling this routine.
- */
-void
-eri_init_tx_channel(struct eri *erip)
-{
-	uint32_t	carrier_ext = 0;
-
-	erip->flags &= ~ERI_TXINIT;
-	(void) eri_etx_reset(erip);
-	PUT_MACREG(txmask, BMAC_TXINTR_MASK);
-	(void) eri_init_txregs(erip);
-	if (erip->ngu_enable)
-		PUT_MACREG(txcfg,
-		((param_mode ? BMAC_TXCFG_FDX: 0) |
-		((param_lance_mode && (erip->lance_mode_enable)) ?
-		BMAC_TXCFG_ENIPG0 : 0) |
-		(carrier_ext ? BMAC_TXCFG_CARR_EXT : 0) |
-		BMAC_TXCFG_NGU));
-	else
-		PUT_MACREG(txcfg,
-		((param_mode ? BMAC_TXCFG_FDX: 0) |
-		((param_lance_mode && (erip->lance_mode_enable)) ?
-		BMAC_TXCFG_ENIPG0 : 0) |
-		(carrier_ext ? BMAC_TXCFG_CARR_EXT : 0)));
-
-	erip->tx_reset_issued = 0;
-	HSTAT(erip, tx_inits);
-	erip->flags |= ERI_TXINIT;
-
-}
-
-#endif
-
 /*
  * This routine is used to init the TX MAC only.
  *	&erip->xmitlock is held before calling this routine.
@@ -4146,18 +2164,16 @@
 	PUT_MACREG(ipg2, param_ipg2);
 
 	if (erip->ngu_enable)
-		PUT_MACREG(txcfg,
-		((param_mode ? BMAC_TXCFG_FDX: 0) |
-		((param_lance_mode && (erip->lance_mode_enable)) ?
-		BMAC_TXCFG_ENIPG0 : 0) |
-		(carrier_ext ? BMAC_TXCFG_CARR_EXT : 0) |
-		BMAC_TXCFG_NGU));
+		PUT_MACREG(txcfg, ((param_mode ? BMAC_TXCFG_FDX: 0) |
+		    ((param_lance_mode && (erip->lance_mode_enable)) ?
+		    BMAC_TXCFG_ENIPG0 : 0) |
+		    (carrier_ext ? BMAC_TXCFG_CARR_EXT : 0) |
+		    BMAC_TXCFG_NGU));
 	else
-		PUT_MACREG(txcfg,
-		((param_mode ? BMAC_TXCFG_FDX: 0) |
-		((param_lance_mode && (erip->lance_mode_enable)) ?
-		BMAC_TXCFG_ENIPG0 : 0) |
-		(carrier_ext ? BMAC_TXCFG_CARR_EXT : 0)));
+		PUT_MACREG(txcfg, ((param_mode ? BMAC_TXCFG_FDX: 0) |
+		    ((param_lance_mode && (erip->lance_mode_enable)) ?
+		    BMAC_TXCFG_ENIPG0 : 0) |
+		    (carrier_ext ? BMAC_TXCFG_CARR_EXT : 0)));
 
 	ENABLE_TXDMA(erip);
 	ENABLE_TXMAC(erip);
@@ -4165,31 +2181,10 @@
 	HSTAT(erip, tx_inits);
 	erip->flags |= ERI_TXINIT;
 }
-/*
- * Start xmit on any msgs previously enqueued on any write queues.
- */
-static void
-eri_wenable(struct eri *erip)
-{
-	struct	eristr	*sbp;
-	queue_t	*wq;
-
-	/*
-	 * Order of wantw accesses is important.
-	 */
-	do {
-		erip->wantw = 0;
-		for (sbp = eristrup; sbp; sbp = sbp->sb_nextp)
-			if ((wq = WR(sbp->sb_rq))->q_first)
-				qenable(wq);
-	} while (erip->wantw);
-}
 
 static void
 eri_unallocthings(struct eri *erip)
 {
-
-
 	uint32_t	flag;
 	uint32_t	i;
 
@@ -4246,7 +2241,7 @@
 
 /*
  * Initialize channel.
- * Return 0 on success, nonzero on error.
+ * Return true on success, false on error.
  *
  * The recommended sequence for initialization is:
  * 1. Issue a Global Reset command to the Ethernet Channel.
@@ -4277,48 +2272,35 @@
  */
 /*
  * lock order:
- *	intrlock->linklock->eristruplock->xmitlock->xcvrlock
+ *	intrlock->linklock->xmitlock->xcvrlock
  */
-static int
+static boolean_t
 eri_init(struct eri *erip)
 {
-	struct	eristr	*sbp;
 	uint32_t	init_stat = 0;
 	uint32_t	partial_init = 0;
 	uint32_t	carrier_ext = 0;
 	uint32_t	mac_ctl = 0;
-	uint_t		ret;
-	uint32_t link_timeout	= ERI_LINKCHECK_TIMER;
-	uint32_t	linkflags;
-
-	ERI_DEBUG_MSG1(erip, INIT_MSG,
-			"eri_init: Entered");
+	boolean_t	ret;
+	uint32_t 	link_timeout = ERI_LINKCHECK_TIMER;
+	link_state_t	linkupdate = LINK_STATE_UNKNOWN;
 
 	/*
-	 * Just return if device is suspended.
+	 * Just return successfully if device is suspended.
 	 * eri_init() will be called again from resume.
 	 */
-	if (erip == NULL) {
-		ERI_DEBUG_MSG1(NULL, INIT_MSG,
-				"eri_init: erip == NULL");
-		ret = 1;
-		goto init_exit;
-	} else if (erip->flags & ERI_SUSPENDED) {
-		ERI_DEBUG_MSG1(NULL, INIT_MSG,
-				"eri_init: erip->flags & ERI_SUSPENDED");
-		ret = 1;
+	ASSERT(erip != NULL);
+
+	if (erip->flags & ERI_SUSPENDED) {
+		ret = B_TRUE;
 		goto init_exit;
 	}
 
-	ERI_DEBUG_MSG1(erip, INIT_MSG,
-			"eri_init: Entered erip");
-
 	mutex_enter(&erip->intrlock);
 	eri_stop_timer(erip);	/* acquire linklock */
-	rw_enter(&eristruplock, RW_WRITER);
 	mutex_enter(&erip->xmitlock);
-	erip->flags &= ERI_DLPI_LINKUP;
-	erip->wantw = 0;
+	erip->flags &= (ERI_DLPI_LINKUP | ERI_STARTED);
+	erip->wantw = B_FALSE;
 	HSTAT(erip, inits);
 	erip->txhung = 0;
 
@@ -4328,15 +2310,14 @@
 	mutex_enter(&erip->xcvrlock);
 	if (!param_linkup || erip->linkcheck) {
 		if (!erip->linkcheck)
-			linkflags = DL_NOTE_LINK_DOWN;
+			linkupdate = LINK_STATE_DOWN;
 		(void) eri_stop(erip);
 	}
 	if (!(erip->flags & ERI_DLPI_LINKUP) || !param_linkup) {
 		erip->flags |= ERI_DLPI_LINKUP;
 		eri_mif_poll(erip, MIF_POLL_STOP);
 		(void) eri_new_xcvr(erip);
-		ERI_DEBUG_MSG1(erip, XCVR_MSG,
-				"New transceiver detected.");
+		ERI_DEBUG_MSG1(erip, XCVR_MSG, "New transceiver detected.");
 		if (param_transceiver != NO_XCVR) {
 			/*
 			 * Reset the new PHY and bring up the
@@ -4349,14 +2330,14 @@
 				link_timeout = 0;
 				goto done;
 			}
-			if (erip->stats.link_up == ERI_LINK_UP)
-				linkflags |= DL_NOTE_LINK_UP;
+			if (erip->stats.link_up == LINK_STATE_UP)
+				linkupdate = LINK_STATE_UP;
 		} else {
 			erip->flags |= (ERI_RUNNING | ERI_INITIALIZED);
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-			linkflags |= DL_NOTE_LINK_DOWN;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
+			linkupdate = LINK_STATE_DOWN;
 			/*
 			 * Still go on and complete the MAC initialization as
 			 * xcvr might show up later.
@@ -4398,47 +2379,6 @@
 	}
 
 	/*
-	 * Determine if promiscuous mode or multicast mode.
-	 */
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & ERI_SALLPHYS)
-				erip->flags |= ERI_PROMISC;
-			if (sbp->sb_flags & ERI_SALLMULTI)
-				erip->flags |= ERI_ALLMULTI;
-			if (sbp->sb_flags & ERI_SMULTI)
-				erip->flags |= ERI_MULTICAST;
-			break;
-		}
-	}
-
-
-	/*
-	 * Determine which internal loopback mode, if any
-	 * only one internal loopback mode is set, the checking order is
-	 * SERDES/SERIAL_LINK, PCS, and MAC
-	 */
-	for (sbp = eristrup; sbp; sbp = sbp->sb_nextp) {
-		if (sbp->sb_erip == erip) {
-			if (sbp->sb_flags & ERI_SSERLPBK) {
-				erip->flags |= ERI_SERLOOPBACK;
-				ERI_DEBUG_MSG2(erip, INIT_MSG,
-						"init(): flags = 0x%x\n",
-						erip->flags);
-				break;
-			}
-
-			if (sbp->sb_flags & ERI_SMACLPBK) {
-				erip->flags |= ERI_MACLOOPBACK;
-				ERI_DEBUG_MSG2(erip, LOOPBACK_MSG,
-						"init(): flags = 0x%x\n",
-						erip->flags);
-				break;
-			}
-		}
-	}
-
-	/*
 	 * BigMAC requires that we confirm that tx, rx and hash are in
 	 * quiescent state.
 	 * MAC will not reset successfully if the transceiver is not reset and
@@ -4448,21 +2388,21 @@
 	 */
 	if (eri_txmac_disable(erip)) {
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				disable_txmac_msg);
+		    disable_txmac_msg);
 		param_linkup = 0;	/* force init again */
-		erip->stats.link_up = ERI_LINK_DOWN;
-		erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-		linkflags |= DL_NOTE_LINK_DOWN;
+		erip->stats.link_up = LINK_STATE_DOWN;
+		erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
+		linkupdate = LINK_STATE_DOWN;
 		goto done;
 	}
 
 	if (eri_rxmac_disable(erip)) {
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				disable_rxmac_msg);
+		    disable_rxmac_msg);
 		param_linkup = 0;	/* force init again */
-		erip->stats.link_up = ERI_LINK_DOWN;
-		erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-		linkflags |= DL_NOTE_LINK_DOWN;
+		erip->stats.link_up = LINK_STATE_DOWN;
+		erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
+		linkupdate = LINK_STATE_DOWN;
 		goto done;
 	}
 
@@ -4500,7 +2440,7 @@
 		 * config, txring_lo, txring_hi
 		 */
 		if (eri_init_txregs(erip))
-				goto done;
+			goto done;
 		/*
 		 * Initialize ERX Registers:
 		 * rxring_lo, rxring_hi, config, rx_blanking,
@@ -4522,15 +2462,13 @@
 
 #ifdef ERI_DONT_STRIP_CRC
 	PUT_MACREG(rxcfg,
-	    ((erip->flags & ERI_PROMISC ? BMAC_RXCFG_PROMIS : 0) |
-	    (erip->flags & ERI_MULTICAST ? BMAC_RXCFG_HASH : 0) |
-	    (erip->flags & ERI_ALLMULTI ? BMAC_RXCFG_GRPROM : 0) |
+	    ((erip->promisc ? BMAC_RXCFG_PROMIS : 0) |
+	    (erip->multi_refcnt ? BMAC_RXCFG_HASH : 0) |
 	    (carrier_ext ? BMAC_RXCFG_CARR_EXT : 0)));
 #else
 	PUT_MACREG(rxcfg,
-	    ((erip->flags & ERI_PROMISC ? BMAC_RXCFG_PROMIS : 0) |
-	    (erip->flags & ERI_MULTICAST ? BMAC_RXCFG_HASH : 0) |
-	    (erip->flags & ERI_ALLMULTI ? BMAC_RXCFG_GRPROM : 0) |
+	    ((erip->promisc ? BMAC_RXCFG_PROMIS : 0) |
+	    (erip->multi_refcnt ? BMAC_RXCFG_HASH : 0) |
 	    BMAC_RXCFG_STRIP_CRC |
 	    (carrier_ext ? BMAC_RXCFG_CARR_EXT : 0)));
 #endif
@@ -4577,11 +2515,6 @@
 	 */
 	if (erip->flags & ERI_MACLOOPBACK) {
 		PUT_MACREG(xifc, GET_MACREG(xifc) | BMAC_XIFC_MIILPBK);
-		ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-		    "eri_init(): put in MAC int loopback mode\n");
-	} else {
-		ERI_DEBUG_MSG1(erip, LOOPBACK_MSG,
-		    "init(): internal loopback mode not set\n");
 	}
 
 	/*
@@ -4589,8 +2522,8 @@
 	 */
 	ENABLE_MAC(erip);
 	erip->flags |= (ERI_RUNNING | ERI_INITIALIZED |
-			    ERI_TXINIT | ERI_RXINIT);
-	eri_wenable(erip);
+	    ERI_TXINIT | ERI_RXINIT);
+	mac_tx_update(erip->mh);
 	erip->global_reset_issued = 0;
 
 #ifdef	ERI_10_10_FORCE_SPEED_WORKAROUND
@@ -4602,16 +2535,16 @@
 		eri_unallocthings(erip);
 
 	mutex_exit(&erip->xmitlock);
-	rw_exit(&eristruplock);
 	eri_start_timer(erip, eri_check_link, link_timeout);
 	mutex_exit(&erip->intrlock);
 
-	eri_send_notifications(erip, linkflags);
-
-	ret = !(erip->flags & ERI_RUNNING);
-	if (ret) {
+	if (linkupdate != LINK_STATE_UNKNOWN)
+		mac_link_update(erip->mh, linkupdate);
+
+	ret = (erip->flags & ERI_RUNNING) ? B_TRUE : B_FALSE;
+	if (!ret) {
 		ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-				"eri_init failed");
+		    "eri_init failed");
 	}
 
 init_exit:
@@ -4627,14 +2560,12 @@
 {
 	ddi_dma_handle_t handle;
 
-	if (ddi_dma_alloc_handle(erip->dip, &dma_attr,
-				DDI_DMA_DONTWAIT, (caddr_t)0, &handle))
+	if (ddi_dma_alloc_handle(erip->dip, &dma_attr, DDI_DMA_DONTWAIT,
+	    NULL, &handle))
 		return (DDI_FAILURE);
 
 	erip->burstsizes = ddi_dma_burstsizes(handle);
 	ddi_dma_free_handle(&handle);
-	ERI_DEBUG_MSG2(erip, INIT_MSG,
-			"burstsize %X", erip->burstsizes);
 
 	if (erip->burstsizes)
 		return (DDI_SUCCESS);
@@ -4672,7 +2603,7 @@
 	mutex_exit(&erip->intrlock);
 
 	if (needind)
-		eri_notify_ind(erip, DL_NOTE_LINK_DOWN);
+		mac_link_update(erip->mh, LINK_STATE_DOWN);
 }
 
 /*
@@ -4707,30 +2638,27 @@
 	/*
 	 * Allocate the TMD and RMD descriptors and extra for alignments.
 	 */
-	size = (ERI_RPENDING * sizeof (struct rmd)
-		+ ERI_TPENDING * sizeof (struct eri_tmd)) + ERI_GMDALIGN;
+	size = (ERI_RPENDING * sizeof (struct rmd) +
+	    ERI_TPENDING * sizeof (struct eri_tmd)) + ERI_GMDALIGN;
 
 	rval = ddi_dma_alloc_handle(erip->dip, &desc_dma_attr,
-			DDI_DMA_DONTWAIT, 0, &erip->md_h);
+	    DDI_DMA_DONTWAIT, 0, &erip->md_h);
 	if (rval != DDI_SUCCESS) {
 		return (++alloc_stat);
 	}
 	erip->alloc_flag |= ERI_DESC_HANDLE_ALLOC;
 
 	rval = ddi_dma_mem_alloc(erip->md_h, size, &erip->dev_attr,
-			DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
-			(caddr_t *)&erip->iopbkbase, &real_len,
-			&erip->mdm_h);
+	    DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0,
+	    (caddr_t *)&erip->iopbkbase, &real_len, &erip->mdm_h);
 	if (rval != DDI_SUCCESS) {
 		return (++alloc_stat);
 	}
 	erip->alloc_flag |= ERI_DESC_MEM_ALLOC;
 
 	rval = ddi_dma_addr_bind_handle(erip->md_h, NULL,
-			(caddr_t)erip->iopbkbase, size,
-			DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
-			DDI_DMA_DONTWAIT, 0,
-			&erip->md_c, &cookiec);
+	    (caddr_t)erip->iopbkbase, size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+	    DDI_DMA_DONTWAIT, 0, &erip->md_c, &cookiec);
 
 	if (rval != DDI_DMA_MAPPED)
 		return (++alloc_stat);
@@ -4832,27 +2760,24 @@
  *	So we cannot use ddi_dma_mem_alloc(, &erip->ge_dev_attr)
  *	because we'll get little endian memory on PCI.
  */
-	if (ddi_dma_alloc_handle(erip->dip, &desc_dma_attr,
-		DDI_DMA_DONTWAIT, 0,
-		&erip->tbuf_handle) != DDI_SUCCESS) {
-			ERI_FAULT_MSG1(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-			alloc_tx_dmah_msg);
-			return (++alloc_stat);
+	if (ddi_dma_alloc_handle(erip->dip, &desc_dma_attr, DDI_DMA_DONTWAIT,
+	    0, &erip->tbuf_handle) != DDI_SUCCESS) {
+		ERI_FAULT_MSG1(erip, SEVERITY_HIGH, ERI_VERB_MSG,
+		    alloc_tx_dmah_msg);
+		return (++alloc_stat);
 	}
 	erip->alloc_flag |= ERI_XBUFS_HANDLE_ALLOC;
 	size = ERI_TPENDING * eri_tx_bcopy_max;
 	erip->tbuf_kaddr = (caddr_t)kmem_alloc(size, KM_NOSLEEP);
 	if (erip->tbuf_kaddr == NULL) {
 		ERI_FAULT_MSG1(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-			alloc_tx_dmah_msg);
+		    alloc_tx_dmah_msg);
 		return (++alloc_stat);
 	}
 	erip->alloc_flag |= ERI_XBUFS_KMEM_ALLOC;
 	if (ddi_dma_addr_bind_handle(erip->tbuf_handle, NULL,
-		erip->tbuf_kaddr, size,
-		DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
-		DDI_DMA_DONTWAIT, 0,
-		&dma_cookie, &cookiec) != DDI_DMA_MAPPED) {
+	    erip->tbuf_kaddr, size, DDI_DMA_WRITE | DDI_DMA_CONSISTENT,
+	    DDI_DMA_DONTWAIT, 0, &dma_cookie, &cookiec) != DDI_DMA_MAPPED) {
 			return (++alloc_stat);
 	}
 	erip->tbuf_ioaddr = dma_cookie.dmac_address;
@@ -4879,29 +2804,31 @@
  *	First check to see if it is our device interrupting.
  */
 static uint_t
-eri_intr(struct eri *erip)
+eri_intr(caddr_t arg)
 {
+	struct eri *erip = (void *)arg;
 	uint32_t erisbits;
 	uint32_t mif_status;
 	uint32_t serviced = DDI_INTR_UNCLAIMED;
-	uint32_t linkflags = 0;
+	link_state_t linkupdate = LINK_STATE_UNKNOWN;
+	boolean_t macupdate = B_FALSE;
+	mblk_t *mp;
+	mblk_t *head;
+	mblk_t **tail;
+
+	head = NULL;
+	tail = &head;
 
 	mutex_enter(&erip->intrlock);
 
 	erisbits = GET_GLOBREG(status);
 
-	ERI_DEBUG_MSG5(erip, DIAG_MSG,
-		"eri_intr: start: erip %p gloregp %p status %X intmask %X",
-		erip, erip->globregp, erisbits, GET_GLOBREG(intmask));
 	/*
 	 * Check if it is only the RX_DONE interrupt, which is
 	 * the most frequent one.
 	 */
 	if (((erisbits & ERI_G_STATUS_RX_INT) == ERI_G_STATUS_RX_DONE) &&
-			(erip->flags & ERI_RUNNING)) {
-		ERI_DEBUG_MSG5(erip, INTR_MSG,
-		"eri_intr:(RX_DONE)erip %p gloregp %p status %X intmask %X",
-		erip, erip->globregp, erisbits, GET_GLOBREG(intmask));
+	    (erip->flags & ERI_RUNNING)) {
 		serviced = DDI_INTR_CLAIMED;
 		goto rx_done_int;
 	}
@@ -4915,32 +2842,29 @@
 	/* Check for interesting events */
 	if ((erisbits & ERI_G_STATUS_INTR) == 0) {
 #ifdef	ESTAR_WORKAROUND
-		uint32_t linkflags;
+		uint32_t linkupdate;
 #endif
 
 		ERI_DEBUG_MSG2(erip, DIAG_MSG,
-			"eri_intr: Interrupt Not Claimed gsbits  %X", erisbits);
+		    "eri_intr: Interrupt Not Claimed gsbits  %X", erisbits);
 #ifdef	DEBUG
 		noteri++;
 #endif
-		ERI_DEBUG_MSG2(erip, DIAG_MSG,
-			"eri_intr:MIF Config = 0x%X",
-			GET_MIFREG(mif_cfg));
-		ERI_DEBUG_MSG2(erip, DIAG_MSG,
-			"eri_intr:MIF imask = 0x%X",
-			GET_MIFREG(mif_imask));
-		ERI_DEBUG_MSG2(erip, DIAG_MSG,
-			"eri_intr:INT imask = 0x%X",
-			GET_GLOBREG(intmask));
-		ERI_DEBUG_MSG2(erip, DIAG_MSG,
-			"eri_intr:alias %X",
-			GET_GLOBREG(status_alias));
+		ERI_DEBUG_MSG2(erip, DIAG_MSG, "eri_intr:MIF Config = 0x%X",
+		    GET_MIFREG(mif_cfg));
+		ERI_DEBUG_MSG2(erip, DIAG_MSG, "eri_intr:MIF imask = 0x%X",
+		    GET_MIFREG(mif_imask));
+		ERI_DEBUG_MSG2(erip, DIAG_MSG, "eri_intr:INT imask = 0x%X",
+		    GET_GLOBREG(intmask));
+		ERI_DEBUG_MSG2(erip, DIAG_MSG, "eri_intr:alias %X",
+		    GET_GLOBREG(status_alias));
 #ifdef	ESTAR_WORKAROUND
-		linkflags = eri_check_link_noind(erip);
+		linkupdate = eri_check_link_noind(erip);
 #endif
 		mutex_exit(&erip->intrlock);
 #ifdef	ESTAR_WORKAROUND
-		eri_send_notifications(erip, linkflags);
+		if (linkupdate != LINK_STATE_UNKNOWN)
+			mac_link_update(erip->mh, linkupdate);
 #endif
 		return (serviced);
 	}
@@ -4949,15 +2873,12 @@
 	if (!(erip->flags & ERI_RUNNING)) {
 		mutex_exit(&erip->intrlock);
 		eri_uninit(erip);
-		ERI_DEBUG_MSG1(erip, INTR_MSG,
-				"eri_intr: eri not running");
 		return (serviced);
 	}
 
 	if (erisbits & ERI_G_STATUS_FATAL_ERR) {
 		ERI_DEBUG_MSG2(erip, INTR_MSG,
-				"eri_intr: fatal error: erisbits = %X",
-				erisbits);
+		    "eri_intr: fatal error: erisbits = %X", erisbits);
 		(void) eri_fatal_err(erip, erisbits);
 		eri_reinit_fatal++;
 
@@ -4967,8 +2888,8 @@
 			mutex_exit(&erip->intrlock);
 		} else {
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 			DISABLE_MAC(erip);
 			mutex_exit(&erip->intrlock);
 			(void) eri_init(erip);
@@ -4978,7 +2899,7 @@
 
 	if (erisbits & ERI_G_STATUS_NONFATAL_ERR) {
 		ERI_DEBUG_MSG2(erip, INTR_MSG,
-			"eri_intr: non-fatal error: erisbits = %X", erisbits);
+		    "eri_intr: non-fatal error: erisbits = %X", erisbits);
 		(void) eri_nonfatal_err(erip, erisbits);
 		if (erip->linkcheck) {
 			mutex_exit(&erip->intrlock);
@@ -4990,8 +2911,7 @@
 	if (erisbits & ERI_G_STATUS_MIF_INT) {
 		uint16_t stat;
 		ERI_DEBUG_MSG2(erip, XCVR_MSG,
-			"eri_intr:MIF Interrupt:mii_status %X",
-			erip->mii_status);
+		    "eri_intr:MIF Interrupt:mii_status %X", erip->mii_status);
 		eri_stop_timer(erip);   /* acquire linklock */
 
 		mutex_enter(&erip->xmitlock);
@@ -5000,16 +2920,16 @@
 		mif_status = GET_MIFREG(mif_bsts);
 		eri_mif_poll(erip, MIF_POLL_STOP);
 		ERI_DEBUG_MSG3(erip, XCVR_MSG,
-			"eri_intr: new MIF interrupt status %X XCVR status %X",
-			mif_status, erip->mii_status);
+		    "eri_intr: new MIF interrupt status %X XCVR status %X",
+		    mif_status, erip->mii_status);
 		(void) eri_mii_read(erip, ERI_PHY_BMSR, &stat);
-		linkflags = eri_mif_check(erip, stat, stat);
+		linkupdate = eri_mif_check(erip, stat, stat);
 
 #else
 		mif_status = GET_MIFREG(mif_bsts);
 		eri_mif_poll(erip, MIF_POLL_STOP);
-		linkflags = eri_mif_check(erip, (uint16_t)mif_status,
-			(uint16_t)(mif_status >> 16));
+		linkupdate = eri_mif_check(erip, (uint16_t)mif_status,
+		    (uint16_t)(mif_status >> 16));
 #endif
 		eri_mif_poll(erip, MIF_POLL_START);
 		mutex_exit(&erip->xcvrlock);
@@ -5017,15 +2937,14 @@
 
 		if (!erip->openloop_autoneg)
 			eri_start_timer(erip, eri_check_link,
-				ERI_LINKCHECK_TIMER);
+			    ERI_LINKCHECK_TIMER);
 		else
 			eri_start_timer(erip, eri_check_link,
-				ERI_P_FAULT_TIMER);
+			    ERI_P_FAULT_TIMER);
 	}
 
 	ERI_DEBUG_MSG2(erip, INTR_MSG,
-		"eri_intr:May have Read Interrupt status:status %X",
-			erisbits);
+	    "eri_intr:May have Read Interrupt status:status %X", erisbits);
 
 rx_done_int:
 	if ((erisbits & (ERI_G_STATUS_TX_INT_ME)) ||
@@ -5034,7 +2953,7 @@
 		erip->tx_completion = (uint32_t)(GET_ETXREG(tx_completion) &
 		    ETX_COMPLETION_MASK);
 
-		(void) eri_reclaim(erip, erip->tx_completion);
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 		mutex_exit(&erip->xmitlock);
 	}
 
@@ -5050,13 +2969,13 @@
 		rmdp = rmdpbase + rmdi;
 
 		ERI_DEBUG_MSG3(erip, INTR_MSG,
-			"eri_intr: packet received: rmdp = %X status %X",
-				rmdp, erisbits);
+		    "eri_intr: packet received: rmdp = %X status %X",
+		    rmdp, erisbits);
 		/*
 		 * Sync RMD before looking at it.
 		 */
 		ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-			DDI_DMA_SYNC_FORCPU);
+		    DDI_DMA_SYNC_FORCPU);
 		/*
 		 * Loop through each RMD.
 		 */
@@ -5064,10 +2983,15 @@
 		flags = GET_RMD_FLAGS(rmdp);
 		while (((flags & ERI_RMD_OWN) == 0) && (loop_limit)) {
 			/* process one packet */
-			eri_read_dma(erip, rmdp, rmdi, flags);
+			mp = eri_read_dma(erip, rmdp, rmdi, flags);
 			rmdi =  (rmdi + 1) & rmdmax_mask;
 			rmdp = rmdpbase + rmdi;
 
+			if (mp != NULL) {
+				*tail = mp;
+				tail = &mp->b_next;
+			}
+
 			/*
 			 * ERI RCV DMA fetches or updates four descriptors
 			 * a time. Also we don't want to update the desc.
@@ -5083,8 +3007,8 @@
 					loop_limit = 1;
 				} else {
 					erip->rx_kick =
-						(rmdi + ERI_RPENDING - 4) &
-						rmdmax_mask;
+					    (rmdi + ERI_RPENDING - 4) &
+					    rmdmax_mask;
 					PUT_ERXREG(rx_kick, erip->rx_kick);
 				}
 			}
@@ -5093,15 +3017,25 @@
 			 * Sync the next RMD before looking at it.
 			 */
 			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-				DDI_DMA_SYNC_FORCPU);
+			    DDI_DMA_SYNC_FORCPU);
 			flags = GET_RMD_FLAGS(rmdp);
 			loop_limit--;
 		}
 		erip->rx_completion = rmdi;
 	}
+
+	erip->wantw = B_FALSE;
+
 	mutex_exit(&erip->intrlock);
 
-	eri_send_notifications(erip, linkflags);
+	if (head)
+		mac_rx(erip->mh, NULL, head);
+
+	if (macupdate)
+		mac_tx_update(erip->mh);
+
+	if (linkupdate != LINK_STATE_UNKNOWN)
+		mac_link_update(erip->mh, linkupdate);
 
 	return (serviced);
 }
@@ -5125,8 +3059,6 @@
 	uint32_t	pci_error_int = 0;
 
 	if (erisbits & ERI_G_STATUS_RX_TAG_ERR) {
-		ERI_DEBUG_MSG1(erip, FATAL_ERR_MSG,
-				"ERI RX Tag Error");
 		erip->rx_reset_issued = 1;
 		HSTAT(erip, rxtag_err);
 	} else {
@@ -5138,8 +3070,6 @@
 			HSTAT(erip, parity_error);
 		} else {
 			HSTAT(erip, unknown_fatal);
-			ERI_DEBUG_MSG1(erip, FATAL_ERR_MSG,
-				"ERI Unknown fatal error");
 		}
 	}
 
@@ -5148,9 +3078,9 @@
 	 */
 	if (pci_error_int && erip->pci_config_handle) {
 		pci_status = pci_config_get16(erip->pci_config_handle,
-			PCI_CONF_STAT);
-		ERI_DEBUG_MSG2(erip, FATAL_ERR_MSG,
-			"Bus Error Status %x", pci_status);
+		    PCI_CONF_STAT);
+		ERI_DEBUG_MSG2(erip, FATAL_ERR_MSG, "Bus Error Status %x",
+		    pci_status);
 		if (pci_status & PCI_DATA_PARITY_REP)
 			HSTAT(erip, pci_data_parity_err);
 		if (pci_status & PCI_SING_TARGET_ABORT)
@@ -5166,8 +3096,8 @@
 		/*
 		 * clear it by writing the value that was read back.
 		 */
-		pci_config_put16(erip->pci_config_handle,
-			PCI_CONF_STAT, pci_status);
+		pci_config_put16(erip->pci_config_handle, PCI_CONF_STAT,
+		    pci_status);
 	}
 }
 
@@ -5190,60 +3120,43 @@
 	if (erisbits & ERI_G_STATUS_TX_MAC_INT) {
 		txmac_sts = GET_MACREG(txsts);
 		if (txmac_sts & BMAC_TXSTS_TX_URUN) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"tx fifo underrun");
 			erip->linkcheck = 1;
 			HSTAT(erip, txmac_urun);
 			HSTAT(erip, oerrors);
 		}
 
 		if (txmac_sts & BMAC_TXSTS_MAXPKT_ERR) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"tx max pkt size error");
 			erip->linkcheck = 1;
 			HSTAT(erip, txmac_maxpkt_err);
 			HSTAT(erip, oerrors);
 		}
 		if (txmac_sts & BMAC_TXSTS_NCC_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Normal collisions counter expired");
 			erip->stats.collisions += 0x10000;
 		}
 
 		if (txmac_sts & BMAC_TXSTS_ECC_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Excessive collisions counter expired");
 			erip->stats.excessive_coll += 0x10000;
 		}
 
 		if (txmac_sts & BMAC_TXSTS_LCC_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Late collisions counter expired");
 			erip->stats.late_coll += 0x10000;
 		}
 
 		if (txmac_sts & BMAC_TXSTS_FCC_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"first collisions counter expired");
 			erip->stats.first_coll += 0x10000;
 		}
 
 		if (txmac_sts & BMAC_TXSTS_DEFER_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"defer timer expired");
 			HSTAT(erip, defer_timer_exp);
 		}
 
 		if (txmac_sts & BMAC_TXSTS_PEAK_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"peak attempts counter expired");
 			erip->stats.peak_attempt_cnt += 0x100;
 		}
 	}
 
 	if (erisbits & ERI_G_STATUS_RX_NO_BUF) {
-		ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-				"rx pkt dropped/no free descriptor error");
+		ERI_DEBUG_MSG1(erip, NONFATAL_MSG, "rx dropped/no free desc");
 
 		if (eri_overflow_reset)
 			erip->linkcheck = 1;
@@ -5261,8 +3174,7 @@
 			erip->rxfifo_wr_ptr = GET_ERXREG(rxfifo_wr_ptr);
 			erip->rxfifo_rd_ptr = GET_ERXREG(rxfifo_rd_ptr);
 
-			ERI_DEBUG_MSG5(erip,
-			    NONFATAL_MSG,
+			ERI_DEBUG_MSG5(erip, NONFATAL_MSG,
 			    "overflow intr %d: %8x wr:%2x rd:%2x",
 			    erip->check_rmac_hang,
 			    GET_MACREG(macsm),
@@ -5270,7 +3182,7 @@
 			    GET_ERXREG(rxfifo_rd_ptr));
 
 			eri_start_timer(erip, eri_check_link,
-				ERI_CHECK_HANG_TIMER);
+			    ERI_CHECK_HANG_TIMER);
 #endif
 			if (eri_overflow_reset)
 				erip->linkcheck = 1;
@@ -5280,29 +3192,21 @@
 		}
 
 		if (rxmac_sts & BMAC_RXSTS_ALE_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"RX Alignment Error Counter Expired");
 			erip->stats.rx_align_err += 0x10000;
 			erip->stats.ierrors += 0x10000;
 		}
 
 		if (rxmac_sts & BMAC_RXSTS_CRC_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"RX CRC Error Counter Expired");
 			erip->stats.rx_crc_err += 0x10000;
 			erip->stats.ierrors += 0x10000;
 		}
 
 		if (rxmac_sts & BMAC_RXSTS_LEN_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"RX Length Error Counter Expired");
 			erip->stats.rx_length_err += 0x10000;
 			erip->stats.ierrors += 0x10000;
 		}
 
 		if (rxmac_sts & BMAC_RXSTS_CVI_EXP) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Rx Code Violation Err Count Expired");
 			erip->stats.rx_code_viol_err += 0x10000;
 			erip->stats.ierrors += 0x10000;
 		}
@@ -5313,25 +3217,22 @@
 		macctl_sts = GET_MACREG(macctl_sts);
 		if (macctl_sts & ERI_MCTLSTS_PAUSE_RCVD) {
 			pause_time = ((macctl_sts &
-					ERI_MCTLSTS_PAUSE_TIME) >> 16);
+			    ERI_MCTLSTS_PAUSE_TIME) >> 16);
 			ERI_DEBUG_MSG2(erip, NONFATAL_MSG,
-				"PAUSE Received. pause time = %X slot_times",
-								pause_time);
+			    "PAUSE Received. pause time = %X slot_times",
+			    pause_time);
 			HSTAT(erip, pause_rxcount);
 			erip->stats.pause_time_count += pause_time;
 		}
 
 		if (macctl_sts & ERI_MCTLSTS_PAUSE_STATE) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Transition to PAUSE state");
 			HSTAT(erip, pause_oncount);
+			erip->stats.pausing = 1;
 		}
 
 		if (macctl_sts & ERI_MCTLSTS_NONPAUSE) {
-			ERI_DEBUG_MSG1(erip, NONFATAL_MSG,
-					"Transition to non-PAUSE state");
 			HSTAT(erip, pause_offcount);
-
+			erip->stats.pausing = 0;
 		}
 	}
 
@@ -5558,23 +3459,17 @@
 	}
 #endif
 	ERI_DEBUG_MSG3(erip, FRM_MSG,
-			"Frame Reg :mii_read: phyad = %X reg = %X ",
-			phyad, regad);
+	    "Frame Reg :mii_read: phyad = %X reg = %X ", phyad, regad);
 
 	PUT_MIFREG(mif_frame, ERI_MIF_FRREAD |
-				(phyad << ERI_MIF_FRPHYAD_SHIFT) |
-				(regad << ERI_MIF_FRREGAD_SHIFT));
+	    (phyad << ERI_MIF_FRPHYAD_SHIFT) |
+	    (regad << ERI_MIF_FRREGAD_SHIFT));
 	MIF_ERIDELAY(300,  phyad, regad);
 	frame = GET_MIFREG(mif_frame);
 	if ((frame & ERI_MIF_FRTA0) == 0) {
-		ERI_DEBUG_MSG2(erip, FRM_MSG,
-				"MIF Read failure: data = %X", frame);
 		return (1);
 	} else {
 		*datap = (uint16_t)(frame & ERI_MIF_FRDATA);
-		ERI_DEBUG_MSG2(erip, FRM_MSG,
-				"Frame Reg :mii_read: successful:data = %X ",
-				*datap);
 		return (0);
 	}
 
@@ -5583,7 +3478,6 @@
 static void
 eri_mii_write(struct eri *erip, uint8_t regad, uint16_t data)
 {
-	uint32_t frame;
 	uint8_t	phyad;
 
 	if (!erip->frame_enable) {
@@ -5593,272 +3487,30 @@
 
 	phyad = erip->phyad;
 
-	ERI_DEBUG_MSG4(erip, FRM_MSG,
-			"Frame Reg:eri_mii_write: phyad = %X \
-			reg = %X data = %X", phyad, regad, data);
-
 	PUT_MIFREG(mif_frame, (ERI_MIF_FRWRITE |
-				(phyad << ERI_MIF_FRPHYAD_SHIFT) |
-				(regad << ERI_MIF_FRREGAD_SHIFT) | data));
+	    (phyad << ERI_MIF_FRPHYAD_SHIFT) |
+	    (regad << ERI_MIF_FRREGAD_SHIFT) | data));
 	MIF_ERIDELAY(300,  phyad, regad);
-	frame = GET_MIFREG(mif_frame);
-	if ((frame & ERI_MIF_FRTA0) == 0) {
-		ERI_DEBUG_MSG1(erip, MIF_MSG,
-		    mif_write_fail_msg);
-	} else {
-		ERI_DEBUG_MSG1(erip, FRM_MSG,
-				"Frame Reg:eri_mii_write: successful");
-		return;
-	}
-}
-
-/*
- * Return TRUE if the given multicast address is one
- * of those that this particular Stream is interested in.
- */
-static int
-eri_mcmatch(struct eristr *sbp, struct ether_addr *addrp)
-{
-	struct	ether_addr *mcbucket;
-	int	mccount;
-	int	i;
-	int	mchash;
-
-	/*
-	 * Return FALSE if not a multicast address.
-	 */
-	if (!(addrp->ether_addr_octet[0] & 01))
-		return (0);
-
-	/*
-	 * Check if all multicasts have been enabled for this Stream
-	 */
-	if (sbp->sb_flags & ERI_SALLMULTI)
-		return (1);
-
-	/*
-	 * Compute the hash value for the address and
-	 * grab the bucket and the number of entries in the
-	 * bucket.
-	 */
-	mchash = MCHASH(addrp);
-	mcbucket = sbp->sb_mctab[mchash];
-	mccount = sbp->sb_mccount[mchash];
-
-	/*
-	 * Return FALSE if no multicast addresses enabled for this Stream.
-	 */
-	if (mccount == 0)
-		return (0);
-
-	/*
-	 * Otherwise, find it in the table.
-	 */
-	if (mcbucket)
-		for (i = 0; i < mccount; i++)
-			if (!ether_cmp(addrp, &mcbucket[i]))
-				return (1);
-	return (0);
+	(void) GET_MIFREG(mif_frame);
 }
 
-/*
- * Send packet upstream.
- * Assume mp->b_rptr points to ether_header.
- */
-static void
-eri_sendup(struct eri *erip, mblk_t *mp, struct eristr *(*acceptfunc)())
-{
-	struct	ether_addr	*dhostp, *shostp;
-	struct	eristr	*sbp, *nsbp;
-	mblk_t	*nmp;
-	uint32_t isgroupaddr;
-	int	type;
-
-	ERI_DEBUG_MSG1(erip, ENTER_MSG, "eri_sendup");
-	dhostp = &((struct ether_header *)mp->b_rptr)->ether_dhost;
-	shostp = &((struct ether_header *)mp->b_rptr)->ether_shost;
-	type = get_ether_type(mp->b_rptr);
-
-	isgroupaddr = dhostp->ether_addr_octet[0] & 01;
-
-	/*
-	 * While holding a reader lock on the linked list of streams structures,
-	 * attempt to match the address criteria for each stream
-	 * and pass up the raw M_DATA ("fastpath") or a DL_UNITDATA_IND.
-	 */
-
-	rw_enter(&eristruplock, RW_READER);
-
-	if ((sbp = (*acceptfunc)(eristrup, erip, type, dhostp)) == NULL) {
-		rw_exit(&eristruplock);
-		freemsg(mp);
-		return;
-	}
-
-	/*
-	 * Loop on matching open streams until (*acceptfunc)() returns NULL.
-	 */
-	for (; nsbp = (*acceptfunc)(sbp->sb_nextp, erip, type, dhostp);
-		sbp = nsbp)
-		if (canputnext(sbp->sb_rq))
-			if (nmp = dupmsg(mp)) {
-				if ((sbp->sb_flags & ERI_SFAST) &&
-							!isgroupaddr) {
-					nmp->b_rptr +=
-						sizeof (struct ether_header);
-					putnext(sbp->sb_rq, nmp);
-				} else if (sbp->sb_flags & ERI_SRAW)
-					putnext(sbp->sb_rq, nmp);
-				else if ((nmp = eri_addudind(erip, nmp, shostp,
-						dhostp, type, isgroupaddr)))
-						putnext(sbp->sb_rq, nmp);
-			} else {
-				HSTAT(erip, allocbfail);
-		} else {
-			HSTAT(erip, nocanput);
-		}
-
-	/*
-	 * Do the last one.
-	 */
-	if (canputnext(sbp->sb_rq)) {
-		if ((sbp->sb_flags & ERI_SFAST) && !isgroupaddr) {
-			mp->b_rptr += sizeof (struct ether_header);
-			putnext(sbp->sb_rq, mp);
-		} else if (sbp->sb_flags & ERI_SRAW)
-			putnext(sbp->sb_rq, mp);
-		else if ((mp = eri_addudind(erip, mp, shostp, dhostp,
-			type, isgroupaddr)))
-			putnext(sbp->sb_rq, mp);
-	} else {
-		freemsg(mp);
-		HSTAT(erip, nocanput);
-		HSTAT(erip, norcvbuf);
-	}
-
-	rw_exit(&eristruplock);
-}
-
-/*
- * Prefix msg with a DL_UNITDATA_IND mblk and return the new msg.
- */
-static mblk_t *
-eri_addudind(struct eri *erip, mblk_t *mp, struct ether_addr *shostp,
-    struct ether_addr *dhostp, int type, uint32_t isgroupaddr)
-{
-	dl_unitdata_ind_t	*dludindp;
-	struct	eridladdr	*dlap;
-	mblk_t	*nmp;
-	int	size;
-
-	mp->b_rptr += sizeof (struct ether_header);
-
-	/*
-	 * Allocate an M_PROTO mblk for the DL_UNITDATA_IND.
-	 */
-	size = sizeof (dl_unitdata_ind_t) + ERI_ADDRL + ERI_ADDRL;
-	if ((nmp = eri_allocb(ERI_HEADROOM + size)) == NULL) {
-		HSTAT(erip, allocbfail);
-		HSTAT(erip, ierrors);
-		ERI_DEBUG_MSG1(erip, RESOURCE_MSG,
-				"allocb failed");
-		freemsg(mp);
-		return (NULL);
-	}
-	DB_TYPE(nmp) = M_PROTO;
-	nmp->b_wptr = nmp->b_datap->db_lim;
-	nmp->b_rptr = nmp->b_wptr - size;
-
-	/*
-	 * Construct a DL_UNITDATA_IND primitive.
-	 */
-	dludindp = (dl_unitdata_ind_t *)nmp->b_rptr;
-	dludindp->dl_primitive = DL_UNITDATA_IND;
-	dludindp->dl_dest_addr_length = ERI_ADDRL;
-	dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
-	dludindp->dl_src_addr_length = ERI_ADDRL;
-	dludindp->dl_src_addr_offset = sizeof (dl_unitdata_ind_t) + ERI_ADDRL;
-	dludindp->dl_group_address = isgroupaddr;
-
-	dlap = (struct eridladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t));
-	ether_bcopy(dhostp, &dlap->dl_phys);
-	dlap->dl_sap = (uint16_t)type;
-
-	dlap = (struct eridladdr *)(nmp->b_rptr + sizeof (dl_unitdata_ind_t)
-		+ ERI_ADDRL);
-	ether_bcopy(shostp, &dlap->dl_phys);
-	dlap->dl_sap = (uint16_t)type;
-
-	/*
-	 * Link the M_PROTO and M_DATA together.
-	 */
-	nmp->b_cont = mp;
-	return (nmp);
-}
-
-/*
- * Test upstream destination sap and address match.
- */
-static struct eristr *
-eri_accept(struct eristr *sbp, struct eri *erip, int type,
-    struct ether_addr *addrp)
-{
-	t_uscalar_t sap;
-	uint32_t flags;
-	for (; sbp; sbp = sbp->sb_nextp) {
-		sap = sbp->sb_sap;
-		flags = sbp->sb_flags;
-
-		if ((sbp->sb_erip == erip) && ERI_SAPMATCH(sap, type, flags))
-			if ((ether_cmp(addrp, &erip->ouraddr) == 0) ||
-				(ether_cmp(addrp, &etherbroadcastaddr) == 0) ||
-				(flags & ERI_SALLPHYS) ||
-				eri_mcmatch(sbp, addrp) ||
-				((addrp->ether_addr_octet[0] & 0x01) &&
-				flags & ERI_SALLMULTI))
-				return (sbp);
-	}
-	return (NULL);
-}
-
-/*
- * Test upstream destination sap and address match for ERI_SALLPHYS only.
- */
-/* ARGSUSED3 */
-struct eristr *
-eri_paccept(struct eristr *sbp, struct eri *erip,
-    int type, struct ether_addr *addrp)
-{
-	t_uscalar_t sap;
-	uint32_t flags;
-
-	for (; sbp; sbp = sbp->sb_nextp) {
-		sap = sbp->sb_sap;
-		flags = sbp->sb_flags;
-
-		if ((sbp->sb_erip == erip) &&
-			ERI_SAPMATCH(sap, type, flags) &&
-			((flags & ERI_SALLPHYS) ||
-			(addrp->ether_addr_octet[0] & 0x01) &&
-			(flags & ERI_SALLMULTI)))
-			return (sbp);
-	}
-	return (NULL);
-}
-
-
 
 /* <<<<<<<<<<<<<<<<<	PACKET TRANSMIT FUNCTIONS	>>>>>>>>>>>>>>>>>>>> */
 
 #define	ERI_CROSS_PAGE_BOUNDRY(i, size, pagesize) \
 	((i & pagesize) != ((i + size) & pagesize))
 
-static int
-eri_start(queue_t *wq, mblk_t *mp, struct eri *erip)
+/*
+ * Send a single mblk.  Returns B_TRUE if the packet is sent, or disposed of
+ * by freemsg.  Returns B_FALSE if the packet was not sent or queued, and
+ * should be retried later (due to tx resource exhaustion.)
+ */
+static boolean_t
+eri_send_msg(struct eri *erip, mblk_t *mp)
 {
 	volatile struct	eri_tmd	*tmdp = NULL;
 	volatile struct	eri_tmd	*tbasep = NULL;
-	mblk_t		*nmp, *pmp = NULL;
+	mblk_t		*nmp;
 	uint32_t	len = 0, len_msg = 0, xover_len = TX_STREAM_MIN;
 	uint32_t	nmblks = 0;
 	uint32_t	i, j;
@@ -5867,7 +3519,7 @@
 	uint_t		start_offset = 0;
 	uint_t		stuff_offset = 0;
 	uint_t		flags = 0;
-	struct ether_header *ehp;
+	boolean_t	macupdate = B_FALSE;
 
 	caddr_t	ptr;
 	uint32_t	offset;
@@ -5877,30 +3529,22 @@
 	ddi_dma_cookie_t	c;
 
 	if (!param_linkup) {
-		eri_cable_down_msg(erip);
 		freemsg(mp);
+		HSTAT(erip, tnocar);
 		HSTAT(erip, oerrors);
-		return (0);
+		return (B_TRUE);
 	}
 
-	if (erip->flags & ERI_PROMISC)
-		if ((pmp = copymsg(mp)) == NULL) { /* copy now, freemsg later */
-			HSTAT(erip, allocbfail);
-			HSTAT(erip, noxmtbuf);
-		}
-
 	nmp = mp;
 
 #ifdef ERI_HWCSUM
-	if (((struct eristr *)wq->q_ptr)->sb_flags & ERI_SCKSUM) {
-		hcksum_retrieve(mp, NULL, NULL, &start_offset, &stuff_offset,
-		    NULL, NULL, &flags);
-
-		if (flags & HCK_PARTIALCKSUM) {
-			start_offset += sizeof (*ehp);
-			stuff_offset += sizeof (*ehp);
-			tmdcsum = ERI_TMD_CSENABL;
-		}
+	hcksum_retrieve(mp, NULL, NULL, &start_offset, &stuff_offset,
+	    NULL, NULL, &flags);
+
+	if (flags & HCK_PARTIALCKSUM) {
+		start_offset += ETHERHEADER_SIZE;
+		stuff_offset += ETHERHEADER_SIZE;
+		tmdcsum = ERI_TMD_CSENABL;
 	}
 #endif /* ERI_HWCSUM */
 	while (nmp != NULL) {
@@ -5913,8 +3557,7 @@
 	/*
 	 * update MIB II statistics
 	 */
-	ehp = (struct ether_header *)mp->b_rptr;
-	BUMP_OutNUcast(erip, ehp);
+	BUMP_OutNUcast(erip, mp->b_rptr);
 
 /*
  * 	----------------------------------------------------------------------
@@ -5933,9 +3576,7 @@
 			HSTAT(erip, allocbfail);
 			HSTAT(erip, noxmtbuf);
 			freemsg(mp);
-			if (pmp)
-				freemsg(pmp);
-			return (1); /* bad case */
+			return (B_TRUE); /* bad case */
 		}
 		mcopymsg(mp, nmp->b_rptr);
 		nmp->b_wptr = nmp->b_rptr + len_msg;
@@ -5964,6 +3605,7 @@
 
 	for (j = 0; j < nmblks; j++) { /* for one or two mb cases */
 
+		/*LINTED E_PTRDIFF_OVERFLOW*/
 		len = nmp->b_wptr - nmp->b_rptr;
 		i = tmdp - tbasep; /* index */
 
@@ -5991,8 +3633,7 @@
 			len = len_msg;
 			c.dmac_address = erip->tbuf_ioaddr + offset;
 			(void) ddi_dma_sync(erip->tbuf_handle,
-					(off_t)offset, len_msg,
-					DDI_DMA_SYNC_FORDEV);
+			    (off_t)offset, len_msg, DDI_DMA_SYNC_FORDEV);
 			nmblks = 1; /* exit this for loop */
 		} else if ((!j) && (len < eri_tx_bcopy_max)) { /* tb-1st mb */
 
@@ -6003,17 +3644,16 @@
 
 			c.dmac_address = erip->tbuf_ioaddr + offset;
 			(void) ddi_dma_sync(erip->tbuf_handle,
-					(off_t)offset, len,
-					DDI_DMA_SYNC_FORDEV);
+			    (off_t)offset, len, DDI_DMA_SYNC_FORDEV);
 			nmp = mp->b_cont;
 			mp->b_cont = NULL;
 			freeb(mp);
 		} else if (erip->eri_dvmaxh != NULL) { /* fast DVMA */
 
-			(void) dvma_kaddr_load(erip->eri_dvmaxh,
-				(caddr_t)nmp->b_rptr, len, 2 * i, &c);
-			(void) dvma_sync(erip->eri_dvmaxh,
-				2 * i, DDI_DMA_SYNC_FORDEV);
+			dvma_kaddr_load(erip->eri_dvmaxh,
+			    (caddr_t)nmp->b_rptr, len, 2 * i, &c);
+			dvma_sync(erip->eri_dvmaxh,
+			    2 * i, DDI_DMA_SYNC_FORDEV);
 
 			erip->tmblkp[i] = nmp;
 			if (!j) {
@@ -6047,10 +3687,7 @@
 				mutex_exit(&erip->xmitlock);
 				HSTAT(erip, noxmtbuf);
 
-				if (pmp)
-					freemsg(pmp);
-
-				return (1); /* bad case */
+				return (B_TRUE); /* bad case */
 			}
 
 			erip->tmblkp[i] = nmp;
@@ -6064,8 +3701,8 @@
 		/* first descr of packet */
 		if (!j) {
 			ctrl = ERI_TMD_SOP| int_me | tmdcsum |
-				(start_offset << ERI_TMD_CSSTART_SHIFT) |
-				(stuff_offset << ERI_TMD_CSSTUFF_SHIFT);
+			    (start_offset << ERI_TMD_CSSTART_SHIFT) |
+			    (stuff_offset << ERI_TMD_CSSTUFF_SHIFT);
 		}
 
 		/* last descr of packet */
@@ -6075,7 +3712,7 @@
 
 		PUT_TMD(tmdp, c, len, ctrl);
 		ERI_SYNCIOPB(erip, tmdp, sizeof (struct eri_tmd),
-				DDI_DMA_SYNC_FORDEV);
+		    DDI_DMA_SYNC_FORDEV);
 
 		tmdp = NEXTTMD(erip, tmdp);
 		erip->tx_cur_cnt++;
@@ -6090,25 +3727,18 @@
 	if (erip->tx_cur_cnt >= tx_interrupt_rate) {
 		erip->tx_completion = (uint32_t)(GET_ETXREG(tx_completion) &
 		    ETX_COMPLETION_MASK);
-		(void) eri_reclaim(erip, erip->tx_completion);
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 	}
 	mutex_exit(&erip->xmitlock);
 
-	if (pmp != NULL) {	/* pmp is copied at the beginning */
-		if (erip->flags & (ERI_PROMISC | ERI_ALLMULTI)) {
-			/* will hold reader lock */
-			eri_sendup(erip, pmp, eri_paccept);
-		} else
-			freemsg(pmp);
-	}
-
-	return (0);
+	if (macupdate)
+		mac_tx_update(erip->mh);
+
+	return (B_TRUE);
 
 notmds:
 	HSTAT(erip, notmds);
-	erip->wantw = 1;
-
-	(void) putbq(wq, mp); /* no qenable, avoid spinning at no-tmds */
+	erip->wantw = B_TRUE;
 
 	if (!erip->tx_int_me) {
 		PUT_GLOBREG(intmask, GET_GLOBREG(intmask) &
@@ -6119,21 +3749,40 @@
 	if (erip->tx_cur_cnt >= tx_interrupt_rate) {
 		erip->tx_completion = (uint32_t)(GET_ETXREG(tx_completion) &
 		    ETX_COMPLETION_MASK);
-		(void) eri_reclaim(erip, erip->tx_completion); /* qenable */
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 	}
 
 	mutex_exit(&erip->xmitlock);
 
-	if (pmp)
-		freemsg(pmp);
-
-	return (1);
+	if (macupdate)
+		mac_tx_update(erip->mh);
+
+	return (B_FALSE);
+}
+
+static mblk_t *
+eri_m_tx(void *arg, mblk_t *mp)
+{
+	struct eri *erip = arg;
+	mblk_t *next;
+
+	while (mp != NULL) {
+		next = mp->b_next;
+		mp->b_next = NULL;
+		if (!eri_send_msg(erip, mp)) {
+			mp->b_next = next;
+			break;
+		}
+		mp = next;
+	}
+
+	return (mp);
 }
 
 /*
  * Transmit completion reclaiming.
  */
-static uint_t
+static boolean_t
 eri_reclaim(struct eri *erip, uint32_t tx_completion)
 {
 	volatile struct	eri_tmd	*tmdp;
@@ -6168,12 +3817,12 @@
 
 		if (bp) {
 			if (erip->eri_dvmaxh) {
-				(void) dvma_unload(erip->eri_dvmaxh, 2 * i,
-						(uint_t)DONT_FLUSH);
-			} else
-
-			/* dma handle case. */
+				dvma_unload(erip->eri_dvmaxh, 2 * i,
+				    (uint_t)DONT_FLUSH);
+			} else {
+				/* dma handle case. */
 				(void) ddi_dma_unbind_handle(erip->ndmaxh[i]);
+			}
 
 			freeb(bp);
 			erip->tmblkp[i] = NULL;
@@ -6186,20 +3835,12 @@
 	erip->tcurp = tmdp;
 	erip->tx_cur_cnt -= reclaimed;
 
-	if (reclaimed) {
-		if (erip->wantw) {
-			mutex_enter(&eriwenlock);
-			eri_wenable(erip);
-			mutex_exit(&eriwenlock);
-		}
-	}
-
-	return (reclaimed);
+	return (erip->wantw && reclaimed ? B_TRUE : B_FALSE);
 }
 
 
 /* <<<<<<<<<<<<<<<<<<<	PACKET RECEIVE FUNCTIONS	>>>>>>>>>>>>>>>>>>> */
-static void
+static mblk_t *
 eri_read_dma(struct eri *erip, volatile struct rmd *rmdp,
 	int rmdi, uint64_t flags)
 {
@@ -6210,8 +3851,7 @@
 #ifdef ERI_RCV_CKSUM
 	ushort_t sum;
 #endif /* ERI_RCV_CKSUM */
-
-	ERI_DEBUG_MSG1(erip, ENTER_MSG, "eri_read_dma");
+	mblk_t *retmp = NULL;
 
 	bp = erip->rmblkp[rmdi];
 	len = (flags & ERI_RMD_BUFSIZE) >> ERI_RMD_BUFSIZE_SHIFT;
@@ -6229,25 +3869,25 @@
 	 * (using CRC or checksum) but it would be expensive in this
 	 * routine, since it is run in interrupt context.
 	 */
-	if ((flags & ERI_RMD_BAD) || (len  < ETHERMIN) || (len > ETHERMAX)) {
-		ERI_DEBUG_MSG3(erip, CORRUPTION_MSG,
-		"eri_read_dma: Corrupted Packet is Recieved flags %p length %d",
-			flags, len);
+	if ((flags & ERI_RMD_BAD) || (len  < ETHERMIN) || (len > ETHERMAX+4)) {
+		ERI_DEBUG_MSG3(erip, CORRUPTION_MSG, "eri_read_dma: "
+		    "Corrupted Packet is Recieved flags %p length %d",
+		    flags, len);
 
 		HSTAT(erip, rx_bad_pkts);
 		if ((flags & ERI_RMD_BAD) == 0)
 			HSTAT(erip, ierrors);
 		if (len < ETHERMIN) {
 			HSTAT(erip, rx_runt);
-		} else if (len > ETHERMAX) {
+		} else if (len > ETHERMAX+4) {
 			HSTAT(erip, rx_toolong_pkts);
 		}
 		HSTAT(erip, drop);
 		UPDATE_RMD(rmdp);
 
 		ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-					DDI_DMA_SYNC_FORDEV);
-		return;
+		    DDI_DMA_SYNC_FORDEV);
+		return (NULL);
 	}
 #ifdef  ERI_DONT_STRIP_CRC
 	{
@@ -6297,13 +3937,13 @@
 	if (len < eri_rx_bcopy_max) {
 		if ((nbp = eri_allocb_sp(len + ERI_FSTBYTE_OFFSET))) {
 			(void) ddi_dma_sync(erip->ndmarh[rmdi], 0,
-				len+ERI_FSTBYTE_OFFSET, DDI_DMA_SYNC_FORCPU);
+			    len + ERI_FSTBYTE_OFFSET, DDI_DMA_SYNC_FORCPU);
 			DB_TYPE(nbp) = M_DATA;
 			bcopy(bp->b_rptr, nbp->b_rptr,
-				len + ERI_FSTBYTE_OFFSET);
+			    len + ERI_FSTBYTE_OFFSET);
 			UPDATE_RMD(rmdp);
 			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-				DDI_DMA_SYNC_FORDEV);
+			    DDI_DMA_SYNC_FORDEV);
 
 			/* Add the First Byte offset to the b_rptr */
 			nbp->b_rptr += ERI_FSTBYTE_OFFSET;
@@ -6311,59 +3951,13 @@
 
 #ifdef ERI_RCV_CKSUM
 			sum = ~(uint16_t)(flags & ERI_RMD_CKSUM);
+			/*LINTED E_PTRDIFF_OVERFLOW*/
 			ERI_PROCESS_READ(erip, nbp, sum);
 #else
+			/*LINTED E_PTRDIFF_OVERFLOW*/
 			ERI_PROCESS_READ(erip, nbp);
 #endif
-		} else {
-
-			/*
-			 * mblk allocation has failed. Re-use the old mblk for
-			 * the next packet. Re-mapping is not required since
-			 * the same mblk and dma cookie is to be used again.
-			 */
-			HSTAT(erip, ierrors);
-			HSTAT(erip, allocbfail);
-			HSTAT(erip, norcvbuf);
-
-			UPDATE_RMD(rmdp);
-			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-					DDI_DMA_SYNC_FORDEV);
-			ERI_DEBUG_MSG1(erip, RESOURCE_MSG,
-				"allocb fail");
-		}
-	} else {
-		/* Use dma unmap/map */
-		if ((nbp = eri_allocb_sp(ERI_BUFSIZE))) {
-			/*
-			 * How do we harden this, specially if unbind
-			 * succeeds and then bind fails?
-			 *  If Unbind fails, we can leave without updating
-			 * the descriptor but would it continue to work on
-			 * next round?
-			 */
-			(void) ddi_dma_unbind_handle(erip->ndmarh[rmdi]);
-			(void) ddi_dma_addr_bind_handle(erip->ndmarh[rmdi],
-				    NULL, (caddr_t)nbp->b_rptr, ERI_BUFSIZE,
-				    DDI_DMA_READ | DDI_DMA_CONSISTENT,
-				    DDI_DMA_DONTWAIT, 0, &c, &ccnt);
-
-				erip->rmblkp[rmdi] = nbp;
-				PUT_RMD(rmdp, c);
-				ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-					DDI_DMA_SYNC_FORDEV);
-
-				/* Add the First Byte offset to the b_rptr */
-
-				bp->b_rptr += ERI_FSTBYTE_OFFSET;
-				bp->b_wptr = bp->b_rptr + len;
-
-#ifdef ERI_RCV_CKSUM
-				sum = ~(uint16_t)(flags & ERI_RMD_CKSUM);
-				ERI_PROCESS_READ(erip, bp, sum);
-#else
-				ERI_PROCESS_READ(erip, bp);
-#endif
+			retmp = nbp;
 		} else {
 
 			/*
@@ -6377,165 +3971,71 @@
 
 			UPDATE_RMD(rmdp);
 			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
-					DDI_DMA_SYNC_FORDEV);
-			ERI_DEBUG_MSG1(erip, RESOURCE_MSG,
-				"allocb fail");
+			    DDI_DMA_SYNC_FORDEV);
+			ERI_DEBUG_MSG1(erip, RESOURCE_MSG, "allocb fail");
+		}
+	} else {
+		/* Use dma unmap/map */
+		if ((nbp = eri_allocb_sp(ERI_BUFSIZE))) {
+			/*
+			 * How do we harden this, specially if unbind
+			 * succeeds and then bind fails?
+			 *  If Unbind fails, we can leave without updating
+			 * the descriptor but would it continue to work on
+			 * next round?
+			 */
+			(void) ddi_dma_unbind_handle(erip->ndmarh[rmdi]);
+			(void) ddi_dma_addr_bind_handle(erip->ndmarh[rmdi],
+			    NULL, (caddr_t)nbp->b_rptr, ERI_BUFSIZE,
+			    DDI_DMA_READ | DDI_DMA_CONSISTENT,
+			    DDI_DMA_DONTWAIT, 0, &c, &ccnt);
+
+			erip->rmblkp[rmdi] = nbp;
+			PUT_RMD(rmdp, c);
+			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
+			    DDI_DMA_SYNC_FORDEV);
+
+			/* Add the First Byte offset to the b_rptr */
+
+			bp->b_rptr += ERI_FSTBYTE_OFFSET;
+			bp->b_wptr = bp->b_rptr + len;
+
+#ifdef ERI_RCV_CKSUM
+			sum = ~(uint16_t)(flags & ERI_RMD_CKSUM);
+			/*LINTED E_PTRDIFF_OVERFLOW*/
+			ERI_PROCESS_READ(erip, bp, sum);
+#else
+			/*LINTED E_PTRDIFF_OVERFLOW*/
+			ERI_PROCESS_READ(erip, bp);
+#endif
+			retmp = bp;
+		} else {
+
+			/*
+			 * mblk allocation has failed. Re-use the old mblk for
+			 * the next packet. Re-mapping is not required since
+			 * the same mblk and dma cookie is to be used again.
+			 */
+			HSTAT(erip, ierrors);
+			HSTAT(erip, allocbfail);
+			HSTAT(erip, norcvbuf);
+
+			UPDATE_RMD(rmdp);
+			ERI_SYNCIOPB(erip, rmdp, sizeof (struct rmd),
+			    DDI_DMA_SYNC_FORDEV);
+			ERI_DEBUG_MSG1(erip, RESOURCE_MSG, "allocb fail");
 		}
 	}
+
+	return (retmp);
 }
 
-#ifdef	 ERI_SERVICE_ROUTINE
-static int
-eri_rsrv(queue_t *q)
-{
-	mblk_t *mp;
-	struct  eristr	*sbp = (struct eristr *)q->q_ptr;
-	struct  eri	*erip;
-	struct		ether_header	*ehp;
-	t_uscalar_t	type;
-	int		len;
-
-	/*
-	 * First check if the stream is still there.
-	 * If the stream is detached free all the mblks
-	 */
-	erip = sbp->sb_erip;
-	if (erip == NULL) {
-		while (mp = getq(q)) {
-			mp->b_wptr = mp->b_rptr;
-			freemsg(mp);
-		}
-		return (-1);
-	}
-
-	while (mp = getq(q)) {
-		len = mp->b_wptr - mp->b_rptr;
-		if ((len  < 0x3c) || (len > 0x5ea)) {
-			erip->drop++;
-			erip->ierrors++;
-
-			ERI_DEBUG_MSG2(erip, CORRUPTION_MSG,
-			    "eri_rsrv: Illegal Size Recieved len %x ", len);
-
-			mp->b_wptr = mp->b_rptr;
-		    freemsg(mp);
-		    continue;
-		}
-		ehp = (struct ether_header *)mp->b_rptr;
-		type = get_ether_type(ehp);
-		/*
-		 * ERI 1.0 has an address filtering bug in which
-		 * it doesn't do any filtering for the last byte of
-		 * the destination MAC address. Thus packets which
-		 * are not intended for us can go thu. Here we filter
-		 * out these packets. This bug will be fixed in the
-		 * next Spin of the ERI ASIC.
-		 */
-
-#ifdef ERI_MAC_ADDR_FLTR_BUG
-		if (INVALID_MAC_ADDRESS(erip, ehp)) {
-			erip->drop++;
-			erip->ierrors++;
-			ERI_DEBUG_MSG1(erip, CORRUPTION_MSG,
-				"Host/Destination MAC address mismatch ");
-			mp->b_wptr = mp->b_rptr;
-			freemsg(mp);
-			continue;
-		}
-#endif
-		/*
-		 * update MIB II statistics
-		 */
-		HSTAT(erip, ipackets64);
-		HSTATN(erip, rbytes64, len);
-
-		if ((type == ETHERTYPE_IPV4) && (IS_NOT_MULTICAST(ehp))) {
-			mp->b_rptr += sizeof (struct ether_header);
-#ifdef ERI_RCV_CKSUM
-			if ((sbp->sb_flags & ERI_SCKSUM) &&
-			    (sbp->sb_flags & ERI_SFAST)) {
-				mp->b_ick_flag = ICK_VALID;
-				mp->b_ick_start = mp->b_rptr +
-					ERI_IPHDR_OFFSET;
-				mp->b_ick_end = mp->b_wptr;
-			    }
-#endif /* ERI_RCV_CKSUM */
-			if (canputnext(q))
-				(void) putnext(q, mp);
-			else {
-				freemsg(mp);
-				HSTAT(erip, nocanput);
-				HSTAT(erip, ierrors);
-			}
-
-		} else if ((type == ETHERTYPE_IPV6) &&
-			IS_NOT_MULTICAST(ehp)) {
-			mp->b_rptr += sizeof (struct ether_header);
-#ifdef ERI_RCV_CKSUM
-			if ((sbp->sb_flags & ERI_SCKSUM) &&
-			    (sbp->sb_flags & ERI_SFAST)) {
-				mp->b_ick_flag = ICK_VALID;
-				mp->b_ick_start = mp->b_rptr +
-					ERI_IPHDR_OFFSET;
-				mp->b_ick_end = mp->b_wptr;
-			    }
-#endif /* ERI_RCV_CKSUM */
-			if (canputnext(q))
-				(void) putnext(q, mp);
-			else {
-				freemsg(mp);
-				HSTAT(erip, nocanput);
-				HSTAT(erip, ierrors);
-			}
-		} else {
-
-		/*
-		 * Strip the PADs for 802.3
-		 */
-		if (type <= ETHERMTU)
-			mp->b_wptr = mp->b_rptr
-			    + sizeof (struct ether_header) + type;
-			BUMP_InNUcast(erip, ehp);
-
-			eri_sendup(erip, mp, eri_accept);
-		}
-	}
-	return (0);
-}
-
-#endif /*  ERI_SERVICE_ROUTINE */
-
-
 #define	LINK_STAT_DISPLAY_TIME	20
 
-static void
-eri_cable_down_msg(struct eri *erip)
-{
-	time_t	now = gethrestime_sec();
-
-	if ((erip->linksts_msg) &&
-	    ((now - erip->msg_time) > LINK_STAT_DISPLAY_TIME)) {
-		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_CON_MSG,
-				link_down_msg);
-		erip->msg_time = now;
-	}
-}
-
 static int
 eri_init_xfer_params(struct eri *erip)
 {
-	int	prop_len = sizeof (int);
 	int	i;
-	int	ipg1_conf, ipg2_conf;
-	int	use_int_xcvr_conf, pace_count_conf;
-	int	autoneg_conf;
-	int	anar_100T4_conf;
-	int	anar_100fdx_conf, anar_100hdx_conf;
-	int	anar_10fdx_conf, anar_10hdx_conf;
-	int	ipg0_conf, lance_mode_conf;
-	int	intr_blank_time_conf, intr_blank_packets_conf;
-	int	anar_pauseTX_conf, anar_pauseRX_conf;
-	int	select_link_conf, default_link_conf;
 	dev_info_t *dip;
 
 	dip = erip->dip;
@@ -6543,8 +4043,6 @@
 	for (i = 0; i < A_CNT(param_arr); i++)
 		erip->param_arr[i] = param_arr[i];
 
-	param_device = erip->instance;
-
 	erip->xmit_dma_mode = 0;
 	erip->rcv_dma_mode = 0;
 	erip->mifpoll_enable = mifpoll_enable;
@@ -6552,13 +4050,10 @@
 	erip->frame_enable = 1;
 	erip->ngu_enable = ngu_enable;
 
-	for (i = 0; i <  A_CNT(param_arr); i++)
-		erip->param_display[i] = param_display_mii[i];
-
 	if (!erip->g_nd && !eri_param_register(erip,
 	    erip->param_arr, A_CNT(param_arr))) {
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				param_reg_fail_msg);
+		    param_reg_fail_msg);
 			return (-1);
 		}
 
@@ -6567,26 +4062,7 @@
 	 * Get the values from the global variables first.
 	 * Use the MASK to limit the value to allowed maximum.
 	 */
-	param_ipg1 = ipg1 & ERI_MASK_8BIT;
-	param_ipg2 = ipg2 & ERI_MASK_8BIT;
-	param_use_intphy = use_int_xcvr & ERI_MASK_1BIT;
-	param_pace_count = pace_size & ERI_MASK_8BIT;
-	param_autoneg = adv_autoneg_cap;
-	param_anar_100T4 = adv_100T4_cap;
-	param_anar_100fdx = adv_100fdx_cap;
-	param_anar_100hdx = adv_100hdx_cap;
-	param_anar_10fdx = adv_10fdx_cap;
-	param_anar_10hdx = adv_10hdx_cap;
-	param_ipg0 = ipg0 & ERI_MASK_8BIT;
-	param_intr_blank_time = intr_blank_time & ERI_MASK_8BIT;
-	param_intr_blank_packets = intr_blank_packets & ERI_MASK_8BIT;
-	param_lance_mode = lance_mode & ERI_MASK_1BIT;
-
-	param_select_link = select_link & ERI_MASK_1BIT;
-	param_default_link = default_link & ERI_MASK_1BIT;
-
-	param_anar_asm_dir = adv_pauseTX_cap;
-	param_anar_pause = adv_pauseRX_cap;
+
 	param_transceiver = NO_XCVR;
 
 /*
@@ -6594,11 +4070,8 @@
  * property "transfer-speed". This may be done in OBP by using the command
  * "apply transfer-speed=<speed> <device>". The speed may be either 10 or 100.
  */
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
-			"transfer-speed", (caddr_t)&i, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		ERI_DEBUG_MSG2(erip, PROP_MSG,
-		    "eri_init_xfer_params:  transfer-speed property = %X", i);
+	i = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "transfer-speed", 0);
+	if (i != 0) {
 		param_autoneg = 0;	/* force speed */
 		param_anar_100T4 = 0;
 		param_anar_10fdx = 0;
@@ -6617,156 +4090,78 @@
 	/*
 	 * Get the parameter values configured in .conf file.
 	 */
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg1",
-				(caddr_t)&ipg1_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		ERI_DEBUG_MSG2(erip, PROP_MSG,
-			"eri_init_xfer_params: ipg1 property %X", ipg1_conf);
-		param_ipg1 = ipg1_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg2",
-				(caddr_t)&ipg2_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_ipg2 = ipg2_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "use_int_xcvr",
-				(caddr_t)&use_int_xcvr_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_use_intphy = use_int_xcvr_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "pace_size",
-				(caddr_t)&pace_count_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_pace_count = pace_count_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_autoneg_cap",
-				(caddr_t)&autoneg_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_autoneg = autoneg_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_100T4_cap",
-				(caddr_t)&anar_100T4_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_100T4 = anar_100T4_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_100fdx_cap",
-				(caddr_t)&anar_100fdx_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_100fdx = anar_100fdx_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_100hdx_cap",
-				(caddr_t)&anar_100hdx_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_100hdx = anar_100hdx_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_10fdx_cap",
-				(caddr_t)&anar_10fdx_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_10fdx = anar_10fdx_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_10hdx_cap",
-				(caddr_t)&anar_10hdx_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_10hdx = anar_10hdx_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "ipg0",
-				(caddr_t)&ipg0_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_ipg0 = ipg0_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "intr_blank_time",
-				(caddr_t)&intr_blank_time_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_intr_blank_time = intr_blank_time_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "intr_blank_packets",
-				(caddr_t)&intr_blank_packets_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_intr_blank_packets =
-		    intr_blank_packets_conf & ERI_MASK_8BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "lance_mode",
-				(caddr_t)&lance_mode_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_lance_mode = lance_mode_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "select_link",
-				(caddr_t)&select_link_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_select_link = select_link_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "default_link",
-				(caddr_t)&default_link_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_default_link = default_link_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_asm_dir_cap",
-				(caddr_t)&anar_pauseTX_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_asm_dir = anar_pauseTX_conf & ERI_MASK_1BIT;
-	}
-	if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0, "adv_pause_cap",
-				(caddr_t)&anar_pauseRX_conf, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		param_anar_pause = anar_pauseRX_conf & ERI_MASK_1BIT;
-	}
+	param_ipg1 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "ipg1", ipg1) &
+	    ERI_MASK_8BIT;
+
+	param_ipg2 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "ipg2", ipg2) &
+	    ERI_MASK_8BIT;
+
+	param_use_intphy = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "use_int_xcvr", use_int_xcvr) & ERI_MASK_1BIT;
+
+	param_use_intphy = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "pace_size", pace_size) & ERI_MASK_8BIT;
+
+	param_autoneg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_autoneg_cap", adv_autoneg_cap) & ERI_MASK_1BIT;
+
+	param_autoneg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_autoneg_cap", adv_autoneg_cap) & ERI_MASK_1BIT;
+
+	param_anar_100T4 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_100T4_cap", adv_100T4_cap) & ERI_MASK_1BIT;
+
+	param_anar_100fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_100fdx_cap", adv_100fdx_cap) & ERI_MASK_1BIT;
+
+	param_anar_100hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_100hdx_cap", adv_100hdx_cap) & ERI_MASK_1BIT;
+
+	param_anar_10fdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_10fdx_cap", adv_10fdx_cap) & ERI_MASK_1BIT;
+
+	param_anar_10hdx = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_10hdx_cap", adv_10hdx_cap) & ERI_MASK_1BIT;
+
+	param_ipg0 = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "ipg0", ipg0) &
+	    ERI_MASK_8BIT;
+
+	param_intr_blank_time = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "intr_blank_time", intr_blank_time) & ERI_MASK_8BIT;
+
+	param_intr_blank_packets = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "intr_blank_packets", intr_blank_packets) & ERI_MASK_8BIT;
+
+	param_lance_mode = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "lance_mode", lance_mode) & ERI_MASK_1BIT;
+
+	param_select_link = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "select_link", select_link) & ERI_MASK_1BIT;
+
+	param_default_link = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "default_link", default_link) & ERI_MASK_1BIT;
+
+	param_anar_asm_dir = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_asm_dir_cap", adv_pauseTX_cap) & ERI_MASK_1BIT;
+
+	param_anar_pause = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
+	    "adv_pause_cap", adv_pauseRX_cap) & ERI_MASK_1BIT;
 
 	if (link_pulse_disabled)
 		erip->link_pulse_disabled = 1;
-	else if (ddi_getlongprop_buf(DDI_DEV_T_ANY, dip, 0,
-			"link-pulse-disabled", (caddr_t)&i, &prop_len)
-				== DDI_PROP_SUCCESS) {
-		ERI_DEBUG_MSG1(erip, PROP_MSG,
-				"eri_init_xfer_params: dis link-pulse prop.");
+	if (ddi_prop_exists(DDI_DEV_T_ANY, dip, 0, "link-pulse-disabled"))
 		erip->link_pulse_disabled = 1;
-	}
+
 	eri_statinit(erip);
 	return (0);
 
 }
 
-static struct eri *
-eri_set_ppa(struct eristr *sbp, queue_t *wq)
+static void
+eri_process_ndd_ioctl(struct eri *erip, queue_t *wq, mblk_t *mp, int cmd)
 {
-	struct	eri	*erip = NULL;
-	int instance;
-
-	if (sbp->sb_erip)	/* ppa has been selected */
-		return (sbp->sb_erip);
-
-	instance = device;
-	if (device == -1) {	/* select the first one found */
-		mutex_enter(&erilock);
-		if (eriup)
-			instance = eriup->instance;
-		mutex_exit(&erilock);
-	}
-	if (instance == -1 || qassociate(wq, instance) != 0) {
-		return (NULL);
-	}
-
-	mutex_enter(&erilock);
-	for (erip = eriup; erip; erip = erip->nextp)
-		if (instance == erip->instance)
-			break;
-	ASSERT(erip != NULL);
-	mutex_exit(&erilock);
-
-	sbp->sb_erip = erip;
-	return (erip);
-}
-
-static void
-eri_process_ndd_ioctl(queue_t *wq, mblk_t *mp, int cmd)
-{
-
-	struct	eristr	*sbp = (struct eristr *)wq->q_ptr;
-	struct	eri		*erip = NULL;
-	struct	eri		*erip1 = NULL;
 
 	uint32_t old_ipg1, old_ipg2, old_use_int_xcvr, old_autoneg;
-	int32_t old_device;
-	int32_t new_device;
 	uint32_t old_100T4;
 	uint32_t old_100fdx, old_100hdx, old_10fdx, old_10hdx;
 	uint32_t old_ipg0, old_lance_mode;
@@ -6774,19 +4169,9 @@
 	uint32_t old_asm_dir, old_pause;
 	uint32_t old_select_link, old_default_link;
 
-	erip = eri_set_ppa(sbp, wq);
-
-	if (erip == NULL) {	/* no device present */
-		miocnak(wq, mp, 0, EINVAL);
-		return;
-	}
-
 	switch (cmd) {
 	case ERI_ND_GET:
 
-		ERI_DEBUG_MSG1(erip, NDD_MSG,
-				"eri_process_ndd_ioctl:ND_GET");
-		mutex_enter(&erilock);
 		old_autoneg =	param_autoneg;
 		old_100T4 =	param_anar_100T4;
 		old_100fdx =	param_anar_100fdx;
@@ -6814,9 +4199,6 @@
 			param_anar_10hdx = old_10hdx;
 			param_anar_asm_dir = old_asm_dir;
 			param_anar_pause = old_pause;
-			mutex_exit(&erilock);
-			ERI_DEBUG_MSG1(erip, NDD_MSG,
-					"ndd_ioctl: _nd_getset nak");
 			miocnak(wq, mp, 0, EINVAL);
 			return;
 		}
@@ -6829,16 +4211,10 @@
 		param_anar_asm_dir = old_asm_dir;
 		param_anar_pause = old_pause;
 
-		mutex_exit(&erilock);
-		ERI_DEBUG_MSG1(erip, NDD_MSG,
-				"ndd_ioctl: _nd_getset ack");
 		qreply(wq, mp);
 		break;
 
 	case ERI_ND_SET:
-		ERI_DEBUG_MSG1(erip, NDD_MSG,
-				"eri_process_ndd_ioctl:ND_SET");
-		old_device = param_device;
 		old_ipg0 = param_ipg0;
 		old_intr_blank_time = param_intr_blank_time;
 		old_intr_blank_packets = param_intr_blank_packets;
@@ -6860,57 +4236,29 @@
 		old_select_link = param_select_link;
 		old_default_link = param_default_link;
 
-		mutex_enter(&erilock);
 		if (!eri_nd_getset(wq, erip->g_nd, mp)) {
 			param_autoneg = old_autoneg;
-			mutex_exit(&erilock);
 			miocnak(wq, mp, 0, EINVAL);
 			return;
 		}
-		mutex_exit(&erilock);
-
-		if (old_device != param_device) {
-			new_device = param_device;
-			param_device = old_device;
-			param_autoneg = old_autoneg;
-			if (new_device != -1 &&
-			    qassociate(wq, new_device) == 0) {
-				mutex_enter(&erilock);
-				for (erip1 = eriup; erip1; erip1 = erip1->nextp)
-					if (new_device == erip1->instance)
-						break;
-				mutex_exit(&erilock);
-				ASSERT(erip1 != NULL);
-			}
-
-			if (erip1 == NULL) {
-				miocnak(wq, mp, 0, EINVAL);
-				return;
-			}
-			device = new_device;
-			sbp->sb_erip = erip1;
-			qreply(wq, mp);
-			return;
-		}
 
 		qreply(wq, mp);
 
 		if (param_autoneg != 0xff) {
 			ERI_DEBUG_MSG2(erip, NDD_MSG,
-				"ndd_ioctl: new param_autoneg %d",
-				param_autoneg);
+			    "ndd_ioctl: new param_autoneg %d", param_autoneg);
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 			(void) eri_init(erip);
 		} else {
 			param_autoneg = old_autoneg;
 			if ((old_use_int_xcvr != param_use_intphy) ||
-				(old_default_link != param_default_link) ||
-				(old_select_link != param_select_link)) {
+			    (old_default_link != param_default_link) ||
+			    (old_select_link != param_select_link)) {
 				param_linkup = 0;
-				erip->stats.link_up = ERI_LINK_DOWN;
-				erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+				erip->stats.link_up = LINK_STATE_DOWN;
+				erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 				(void) eri_init(erip);
 			} else if ((old_ipg1 != param_ipg1) ||
 			    (old_ipg2 != param_ipg2) ||
@@ -6918,16 +4266,14 @@
 			    (old_intr_blank_time != param_intr_blank_time) ||
 			    (old_intr_blank_packets !=
 			    param_intr_blank_packets) ||
-				(old_lance_mode != param_lance_mode)) {
+			    (old_lance_mode != param_lance_mode)) {
 				param_linkup = 0;
-				erip->stats.link_up = ERI_LINK_DOWN;
-				erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
+				erip->stats.link_up = LINK_STATE_DOWN;
+				erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
 				(void) eri_init(erip);
 			}
 		}
 		break;
-	default:
-		break;
 	}
 }
 
@@ -6938,10 +4284,13 @@
 	struct eri *erip;
 	struct erikstat *erikp;
 	struct stats *esp;
+	boolean_t macupdate = B_FALSE;
 
 	erip = (struct eri *)ksp->ks_private;
 	erikp = (struct erikstat *)ksp->ks_data;
 
+	if (rw != KSTAT_READ)
+		return (EACCES);
 	/*
 	 * Update all the stats by reading all the counter registers.
 	 * Counter register stats are not updated till they overflow
@@ -6951,207 +4300,57 @@
 	mutex_enter(&erip->xmitlock);
 	if ((erip->flags & ERI_RUNNING) && (erip->flags & ERI_TXINIT)) {
 		erip->tx_completion =
-			GET_ETXREG(tx_completion) & ETX_COMPLETION_MASK;
-		(void) eri_reclaim(erip, erip->tx_completion);
+		    GET_ETXREG(tx_completion) & ETX_COMPLETION_MASK;
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 	}
 	mutex_exit(&erip->xmitlock);
+	if (macupdate)
+		mac_tx_update(erip->mh);
 
 	eri_savecntrs(erip);
 
 	esp = &erip->stats;
 
-	if (rw == KSTAT_WRITE) {
-		esp->ipackets64	= erikp->erik_ipackets64.value.ull;
-		esp->ierrors	= erikp->erik_ierrors.value.ul;
-		esp->opackets64	= erikp->erik_opackets64.value.ull;
-		esp->oerrors	= erikp->erik_oerrors.value.ul;
-
-		/*
-		 * MIB II kstat variables
-		 */
-		esp->rbytes64	= erikp->erik_rbytes64.value.ull;
-		esp->obytes64	= erikp->erik_obytes64.value.ull;
-		esp->multircv	= erikp->erik_multircv.value.ul;
-		esp->multixmt	= erikp->erik_multixmt.value.ul;
-		esp->brdcstrcv	= erikp->erik_brdcstrcv.value.ul;
-		esp->brdcstxmt	= erikp->erik_brdcstxmt.value.ul;
-		esp->norcvbuf	= erikp->erik_norcvbuf.value.ul;
-		esp->noxmtbuf	= erikp->erik_noxmtbuf.value.ul;
-
-#ifdef	kstat
-		esp->ifspeed	= erikp->erik_ifspeed.value.ull;
-		esp->txmac_urun	= erikp->erik_txmac_urun.value.ul;
-		esp->txmac_maxpkt_err =
-					erikp->erik_txmac_maxpkt_err.value.ul;
-
-		esp->excessive_coll = erikp->erik_excessive_coll.value.ul;
-		esp->late_coll	= erikp->erik_late_coll.value.ul;
-		esp->first_coll	= erikp->erik_first_coll.value.ul;
-		esp->defer_timer_exp =
-					erikp->erik_defer_timer_exp.value.ul;
-
-		esp->peak_attempt_cnt =
-					erikp->erik_peak_attempt_cnt.value.ul;
-		esp->tx_hang 	= erikp->erik_tx_hang.value.ul;
-
-		esp->rx_corr 	= erikp->erik_rx_corr.value.ul;
-		esp->no_free_rx_desc =
-					erikp->erik_no_free_rx_desc.value.ul;
-
-		esp->rx_overflow	= erikp->erik_rx_overflow.value.ul;
-		esp->rx_hang 	= erikp->erik_rx_hang.value.ul;
-		esp->rx_align_err	= erikp->erik_rx_align_err.value.ul;
-		esp->rx_crc_err	= erikp->erik_rx_crc_err.value.ul;
-		esp->rx_length_err	= erikp->erik_rx_length_err.value.ul;
-		esp->rx_code_viol_err =
-					erikp->erik_rx_code_viol_err.value.ul;
-
-		esp->pause_rxcount	= erikp->erik_pause_rxcount.value.ul;
-		esp->pause_oncount	= erikp->erik_pause_oncount.value.ul;
-		esp->pause_offcount = erikp->erik_pause_offcount.value.ul;
-		esp->pause_time_count =
-					erikp->erik_pause_time_count.value.ul;
-
-		esp->inits		= erikp->erik_inits.value.ul;
-		esp->rx_inits	= erikp->erik_rx_inits.value.ul;
-		esp->tx_inits	= erikp->erik_tx_inits.value.ul;
-		esp->tnocar	= erikp->erik_tnocar.value.ul;
-		esp->jab		= erikp->erik_jab.value.ul;
-		esp->notmds	= erikp->erik_notmds.value.ul;
-		esp->nocanput	= erikp->erik_nocanput.value.ul;
-		esp->allocbfail	= erikp->erik_allocbfail.value.ul;
-		esp->drop		= erikp->erik_drop.value.ul;
-		esp->rx_bad_pkts	= erikp->erik_rx_bad_pkts.value.ul;
-		esp->rx_runt		= erikp->erik_rx_runt.value.ul;
-		esp->rx_toolong_pkts	= erikp->erik_rx_toolong_pkts.value.ul;
-
-		esp->rxtag_err	= erikp->erik_rxtag_err.value.ul;
-
-		esp->parity_error	= erikp->erik_parity_error.value.ul;
-
-		esp->eri_pci_error_int	= erikp->erik_pci_error_int.value.ul;
-		esp->unknown_fatal	= erikp->erik_unknown_fatal.value.ul;
-		esp->pci_data_parity_err
-				= erikp->erik_pci_data_parity_err.value.ul;
-		esp->pci_signal_target_abort
-				= erikp->erik_pci_signal_target_abort.value.ul;
-		esp->pci_rcvd_target_abort
-				= erikp->erik_pci_rcvd_target_abort.value.ul;
-		esp->pci_rcvd_master_abort
-				= erikp->erik_pci_rcvd_master_abort.value.ul;
-		esp->pci_signal_system_err
-				= erikp->erik_pci_signal_system_err.value.ul;
-		esp->pci_det_parity_err
-				= erikp->erik_pci_det_parity_err.value.ul;
-
-		esp->pmcap	= erikp->erik_pmcap.value.ul;
-
-		esp->link_up	= erikp->erik_link_up.value.ul;
-
-		esp->link_duplex = erikp->erik_link_duplex.value.ul;
-
-#endif	/* kstat */
-		return (0);
-	} else {
-		erikp->erik_ipackets64.value.ull	= esp->ipackets64;
-		erikp->erik_ipackets.value.ul		= esp->ipackets64;
-		erikp->erik_ierrors.value.ul		= esp->ierrors;
-		erikp->erik_opackets64.value.ull	= esp->opackets64;
-		erikp->erik_opackets.value.ul		= esp->opackets64;
-		erikp->erik_oerrors.value.ul		= esp->oerrors;
-		erikp->erik_collisions.value.ul		= esp->collisions;
-		erikp->erik_ifspeed.value.ull = esp->ifspeed * 1000000ULL;
-
-		/*
-		 * MIB II kstat variables
-		 */
-		erikp->erik_rbytes64.value.ull		= esp->rbytes64;
-		erikp->erik_rbytes.value.ul		= esp->rbytes64;
-		erikp->erik_obytes64.value.ull		= esp->obytes64;
-		erikp->erik_obytes.value.ul		= esp->obytes64;
-
-		erikp->erik_multircv.value.ul		= esp->multircv;
-		erikp->erik_multixmt.value.ul		= esp->multixmt;
-		erikp->erik_brdcstrcv.value.ul		= esp->brdcstrcv;
-		erikp->erik_brdcstxmt.value.ul		= esp->brdcstxmt;
-		erikp->erik_norcvbuf.value.ul		= esp->norcvbuf;
-		erikp->erik_noxmtbuf.value.ul		= esp->noxmtbuf;
-
-		erikp->erik_txmac_urun.value.ul		= esp->txmac_urun;
-		erikp->erik_txmac_maxpkt_err.value.ul
-					= esp->txmac_maxpkt_err;
-		erikp->erik_excessive_coll.value.ul
-					= esp->excessive_coll;
-		erikp->erik_late_coll.value.ul		= esp->late_coll;
-		erikp->erik_first_coll.value.ul		= esp->first_coll;
-		erikp->erik_defer_timer_exp.value.ul
-					= esp->defer_timer_exp;
-		erikp->erik_peak_attempt_cnt.value.ul
-					= esp->peak_attempt_cnt;
-		erikp->erik_tx_hang.value.ul	= esp->tx_hang;
-
-		erikp->erik_rx_corr.value.ul	= esp->rx_corr;
-		erikp->erik_no_free_rx_desc.value.ul
-					= esp->no_free_rx_desc;
-
-		erikp->erik_rx_overflow.value.ul = esp->rx_overflow;
-		erikp->erik_rx_hang.value.ul	= esp->rx_hang;
-		erikp->erik_rx_align_err.value.ul = esp->rx_align_err;
-		erikp->erik_rx_crc_err.value.ul	= esp->rx_crc_err;
-		erikp->erik_rx_length_err.value.ul
-					= esp->rx_length_err;
-		erikp->erik_rx_code_viol_err.value.ul
-					= esp->rx_code_viol_err;
-		erikp->erik_pause_rxcount.value.ul
-					= esp->pause_rxcount;
-		erikp->erik_pause_oncount.value.ul
-					= esp->pause_oncount;
-		erikp->erik_pause_offcount.value.ul
-					= esp->pause_offcount;
-		erikp->erik_pause_time_count.value.ul
-					= esp->pause_time_count;
-
-		erikp->erik_inits.value.ul	= esp->inits;
-		erikp->erik_tnocar.value.ul	= esp->tnocar;
-		erikp->erik_jab.value.ul	= esp->jab;
-		erikp->erik_notmds.value.ul	= esp->notmds;
-		erikp->erik_nocanput.value.ul	= esp->nocanput;
-		erikp->erik_allocbfail.value.ul	= esp->allocbfail;
-		erikp->erik_drop.value.ul	= esp->drop;
-		erikp->erik_rx_bad_pkts.value.ul = esp->rx_bad_pkts;
-		erikp->erik_rx_runt.value.ul    = esp->rx_runt;
-		erikp->erik_rx_toolong_pkts.value.ul
-					= esp->rx_toolong_pkts;
-		erikp->erik_rx_inits.value.ul
-					= esp->rx_inits;
-		erikp->erik_tx_inits.value.ul
-					= esp->tx_inits;
-
-		erikp->erik_rxtag_err.value.ul	= esp->rxtag_err;
-
-		erikp->erik_parity_error.value.ul = esp->parity_error;
-
-		erikp->erik_pci_error_int.value.ul = esp->pci_error_int;
-		erikp->erik_unknown_fatal.value.ul = esp->unknown_fatal;
-		erikp->erik_pci_data_parity_err.value.ul
-					= esp->pci_data_parity_err;
-		erikp->erik_pci_signal_target_abort.value.ul
-					= esp->pci_signal_target_abort;
-		erikp->erik_pci_rcvd_target_abort.value.ul
-					= esp->pci_rcvd_target_abort;
-		erikp->erik_pci_rcvd_master_abort.value.ul
-					= esp->pci_rcvd_master_abort;
-		erikp->erik_pci_signal_system_err.value.ul
-					= esp->pci_signal_system_err;
-		erikp->erik_pci_det_parity_err.value.ul
-					= esp->pci_det_parity_err;
-
-		erikp->erik_pmcap.value.ul		= esp->pmcap;
-
-		erikp->erik_link_up.value.ul		= esp->link_up;
-
-		erikp->erik_link_duplex.value.ul	= esp->link_duplex;
-	}
+	erikp->erik_txmac_maxpkt_err.value.ul = esp->txmac_maxpkt_err;
+	erikp->erik_defer_timer_exp.value.ul = esp->defer_timer_exp;
+	erikp->erik_peak_attempt_cnt.value.ul = esp->peak_attempt_cnt;
+	erikp->erik_tx_hang.value.ul	= esp->tx_hang;
+
+	erikp->erik_no_free_rx_desc.value.ul	= esp->no_free_rx_desc;
+
+	erikp->erik_rx_hang.value.ul		= esp->rx_hang;
+	erikp->erik_rx_length_err.value.ul	= esp->rx_length_err;
+	erikp->erik_rx_code_viol_err.value.ul	= esp->rx_code_viol_err;
+	erikp->erik_pause_rxcount.value.ul	= esp->pause_rxcount;
+	erikp->erik_pause_oncount.value.ul	= esp->pause_oncount;
+	erikp->erik_pause_offcount.value.ul	= esp->pause_offcount;
+	erikp->erik_pause_time_count.value.ul	= esp->pause_time_count;
+
+	erikp->erik_inits.value.ul		= esp->inits;
+	erikp->erik_jab.value.ul		= esp->jab;
+	erikp->erik_notmds.value.ul		= esp->notmds;
+	erikp->erik_allocbfail.value.ul		= esp->allocbfail;
+	erikp->erik_drop.value.ul		= esp->drop;
+	erikp->erik_rx_bad_pkts.value.ul	= esp->rx_bad_pkts;
+	erikp->erik_rx_inits.value.ul		= esp->rx_inits;
+	erikp->erik_tx_inits.value.ul		= esp->tx_inits;
+	erikp->erik_rxtag_err.value.ul		= esp->rxtag_err;
+	erikp->erik_parity_error.value.ul	= esp->parity_error;
+	erikp->erik_pci_error_int.value.ul	= esp->pci_error_int;
+	erikp->erik_unknown_fatal.value.ul	= esp->unknown_fatal;
+	erikp->erik_pci_data_parity_err.value.ul = esp->pci_data_parity_err;
+	erikp->erik_pci_signal_target_abort.value.ul =
+	    esp->pci_signal_target_abort;
+	erikp->erik_pci_rcvd_target_abort.value.ul =
+	    esp->pci_rcvd_target_abort;
+	erikp->erik_pci_rcvd_master_abort.value.ul =
+	    esp->pci_rcvd_master_abort;
+	erikp->erik_pci_signal_system_err.value.ul =
+	    esp->pci_signal_system_err;
+	erikp->erik_pci_det_parity_err.value.ul = esp->pci_det_parity_err;
+
+	erikp->erik_pmcap.value.ul = esp->pmcap;
+
 	return (0);
 }
 
@@ -7161,225 +4360,94 @@
 	struct	kstat	*ksp;
 	struct	erikstat	*erikp;
 
-#ifdef	kstat
-	if ((ksp = kstat_create("eri", erip->instance,
-		NULL, "net", KSTAT_TYPE_NAMED,
-		sizeof (struct erikstat) / sizeof (kstat_named_t),
-		KSTAT_FLAG_PERSISTENT)) == NULL) {
-#else
-	if ((ksp = kstat_create("eri", erip->instance,
-	    NULL, "net", KSTAT_TYPE_NAMED,
+	if ((ksp = kstat_create("eri", erip->instance, "driver_info", "net",
+	    KSTAT_TYPE_NAMED,
 	    sizeof (struct erikstat) / sizeof (kstat_named_t), 0)) == NULL) {
-#endif	/* kstat */
 		ERI_FAULT_MSG1(erip, SEVERITY_LOW, ERI_VERB_MSG,
-				kstat_create_fail_msg);
+		    kstat_create_fail_msg);
 		return;
 	}
 
 	erip->ksp = ksp;
 	erikp = (struct erikstat *)(ksp->ks_data);
-	kstat_named_init(&erikp->erik_ipackets,		"ipackets",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_ierrors,		"ierrors",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_opackets,		"opackets",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_oerrors,		"oerrors",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_collisions,	"collisions",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_ifspeed,		"ifspeed",
-		KSTAT_DATA_ULONGLONG);
-
 	/*
 	 * MIB II kstat variables
 	 */
-	kstat_named_init(&erikp->erik_rbytes,		"rbytes",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_obytes,		"obytes",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_multircv,		"multircv",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_multixmt,		"multixmt",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_brdcstrcv,	"brdcstrcv",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_brdcstxmt,	"brdcstxmt",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_norcvbuf,		"norcvbuf",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_noxmtbuf,		"noxmtbuf",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_inits,		"inits",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_tnocar,		"nocarrier",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_txmac_urun,	"txmac_urun",
-		KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_inits, "inits", KSTAT_DATA_ULONG);
+
 	kstat_named_init(&erikp->erik_txmac_maxpkt_err,	"txmac_maxpkt_err",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_excessive_coll,	"excessive_coll",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_late_coll,	"late_coll",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_first_coll,	"first_coll",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_defer_timer_exp,	"defer_timer_exp",
-		KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+	kstat_named_init(&erikp->erik_defer_timer_exp, "defer_timer_exp",
+	    KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_peak_attempt_cnt,	"peak_attempt_cnt",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_tx_hang,		"tx_hang",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_rx_corr,		"rx_corr",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_no_free_rx_desc,	"no_free_rx_desc",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_rx_overflow,	"rx_overflow",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_rx_hang,		"rx_hang",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_rx_align_err,	"rx_align_err",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_rx_crc_err,	"rx_crc_err",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_rx_length_err,	"rx_length_err",
-		KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+	kstat_named_init(&erikp->erik_tx_hang, "tx_hang", KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_no_free_rx_desc, "no_free_rx_desc",
+	    KSTAT_DATA_ULONG);
+	kstat_named_init(&erikp->erik_rx_hang, "rx_hang", KSTAT_DATA_ULONG);
+	kstat_named_init(&erikp->erik_rx_length_err, "rx_length_err",
+	    KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_rx_code_viol_err,	"rx_code_viol_err",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_pause_rxcount,	"pause_rcv_cnt",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_pause_oncount,	"pause_on_cnt",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_pause_offcount,	"pause_off_cnt",
-		KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_pause_rxcount, "pause_rcv_cnt",
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_pause_oncount, "pause_on_cnt",
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_pause_offcount, "pause_off_cnt",
+	    KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pause_time_count,	"pause_time_cnt",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_jab, "jabber",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_notmds, "no_tmds",
-		KSTAT_DATA_ULONG);
-	kstat_named_init(&erikp->erik_nocanput,	"nocanput",
-		KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_jab, "jabber", KSTAT_DATA_ULONG);
+	kstat_named_init(&erikp->erik_notmds, "no_tmds", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_allocbfail, "allocbfail",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_drop, "drop",
-			KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_drop, "drop", KSTAT_DATA_ULONG);
 
 	kstat_named_init(&erikp->erik_rx_bad_pkts, "bad_pkts",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_rx_runt, "runt",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_rx_toolong_pkts, "toolong_pkts",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_rx_inits, "rx_inits",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_tx_inits, "tx_inits",
-			KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_rx_inits, "rx_inits", KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_tx_inits, "tx_inits", KSTAT_DATA_ULONG);
 
 	kstat_named_init(&erikp->erik_rxtag_err, "rxtag_error",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_parity_error,
-			"parity_error",
-			KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_pci_error_int,
-			"pci_error_interrupt",
-			KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_parity_error, "parity_error",
+	    KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_pci_error_int, "pci_error_interrupt",
+	    KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_unknown_fatal, "unknown_fatal",
-			KSTAT_DATA_ULONG);
+	    KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_data_parity_err,
-			"pci_data_parity_err", KSTAT_DATA_ULONG);
+	    "pci_data_parity_err", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_signal_target_abort,
-			"pci_signal_target_abort", KSTAT_DATA_ULONG);
+	    "pci_signal_target_abort", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_rcvd_target_abort,
-			"pci_rcvd_target_abort", KSTAT_DATA_ULONG);
+	    "pci_rcvd_target_abort", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_rcvd_master_abort,
-			"pci_rcvd_master_abort", KSTAT_DATA_ULONG);
+	    "pci_rcvd_master_abort", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_signal_system_err,
-			"pci_signal_system_err", KSTAT_DATA_ULONG);
+	    "pci_signal_system_err", KSTAT_DATA_ULONG);
 	kstat_named_init(&erikp->erik_pci_det_parity_err,
-			"pci_det_parity_err", KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_pmcap,		"pmcap",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_link_up,		"link_up",
-		KSTAT_DATA_ULONG);
-
-	kstat_named_init(&erikp->erik_link_duplex,	"link_duplex",
-		KSTAT_DATA_ULONG);
-	/*
-	 * 64-bit kstats : PSARC 1997/198
-	 */
-	kstat_named_init(&erikp->erik_ipackets64,	"ipackets64",
-		KSTAT_DATA_ULONGLONG);
-	kstat_named_init(&erikp->erik_opackets64,	"opackets64",
-		KSTAT_DATA_ULONGLONG);
-	kstat_named_init(&erikp->erik_rbytes64,		"rbytes64",
-		KSTAT_DATA_ULONGLONG);
-	kstat_named_init(&erikp->erik_obytes64,		"obytes64",
-		KSTAT_DATA_ULONGLONG);
+	    "pci_det_parity_err", KSTAT_DATA_ULONG);
+
+	kstat_named_init(&erikp->erik_pmcap, "pmcap", KSTAT_DATA_ULONG);
+
 
 	ksp->ks_update = eri_stat_kstat_update;
 	ksp->ks_private = (void *) erip;
 	kstat_install(ksp);
 }
 
-/* <<<<<<<<<<<<<<<<<<<	PERFORMANCE MEASUREMENT FUNCTIONS	>>>>>>>>>>> */
-
-/* The following code is used for performance metering and debugging; */
-/* This routine is invoked via "TIME_POINT(label)" macros, which will */
-/* store the label and a timestamp. This allows to execution sequences */
-/* and timestamps associated with them. */
-
-
-#ifdef TPOINTS
-/* Time trace points */
-int time_point_active;
-static int time_point_offset, time_point_loc;
-hrtime_t last_time_point;
-#define	POINTS 1024
-int time_points[POINTS];
-#define	TPOINT(x) if (time_point_active) eri_time_point(x);
-void
-eri_time_point(int loc)
-{
-	static hrtime_t time_point_base;
-
-	hrtime_t now;
-
-	now = gethrtime();
-	if (time_point_base == 0) {
-		time_point_base = now;
-		time_point_loc = loc;
-		time_point_offset = 0;
-	} else {
-		time_points[time_point_offset] = loc;
-		time_points[time_point_offset+1] =
-		    (now - last_time_point) / 1000;
-		time_point_offset += 2;
-		if (time_point_offset >= POINTS)
-		    time_point_offset = 0; /* wrap at end */
-		/* time_point_active = 0;  disable at end */
-	}
-	last_time_point = now;
-}
-#else
-#define	TPOINT(x)
-#endif
 
 /* <<<<<<<<<<<<<<<<<<<<<<< NDD SUPPORT FUNCTIONS	>>>>>>>>>>>>>>>>>>> */
 /*
@@ -7401,7 +4469,7 @@
 static int
 eri_param_get(queue_t *q, mblk_t *mp, caddr_t cp)
 {
-	param_t		*eripa = (param_t *)cp;
+	param_t		*eripa = (void *)cp;
 	int		param_len = 1;
 	uint32_t	param_val;
 	mblk_t		*nmp;
@@ -7438,6 +4506,7 @@
 	while (tmp->b_cont)
 		tmp = tmp->b_cont;
 
+	/*LINTED E_BAD_PTR_CAST_ALIGN*/
 	if (MBLKTAIL(tmp) < sz) {
 		if ((tmp->b_cont = allocb(1024, BPRI_HI)) == NULL)
 			return (ENOMEM);
@@ -7452,102 +4521,37 @@
  * named dispatch handler. Each element is loaded using
  * eri_nd_load()
  */
-/* ARGSUSED */
 static int
 eri_param_register(struct eri *erip, param_t *eripa, int cnt)
+{
 	/* cnt gives the count of the number of */
 	/* elements present in the parameter array */
-{
-	int i, k;
-
-	/* First 4 elements are read-only */
-	for (i = 0, k = 0; i < 4; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (!eri_nd_load(&erip->g_nd,
-			    eripa->param_name, (pfi_t)eri_param_get,
-			    (pfi_t)0, (caddr_t)eripa)) {
-				(void) eri_nd_free(&erip->g_nd);
-				return (B_FALSE);
-		}
-
-	/* Next 10 elements are read and write */
-	for (i = 0; i < 10; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (eripa->param_name && eripa->param_name[0]) {
-				if (!eri_nd_load(&erip->g_nd,
-				    eripa->param_name, (pfi_t)eri_param_get,
-				    (pfi_t)eri_param_set, (caddr_t)eripa)) {
-					(void) eri_nd_free(&erip->g_nd);
-					return (B_FALSE);
-			}
-		}
-
-	/* next 12 elements are read-only */
-	for (i = 0; i < 12; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (!eri_nd_load(&erip->g_nd, eripa->param_name,
-			    (pfi_t)eri_param_get, (pfi_t)0, (caddr_t)eripa)) {
-				(void) eri_nd_free(&erip->g_nd);
-				return (B_FALSE);
-		}
-
-	/* Next 5 elements are read and write */
-	for (i = 0; i < 5; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (eripa->param_name && eripa->param_name[0]) {
-				if (!eri_nd_load(&erip->g_nd,
-				    eripa->param_name, (pfi_t)eri_param_get,
-				    (pfi_t)eri_param_set, (caddr_t)eripa)) {
-					(void) eri_nd_free(&erip->g_nd);
-					return (B_FALSE);
-			}
+
+	int i;
+
+	for (i = 0; i < cnt; i++) {
+		pfi_t	setter = (pfi_t)eri_param_set;
+
+		switch (eripa->param_name[0]) {
+		case '+':	/* read-write */
+			setter = (pfi_t)eri_param_set;
+			break;
+
+		case '-':	/* read-only */
+			setter = NULL;
+			break;
+
+		case '!':	/* read-only, not displayed */
+		case '%':	/* read-write, not displayed */
+			continue;
 		}
-	/* next 2 elements are read-only */
-	for (i = 0; i < 2; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (!eri_nd_load(&erip->g_nd, eripa->param_name,
-			    (pfi_t)eri_param_get, (pfi_t)0, (caddr_t)eripa)) {
-				(void) eri_nd_free(&erip->g_nd);
-				return (B_FALSE);
-		}
-	/* Next 2   element is read and write */
-	for (i = 0; i < 2; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (eripa->param_name && eripa->param_name[0]) {
-				if (!eri_nd_load(&erip->g_nd,
-				    eripa->param_name, (pfi_t)eri_param_get,
-				    (pfi_t)eri_param_set, (caddr_t)eripa)) {
-					(void) eri_nd_free(&erip->g_nd);
-					return (B_FALSE);
-			}
+
+		if (!eri_nd_load(&erip->g_nd, eripa->param_name + 1,
+		    (pfi_t)eri_param_get, setter, (caddr_t)erip)) {
+			(void) eri_nd_free(&erip->g_nd);
+			return (B_FALSE);
 		}
-	/* next 1 element is read-only */
-	for (i = 0; i < 1; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (!eri_nd_load(&erip->g_nd, eripa->param_name,
-			    (pfi_t)eri_param_get, (pfi_t)0, (caddr_t)eripa)) {
-				(void) eri_nd_free(&erip->g_nd);
-				return (B_FALSE);
-		}
-	/* Next 5   elements are read and write */
-	for (i = 0; i < 5; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (eripa->param_name && eripa->param_name[0]) {
-				if (!eri_nd_load(&erip->g_nd,
-				    eripa->param_name, (pfi_t)eri_param_get,
-				    (pfi_t)eri_param_set, (caddr_t)eripa)) {
-					(void) eri_nd_free(&erip->g_nd);
-					return (B_FALSE);
-			}
-		}
-	/* next 10 elements are read-only */
-	for (i = 0; i < 10; i++, k++, eripa++)
-		if (erip->param_display[k] == DISPLAY_PARAM)
-			if (!eri_nd_load(&erip->g_nd, eripa->param_name,
-			    (pfi_t)eri_param_get, (pfi_t)0, (caddr_t)eripa)) {
-				(void) eri_nd_free(&erip->g_nd);
-				return (B_FALSE);
-		}
+	}
 
 	return (B_TRUE);
 }
@@ -7561,15 +4565,16 @@
 eri_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp)
 {
 	char *end;
-	size_t new_value;
-	param_t	*eripa = (param_t *)cp;
-
-	new_value = eri_strtol(value, &end, 10);
+	long new_value;
+	param_t	*eripa = (void *)cp;
+
+	if (ddi_strtol(value, &end, 10, &new_value) != 0)
+		return (EINVAL);
 	if (end == value || new_value < eripa->param_min ||
 	    new_value > eripa->param_max) {
 			return (EINVAL);
 	}
-	eripa->param_val = new_value;
+	eripa->param_val = (uint32_t)new_value;
 	return (0);
 
 }
@@ -7580,10 +4585,10 @@
 {
 	ND	*nd;
 
-	if ((nd = (ND *)(*nd_pparam)) != NULL) {
+	if ((nd = (void *)(*nd_pparam)) != NULL) {
 		if (nd->nd_tbl)
-			kmem_free((char *)nd->nd_tbl, nd->nd_size);
-		kmem_free((char *)nd, sizeof (ND));
+			kmem_free(nd->nd_tbl, nd->nd_size);
+		kmem_free(nd, sizeof (ND));
 		*nd_pparam = NULL;
 	}
 }
@@ -7603,8 +4608,8 @@
 	if (!nd_param)
 		return (B_FALSE);
 
-	nd = (ND *)nd_param;
-	iocp = (IOCP)mp->b_rptr;
+	nd = (void *)nd_param;
+	iocp = (void *)mp->b_rptr;
 	if ((iocp->ioc_count == 0) || !(mp1 = mp->b_cont)) {
 		mp->b_datap->db_type = M_IOCACK;
 		iocp->ioc_count = 0;
@@ -7648,7 +4653,7 @@
 	 * bad or not given.
 	 */
 		if (valp)
-			avail = eri_strtol(valp, (char **)0, 10);
+			(void) ddi_strtol(valp, NULL, 10, (long *)&avail);
 		/* We overwrite the name/value with the reply data */
 		{
 			mblk_t *mp2 = mp1;
@@ -7672,11 +4677,11 @@
 				size_out = msgdsize(mp1);
 				excess = size_out - avail;
 				if (excess > 0) {
-					iocp->ioc_rval = size_out;
+					iocp->ioc_rval = (unsigned)size_out;
 					size_out -= excess;
 					(void) adjmsg(mp1, -(excess + 1));
 					err = eri_mk_mblk_tail_space(mp1,
-						&nmp, 1);
+					    &nmp, 1);
 					if (!err)
 						*nmp->b_wptr++ = '\0';
 					else
@@ -7692,23 +4697,15 @@
 
 	case ND_SET:
 		if (valp) {
-			if ((iocp->ioc_cr != NULL) &&
-			    ((err = secpolicy_net_config(iocp->ioc_cr, B_FALSE))
-			    == 0)) {
-				err = (*nde->nde_set_pfi)(q, mp1, valp,
-				    nde->nde_data, iocp->ioc_cr);
-			}
+			err = (*nde->nde_set_pfi)(q, mp1, valp,
+			    nde->nde_data, iocp->ioc_cr);
 			iocp->ioc_count = 0;
 			freemsg(mp1);
 			mp->b_cont = NULL;
 		}
 		break;
-
-	default:
-		ERI_DEBUG_MSG1(NULL, DEFAULT_MSG,
-		    "nd_getset: cmd is default");
-		break;
 	}
+
 	iocp->ioc_error = err;
 	mp->b_datap->db_type = M_IOCACK;
 	return (B_TRUE);
@@ -7731,7 +4728,7 @@
 	if (!nd_pparam)
 		return (B_FALSE);
 
-	if ((nd = (ND *)(*nd_pparam)) == NULL) {
+	if ((nd = (void *)(*nd_pparam)) == NULL) {
 		if ((nd = (ND *)kmem_zalloc(sizeof (ND), KM_NOSLEEP))
 		    == NULL)
 			return (B_FALSE);
@@ -7778,15 +4775,10 @@
  * New Section
  */
 #ifdef  DEBUG
-/*VARARGS*/
-/* ARGSUSED */
+/*PRINTFLIKE5*/
 static void
-eri_debug_msg(
-	char *file,
-	int line,
-	struct eri *erip,
-	debug_msg_t type,
-	char *fmt, ...)
+eri_debug_msg(const char *file, int line, struct eri *erip,
+	debug_msg_t type, const char *fmt, ...)
 {
 	char	msg_buffer[255];
 	va_list ap;
@@ -7811,16 +4803,16 @@
 
 	if (eri_msg_out & ERI_CON_MSG) {
 		if (((type <= eri_debug_level) && eri_debug_all) ||
-			((type == eri_debug_level) && !eri_debug_all)) {
+		    ((type == eri_debug_level) && !eri_debug_all)) {
 			if (erip)
-				cmn_err(CE_CONT, "D: %s %s(%d):(%s%d) %s\n",
-					debug_msg_string[type], file, line,
-					DEVICE_NAME(erip->dip), erip->instance,
-					msg_buffer);
+				cmn_err(CE_CONT, "D: %s %s%d:(%s%d) %s\n",
+				    debug_msg_string[type], file, line,
+				    ddi_driver_name(erip->dip), erip->instance,
+				    msg_buffer);
 			else
 				cmn_err(CE_CONT, "D: %s %s(%d): %s\n",
-					debug_msg_string[type], file,
-					line, msg_buffer);
+				    debug_msg_string[type], file,
+				    line, msg_buffer);
 		}
 	}
 	mutex_exit(&eridebuglock);
@@ -7828,51 +4820,45 @@
 #endif
 
 
-/* VARARGS  */
-/* ARGSUSED */
+/*PRINTFLIKE4*/
 static void
-eri_fault_msg(char *file, uint_t line, struct eri *erip, uint_t severity,
-		msg_t type, char *fmt, ...)
+eri_fault_msg(struct eri *erip, uint_t severity, msg_t type,
+	const char *fmt, ...)
 {
 	char	msg_buffer[255];
 	va_list	ap;
 
-	mutex_enter(&erilock);
-
 	va_start(ap, fmt);
 	(void) vsprintf(msg_buffer, fmt, ap);
 	va_end(ap);
 
 	if (erip == NULL) {
 		cmn_err(CE_NOTE, "eri : %s", msg_buffer);
-		mutex_exit(&erilock);
 		return;
 	}
 
 	if (severity == SEVERITY_HIGH) {
-		cmn_err(CE_WARN, "%s%d : %s", DEVICE_NAME(erip->dip),
+		cmn_err(CE_WARN, "%s%d : %s", ddi_driver_name(erip->dip),
 		    erip->instance, msg_buffer);
 	} else switch (type) {
 	case ERI_VERB_MSG:
-		cmn_err(CE_CONT, "?%s%d : %s", DEVICE_NAME(erip->dip),
+		cmn_err(CE_CONT, "?%s%d : %s", ddi_driver_name(erip->dip),
 		    erip->instance, msg_buffer);
 		break;
 	case ERI_LOG_MSG:
-		cmn_err(CE_NOTE, "^%s%d : %s", DEVICE_NAME(erip->dip),
+		cmn_err(CE_NOTE, "^%s%d : %s", ddi_driver_name(erip->dip),
 		    erip->instance, msg_buffer);
 		break;
 	case ERI_BUF_MSG:
-		cmn_err(CE_NOTE, "!%s%d : %s", DEVICE_NAME(erip->dip),
+		cmn_err(CE_NOTE, "!%s%d : %s", ddi_driver_name(erip->dip),
 		    erip->instance, msg_buffer);
 		break;
 	case ERI_CON_MSG:
-		cmn_err(CE_CONT, "%s%d : %s", DEVICE_NAME(erip->dip),
+		cmn_err(CE_CONT, "%s%d : %s", ddi_driver_name(erip->dip),
 		    erip->instance, msg_buffer);
 	default:
 		break;
 	}
-
-	mutex_exit(&erilock);
 }
 
 /*
@@ -7888,7 +4874,6 @@
 eri_stop_timer(struct eri *erip)
 {
 	timeout_id_t id;
-	ERI_DEBUG_MSG1(erip, XCVR_MSG, "stop timer");
 	mutex_enter(&erip->linklock);
 	if (erip->timerid) {
 		erip->flags |= ERI_NOTIMEOUTS; /* prevent multiple timeout */
@@ -7908,13 +4893,11 @@
 static void
 eri_start_timer(struct eri *erip, fptrv_t func, clock_t msec)
 {
-	ERI_DEBUG_MSG1(erip, XCVR_MSG, "start timer");
-
 	if (msec) {
 		if (!(erip->flags & ERI_NOTIMEOUTS) &&
-			(erip->flags & ERI_RUNNING)) {
-				erip->timerid = timeout(func, (caddr_t)erip,
-					drv_usectohz(1000*msec));
+		    (erip->flags & ERI_RUNNING)) {
+			erip->timerid = timeout(func, (caddr_t)erip,
+			    drv_usectohz(1000*msec));
 		}
 	}
 
@@ -7934,8 +4917,7 @@
 
 	status = B_FALSE;			/* no change */
 	cfg = GET_MIFREG(mif_cfg);
-	ERI_DEBUG_MSG2(erip, MIF_MSG,
-			"cfg value = %X", cfg);
+	ERI_DEBUG_MSG2(erip, MIF_MSG, "cfg value = %X", cfg);
 	old_transceiver = param_transceiver;
 
 	if ((cfg & ERI_MIF_CFGM1) && !use_int_xcvr) {
@@ -7952,8 +4934,8 @@
 			 */
 			if (old_transceiver == INTERNAL_XCVR) {
 				eri_mii_write(erip, ERI_PHY_BMCR,
-					(PHY_BMCR_ISOLATE | PHY_BMCR_PWRDN |
-					PHY_BMCR_LPBK));
+				    (PHY_BMCR_ISOLATE | PHY_BMCR_PWRDN |
+				    PHY_BMCR_LPBK));
 			}
 			status = B_TRUE;
 		}
@@ -7982,10 +4964,10 @@
 			 * transceiver state.
 			 */
 			if ((old_transceiver == EXTERNAL_XCVR) &&
-				(cfg & ERI_MIF_CFGM0)) {
+			    (cfg & ERI_MIF_CFGM0)) {
 				eri_mii_write(erip, ERI_PHY_BMCR,
-					(PHY_BMCR_ISOLATE | PHY_BMCR_PWRDN |
-					PHY_BMCR_LPBK));
+				    (PHY_BMCR_ISOLATE | PHY_BMCR_PWRDN |
+				    PHY_BMCR_LPBK));
 			}
 			status = B_TRUE;
 		}
@@ -8005,10 +4987,10 @@
 		/*
 		 * Did not find a valid xcvr.
 		 */
-	    ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-		"Eri_new_xcvr : Select None");
-	    param_transceiver = NO_XCVR;
-	    erip->xcvr_status = PHY_LINK_DOWN;
+		ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
+		    "Eri_new_xcvr : Select None");
+		param_transceiver = NO_XCVR;
+		erip->xcvr_status = PHY_LINK_DOWN;
 	}
 
 	if (erip->stats.pmcap == ERI_PMCAP_NONE) {
@@ -8026,7 +5008,10 @@
 static void
 eri_check_link(struct eri *erip)
 {
-	eri_send_notifications(erip, eri_check_link_noind(erip));
+	link_state_t	linkupdate = eri_check_link_noind(erip);
+
+	if (linkupdate != LINK_STATE_UNKNOWN)
+		mac_link_update(erip->mh, linkupdate);
 }
 
 /*
@@ -8043,9 +5028,8 @@
 {
 	uint16_t stat, control, mif_ints;
 	uint32_t link_timeout	= ERI_LINKCHECK_TIMER;
-	uint32_t linkflags = 0;
-
-	ERI_DEBUG_MSG1(erip, XCVR_MSG, "eri_check_link_enter");
+	uint32_t linkupdate = 0;
+
 	eri_stop_timer(erip);	/* acquire linklock */
 
 	mutex_enter(&erip->xmitlock);
@@ -8058,35 +5042,35 @@
 	if (erip->openloop_autoneg) {
 		(void) eri_mii_read(erip, ERI_PHY_BMSR, &stat);
 		ERI_DEBUG_MSG3(erip, XCVR_MSG,
-			"eri_check_link:openloop stat %X mii_status %X",
-			stat, erip->mii_status);
+		    "eri_check_link:openloop stat %X mii_status %X",
+		    stat, erip->mii_status);
 		(void) eri_mii_read(erip, ERI_PHY_BMCR, &control);
 		if (!(stat & PHY_BMSR_LNKSTS) &&
-			(erip->openloop_autoneg < 2)) {
+		    (erip->openloop_autoneg < 2)) {
 			if (param_speed) {
 				control &= ~PHY_BMCR_100M;
 				param_anlpar_100hdx = 0;
 				param_anlpar_10hdx = 1;
 				param_speed = 0;
-				erip->stats.ifspeed = SPEED_10;
+				erip->stats.ifspeed = 10;
 
 			} else {
 				control |= PHY_BMCR_100M;
 				param_anlpar_100hdx = 1;
 				param_anlpar_10hdx = 0;
 				param_speed = 1;
-				erip->stats.ifspeed = SPEED_100;
+				erip->stats.ifspeed = 100;
 			}
 			ERI_DEBUG_MSG3(erip, XCVR_MSG,
-				"eri_check_link: trying speed %X stat %X",
-					param_speed, stat);
+			    "eri_check_link: trying speed %X stat %X",
+			    param_speed, stat);
 
 			erip->openloop_autoneg ++;
 			eri_mii_write(erip, ERI_PHY_BMCR, control);
 			link_timeout = ERI_P_FAULT_TIMER;
 		} else {
 			erip->openloop_autoneg = 0;
-			linkflags = eri_mif_check(erip, stat, stat);
+			linkupdate = eri_mif_check(erip, stat, stat);
 			if (erip->openloop_autoneg)
 				link_timeout = ERI_P_FAULT_TIMER;
 		}
@@ -8095,10 +5079,10 @@
 		mutex_exit(&erip->xmitlock);
 
 		eri_start_timer(erip, eri_check_link, link_timeout);
-		return (linkflags);
+		return (linkupdate);
 	}
 
-	linkflags = eri_mif_check(erip, mif_ints, stat);
+	linkupdate = eri_mif_check(erip, mif_ints, stat);
 	eri_mif_poll(erip, MIF_POLL_START);
 	mutex_exit(&erip->xcvrlock);
 	mutex_exit(&erip->xmitlock);
@@ -8125,7 +5109,7 @@
 
 			eri_start_timer(erip, eri_check_link,
 			    ERI_CHECK_HANG_TIMER);
-			return (linkflags);
+			return (linkupdate);
 		}
 
 		if (erip->check2_rmac_hang) {
@@ -8157,7 +5141,7 @@
 				eri_start_timer(erip, eri_check_link,
 				    ERI_LINKCHECK_TIMER);
 				(void) eri_init(erip);
-				return (linkflags);
+				return (linkupdate);
 			}
 		}
 	}
@@ -8167,19 +5151,14 @@
 	 * Check if tx hung.
 	 */
 #ifdef	ERI_TX_HUNG
-	if ((erip->flags & ERI_RUNNING) &&
-		param_linkup && (eri_check_txhung(erip))) {
+	if ((erip->flags & ERI_RUNNING) && param_linkup &&
+	    (eri_check_txhung(erip))) {
 		HSTAT(erip, tx_hang);
 		eri_reinit_txhung++;
-#ifdef	LATER_SPLIT_TX_RX
-		mutex_enter(&erip->xmitlock);
-		eri_init_tx(erip);
-		mutex_exit(&erip->xmitlock);
-#endif
 		erip->linkcheck = 1;
 		eri_start_timer(erip, eri_check_link, ERI_CHECK_HANG_TIMER);
 		(void) eri_init(erip);
-		return (linkflags);
+		return (linkupdate);
 	}
 #endif
 
@@ -8197,20 +5176,19 @@
 		eri_start_timer(erip, eri_check_link, ERI_CHECK_HANG_TIMER);
 	else
 		eri_start_timer(erip, eri_check_link, ERI_LINKCHECK_TIMER);
-	return (linkflags);
+	return (linkupdate);
 }
 
-static uint32_t
+static link_state_t
 eri_mif_check(struct eri *erip, uint16_t mif_ints, uint16_t mif_data)
 {
 	uint16_t control, aner, anlpar, anar, an_common;
 	uint16_t old_mintrans;
 	int restart_autoneg = 0;
-	uint32_t retv;
-
-	ERI_DEBUG_MSG4(erip, XCVR_MSG,
-		"eri_mif_check: mif_mask: %X, %X, %X",
-		erip->mif_mask, mif_ints, mif_data);
+	link_state_t retv;
+
+	ERI_DEBUG_MSG4(erip, XCVR_MSG, "eri_mif_check: mif_mask: %X, %X, %X",
+	    erip->mif_mask, mif_ints, mif_data);
 
 	mif_ints &= ~erip->mif_mask;
 	erip->mii_status = mif_data;
@@ -8220,9 +5198,9 @@
 	 * If so try to find out what the new xcvr setup is.
 	 */
 	if (((mif_ints & PHY_BMSR_RES1) && (mif_data == 0xFFFF)) ||
-			(param_transceiver == NO_XCVR)) {
+	    (param_transceiver == NO_XCVR)) {
 		ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-				"No status transceiver gone");
+		    "No status transceiver gone");
 		if (eri_new_xcvr(erip)) {
 			if (param_transceiver != NO_XCVR) {
 				/*
@@ -8231,20 +5209,19 @@
 				(void) eri_reset_xcvr(erip);
 			}
 		}
-		return (0);
+		return (LINK_STATE_UNKNOWN);
 	}
 
 	if (param_autoneg && (mif_ints & PHY_BMSR_LNKSTS) &&
-		(mif_data & PHY_BMSR_LNKSTS) && (mif_data & PHY_BMSR_ANC)) {
+	    (mif_data & PHY_BMSR_LNKSTS) && (mif_data & PHY_BMSR_ANC)) {
 		mif_ints |= PHY_BMSR_ANC;
 		ERI_DEBUG_MSG3(erip, PHY_MSG,
-			"eri_mif_check: Set ANC bit mif_data %X mig_ints %X",
-			mif_data, mif_ints);
+		    "eri_mif_check: Set ANC bit mif_data %X mig_ints %X",
+		    mif_data, mif_ints);
 	}
 
 	if ((mif_ints & PHY_BMSR_ANC) && (mif_data & PHY_BMSR_ANC)) {
-		ERI_DEBUG_MSG1(erip, PHY_MSG,
-				"Auto-negotiation interrupt.");
+		ERI_DEBUG_MSG1(erip, PHY_MSG, "Auto-negotiation interrupt.");
 
 		/*
 		 * Switch off Auto-negotiation interrupts and switch on
@@ -8256,34 +5233,33 @@
 		param_aner_lpancap = 1 && (aner & PHY_ANER_LPNW);
 		if ((aner & PHY_ANER_MLF) || (eri_force_mlf)) {
 			ERI_DEBUG_MSG1(erip, XCVR_MSG,
-					"parallel detection fault");
+			    "parallel detection fault");
 			/*
 			 * Consider doing open loop auto-negotiation.
 			 */
 			ERI_DEBUG_MSG1(erip, XCVR_MSG,
-					"Going into Open loop Auto-neg");
+			    "Going into Open loop Auto-neg");
 			(void) eri_mii_read(erip, ERI_PHY_BMCR, &control);
 
 			control &= ~(PHY_BMCR_ANE | PHY_BMCR_RAN |
-					PHY_BMCR_FDX);
+			    PHY_BMCR_FDX);
 			if (param_anar_100fdx || param_anar_100hdx) {
 				control |= PHY_BMCR_100M;
 				param_anlpar_100hdx = 1;
 				param_anlpar_10hdx = 0;
 				param_speed = 1;
-				erip->stats.ifspeed = SPEED_100;
-
-			} else if (param_anar_10fdx ||
-					param_anar_10hdx) {
-					control &= ~PHY_BMCR_100M;
-					param_anlpar_100hdx = 0;
-					param_anlpar_10hdx = 1;
-					param_speed = 0;
-					erip->stats.ifspeed = SPEED_10;
+				erip->stats.ifspeed = 100;
+
+			} else if (param_anar_10fdx || param_anar_10hdx) {
+				control &= ~PHY_BMCR_100M;
+				param_anlpar_100hdx = 0;
+				param_anlpar_10hdx = 1;
+				param_speed = 0;
+				erip->stats.ifspeed = 10;
 			} else {
 				ERI_FAULT_MSG1(erip, SEVERITY_NONE,
-					ERI_VERB_MSG,
-					"Transceiver speed set incorrectly.");
+				    ERI_VERB_MSG,
+				    "Transceiver speed set incorrectly.");
 				return (0);
 			}
 
@@ -8298,25 +5274,23 @@
 		(void) eri_mii_read(erip, ERI_PHY_ANAR, &anar);
 		an_common = anar & anlpar;
 
-		ERI_DEBUG_MSG2(erip, XCVR_MSG,
-				"an_common = 0x%X", an_common);
+		ERI_DEBUG_MSG2(erip, XCVR_MSG, "an_common = 0x%X", an_common);
 
 		if (an_common & (PHY_ANLPAR_TXFDX | PHY_ANLPAR_TX)) {
 			param_speed = 1;
-			erip->stats.ifspeed = SPEED_100;
+			erip->stats.ifspeed = 100;
 			param_mode = 1 && (an_common & PHY_ANLPAR_TXFDX);
 
 		} else if (an_common & (PHY_ANLPAR_10FDX | PHY_ANLPAR_10)) {
 			param_speed = 0;
-			erip->stats.ifspeed = SPEED_10;
+			erip->stats.ifspeed = 10;
 			param_mode = 1 && (an_common & PHY_ANLPAR_10FDX);
 
 		} else an_common = 0x0;
 
 		if (!an_common) {
 			ERI_FAULT_MSG1(erip, SEVERITY_MID, ERI_VERB_MSG,
-					"Transceiver: anar"
-					" not set with speed selection");
+			    "Transceiver: anar not set with speed selection");
 		}
 		param_anlpar_100T4 = 1 && (anlpar & PHY_ANLPAR_T4);
 		param_anlpar_100fdx = 1 && (anlpar & PHY_ANLPAR_TXFDX);
@@ -8325,13 +5299,13 @@
 		param_anlpar_10hdx = 1 && (anlpar & PHY_ANLPAR_10);
 
 		ERI_DEBUG_MSG2(erip, PHY_MSG,
-				"Link duplex = 0x%X", param_mode);
+		    "Link duplex = 0x%X", param_mode);
 		ERI_DEBUG_MSG2(erip, PHY_MSG,
-				"Link speed = 0x%X", param_speed);
+		    "Link speed = 0x%X", param_speed);
 	/*	mif_ints |= PHY_BMSR_LNKSTS; prevent double msg */
 	/*	mif_data |= PHY_BMSR_LNKSTS; prevent double msg */
 	}
-	retv = 0;
+	retv = LINK_STATE_UNKNOWN;
 	if (mif_ints & PHY_BMSR_LNKSTS) {
 		if (mif_data & PHY_BMSR_LNKSTS) {
 			ERI_DEBUG_MSG1(erip, PHY_MSG, "Link Up");
@@ -8349,21 +5323,19 @@
 			 */
 			eri_init_txmac(erip);
 			param_linkup = 1;
-			erip->stats.link_up = ERI_LINK_UP;
+			erip->stats.link_up = LINK_STATE_UP;
 			if (param_mode)
-				erip->stats.link_duplex = ERI_FULL_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_FULL;
 			else
-				erip->stats.link_duplex = ERI_HALF_DUPLEX;
-
-			retv = DL_NOTE_LINK_UP;
-			eri_display_link_status(erip);
+				erip->stats.link_duplex = LINK_DUPLEX_HALF;
+
+			retv = LINK_STATE_UP;
 		} else {
-			ERI_DEBUG_MSG1(erip, PHY_MSG,
-					"Link down.");
+			ERI_DEBUG_MSG1(erip, PHY_MSG, "Link down.");
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-			retv = DL_NOTE_LINK_DOWN;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
+			retv = LINK_STATE_DOWN;
 			if (param_autoneg) {
 				restart_autoneg = 1;
 			}
@@ -8372,14 +5344,14 @@
 		if (mif_data & PHY_BMSR_LNKSTS) {
 			if (!param_linkup) {
 				ERI_DEBUG_MSG1(erip, PHY_MSG,
-					"eri_mif_check: MIF data link up");
+				    "eri_mif_check: MIF data link up");
 				/*
 				 * Program Lu3X31T for minimum transition
 				 */
 				if (eri_phy_mintrans) {
 					eri_mii_write(erip, 31, 0x8000);
 					(void) eri_mii_read(erip, 0,
-						&old_mintrans);
+					    &old_mintrans);
 					eri_mii_write(erip, 0, 0x00F1);
 					eri_mii_write(erip, 31, 0x0000);
 				}
@@ -8389,27 +5361,26 @@
 				eri_init_txmac(erip);
 
 				param_linkup = 1;
-				erip->stats.link_up = ERI_LINK_UP;
+				erip->stats.link_up = LINK_STATE_UP;
 				if (param_mode)
 					erip->stats.link_duplex =
-					    ERI_FULL_DUPLEX;
+					    LINK_DUPLEX_FULL;
 				else
 					erip->stats.link_duplex =
-					    ERI_HALF_DUPLEX;
-
-				retv = DL_NOTE_LINK_UP;
-				eri_display_link_status(erip);
+					    LINK_DUPLEX_HALF;
+
+				retv = LINK_STATE_UP;
 			}
 		} else if (param_linkup) {
 			/*
 			 * The link is down now.
 			 */
 			ERI_DEBUG_MSG1(erip, PHY_MSG,
-				"eri_mif_check:Link was up and went down");
+			    "eri_mif_check:Link was up and went down");
 			param_linkup = 0;
-			erip->stats.link_up = ERI_LINK_DOWN;
-			erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-			retv = DL_NOTE_LINK_DOWN;
+			erip->stats.link_up = LINK_STATE_DOWN;
+			erip->stats.link_duplex = LINK_DUPLEX_UNKNOWN;
+			retv = LINK_STATE_DOWN;
 			if (param_autoneg)
 				restart_autoneg = 1;
 		}
@@ -8419,7 +5390,7 @@
 		 * Restart normal auto-negotiation.
 		 */
 		ERI_DEBUG_MSG1(erip, PHY_MSG,
-			"eri_mif_check:Restart AUto Negotiation");
+		    "eri_mif_check:Restart AUto Negotiation");
 		erip->openloop_autoneg = 0;
 		param_mode = 0;
 		param_speed = 0;
@@ -8429,24 +5400,19 @@
 		param_anlpar_10fdx = 0;
 		param_anlpar_10hdx = 0;
 		param_aner_lpancap = 0;
-		(void) eri_mii_read(erip, ERI_PHY_BMCR,
-				    &control);
+		(void) eri_mii_read(erip, ERI_PHY_BMCR, &control);
 		control |= (PHY_BMCR_ANE | PHY_BMCR_RAN);
 		eri_mii_write(erip, ERI_PHY_BMCR, control);
 	}
 	if (mif_ints & PHY_BMSR_JABDET) {
 		if (mif_data & PHY_BMSR_JABDET) {
-			ERI_DEBUG_MSG1(erip, PHY_MSG,
-					"Jabber detected.");
+			ERI_DEBUG_MSG1(erip, PHY_MSG, "Jabber detected.");
 			HSTAT(erip, jab);
 			/*
 			 * Reset the new PHY and bring up the link
+			 * (Check for failure?)
 			 */
 			(void) eri_reset_xcvr(erip);
-				/*
-				 * eri_FAULT_MSG1(erip, SEVERITY_NONE, XCVR_MSG,
-				 * 		"Unable to reset transceiver.");
-				 */
 		}
 	}
 	return (retv);
@@ -8467,8 +5433,8 @@
 	int n;
 
 	ERI_DEBUG_MSG4(erip, XCVR_MSG,
-		"eri_reset_xcvr:ifspeed %X param_speed %X mif_mask %X",
-		erip->stats.ifspeed, param_speed, erip->mif_mask);
+	    "eri_reset_xcvr:ifspeed %X param_speed %X mif_mask %X",
+	    erip->stats.ifspeed, param_speed, erip->mif_mask);
 
 #ifdef	ERI_10_10_FORCE_SPEED_WORKAROUND
 	erip->ifspeed_old = erip->stats.ifspeed;
@@ -8494,21 +5460,20 @@
 		if (eri_mii_read(erip, ERI_PHY_BMCR, &control) == 1) {
 			/* Transceiver does not talk MII */
 			ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-				"eri_reset_xcvr: no mii");
+			    "eri_reset_xcvr: no mii");
 		}
 		if ((control & PHY_BMCR_RESET) == 0)
 			goto reset_done;
 	}
 	ERI_FAULT_MSG2(erip, SEVERITY_NONE, ERI_VERB_MSG,
-		"eri_reset_xcvr:reset_failed n == 0, control %x",
-		control);
+	    "eri_reset_xcvr:reset_failed n == 0, control %x", control);
 	goto eri_reset_xcvr_failed;
 
 reset_done:
 
 	ERI_DEBUG_MSG2(erip, AUTOCONFIG_MSG,
-		"eri_reset_xcvr: reset complete in %d us",
-		(1000 - n) * PHYRST_PERIOD);
+	    "eri_reset_xcvr: reset complete in %d us",
+	    (1000 - n) * PHYRST_PERIOD);
 
 	(void) eri_mii_read(erip, ERI_PHY_BMSR, &stat);
 	(void) eri_mii_read(erip, ERI_PHY_ANAR, &anar);
@@ -8516,8 +5481,7 @@
 	(void) eri_mii_read(erip, ERI_PHY_IDR2, &idr2);
 
 	ERI_DEBUG_MSG4(erip, XCVR_MSG,
-		"eri_reset_xcvr: control %x stat %x anar %x",
-		control, stat, anar);
+	    "eri_reset_xcvr: control %x stat %x anar %x", control, stat, anar);
 
 	/*
 	 * Initialize the read only transceiver ndd information
@@ -8543,8 +5507,6 @@
 	 * Select the operation mode of the transceiver.
 	 */
 	if (param_autoneg) {
-		ERI_DEBUG_MSG1(erip, PHY_MSG,
-			"Phy Supports Auto-negotiation.");
 		/*
 		 * Initialize our auto-negotiation capabilities.
 		 */
@@ -8559,19 +5521,15 @@
 			anar |= PHY_ANAR_10FDX;
 		if (param_anar_10hdx)
 			anar |= PHY_ANAR_10;
-		ERI_DEBUG_MSG2(erip, XCVR_MSG,
-				"anar = %x", anar);
+		ERI_DEBUG_MSG2(erip, XCVR_MSG, "anar = %x", anar);
 		eri_mii_write(erip, ERI_PHY_ANAR, anar);
-	} else {
-		ERI_DEBUG_MSG1(erip, PHY_MSG,
-			"Phy Doesn't support Auto-negotiation.");
 	}
 
 	/* Place the Transceiver in normal operation mode */
 	if ((control & PHY_BMCR_ISOLATE) || (control & PHY_BMCR_LPBK)) {
 		control &= ~(PHY_BMCR_ISOLATE | PHY_BMCR_LPBK);
 		eri_mii_write(erip, ERI_PHY_BMCR,
-				(control & ~PHY_BMCR_ISOLATE));
+		    (control & ~PHY_BMCR_ISOLATE));
 	}
 
 	/*
@@ -8594,12 +5552,11 @@
 	speed_10 = param_anar_10fdx | param_anar_10hdx;
 
 	ERI_DEBUG_MSG5(erip, XCVR_MSG, "eri_reset_xcvr: %d %d %d %d",
-		param_anar_100fdx, param_anar_100hdx, param_anar_10fdx,
-		param_anar_10hdx);
+	    param_anar_100fdx, param_anar_100hdx, param_anar_10fdx,
+	    param_anar_10hdx);
 
 	ERI_DEBUG_MSG3(erip, XCVR_MSG,
-		"eri_reset_xcvr: speed_100 %d speed_10 %d",
-		speed_100, speed_10);
+	    "eri_reset_xcvr: speed_100 %d speed_10 %d", speed_100, speed_10);
 
 	if ((!speed_100) && (speed_10)) {
 		erip->mif_mask &= ~PHY_BMSR_JABDET;
@@ -8612,13 +5569,11 @@
 			nicr &= ~PHY_NICR_LD;
 			eri_mii_write(erip, ERI_PHY_NICR, nicr);
 			param_linkup = 1;
-			erip->stats.link_up = ERI_LINK_UP;
+			erip->stats.link_up = LINK_STATE_UP;
 			if (param_mode)
-				erip->stats.link_duplex = ERI_FULL_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_FULL;
 			else
-				erip->stats.link_duplex = ERI_HALF_DUPLEX;
-
-			eri_display_link_status(erip);
+				erip->stats.link_duplex = LINK_DUPLEX_HALF;
 		}
 	}
 
@@ -8631,8 +5586,6 @@
 		/*
 		 * Setup the transceiver for autonegotiation.
 		 */
-		ERI_DEBUG_MSG1(erip, PHY_MSG,
-				"Setup for Auto-negotiation");
 		erip->mif_mask &= ~PHY_BMSR_ANC;
 
 		/*
@@ -8650,8 +5603,6 @@
 		/*
 		 * Force the transceiver.
 		 */
-		ERI_DEBUG_MSG1(erip, PHY_MSG,
-				"Setup for forced mode");
 		erip->mif_mask &= ~PHY_BMSR_LNKSTS;
 
 		/*
@@ -8668,13 +5619,13 @@
 			param_anlpar_100fdx = param_anar_100fdx;
 			param_anlpar_100hdx = param_anar_100hdx;
 			param_speed = 1;
-			erip->stats.ifspeed = SPEED_100;
+			erip->stats.ifspeed = 100;
 			param_mode = param_anar_100fdx;
 			if (param_mode) {
 				param_anlpar_100hdx = 0;
-				erip->stats.link_duplex = ERI_FULL_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_FULL;
 			} else {
-				erip->stats.link_duplex = ERI_HALF_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_HALF;
 			}
 		} else if (speed_10) {
 			control &= ~PHY_BMCR_100M;
@@ -8685,17 +5636,17 @@
 			param_anlpar_10fdx = param_anar_10fdx;
 			param_anlpar_10hdx = param_anar_10hdx;
 			param_speed = 0;
-			erip->stats.ifspeed = SPEED_10;
+			erip->stats.ifspeed = 10;
 			param_mode = param_anar_10fdx;
 			if (param_mode) {
 				param_anlpar_10hdx = 0;
-				erip->stats.link_duplex = ERI_FULL_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_FULL;
 			} else {
-				erip->stats.link_duplex = ERI_HALF_DUPLEX;
+				erip->stats.link_duplex = LINK_DUPLEX_HALF;
 			}
 		} else {
 			ERI_FAULT_MSG1(erip, SEVERITY_NONE, ERI_VERB_MSG,
-					"Transceiver speed set incorrectly.");
+			    "Transceiver speed set incorrectly.");
 		}
 
 		if (param_mode) {
@@ -8703,8 +5654,8 @@
 		}
 
 		ERI_DEBUG_MSG4(erip, PHY_MSG,
-			"control = %x status = %x param_mode %d",
-			control, stat, param_mode);
+		    "control = %x status = %x param_mode %d",
+		    control, stat, param_mode);
 
 		eri_mii_write(erip, ERI_PHY_BMCR, control);
 /*
@@ -8722,7 +5673,7 @@
 	(void) eri_mii_read(erip, ERI_PHY_ANAR, &anar);
 #endif
 	ERI_DEBUG_MSG4(erip, PHY_MSG,
-		"control %X status %X anar %X", control, stat, anar);
+	    "control %X status %X anar %X", control, stat, anar);
 
 eri_reset_xcvr_exit:
 	return (0);
@@ -8737,16 +5688,14 @@
 eri_xcvr_force_mode(struct eri *erip, uint32_t *link_timeout)
 {
 
-	if (!param_autoneg && !param_linkup &&
-		(erip->stats.ifspeed == SPEED_10) &&
-		(param_anar_10fdx | param_anar_10hdx)) {
+	if (!param_autoneg && !param_linkup && (erip->stats.ifspeed == 10) &&
+	    (param_anar_10fdx | param_anar_10hdx)) {
 		*link_timeout = SECOND(1);
 		return;
 	}
 
-	if (!param_autoneg && !param_linkup &&
-		(erip->ifspeed_old == SPEED_10) &&
-		(param_anar_100fdx | param_anar_100hdx)) {
+	if (!param_autoneg && !param_linkup && (erip->ifspeed_old == 10) &&
+	    (param_anar_100fdx | param_anar_100hdx)) {
 		/*
 		 * May have to set link partner's speed and mode.
 		 */
@@ -8757,186 +5706,47 @@
 #endif
 
 static void
-eri_display_link_status(struct eri *erip)
-{
-	char link_up_msg[64];
-
-	ERI_DEBUG_MSG3(erip, PHY_MSG,
-		"eri_display_link_status: ifspeed %X param_mode %d",
-		erip->stats.ifspeed, param_mode);
-	switch (erip->stats.ifspeed) {
-	case SPEED_100:
-		(void) sprintf(link_up_msg, "100 Mbps ");
-		break;
-	case SPEED_10:
-		(void) sprintf(link_up_msg, "10 Mbps ");
-		break;
-	default:
-		link_up_msg[0] = '\0';
-	}
-
-	if (param_mode)
-		(void) strcat(link_up_msg, "full duplex link up");
-	else
-		(void) strcat(link_up_msg, "half duplex link up");
-
-	ERI_FAULT_MSG2(erip, SEVERITY_NONE, ERI_CON_MSG, "%s\n", link_up_msg);
-
-	erip->linksts_msg = ERI_VERB_MSG;
-	HSTAT(erip, tnocar);
-}
-
-static void
 eri_mif_poll(struct eri *erip, soft_mif_enable_t enable)
 {
 	if (enable == MIF_POLL_START) {
-		if (erip->mifpoll_enable &&
-			!erip->openloop_autoneg) {
-			ERI_DEBUG_MSG1(erip, XCVR_MSG,
-				"Starting mif poll: normal start");
+		if (erip->mifpoll_enable && !erip->openloop_autoneg) {
 			erip->mif_config |= ERI_MIF_CFGPE;
 			PUT_MIFREG(mif_cfg, erip->mif_config);
 			drv_usecwait(ERI_MIF_POLL_DELAY);
 			PUT_GLOBREG(intmask, GET_GLOBREG(intmask) &
-				~ERI_G_MASK_MIF_INT);
+			    ~ERI_G_MASK_MIF_INT);
 			PUT_MIFREG(mif_imask, erip->mif_mask);
-		} else {
-			ERI_DEBUG_MSG1(erip, XCVR_MSG,
-				"Starting mif poll:fault start");
 		}
 	} else if (enable == MIF_POLL_STOP) {
-			ERI_DEBUG_MSG1(erip, XCVR_MSG,
-				"Stopping mif poll");
 			erip->mif_config &= ~ERI_MIF_CFGPE;
 			PUT_MIFREG(mif_cfg, erip->mif_config);
 			drv_usecwait(ERI_MIF_POLL_DELAY);
 			PUT_GLOBREG(intmask, GET_GLOBREG(intmask) |
-				ERI_G_MASK_MIF_INT);
+			    ERI_G_MASK_MIF_INT);
 			PUT_MIFREG(mif_imask, ERI_MIF_INTMASK);
 	}
 	ERI_DEBUG_MSG2(erip, XCVR_MSG, "MIF Config = 0x%X",
-			GET_MIFREG(mif_cfg));
+	    GET_MIFREG(mif_cfg));
 	ERI_DEBUG_MSG2(erip, XCVR_MSG, "MIF imask = 0x%X",
-			GET_MIFREG(mif_imask));
+	    GET_MIFREG(mif_imask));
 	ERI_DEBUG_MSG2(erip, XCVR_MSG, "INT imask = 0x%X",
-			GET_GLOBREG(intmask));
+	    GET_GLOBREG(intmask));
 	ERI_DEBUG_MSG1(erip, XCVR_MSG, "<== mif_poll");
 }
 
-/*
- * This function is cut&pasted from mi.c, part of IP source base.
- * By defining this function in eri, we remove dependency from ip module.
- * This function can be removed once kernel level 'strtol' becomes available.
- */
-static long
-eri_strtol(char *str, char **ptr, int base)
-{
-	char *cp;
-	int digits;
-	long value;
-	boolean_t is_negative;
-
-	cp = str;
-	while (*cp == ' ' || *cp == '\t' || *cp == '\n')
-		cp++;
-	is_negative = (*cp == '-');
-	if (is_negative)
-		cp++;
-	if (base == 0) {
-		base = 10;
-		if (*cp == '0') {
-			base = 8;
-			cp++;
-			if (*cp == 'x' || *cp == 'X') {
-				base = 16;
-				cp++;
-			}
-		}
-	}
-	value = 0;
-	for (; *cp != '\0'; cp++) {
-		if (*cp >= '0' && *cp <= '9')
-			digits = *cp - '0';
-		else if (*cp >= 'a' && *cp <= 'f')
-			digits = *cp - 'a' + 10;
-		else if (*cp >= 'A' && *cp <= 'F')
-			digits = *cp - 'A' + 10;
-		else
-			break;
-		if (digits >= base)
-			break;
-		value = (value * base) + digits;
-	}
-
-	/*
-	 * Note: we cast away const here deliberately
-	 */
-	if (ptr != NULL)
-		*ptr = (char *)cp;
-	if (is_negative)
-		value = -value;
-	return (value);
-}
-
-
-#ifdef	XCVR
-static int
-eri_init_xcvr_info(struct eri *erip, int display_msg)
-{
-	uint16_t phy_id1, phy_id2;
-	uint32_t vendor_id;
-	uint16_t device_id;
-	uint16_t device_rev;
-
-	(void) eri_mii_read(erip, ERI_PHY_IDR1, &phy_id1);
-	(void) eri_mii_read(erip, ERI_PHY_IDR2, &phy_id2);
-
-	vendor_id = ((phy_id1 << 0x6) | (phy_id2 >> 10));
-	device_id = (phy_id2 >>4) & 0x3f;
-	device_rev =  (phy_id2 & 0xf);
-
-	switch (vendor_id) {
-	case  PHY_VENDOR_LUCENT:
-		if (display_msg)
-			ERI_FAULT_MSG2(erip, SEVERITY_NONE, ERI_VERB_MSG,
-					lucent_phy_msg, vendor_id);
-		break;
-
-	/*
-	 * No Phy/xcvrs are executed as default.
-	 * This can happen if the xcvr is changed after the attach of a
-	 * I/O board or a future NIC.
-	 */
-	default:
-		ERI_FAULT_MSG2(erip, SEVERITY_HIGH, ERI_VERB_MSG,
-				unk_phy_msg, vendor_id);
-		erip->vendor_id = 0;
-		erip->device_id = 0;
-		erip->device_rev = 0;
-		param_linkup = 0;
-		erip->stats.link_up = ERI_LINK_DOWN;
-		erip->stats.link_duplex = ERI_UNKNOWN_DUPLEX;
-		eri_notify_ind(erip, DL_NOTE_LINK_DOWN);
-		return (1);
-	}
-	erip->vendor_id = vendor_id;
-	erip->device_id = device_id;
-	erip->device_rev = device_rev;
-	return (0);
-}
-#endif
-
 /* Decide if transmitter went dead and reinitialize everything */
 #ifdef	ERI_TX_HUNG
 static int eri_txhung_limit = 2;
 static int
 eri_check_txhung(struct eri *erip)
 {
+	boolean_t	macupdate = B_FALSE;
+
 	mutex_enter(&erip->xmitlock);
 	if (erip->flags & ERI_RUNNING)
-		erip->tx_completion = (uint32_t)(GET_ETXREG(tx_completion)
-				& ETX_COMPLETION_MASK);
-		(void) eri_reclaim(erip, erip->tx_completion);
+		erip->tx_completion = (uint32_t)(GET_ETXREG(tx_completion) &
+		    ETX_COMPLETION_MASK);
+		macupdate |= eri_reclaim(erip, erip->tx_completion);
 
 	/* Something needs to be sent out but it is not going out */
 	if ((erip->tcurp != erip->tnextp) &&
@@ -8950,159 +5760,9 @@
 	erip->erisave.starts = erip->stats.collisions;
 	mutex_exit(&erip->xmitlock);
 
+	if (macupdate)
+		mac_tx_update(erip->mh);
+
 	return (erip->txhung >= eri_txhung_limit);
 }
 #endif
-
-/* Process a DL_CAPABILITY_REQ */
-static void
-eri_dlcap_req(queue_t *wq, mblk_t *mp)
-{
-	struct eristr *sbp;
-	struct eri *erip;
-	dl_capability_req_t *icap;
-	int prim;
-	mblk_t *nmp;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	erip = sbp->sb_erip;
-	icap = (dl_capability_req_t *)mp->b_rptr;
-	prim = icap->dl_primitive;
-
-	ASSERT(prim == DL_CAPABILITY_REQ);
-
-	ERI_DEBUG_MSG2(erip, DLCAPAB_MSG, "eri_dlcap_req: DL_CAPABILITY for "
-	    "instance=%d\n", erip->instance);
-
-	if (icap->dl_sub_length == 0) {
-		/* IP wants to have a list of the capabilities we support. */
-		ERI_DEBUG_MSG1(erip, DLCAPAB_MSG, "eri_dlcap_req: got request "
-		    "for all capabilities");
-
-		nmp = eri_dlcap_all(wq);
-		if (nmp == NULL) {
-			dlerrorack(wq, mp, prim, DL_SYSERR, ENOSR);
-			return;
-		}
-		freemsg(mp);
-	} else {
-		/*
-		 * IP is probably trying to enable or disable one or more
-		 * capabilities. Reuse received mp to construct reply.
-		 */
-		ERI_DEBUG_MSG1(erip, DLCAPAB_MSG, "eri_dlcap_req: got len!=0 "
-		    "DL_CAPABILITY_REQ\n");
-		eri_dlcap_enable(wq, mp);
-		nmp = mp;
-	}
-	ASSERT(nmp != NULL);
-
-	/* send reply back up */
-	ERI_DEBUG_MSG1(erip, DLCAPAB_MSG, "eri_dlcap_req: sending ACK\n");
-	qreply(wq, nmp);
-}
-
-static mblk_t *
-eri_dlcap_all(queue_t *wq)
-{
-	mblk_t *nmp;
-	dl_capability_ack_t *ocap;
-	dl_capability_sub_t *osub;
-	dl_capab_hcksum_t *ocksum;
-	uint_t size;
-
-	/* Size of reply to send back up, say we support hardware checksum */
-	size = sizeof (dl_capability_ack_t) +
-	    sizeof (dl_capability_sub_t) +
-	    sizeof (dl_capab_hcksum_t);
-
-	/* allocate result mblk and get it started */
-	if ((nmp = allocb(size, BPRI_MED)) == NULL)
-		return (NULL);
-
-	/* update mblk info */
-	nmp->b_datap->db_type = M_PROTO;
-
-	/* dl_capability_ack_t, one per message */
-	ocap = (dl_capability_ack_t *)nmp->b_rptr;
-	ocap->dl_primitive = DL_CAPABILITY_ACK;
-	ocap->dl_sub_length = size - sizeof (dl_capability_ack_t);
-	ocap->dl_sub_offset = sizeof (dl_capability_ack_t);
-	nmp->b_wptr += sizeof (dl_capability_ack_t);
-
-	/* dl_capability_sub_t for hardware checksum offload */
-	osub = (dl_capability_sub_t *)nmp->b_wptr;
-	osub->dl_cap = DL_CAPAB_HCKSUM;
-	osub->dl_length = sizeof (dl_capab_hcksum_t);
-	nmp->b_wptr += sizeof (dl_capability_sub_t);
-
-	/* dl_capab_hcksum_t */
-	ocksum = (dl_capab_hcksum_t *)nmp->b_wptr;
-	ocksum->hcksum_version = HCKSUM_VERSION_1;
-	/* tell ip that we're capable, but don't enable until ip says so */
-	ocksum->hcksum_txflags = HCKSUM_INET_PARTIAL;
-	dlcapabsetqid(&ocksum->hcksum_mid, RD(wq));
-	nmp->b_wptr += sizeof (dl_capab_hcksum_t);
-
-	return (nmp);
-}
-
-/* Process a non-zero length DL_CAPABILITY_REQ message */
-static void
-eri_dlcap_enable(queue_t *wq, mblk_t *mp)
-{
-	struct eristr *sbp;
-	struct eri *erip;
-	dl_capability_req_t *icap;
-	dl_capability_sub_t *isub, *endp;
-	dl_capab_hcksum_t *icksum;
-
-	sbp = (struct eristr *)wq->q_ptr;
-	ASSERT(MUTEX_HELD(&sbp->sb_lock));
-	erip = sbp->sb_erip;
-	icap = (dl_capability_req_t *)mp->b_rptr;
-	icap->dl_primitive = DL_CAPABILITY_ACK;
-
-	/* Make sure that IP supplied correct dl_sub_length */
-	if ((sizeof (*icap) + icap->dl_sub_length) > MBLKL(mp)) {
-		ERI_DEBUG_MSG2(erip, DLCAPAB_MSG, "eri_dlcap_enable: bad "
-		    "DL_CAPABILITY_REQ, invalid dl_sub_length (%d)\n",
-		    icap->dl_sub_length);
-		return;
-	}
-
-#define	SC(base, offset) (dl_capability_sub_t *)(((uchar_t *)(base))+(offset))
-	/*
-	 * There are sub-capabilities. Process the ones we know about.
-	 * Loop until we don't have room for another sub-cap header..
-	 */
-	for (isub = SC(icap, icap->dl_sub_offset),
-	    endp = SC(isub, icap->dl_sub_length - sizeof (*isub));
-	    isub <= endp; isub = SC(isub,
-	    sizeof (dl_capability_sub_t) + isub->dl_length)) {
-
-		switch (isub->dl_cap) {
-		case DL_CAPAB_HCKSUM:
-			if ((uint8_t *)(isub + 1) + isub->dl_length >
-			    mp->b_wptr) {
-				ERI_DEBUG_MSG1(erip, DLCAPAB_MSG,
-				    "eri_dlcap_enable: malformed "
-				    "sub-capability too long for mblk");
-				break;
-			}
-			icksum = (dl_capab_hcksum_t *)(isub + 1);
-
-			if (icksum->hcksum_txflags & HCKSUM_ENABLE)
-				sbp->sb_flags |= ERI_SCKSUM;
-			else
-				sbp->sb_flags &= ~ERI_SCKSUM;
-			dlcapabsetqid(&icksum->hcksum_mid, RD(wq));
-			break;
-
-		default:
-			/* Unknown sub-capability; ignore it */
-			break;
-		}
-	}
-#undef SC
-}
--- a/usr/src/uts/sun/sys/eri.h	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sun/sys/eri.h	Thu Jun 07 06:48:35 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,9 +35,6 @@
 
 #ifdef _KERNEL
 
-#define	ETHERTYPE_IPV4	ETHERTYPE_IP
-#define	ETHERTYPE_IPV6	(0x86dd)	/* IPv6 */
-
 /* Named Dispatch Parameter Management Structure */
 typedef struct param_s {
 	uint32_t param_min;
@@ -103,6 +99,7 @@
 	uint32_t	pause_oncount;
 	uint32_t	pause_offcount;
 	uint32_t	pause_time_count;
+	uint32_t	pausing;
 
 	/*
 	 * Software event stats
@@ -174,17 +171,6 @@
 #define	HSTATN(erip, x, n)	erip->stats.x += n;
 
 
-/*
- * Definitions for module_info.
- */
-
-#define	ERI_IDNUM	(130)		/* module ID number */
-#define	ERI_NAME	"eri"		/* module name */
-#define	ERI_MINPSZ	(0)		/* min packet size */
-#define	ERI_MAXPSZ	(ETHERMTU +14) 	/* max packet size */
-#define	ERI_HIWAT	(128 * 1024)	/* hi-water mark */
-#define	ERI_LOWAT	(1)		/* lo-water mark */
-
 #define	TX_BCOPY_MAX		704	/* bcopy for packets < 704 bytes */
 #define	RX_BCOPY_MAX		704	/* bcopy for packets < 704 bytes */
 #define	TX_STREAM_MIN		512
@@ -199,52 +185,8 @@
  * ordered on minor device number.
  */
 
-#define	NMCHASH	64			/* # of multicast hash buckets */
-#define	INIT_BUCKET_SIZE 16		/* Initial Hash Bucket Size */
 #define	NMCFILTER_BITS	256		/* # of multicast filter bits */
 
-struct eristr {
-	struct eristr *sb_nextp;	/* next in list */
-	queue_t	*sb_rq;			/* pointer to our rq */
-	struct eri *sb_erip;		/* attached device */
-	t_uscalar_t sb_state;		/* current DL state */
-	t_uscalar_t sb_sap;		/* bound sap */
-	uint32_t sb_flags;		/* misc. flags */
-	minor_t sb_minor;		/* minor device number */
-
-	struct ether_addr
-		*sb_mctab[NMCHASH];	/* Hash table of multicast addrs */
-	uint32_t sb_mccount[NMCHASH];	/* # valid addresses in mctab[i] */
-	uint32_t sb_mcsize[NMCHASH];	/* Allocated size of mctab[i] */
-
-	uint16_t sb_ladrf[NMCFILTER_BITS/16];	/* Multicast filter bits */
-	uint16_t sb_ladrf_refcnt[NMCFILTER_BITS];
-					/* Reference count for filter bits */
-
-	kmutex_t sb_lock;	/* protect this structure */
-
-	uint32_t sb_notifications;	/* DLPI notifications */
-};
-
-#define	MCHASH(a)	((*(((uint8_t *)(a)) + 0) ^		\
-			*(((uint8_t *)(a)) + 1) ^		\
-			*(((uint8_t *)(a)) + 2) ^		\
-			*(((uint8_t *)(a)) + 3) ^		\
-			*(((uint8_t *)(a)) + 4) ^		\
-			*(((uint8_t *)(a)) + 5)) % (uint32_t)NMCHASH)
-
-/*
- * per-stream flags
- */
-#define	ERI_SFAST	0x01	/* "M_DATA fastpath" mode */
-#define	ERI_SRAW	0x02	/* M_DATA plain raw mode */
-#define	ERI_SALLPHYS	0x04	/* "promiscuous mode" */
-#define	ERI_SALLMULTI	0x08	/* enable all multicast addresses */
-#define	ERI_SALLSAP	0x10	/* enable all ether type values */
-#define	ERI_SCKSUM	0x20	/* Enable hardware tcp checksumming */
-#define	ERI_SMULTI	0x40    /* enable multicast addresses */
-#define	ERI_SSERLPBK	0x80    /* Enable SERDES loopback (DIAG) */
-#define	ERI_SMACLPBK	0x100   /* Enable MAC int loopback (DIAG) */
 
 /*
  * Maximum number of receive descriptors posted to the chip.
@@ -257,11 +199,6 @@
 #define	ERI_TPENDING	(erip->tpending)
 
 /*
- * Full DLSAP address length (in struct dladdr format).
- */
-#define	ERI_ADDRL	(sizeof (uint16_t) + ETHERADDRL)
-
-/*
  * Return the address of an adjacent descriptor in the given ring.
  */
 #define	NEXTRMD(erip, rmdp)	(((rmdp) + 1) == (erip)->rmdlimp ?	\
@@ -388,20 +325,6 @@
 #define	ERI_USE_NON_SERIAL_LINK		2	/* Select non-serial-link */
 
 /*
- * Speed definitions for param_speed
- */
-#define	SPEED_10	10
-#define	SPEED_100	100
-#define	SPEED_UNK	0
-
-/*
- * Mode definitions for param_mode
- */
-#define	ERI_MODE_HDX	0
-#define	ERI_MODE_FDX	1
-#define	ERI_MODE_UDX	2
-
-/*
  * eri_linkup_state" definitions
  */
 #define	ERI_START_LINK_BRINGUP	0
@@ -425,8 +348,8 @@
  * Each instance is dynamically allocated on first attach.
  */
 struct	eri {
-	struct	eri		*nextp;	/* next in a linked list */
-	dev_info_t		*dip;	/* associated dev_info */
+	mac_handle_t		mh;		/* GLDv3 handle */
+	dev_info_t		*dip;		/* associated dev_info */
 	uint_t			instance;	/* instance */
 
 	int			pci_mode;	/* sbus/pci device (future) */
@@ -434,17 +357,16 @@
 	int			low_power_mode; /* E* (low power) */
 	int			asic_rev;	/* ERI ASIC rev no. */
 	int			board_rev;	/* ERI ASIC rev no. */
-	int			burstsizes; /* binary encoded val */
+	int			burstsizes;	/* binary encoded val */
 	int			pagesize;	/* btop(9f) */
-	uint32_t		rxfifo_size; /* RX FIFO size */
+	uint32_t		rxfifo_size;	/* RX FIFO size */
 
 	int			rpending;	/* Max.no. of RX bufs post */
 	int			tpending;	/* Max.no. of tX bufs post */
 	int			tx_cur_cnt;	/* # of packets for int_me */
 
-	uint_t			promisc_cnt;	/* Promiscous streams open */
-	uint_t			all_sap_cnt;
-	uint_t			all_multi_cnt;
+	uint_t			multi_refcnt;
+	boolean_t		promisc;
 
 	int			mifpoll_enable;
 	int			frame_enable;
@@ -453,12 +375,13 @@
 	int			link_pulse_disabled;
 	int			xmit_dma_mode;
 	int			rcv_dma_mode;
-	struct	ether_addr	factaddr;	/* factory mac address */
-	struct	ether_addr	ouraddr;	/* individual address */
-	uint32_t		addrflags;	/* address flags */
-	uint32_t		flags;	/* misc. flags */
+	uint8_t			ouraddr[ETHERADDRL];	/* unicast address */
+	uint32_t		flags;		/* misc. flags */
 	uint32_t		alloc_flag;	/* Buff alloc. status flags */
-	uint32_t		wantw;	/* xmit: out of resources */
+	boolean_t		wantw;		/* xmit: out of resources */
+
+	uint16_t		ladrf[NMCFILTER_BITS/16]; /* Multicast filter */
+	uint16_t		ladrf_refcnt[NMCFILTER_BITS];
 
 	volatile struct	global	*globregp;	/* ERI global regs */
 	volatile struct	etx	*etxregp;	/* ERI ETX regs */
@@ -470,9 +393,6 @@
 
 	uint32_t		*sw_reset_reg;
 
-	queue_t			*ip4q;	/* ip read queue */
-	queue_t			*ip6q;	/* ip read queue */
-
 	uint32_t		rx_kick;	/* RX kick register val */
 	uint32_t		rx_completion;	/* RX completion reg val */
 #ifdef	RCV_OVRFLOW_CORRUPTION_BUG
@@ -576,7 +496,6 @@
 	int			linkup_changed; /* link bringup state */
 
 	int			linkcheck;
-	int			linksts_msg;
 	caddr_t			g_nd;	/* head of the */
 						/* named dispatch table */
 
@@ -614,7 +533,6 @@
 	mblk_t		*tmblkp[ERI_TMDMAX]; /* mblks assoc with TMD */
 	mblk_t		*rmblkp[ERI_RMDMAX]; /* mblks assoc with RMD */
 	param_t		param_arr[ERI_PARAM_CNT];
-	uint_t		param_display[ERI_PARAM_CNT]; /* cntrl display */
 
 	struct	stats stats;	/* kstats */
 
@@ -623,18 +541,8 @@
 	 */
 	uint32_t	starts;
 	uint32_t	txhung;
-	time_t		msg_time;
 	struct		erisave erisave;
 
-#ifdef XMIT_SERIAL_QUEUE
-	/* A syncq implementation. */
-	mblk_t		*sqfirst;	/* first mblk chain or NULL */
-	mblk_t		*sqlast;	/* last mblk chain or NULL */
-	kmutex_t	sqlock;		/* lock before using any member */
-	uint16_t	sqrefcnt;	/* count of threads using */
-	uint16_t	sqnmblks;
-#endif
-
 	uint64_t	ifspeed_old;
 
 #ifdef ERI_RMAC_HANG_WORKAROUND
@@ -648,6 +556,16 @@
 	uint32_t	tx_int_me;
 };
 
+/*
+ * LADRF bit array manipulation macros.  These are for working within the
+ * array of words defined by erip->ladrf, converting a bit (0-255) into
+ * the index and offset in the ladrf bit array.  Note that the array is
+ * provided in "Big Endian" order.
+ */
+#define	LADRF_MASK(bit)		(1 << ((bit) % 16))
+#define	LADRF_WORD(erip, bit)	erip->ladrf[(15 - ((bit) / 16))]
+#define	LADRF_SET(erip, bit)	(LADRF_WORD(erip, bit) |= LADRF_MASK(bit))
+#define	LADRF_CLR(erip, bit)	(LADRF_WORD(erip, bit) &= ~LADRF_MASK(bit))
 
 /*
  * ERI IOCTLS.
@@ -679,8 +597,7 @@
  */
 #define	ERI_UNKOWN	0x00	/* unknown state	*/
 #define	ERI_RUNNING	0x01	/* chip is initialized	*/
-#define	ERI_PROMISC	0x02	/* promiscuous mode enabled */
-#define	ERI_MULTICAST	0x04	/* Multicast mode enabled */
+#define	ERI_STARTED	0x02	/* mac layer started */
 #define	ERI_SUSPENDED	0x08	/* suspended interface	*/
 #define	ERI_INITIALIZED	0x10	/* interface initialized */
 #define	ERI_NOTIMEOUTS	0x20	/* disallow timeout rescheduling */
@@ -689,7 +606,6 @@
 #define	ERI_MACLOOPBACK	0x100	/* device has MAC int lpbk (DIAG) */
 #define	ERI_SERLOOPBACK	0x200	/* device has SERDES int lpbk (DIAG) */
 #define	ERI_DLPI_LINKUP	0x400	/* */
-#define	ERI_ALLMULTI	0x800	/* */
 
 /*
  * Mac address flags
@@ -699,46 +615,12 @@
 
 struct erikstat {
 	/*
-	 * Link Input/Output stats
-	 */
-	struct kstat_named	erik_ipackets;
-	struct kstat_named	erik_ierrors;
-	struct kstat_named	erik_opackets;
-	struct kstat_named	erik_oerrors;
-	struct kstat_named	erik_collisions;
-	struct kstat_named	erik_ifspeed;	/* Interface Speed */
-	/*
-	 * required by kstat for MIB II objects(RFC 1213)
-	 */
-	struct  kstat_named	erik_rbytes; 	/* # octets received */
-						/* MIB - ifInOctets */
-	struct  kstat_named	erik_obytes; 	/* # octets transmitted */
-						/* MIB - ifOutOctets */
-	struct  kstat_named	erik_multircv; 	/* # multicast packets */
-						/* delivered to upper layer */
-						/* MIB - ifInNUcastPkts */
-	struct  kstat_named	erik_multixmt; 	/* # multicast packets */
-						/* requested to be sent */
-						/* MIB - ifOutNUcastPkts */
-	struct  kstat_named	erik_brdcstrcv;	/* # broadcast packets */
-						/* delivered to upper layer */
-						/* MIB - ifInNUcastPkts */
-	struct  kstat_named	erik_brdcstxmt;	/* # broadcast packets */
-						/* requested to be sent */
-						/* MIB - ifOutNUcastPkts */
-	struct  kstat_named	erik_norcvbuf; 	/* # rcv packets discarded */
-						/* MIB - ifInDiscards */
-	struct  kstat_named	erik_noxmtbuf; 	/* # xmt packets discarded */
-						/* MIB - ifOutDiscards */
-	/*
 	 * Software event stats
 	 */
 	struct kstat_named	erik_inits;
 	struct kstat_named	erik_rx_inits;
 	struct kstat_named	erik_tx_inits;
-	struct kstat_named	erik_tnocar;	/* Link down counter */
 
-	struct kstat_named	erik_nocanput;
 	struct kstat_named	erik_allocbfail;
 	struct kstat_named	erik_drop;
 
@@ -753,11 +635,7 @@
 	/*
 	 * MAC TX Event stats
 	 */
-	struct kstat_named	erik_txmac_urun;
 	struct kstat_named	erik_txmac_maxpkt_err;
-	struct kstat_named	erik_excessive_coll;
-	struct kstat_named	erik_late_coll;
-	struct kstat_named	erik_first_coll;
 	struct kstat_named	erik_defer_timer_exp;
 	struct kstat_named	erik_peak_attempt_cnt;
 	struct kstat_named	erik_jab;
@@ -767,17 +645,11 @@
 	/*
 	 * MAC RX Event stats
 	 */
-	struct kstat_named	erik_rx_corr;
 	struct kstat_named	erik_no_free_rx_desc; /* no free rx desc. */
-	struct kstat_named	erik_rx_overflow;
 	struct kstat_named	erik_rx_hang;
-	struct kstat_named	erik_rx_align_err;
-	struct kstat_named	erik_rx_crc_err;
 	struct kstat_named	erik_rx_length_err;
 	struct kstat_named	erik_rx_code_viol_err;
 	struct kstat_named	erik_rx_bad_pkts;
-	struct kstat_named	erik_rx_runt;
-	struct kstat_named	erik_rx_toolong_pkts;
 
 	/*
 	 * Fatal errors
@@ -806,21 +678,7 @@
 	struct kstat_named	erik_pci_det_parity_err;
 
 
-	/*
-	 * PSARC 1997/198 : 64bit kstats
-	 */
-	struct kstat_named	erik_ipackets64;
-	struct kstat_named	erik_opackets64;
-	struct kstat_named	erik_rbytes64; 	/* # octets received */
-						/* MIB - ifInOctets */
-	struct kstat_named	erik_obytes64; 	/* # octets transmitted */
-						/* MIB - ifOutOctets */
-
 	struct kstat_named	erik_pmcap;	/* Power management */
-
-	struct kstat_named	erik_link_up;	/* Link Status */
-
-	struct kstat_named	erik_link_duplex;	/* Link duplex */
 };
 
 /* TBD: new value ? */
@@ -849,13 +707,6 @@
 #define	ERI_FSTBYTE_OFFSET	2
 #define	ERI_CKSUM_OFFSET	14
 
-/*
- * Private DLPI full dlsap address format.
- */
-struct	eridladdr {
-	struct	ether_addr	dl_phys;
-	uint16_t dl_sap;
-};
 
 #define	ERI_PMCAP_NONE	0
 #define	ERI_PMCAP_4MHZ	4
--- a/usr/src/uts/sun/sys/eri_common.h	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sun/sys/eri_common.h	Thu Jun 07 06:48:35 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 1999-2001, 2003 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -35,7 +34,6 @@
 
 #ifdef _KERNEL
 
-typedef int	(*fptri_t)();
 typedef void	(*fptrv_t)();
 
 typedef enum {
@@ -70,16 +68,16 @@
 
 
 #define	ERI_FAULT_MSG1(p, t, f, a) \
-    eri_fault_msg(__FILE__, __LINE__, (p), (t), (f), (a));
+    eri_fault_msg((p), (t), (f), (a));
 
 #define	ERI_FAULT_MSG2(p, t, f, a, b) \
-    eri_fault_msg(__FILE__, __LINE__, (p), (t), (f), (a), (b));
+    eri_fault_msg((p), (t), (f), (a), (b));
 
 #define	ERI_FAULT_MSG3(p, t, f, a, b, c) \
-    eri_fault_msg(__FILE__, __LINE__, (p), (t), (f), (a), (b), (c));
+    eri_fault_msg((p), (t), (f), (a), (b), (c));
 
 #define	ERI_FAULT_MSG4(p, t, f, a, b, c, d) \
-    eri_fault_msg(__FILE__, __LINE__, (p), (t), (f), (a), (b), (c), (d));
+    eri_fault_msg((p), (t), (f), (a), (b), (c), (d));
 
 #ifdef  DEBUG
 typedef enum {
@@ -178,8 +176,8 @@
 	"DLCAPAB"
 };
 
-static void	eri_debug_msg(char *, int, struct eri *, debug_msg_t,
-    char *, ...);
+static void	eri_debug_msg(const char *, int, struct eri *, debug_msg_t,
+    const char *, ...);
 
 #define	ERI_DEBUG_MSG1(t, f, a) \
     eri_debug_msg(__FILE__, __LINE__, (t), (f), (a));
@@ -298,7 +296,7 @@
 #define	ERI_MASK_8BIT	0xff
 
 #define	param_transceiver	(erip->param_arr[0].param_val)
-#define	param_linkup	(erip->param_arr[1].param_val)
+#define	param_linkup		(erip->param_arr[1].param_val)
 #define	param_speed		(erip->param_arr[2].param_val)
 #define	param_mode		(erip->param_arr[3].param_val)
 #define	param_ipg1		(erip->param_arr[4].param_val)
@@ -325,33 +323,22 @@
 #define	param_anlpar_100hdx	(erip->param_arr[23].param_val)
 #define	param_anlpar_10fdx	(erip->param_arr[24].param_val)
 #define	param_anlpar_10hdx	(erip->param_arr[25].param_val)
-#define	param_device		(erip->param_arr[26].param_val)
-#define	param_lance_mode	(erip->param_arr[27].param_val)
-#define	param_ipg0		(erip->param_arr[28].param_val)
-#define	param_intr_blank_time		(erip->param_arr[29].param_val)
-#define	param_intr_blank_packets	(erip->param_arr[30].param_val)
-#define	param_serial_link	(erip->param_arr[31].param_val)
+#define	param_lance_mode	(erip->param_arr[26].param_val)
+#define	param_ipg0		(erip->param_arr[27].param_val)
+#define	param_intr_blank_time		(erip->param_arr[28].param_val)
+#define	param_intr_blank_packets	(erip->param_arr[29].param_val)
+#define	param_serial_link	(erip->param_arr[30].param_val)
 
-#define	param_non_serial_link	(erip->param_arr[32].param_val)
-#define	param_select_link	(erip->param_arr[33].param_val)
-#define	param_default_link	(erip->param_arr[34].param_val)
-#define	param_link_in_use	(erip->param_arr[35].param_val)
-#define	param_unknown0		(erip->param_arr[36].param_val)
-#define	param_unknown1		(erip->param_arr[37].param_val)
-#define	param_unknown2		(erip->param_arr[38].param_val)
-#define	param_anar_asm_dir	(erip->param_arr[39].param_val)
-#define	param_anar_pause	(erip->param_arr[40].param_val)
-#define	param_unknown3		(erip->param_arr[41].param_val)
-
-#define	param_unknown4		(erip->param_arr[42].param_val)
-#define	param_unknown5		(erip->param_arr[43].param_val)
-#define	param_bmsr_asm_dir	(erip->param_arr[44].param_val)
-#define	param_bmsr_pause	(erip->param_arr[45].param_val)
-#define	param_anlpar_autoneg 	(erip->param_arr[46].param_val)
-#define	param_unknown6		(erip->param_arr[47].param_val)
-#define	param_unknown7		(erip->param_arr[48].param_val)
+#define	param_non_serial_link	(erip->param_arr[31].param_val)
+#define	param_select_link	(erip->param_arr[32].param_val)
+#define	param_default_link	(erip->param_arr[33].param_val)
+#define	param_link_in_use	(erip->param_arr[34].param_val)
+#define	param_anar_asm_dir	(erip->param_arr[35].param_val)
+#define	param_anar_pause	(erip->param_arr[36].param_val)
+#define	param_bmsr_asm_dir	(erip->param_arr[37].param_val)
+#define	param_bmsr_pause	(erip->param_arr[38].param_val)
 #define	param_anlpar_pauseTX 	(erip->param_arr[49].param_val)
-#define	param_anlpar_pauseRX 	(erip->param_arr[50].param_val)
+#define	param_anlpar_pauseRX 	(erip->param_arr[40].param_val)
 
 /* <<<<<<<<<<<<<<<<<<<<<<  Register operations >>>>>>>>>>>>>>>>>>>>> */
 #define	GET_PCSREG(reg) \
@@ -454,57 +441,12 @@
 
 
 /*
- * Ether_copy is not endian-correct. Define an endian-correct version.
- */
-#define	ether_bcopy(a, b) (bcopy((caddr_t)a, (caddr_t)b, 6))
-
-/*
  * Ether-type is specifically big-endian, but data region is unknown endian
+ * Ether-type lives at offset 12 from the start of the packet.
  */
 
-typedef struct ether_header *eehp;
-
-#define	get_ether_type(ptr) (\
-	(((uint8_t *)&((eehp)ptr)->ether_type)[0] << 8) | \
-	(((uint8_t *)&((eehp)ptr)->ether_type)[1]))
-#define	put_ether_type(ptr, value) {\
-	((uint8_t *)(&((eehp)ptr)->ether_type))[0] = \
-	    ((uint16_t)value & 0xff00) >> 8; \
-	((uint8_t *)(&((eehp)ptr)->ether_type))[1] = (value & 0xff); }
-
-
-/*
- * The following MACROS are used to filter out bad packets which are
- * a result of descriptor corruption in ERI 1.0 ASIC. The packets are
- * either concatenated or truncated. Here we compare the length field
- * of the incoming packet with what is reported by the decriptor
- * length field. This check is in addition to the illegal packet
- *  (64 < len < 1518)  size check done in eri_read routines.
- */
-
-#ifdef ERI_ERI_REV_1_0
-#define	IP_PACKET_LEN(len) \
-	(len - 14)
-#define	INVALID_IP_PACKET_LENGTH(ipp, len) \
-	((len > 0x3c) && (ipp->ip_len != (len - 14)))
-
-#define	IP_PACKET_IS_TCP(ipp)	(ipp->ip_p & 0x06)
-
-#define	ERI_ERX_HANG(wp, rp) \
-	    ((rp <= wp) ? ((wp - rp) > 1275) : ((rp -wp) < 4))
-#endif
-
-
-#define	DEVICE_NAME(dip) \
-	    ((strcmp(ddi_get_name(dip), "pci108e,1101") == 0) ? \
-	    "SUNW,eri" : "SUNW,eri:unknown")
-
-/*
- * Allocate and zero-out "number" structures
- * each of type "structure" in kernel memory.
- */
-#define	GETSTRUCT(structure, number)   \
-	(kmem_zalloc((size_t)(sizeof (structure) * (number)), KM_SLEEP))
+#define	get_ether_type(ptr) \
+	(((((uint8_t *)ptr)[12] << 8) | (((uint8_t *)ptr)[13])))
 
 #endif	/* _KERNEL */
 
--- a/usr/src/uts/sun/sys/eri_mac.h	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sun/sys/eri_mac.h	Thu Jun 07 06:48:35 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef	_SYS_ERI_MAC_H
@@ -745,7 +744,7 @@
 #define	BMAC_SLOT_TIME		0x40
 #define	BMAC_EXT_SLOT_TIME	0x200
 #define	BMAC_MIN_FRAME_SIZE	0x40
-#define	BMAC_MAX_FRAME_SIZE	(ETHERMTU + 18)
+#define	BMAC_MAX_FRAME_SIZE	(ETHERMTU + 18 + 4)	/* enet + vlan */
 
 /*
  *	Hardware bug: set MAC_FRAME_SIZE to 0x7fff to
--- a/usr/src/uts/sun/sys/eri_msg.h	Thu Jun 07 06:43:34 2007 -0700
+++ b/usr/src/uts/sun/sys/eri_msg.h	Thu Jun 07 06:48:35 2007 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,8 +19,8 @@
  * CDDL HEADER END
  */
 /*
- * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
- * All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
  */
 
 #ifndef	_SYS_ERI_MSG_H
@@ -36,28 +35,6 @@
 /*
  * All strings used by eri messaging functions
  */
-
-#if defined(DEBUG)
-#ifdef	LATER
-static  char *par_detect_fault_msg = "Parallel Detection Fault";
-static  char *autoneg_speed_bad_msg = "Autonegotiated speed is bad";
-static  char *phy_speed_bad_msg = "The current Phy/xcvr speed is not valid";
-static  char *no_phy_msg = "No Phy/xcvr found";
-static  char *unk_phy_msg = "Non supported Phy/Xcvr, Vendor Id: %x";
-static  char *lucent_phy_msg = "Lucent Phy, Vendor Id: %x";
-static  char *link_up_msg = "Link Up";
-static  char *link_status_msg = "%s %4d Mbps %s-Duplex Link Up";
-#endif
-#if	0
-static	char *link_down_msg =
-	"No response from Ethernet network : Link down -- cable problem?";
-#endif
-static  char *mif_write_fail_msg = "MIF Write failure";
-#endif
-
-/*
- * All strings used by eri messaging functions
- */
 static  char *loopback_val_default = "Loopback Value: Error In Value.";
 static  char *loopback_cmd_default = "Loopback Command: Error In Value.";
 static  char *lmac_addr_msg = "Using local MAC address";
@@ -65,20 +42,6 @@
 static  char *busy_msg = "Driver is BUSY with upper layer";
 static  char *attach_fail_msg = "Attach entry point failed";
 
-#if defined(DEBUG)
-static  char *attach_bad_cmd_msg = "Attach entry point rcv'd a bad command";
-static  char *burst_size_msg = "Could not identify the burst size";
-static  char *detach_bad_cmd_msg = "Detach entry point rcv'd a bad command";
-static  char *add_intr_fail_msg = "ddi_add_intr(9F) failed";
-static  char *create_minor_node_fail_msg = "ddi_create_minor_node(9F) failed";
-#ifdef	LATER
-static  char *mregs_4config_fail_msg =
-	"ddi_regs_map_setup(9F) for config space failed";
-#endif
-static  char *mregs_4global_reg_fail_msg =
-	"ddi_regs_map_setup(9F) for global reg failed";
-#endif
-
 static  char *mregs_4soft_reset_fail_msg =
 	"ddi_regs_map_setup(9F) for soft reset failed";
 static  char *disable_erx_msg = "Can not disable Rx.";
@@ -91,8 +54,6 @@
 static  char *alloc_rx_dmah_msg = "Can not allocate Rx dma handle.";
 static  char *config_space_fatal_msg =
 	"Configuration space failed in routine.";
-static  char *link_down_msg =
-	"No response from Ethernet network : Link down -- cable problem?";
 static  char *kstat_create_fail_msg = "kstat_create failed";
 static  char *param_reg_fail_msg = "param_register failed";